CoolFace
Modelpublic

hoailebads/Qwen3-Embedding-0.6B-VLSP-Legal-Retrieval-LoRA

sourceHugging Faceapache-2.0updated 1mo agoView on Hugging Face
0likes
Model Card

Qwen3-Embedding-0.6B — VLSP Legal Retrieval (Dual-LoRA)

Bi-encoder truy hồi điều luật tiếng Việt cho bài toán VLSP Legal Text Retrieval. Kiến trúc dual-LoRA: hai adapter LoRA riêng biệt dùng chung một base model đóng băng — query_adapter mã hoá câu hỏi, passage_adapter mã hoá điều luật.

Đây là checkpoint retrieval tốt nhất trong 22 lần train được đo trên cùng tập eval (train_synthetic_hoi_dap), dùng để sinh top-100 candidate cho pha rerank trong hoaileba/Qwen-Retrieval-Tuning.

Kết quả

Tập eval: 219 câu hỏi unique (VLSP eval.json, ground truth dedup theo aid). Corpus: 67,561 chunk / 59,628 điều luật. FAISS inner-product, dedup theo aid.

KRecall@KPrecision@KHit@K
145.8152.9752.97
362.6025.2771.69
569.2916.9979.00
1080.9010.1889.95
10094.981.2598.63

R@100 = 94.98 là trần recall cho pha rerank phía sau — ~5% câu hỏi không có đáp án đúng trong 100 candidate, và đó là giới hạn thật của pipeline chứ không phải của reranker.

So với các checkpoint khác (cùng tập eval 219 câu)

RunR@1R@10R@100
`train_synthetic_hoi_dap` ← model này45.8180.9094.98
train_synthetic_only_hn (checkpoint cha)44.2281.2894.18
train_dual_syn_ques_filtered_cont44.2277.8294.98
train_dual_vlsp_only_original43.6178.7794.33
train_synthetic_binh_dan42.6281.2093.42
train_synthetic_dong_nghia_new42.5481.4394.03
single-adapter LoRA (train_single_vlsp_only)41.0279.2294.10
fast_cached_mnrl_hn_dual_syn_ques (bản sớm)32.9968.3886.68

Hai điều đọc được từ bảng: dual-adapter hơn single-adapter (+4.8 R@1 so với train_single_vlsp_only), và augment câu hỏi dạng hỏi–đáp (hoi_dap) là biến thể synthetic cho lợi ích lớn nhất — cộng thêm +1.6 R@1 lên trên checkpoint cha train_synthetic_only_hn.

Số đo đầy đủ: `eval_results.json`.

Cách dùng

Model gồm hai adapter nên không load thẳng bằng AutoModel được — phải nạp cả hai và chuyển adapter theo loại text. File `modeling_dual_lora.py` trong repo này làm sẵn việc đó:

python
from modeling_dual_lora import DualLoRAEncoder
import numpy as np

enc = DualLoRAEncoder.from_pretrained("hoailebads/Qwen3-Embedding-0.6B-VLSP-Legal-Retrieval-LoRA")

questions = ["Người điều khiển xe máy không đội mũ bảo hiểm bị phạt bao nhiêu tiền?"]
articles  = ["Điều 6. Xử phạt người điều khiển xe mô tô, xe gắn máy ... "]

q = enc.encode(questions, is_query=True)    # (1, 1024), đã L2-normalize
d = enc.encode(articles,  is_query=False)   # (N, 1024)

scores = q @ d.T                            # inner product == cosine
top = np.argsort(-scores[0])[:10]

Hoặc tự nạp bằng PEFT:

python
from transformers import AutoModel, AutoTokenizer
from peft import PeftModel
import torch

base = AutoModel.from_pretrained("Qwen/Qwen3-Embedding-0.6B",
                                 torch_dtype=torch.bfloat16, trust_remote_code=True)
model = PeftModel.from_pretrained(base, "<repo>/query_adapter", adapter_name="query_adapter")
model.load_adapter("<repo>/passage_adapter", adapter_name="passage_adapter")

model.set_adapter("query_adapter")     # trước khi encode câu hỏi
model.set_adapter("passage_adapter")   # trước khi encode điều luật

Quy ước bắt buộc (phải khớp lúc train)

  • —Không có instruction prefix. Encode raw text — thêm "Instruct: ..." sẽ lệch phân bố.
  • —Pooling = hidden state của token thật cuối cùng, sau đó L2-normalize.
  • —max_length = 1024, truncation bên phải (mặc định của tokenizer).
  • —Passage text = article_title + "\n" + content.
  • —Encode query bằng `passage_adapter` (hoặc ngược lại) làm hỏng kết quả — đây là lỗi dễ mắc nhất khi dùng model này.

Huấn luyện

Base modelQwen/Qwen3-Embedding-0.6B (đóng băng)
LoRAr=16, alpha=32, dropout=0.05, target = q,k,v,o,gate,up,down_proj
Trainable20,185,088 / 615,961,600 params (3.28%), ×2 adapter
Lossfast_cached_mnrl_dual — cached multiple-negatives ranking, temperature=0.05
Hard negatives1/query (mine từ chính checkpoint cha)
Batch size256 (cached mini-batch 16)
Epochs / steps5 epochs, 20 optimizer steps
Precisionbf16 + Flash Attention 2, 2×GPU torchrun
Resume từoutput/train_synthetic_only_hn (huấn luyện nối tiếp nhiều pha)
Train loss1.5675 → 1.3703
Dataset2,038 sample — VLSP gốc + câu hỏi synthetic biến thể hỏi–đáp

Model là kết quả của một chuỗi train nối tiếp, không phải một lần train từ base: mỗi pha mine lại hard negative bằng checkpoint ngay trước đó rồi train tiếp trên một biến thể synthetic mới. train_synthetic_hoi_dap là pha cuối của nhánh thắng.

Vị trí trong pipeline

câu hỏi → [RETRIEVAL: model này] → top-100 → [RERANK: Qwen3-Reranker-8B] → dynamic top-k → đáp án

Model liên quan:

Code + số đo đầy đủ: hoaileba/Qwen-Retrieval-Tuning

Giới hạn

  • —Chỉ đo trên văn bản pháp luật tiếng Việt; chưa đo trên domain khác hay ngôn ngữ khác.
  • —Tập eval 219 câu là nhỏ — chênh lệch <1 điểm R@1 giữa các checkpoint nằm trong nhiễu.
  • —Corpus VLSP có ~1.35 điều luật đúng/câu hỏi; metric ở đây là retrieval thuần, chưa phải F2MACRO của giải (cần thêm rerank + chọn top-k động).

License

Apache-2.0, theo base model Qwen/Qwen3-Embedding-0.6B.