Legal RAG (retrieval-augmented legal Q&A)
Local embeddings index over legal documents + grounded answers from Gemini 3.1 Pro (strong on LegalBench). Bilingual (Arabic + English). Citations by [n] markers tied to source chunks.
Setup
- Put legal docs (
.txt/.md) inskills/legal-rag/data/. - Env:
GEMINI_API_KEY/GOOGLE_API_KEY. For legal-tuned embeddings:VOYAGE_API_KEY. - Python stdlib +
requests(no heavy vector DB; cosine over a JSON index).
Usage
bash
. /data/.openclaw/secrets/env.sh
python3 scripts/legal_rag.py --index # build index from data/
python3 scripts/legal_rag.py --ask "question" --k 4 # retrieve + grounded answer
python3 scripts/legal_rag.py --ask "..." --embed voyage # voyage-law-2 (legal-tuned)
python3 scripts/legal_rag.py --ask "..." --lang ar # force Arabic answer
How it works
1. Chunk docs (~1200 chars, 200 overlap). 2. Embed chunks —gemini-embedding-001 (default) or voyage-law-2 (--embed voyage, 1024-dim, legal-tuned).
3. Store vectors in index.json (records: source, chunk, text, embedding).
4. On query: embed question → cosine top-k → feed passages to gemini-3.1-pro-preview with a strict "answer only from passages, cite [n], say if not found" prompt.Verified (2026-06-14 — rebuilt on voyage-law-2)
- Active index backend: voyage-law-2 (1024-dim), 7 chunks from 4 docs (enriched Kuwaiti civil/labor/personal-status laws + sample contract) ✅
- AR query "مكافأة نهاية الخدمة" → cited M.51 + M.53 (labor law 6/2010) ✅
- AR query "التقادم في القانون المدني" → cited M.437 (15yr) + M.442 (5yr) ✅
retrieve()readsr["embedding"]and embeds query with the index's recorded backend (voyage) ✅- 429 retry/backoff added for Voyage free tier (3 RPM) — robust against rate limits ✅
Notes
- Switching
--embedrequires re-running--index(vectors must match query backend; the index records its backend and query uses the same one). - Voyage free tier = 3 requests/min. The script auto-retries 429 with backoff (5–25s). For heavy use, add a payment method on the Voyage dashboard.
- Not legal advice; retrieval is bounded to provided docs only.
- Backup of prior gemini index kept as
index.json.bak-gemini-*.