deka-qwen3-emb-0.6b-multipos-lawyer-anompos
Full fine-tune of Qwen/Qwen3-Embedding-0.6B for Thai Supreme Court (deka) case retrieval.
- objective:
multipos - document register:
lawyer(query side trained againstfacttext) - best epoch: 2 (early-stopped on dev R@10 = 29.25)
- pooling: last token (left padding) + L2 normalize
- lr 2e-05, batch 16, tau 0.05, max_len doc 1300 / query 256, seed 42
Test results (full corpus, clean qrels)
| eval register | R@5 | R@10 | R@50 | R@100 | ndcg@10 | mrr |
|---|---|---|---|---|---|---|
| user | 6.67 | 12.38 | 36.19 | 46.67 | 7.03 | 0.0883 |
| lawer | 15.24 | 25.24 | 56.67 | 69.05 | 14.8 | 0.1687 |
| fact | 18.57 | 27.62 | 59.05 | 75.24 | 18.06 | 0.2368 |
Usage
Queries must carry the instruction prefix used in training; documents must not.
from sentence_transformers import SentenceTransformer
m = SentenceTransformer("anonymousresearch123/deka-qwen3-emb-0.6b-multipos-lawyer-anompos")
q = m.encode(["ลูกจ้างถูกเลิกจ้างโดยไม่บอกกล่าวล่วงหน้า"], prompt_name="query")
d = m.encode(["<คำพิพากษาฎีกา ...>"])
print(m.similarity(q, d))
Plain transformers:
import torch, torch.nn.functional as F
from transformers import AutoModel, AutoTokenizer
tok = AutoTokenizer.from_pretrained("anonymousresearch123/deka-qwen3-emb-0.6b-multipos-lawyer-anompos", padding_side="left")
net = AutoModel.from_pretrained("anonymousresearch123/deka-qwen3-emb-0.6b-multipos-lawyer-anompos", torch_dtype=torch.bfloat16).eval()
INSTRUCT = "Given a legal case search query, retrieve relevant prior Supreme Court cases"
texts = [f"Instruct: {INSTRUCT}\nQuery: ลูกจ้างถูกเลิกจ้าง..."] # query side only
enc = tok(texts, padding=True, truncation=True, max_length=1300, return_tensors="pt")
with torch.no_grad():
h = net(**enc).last_hidden_state
emb = F.normalize(h[:, -1].float(), p=2, dim=-1)
Left padding is required — pooling takes the last position.
Training data
anonymousresearch123/deka-retrieval — splits train / eval / test.
training_history.json in this repo holds the full per-epoch log and config.