Retrieval-augmented QA over Ghana presidential election results (1992-2020) and the 2025 Budget Statement. Hybrid BM25 + dense retrieval, custom NumPy vector store, Groq LLM, Streamlit. CS4241 project.
# Ghana Elections + 2025 Budget — RAG
**CS4241 project · index 10022200110**
A retrieval-augmented QA system over two Ghanaian public-interest documents:
- Ghana Presidential Election results for 2012, 2016, 2020
- The Government of Ghana **2025 Budget Statement and Economic Policy**
Stack: **Groq (Llama 3.1 8B Instant) · sentence-transformers · custom NumPy vector store · hybrid BM25 + dense retrieval · Streamlit**, deployed on Streamlit Community Cloud.
---
## Feature summary
- **Ingestion** — 866 raw docs → 397 chunks (98 election year-region groups + 299 sentence-window PDF chunks, 300w / 50w overlap).
- **Embeddings** — `all-MiniLM-L6-v2`, 384 dims, L2-normalized, disk-cached.
- **Vector store** — from-scratch NumPy, cosine = dot product, `argpartition` top-k.
- **Hybrid retrieval** — dense + custom BM25, fused with Reciprocal Rank Fusion (k=60), then dense-cosine reranking on the pooled candidates.
- **Prompt & hallucination guard** — strict system prompt, numbered `[C1]` citations, post-hoc grounding audit flags suspicious answers.
- **Feedback-loop innovation** — Chunk Reputation Boosting: each thumbs-up/down updates per-chunk reputation and influences future retrieval, bounded to prevent runaway effects.
- **Adversarial evaluation** — ground-truth, numeric, out-of-scope, and false-premise cases with reported hallucination and refusal rates.
- **Streamlit UI** — Chat, Retrieval inspector, Failure-case demo, Evaluation, Feedback report.
---
## Repository layout
```
rag_project/
├── app.py # Streamlit UI
├── data_loader.py # (your module) CSV + PDF loader
├── chunker.py # (your module) chunking with filters
├── modules/
│ ├── __init__.py
│ ├── embedder.py # MiniLM wrapper, disk cache
│ ├── vector_store.py # NumPy-only k-NN
│ ├── retriever.py # BM25 + dense + RRF + rerank + failure-case demo
│ ├── prompt_builder.py # grounded prompt + citati …