An end-to-end Retrieval-Augmented Generation (RAG) system that lets you upload documents (PDFs, code, text) and ask questions grounded in their content โ no hallucinations, just answers backed by your own data.
Built with FastAPI ยท ChromaDB ยท sentence-transformers ยท Groq (LLaMA 3)
Large Language Models are powerful, but they suffer from two hard limitations: they hallucinate, and they have no access to your private or recent data.
RAG solves this by retrieving relevant context from your documents and injecting it directly into the prompt โ so the model answers from your knowledge base, not from memory.
User Query โ Embed โ Vector Search โ Top-K Chunks โ Rerank โ Prompt โ LLM โ Grounded Answer + Citations
- ๐ Upload documents โ
.pdf,.txt,.md, code files - โ๏ธ Smart chunking with overlap for context continuity
- ๐ Semantic search via sentence-transformer embeddings
- ๐ง Persistent vector store with ChromaDB
- ๐ค LLM generation via Groq (LLaMA 3) โ low-latency inference
- ๐ Grounded answers with chunk citations
[Chunk X] - ๐งพ Raw retrieved chunks returned alongside the answer
- ๐ Retrieval reranking via keyword overlap scoring
- ๐ฏ Metadata filtering by
document_id - ๐ Multi-document support
- โก Fast, async-ready API with FastAPI
| Layer | Technology |
|---|---|
| API | FastAPI + Uvicorn |
| Embeddings | sentence-transformers (all-MiniLM-L6-v2) |
| Vector Store | ChromaDB (persistent, local) |
| LLM | Groq โ LLaMA 3 |
| Validation | Pydantic |
| Containerisation | Docker (optional) |
rag-doc-assistant/
โโโ ๐ backend/
โ โโโ ๐ app/
โ โ โโโ ๐ api/ # Routes
โ โ โ โโโ ๐ upload.py # POST /upload/ โ ingest docs, chunk & embed
โ โ โ โโโ ๐ ask.py # POST /ask/ โ retrieve, rerank & generate
โ โ โโโ ๐ services/ # AI Logic
โ โ โ โโโ ๐ chunker.py # Fixed-size overlapping text chunking
โ โ โ โโโ ๐ embedder.py # all-MiniLM-L6-v2 โ 384-dim vectors
โ โ โ โโโ ๐ retriever.py # ChromaDB top-K cosine similarity search
โ โ โ โโโ ๐ reranker.py # Keyword overlap re-scoring
โ โ โ โโโ ๐ generator.py # Groq / LLaMA 3 grounded generation
โ โ โโโ ๐ core/ # DB
โ โ โ โโโ ๐ vector_store.py # ChromaDB client, collections & upserts
โ โ โโโ ๐ schemas/
โ โ โโโ ๐ main.py # Entry โ FastAPI app factory & router setup
โ โโโ ๐ requirements.txt
โ โโโ ๐ณ Dockerfile
โโโ ๐๏ธ chroma_db/ # Persistent vector store (mount as volume)
โโโ ๐ README.md
git clone https://github.com/ApplexX7/rag-doc-assistant.git
cd rag-doc-assistant/backendpip install -r requirements.txtexport GROQ_API_KEY="your_api_key"uvicorn app.main:app --reloadhttp://127.0.0.1:8000/docs
POST /upload/
Content-Type: multipart/form-dataResponse
{
"document_id": "abc123",
"filename": "resume.pdf",
"chunk_count": 6
}POST /ask/
Content-Type: application/json{
"question": "What backend technologies does he know?",
"top_k": 3,
"document_id": "abc123"
}Response
{
"question": "What backend technologies does he know?",
"answer": "He has experience with Node.js, Fastify, and FastAPI... [Chunk 1]",
"results": [
{ "chunk_id": 1, "text": "...", "score": 0.91 }
]
}Fixed-size chunks with overlap ensure context continuity across boundaries. The tradeoff is precision (smaller chunks) vs. recall (larger chunks with more context).
all-MiniLM-L6-v2 from sentence-transformers โ lightweight (80MB), fast, and strong on semantic similarity tasks. No GPU required.
ChromaDB runs locally with persistence out of the box. No external service needed โ just mount chroma_db/ as a Docker volume to survive restarts.
Top-K semantic search gives high recall. The reranker then re-scores by keyword overlap to improve precision before passing chunks to the LLM.
The prompt template explicitly instructs the model to cite sources as [Chunk X] and to not answer beyond the retrieved context โ minimising hallucinations by design.
- Retrieval quality is sensitive to chunk size tuning
- No hybrid search (BM25 + vector) โ pure semantic only
- No conversation memory across turns
- Reranker is keyword-based, not ML (cross-encoder)
- No evaluation metrics or benchmarking yet
- Hybrid search โ BM25 + dense embeddings
- Cross-encoder reranking
- Code-aware chunking (by function / class)
- Streaming responses (SSE)
- Multi-hop retrieval
- Query rewriting before embedding
- Context compression
- Hallucination detection layer
- Next.js frontend with chat UI
- File upload dashboard
- Source highlighting in answers
- Chunk visualisation
- Async ingestion pipeline with background workers
- Redis caching for repeated queries
- Postgres metadata layer
"I built a full RAG system from scratch โ document ingestion, embedding, vector storage, semantic retrieval, reranking, and grounded LLM generation. I made deliberate tradeoffs around chunking strategy, embedding model size, and reranking approach, and the prompt architecture enforces citation-based answers to reduce hallucinations."
What this project demonstrates:
- AI system design and LLM integration
- Production-style backend engineering
- Data pipeline design
- Tradeoff thinking โ latency vs. accuracy, precision vs. recall
- Practical knowledge of RAG patterns used in real AI products
Mohammed Hilali
- ๐ Portfolio: applexx.me
- ๐ GitHub: @ApplexX7
This is not just a demo โ it's a production-style RAG system reflecting real-world AI engineering patterns used in modern startups and AI products.