Bilingual (EN/FR) legal AI assistant for Cameroon - grounded RAG over 13k+ passages of real law, cited answers, honest abstention. Web + Telegram, deployed 24/7.
# Cameroon Legal Assistant (RAG chatbot)
A citizen-facing legal-information chatbot. Ask a question in **English or French**
about Cameroonian law, the constitution, custom, or an administrative procedure,
and get a **plain-language, grounded, cited** answer — built only from a verified
catalogue of legal sources, never invented law.
This is a Retrieval-Augmented Generation (RAG) system:
```
BUILD (offline, re-runnable) ANSWER (per question)
Master sheet (registry, .xlsx) User question (EN/FR)
│ │
▼ ▼
Ingestion script ── fetch/extract/chunk ─▶ (corpus)
│ │
▼ ▼
Local embeddings (bge-m3) ───────────────▶ Hybrid retrieval (vector + BM25)
│ │
▼ ▼
Chroma (vectors) + BM25 index ───────────▶ Grok 4.1-fast (generate, cite)
│
▼
Answer + source links
```
- **Registry:** the local `Cameroon_Law_Master_Catalogue (3).xlsx` (sheet `Master`)
— an index of ~115 sources (URL + metadata), not the law text itself.
- **Embeddings + store:** `BAAI/bge-m3` (free, local, multilingual) + Chroma + BM25.
No paid services; runs on a laptop.
- **Generation:** Grok via the xAI API (OpenAI-compatible SDK). The model answers
**only** from retrieved sources and cites them every time.
---
## Setup
```bash
python -m venv .venv
source .venv/Scripts/activate # Windows (Git Bash); use .venv\Scripts\activate on cmd/PowerShell
# macOS/Linux: source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env # then fill in XAI_API_KEY (SHEET defaults to the local .xlsx)
```
`.env` keys: `XAI_API_KEY`, `GROK_MODEL=grok-4.1-fast`, `EMBED_MODEL=BAAI/bge-m3`,
`TOP_K=6`, `SHEET_XLSX_PATH` (defaults to the bundled file), optional `SHEET_CSV_URL`,
`CORS_ORIGINS`.
> The first build downloads the bge-m3 model …