calvinothayoth/pm-proj-rag
0
Mutual Fund FAQ Assistant - RAG Prototype
A facts-only mutual fund FAQ assistant demonstrating production-grade RAG architecture using a fixed Groww corpus for five HDFC mutual fund schemes.
๐ฏ Project Goal
Build a RAG (Retrieval-Augmented Generation) system that:
- Answers objective, verifiable questions using only retrieved evidence
- Refuses advisory, comparative, speculative, or out-of-corpus requests
- Enforces strict response contracts (3 sentences, 1 citation, source date)
- Demonstrates proper RAG components (embeddings, vector search, reranking, LLM generation)
๐๏ธ RAG Architecture
flowchart LR
user[User Query] --> ui[Web UI]
ui --> api[FastAPI Server]
api --> classify[Intent Classification<br/>BGE Embeddings + Keywords]
classify -->|Advisory/Unsafe| refusal[Refusal Response]
classify -->|Factual| retrieve[Hybrid Retrieval]
subgraph Retrieval Pipeline
retrieve --> faiss[FAISS Vector Search<br/>BGE Embeddings]
retrieve --> bm25[BM25 Keyword Search<br/>Corpus-aware IDF]
faiss --> combine[Fusion: 60% dense + 40% sparse]
bm25 --> combine
combine --> rerank[Cross-Encoder Reranking<br/>ms-marco-MiniLM]
end
rerank --> generate[LLM Generation<br/>Groq Llama 3.1]
generate --> validate[Response Validation<br/>3 sentences, 1 link, footer]
validate --> answer[Final Answer]
refusal --> answer
subgraph Data Pipeline
corpus[5 Groww URLs] --> fetch[HTML Fetch]
fetch --> parse[HTML Parser]
parse --> chunk[Overlap Chunking<br/>700 chars, 100 overlap]
chunk --> embed[BGE Embeddings]
embed --> index[FAISS Index]
end
index --> faiss๐ง Core RAG Components
1. Embedding Model: BGE Small (BAAI/bge-small-en-v1.5)
- Type: Dense bi-encoder
- Dimensions: 384
- Framework: FastEmbed (optimized ONNX runtime)
- Usage:
- Query understanding (intent classification)
- Document embeddings for vector search
- Semantic similarity scoring
2. Vector Index: FAISS (Facebook AI Similarity Search)
- Index Type:
IndexFlatIP(Inner Product on L2-normalized vectors = cosine similarity) - Storage: Binary format (
faiss_index.bin) + metadata JSON - Search: Approximate nearest neighbor (ANN) for O(log n) retrieval
- Why FAISS: Industry standard for production vector search, supports billions of vectors
3. Hybrid Retrieval
Final Score = 0.6 * FAISS_Cosine_Similarity + 0.4 * BM25_Score- Dense (FAISS): Captures semantic meaning ("minimum investment" โ "SIP amount")
- Sparse (BM25): Captures exact keyword matches ("expense ratio", "exit load")
- Fusion: Weighted combination for best recall
4. Cross-Encoder Reranking
- Model:
cross-encoder/ms-marco-MiniLM-L-6-v2 - Purpose: Precise query-document relevance scoring
- How it works:
- Takes (query, document) pair as input
- Outputs relevance score (typically [-10, 10])
- More accurate than bi-encoder but slower
- Standard RAG pattern:
- Bi-encoder retrieves top 50-100 candidates (fast)
- Cross-encoder reranks to top 5-10 (accurate)
5. BM25 Keyword Search
- Implementation: Corpus-aware with proper IDF calculation
- Formula:
IDF(t) = log((N - n(t) + 0.5) / (n(t) + 0.5) + 1.0)
Score = IDF * (tf * (k1 + 1)) / (tf + k1 * (1 - b + b * |D|/avgdl))- Parameters: k1=1.5, b=0.75 (standard values)
6. LLM Generation: Groq (Llama 3.1 8B)
- Provider: Groq API (ultra-fast inference)
- Model:
llama-3.1-8b-instant - Temperature: 0.0 (deterministic, factual)
- Max tokens: 150 (concise answers)
- Prompt: Facts-only instructions with retrieved context
7. Intent Classification
- Primary: Semantic similarity using BGE embeddings
- Fallback: Keyword matching for robustness
- Categories:
- Allowed: expenseratio, exitload, minimumsip, lockinperiod, riskometer, benchmark, documentdownload
- Refused: investmentadvice, comparison, ranking, returnprojection, performance_calculation
๐ฆ Tech Stack
๐ Setup & Usage
Prerequisites
- Python 3.9+
- Groq API key (for LLM generation)
Installation
# Clone repository
git clone <repo-url>
cd pm-proj-rag
# Install dependencies
pip install -e .
# Set environment variables
echo "GROQ_API_KEY=your_key_here" > .envData Pipeline
# 1. Ingest Groww pages (fetch, parse, chunk)
python scripts/ingest.py
# 2. Build FAISS index (embed chunks, create vector index)
python scripts/build_index.pyRun the Application
# Start API server + UI
uvicorn src.pm_rag.api.server:app --reload --port 8000
# Open browser
http://localhost:8000Run Tests
python -m unittest discover -s tests๐ Data Flow
Ingestion Pipeline (Offline)
5 Groww URLs
โ HTML Fetch (requests)
โ HTML Parse (BeautifulSoup4)
โ Text Chunking (700 chars, 100 overlap)
โ BGE Embeddings (FastEmbed)
โ FAISS Index (IndexFlatIP)
โ Save: faiss_index.bin + metadata.jsonQuery Pipeline (Online)
User Query
โ Intent Classification (BGE embeddings + keywords)
โ If allowed:
โ FAISS Search (top 10 candidates)
โ BM25 Search (lexical matching)
โ Fusion (60% dense + 40% sparse)
โ Cross-Encoder Reranking (top 5)
โ LLM Generation (Groq Llama 3.1)
โ Response Validation (3 sentences, 1 link, footer)
โ If refused:
โ Polite refusal message๐ฏ Response Contract
Every answer must:
- โ Stay within 3 sentences
- โ Include exactly one source link from the fixed 5-URL corpus
- โ
End with
Last updated from sources: <YYYY-MM-DD> - โ Avoid investment advice, opinions, recommendations, return calculations
Example Response:
The HDFC Mid Cap Fund has an expense ratio of 0.73%. This is a direct plan growth option with no distributor commissions.
Source: https://groww.in/mutual-funds/hdfc-mid-cap-fund-direct-growth
Last updated from sources: 2026-05-29๐ Project Structure
pm-proj-rag/
โโโ src/pm_rag/
โ โโโ api/
โ โ โโโ server.py # FastAPI server
โ โโโ ui/
โ โ โโโ index.html # Web UI
โ โ โโโ styles.css # Styling
โ โ โโโ app.js # Frontend logic
โ โโโ core/
โ โโโ ingestion/
โ โ โโโ fetcher.py # HTML fetcher
โ โ โโโ parser.py # HTML parser
โ โ โโโ chunker.py # Text chunking
โ โ โโโ pipeline.py # Ingestion orchestration
โ โโโ retrieval/
โ โ โโโ faiss_index.py # FAISS vector index โญ
โ โ โโโ embedder.py # BGE embeddings โญ
โ โ โโโ keyword_search.py # BM25 search โญ
โ โ โโโ reranker.py # Rule-based reranking
โ โ โโโ cross_encoder_reranker.py # Cross-encoder โญ
โ โ โโโ retriever.py # Hybrid retrieval โญ
โ โโโ compliance/
โ โ โโโ classifier.py # Intent classification โญ
โ โ โโโ policies.py # Allowed/refused policies
โ โ โโโ validators.py # Response validation
โ โโโ answering/
โ โ โโโ prompts.py # LLM prompts
โ โ โโโ generator.py # LLM generation โญ
โ โ โโโ formatter.py # Response formatting
โ โโโ sources/
โ โโโ catalog.py # Corpus validation
โโโ configs/
โ โโโ corpus.yaml # Fixed 5-URL corpus
โโโ data/
โ โโโ raw/ # HTML snapshots
โ โโโ processed/ # Chunks with metadata
โ โโโ indexes/ # FAISS index + metadata
โโโ scripts/
โ โโโ ingest.py # Run ingestion
โ โโโ build_index.py # Build FAISS index
โโโ tests/ # Phase-wise tests๐งช What This Prototype Demonstrates
โ Proper RAG Patterns
- Embedding-based retrieval (not keyword-only)
- Vector database (FAISS, not JSON file)
- Hybrid search (dense + sparse)
- Cross-encoder reranking (production pattern)
- Semantic intent classification (not just regex)
- Response validation (contract enforcement)
โ Engineering Best Practices
- Modular architecture (separation of concerns)
- Fallback mechanisms (LLM โ regex simulator)
- Corpus validation (fixed source guardrails)
- Traceability (source URLs, dates, metadata)
- Compliance gates (pre/post generation checks)
๐ Safety & Compliance
- Fixed corpus only: 5 Groww URLs, no external sources
- No advisory responses: Refuses "should I invest?", "which is better?"
- No sensitive data: Rejects PAN, Aadhaar, account number requests
- Facts-only generation: No hallucination, no opinions
- Source attribution: Every answer cites the exact Groww URL
๐ Known Limitations
- Small corpus: Only 5 URLs (73 chunks) - designed for demonstration
- Single LLM provider: Groq only (no fallback provider)
- No caching: Every query re-runs embedding + LLM
- No rate limiting: Not hardened for production traffic
- No monitoring: No logging, metrics, or alerting
๐ RAG Concepts Demonstrated
๐ License
This project is for educational/demonstration purposes.
Disclaimer
Facts-only. No investment advice.
Active Source Rule
Only the five exact Groww URLs listed in configs/corpus.yaml may be used. Do not add AMC pages, AMFI pages, SEBI pages, third-party pages, extra Groww pages, or links discovered from these pages.
