pan0sk/bge-m3-legal-v4
bge-m3-legal-v4 — Greek legal/administrative retrieval embedder
Fine-tune of BAAI/bge-m3 for Greek legal, statute/administrative and daily-Greek retrieval. Dense, 1024-dim, CLS-free (mean-pooled per bge-m3), served as f16 GGUF or safetensors.
Held-out results (recall@1, rank-the-true-passage)
Companion reranker: pan0sk/bge-reranker-v2-m3-legal.
Chunking & embedding — best practices (measured, not generic)
These reflect the model's actual training distribution; deviating from them costs recall.
Chunk size: 1,200–2,400 characters of Greek (≈300–600 tokens), overlap ~200 chars. Training passages had median ~1,500 chars; both training and validation truncated at 256–512 tokens. Greek is token-dense in the XLM-R vocabulary (≈1 token/char worst case, plan with ≈3–4 chars/token typical) — chunks beyond ~2,400 chars get tail-truncated and waste content. Do NOT embed whole documents as one vector: long-input embeddings go diffuse and localized-evidence retrieval degrades (measured repeatedly in this program).
Chunk on structure, not fixed windows, when the text has structure. For statutes, one άρθρο (or one paragraph of a long άρθρο) per chunk. For court decisions, paragraph boundaries of the σκεπτικό. Keep a sentence-safe split otherwise.
Prefix each chunk with its provenance (contextual retrieval). A chunk of «Άρθρο 12» means little without which law it belongs to. Prepend a short breadcrumb line, e.g. Ν. 4808/2021, Άρθρο 12 — [chunk text]. Title/heading + body was exactly the statute training format, so this matches the model's distribution.
Queries: natural questions or descriptive phrases, as-is. No instruction prefixes — bge-m3 is not instruction-tuned and none were used in training. Both interrogative («Ποια είναι η προθεσμία…;») and nominal («προθεσμία έφεσης κατά απόφασης») styles were trained.
Cross-lingual: translate-then-retrieve beats direct embedding. Direct EN query → EL corpus scores 82.1 here; translating the English query to Greek first and retrieving Greek→Greek operates at the 85–92 band. If your users query in English over Greek documents, machine-translate the query first.
Always L2-normalize vectors (Ollama's /api/embed returns them normalized; if you call the model another way, normalize yourself). With normalized vectors, L2 and cosine ranking are identical. Use exact (brute-force) search below ~100k vectors — lossy ANN indexes (IVF_PQ) cost 5–15% recall and are unnecessary at document-collection scale.
Batching: ≤32 texts or ≈8,000 estimated tokens per request keeps within the context window and gives stable throughput.
Version migrations: vectors from different embedder versions (or other models) are NOT comparable. Any model switch requires re-embedding the entire store.
Serving
ollama pull hf.co/pan0sk/bge-m3-legal-v4Or SentenceTransformer("pan0sk/bge-m3-legal-v4") for GPU/server (vLLM/TEI compatible via the safetensors).
Training summary
~147k (query→passage) pairs across 6 registers: Greek legal 82k (court decisions), statute 13.5k (greeklegalcode CC-BY-4.0), daily 15k (clips/mqa CC0 + el-Wikipedia), English 6k (SQuAD), task cross-lingual 4.5k, EL↔EN bitext 24k (JRC-Acquis + Europarl). MNRL, homogeneous per-register batches, TopK-PercPos-denoised hard negatives (legal/statute), 2 epochs (epoch-2 checkpoint). GreekBarBench fully held out.
