NiveshSaathi / rag_module.py
Ritidube
Clean commit with LFS images
416ee80
Raw
History Blame Contribute Delete
25 kB
"""
rag_module.py β€” RAG Financial Advisor for NiveshSaathi
Uses ChromaDB (vector store) + Groq API (free LLM) + HuggingFace embeddings
Answers financial questions in Hindi for low-income users
"""
import os
import threading
_chroma_lock = threading.Lock()
_chroma_collection = None
import json
from pathlib import Path
# ── FINANCIAL KNOWLEDGE BASE ──────────────────────────────────────────────────
# All the financial knowledge in simple Hindi + English
# This is the "R" in RAG β€” the documents we retrieve from
FINANCIAL_KNOWLEDGE = [
# ── RD / FD BASICS ────────────────────────────────────────────────────────
{
"id": "rd_basics_1",
"topic": "Recurring Deposit RD",
"content": """
Recurring Deposit (RD) kya hai: RD ek bank savings scheme hai jisme aap har mahine ek fixed amount jama karte ho.
Bank aapko 6.5% se 7.5% tak byaaj deta hai.
RD bilkul safe hai β€” bank kisi bhi halat mein aapka paisa wapas karta hai.
Minimum amount: SBI mein sirf Rs.100/mahine se shuru kar sakte ho.
Duration: 6 mahine se 10 saal tak.
RD mature hone par: aapka original paisa + byaaj milta hai.
Example: Agar aap Rs.500/mahine 1 saal RD mein daalte ho, to 12 mahine baad Rs.6,175 milenge (original Rs.6,000 + Rs.175 byaaj).
RD kahan khole: SBI, PNB, Post Office β€” sabse safe options hain.
RD vs FD: RD mein monthly jama karte ho, FD mein ek baar mein poora paisa dete ho.
Teacher, daily wage worker, kirana shopkeeper β€” sabke liye RD best hai.
""",
"keywords": ["rd", "recurring deposit", "baar baar", "monthly savings", "bank savings", "byaaj", "interest"]
},
{
"id": "fd_basics_1",
"topic": "Fixed Deposit FD",
"content": """
Fixed Deposit (FD) kya hai: FD mein aap ek baar mein puri raqam bank ko dete ho.
Bank aapko 6% se 8% tak byaaj deta hai β€” RD se thoda zyada.
FD bilkul safe hai β€” DICGC insurance se Rs.5 lakh tak guarantee hai.
Minimum amount: Rs.1,000 se shuru.
Duration: 7 din se 10 saal.
Premature withdrawal: zarurat padne par paise nikal sakte ho par thodi penalty lagti hai.
Senior citizens ko 0.5% extra byaaj milta hai.
Tax: 40,000 se zyada byaaj par TDS katega.
Best FD rates 2024: Small Finance Banks mein 8-9% milta hai.
FD sirf usi paison ke liye jo 1-2 saal tak zarurat na ho.
""",
"keywords": ["fd", "fixed deposit", "ek baar", "lump sum", "bank mein daalo", "guaranteed return"]
},
# ── DIGITAL GOLD ──────────────────────────────────────────────────────────
{
"id": "digital_gold_1",
"topic": "Digital Gold",
"content": """
Digital Gold kya hai: Aap 1 rupee se bhi sona khareed sakte ho digitally.
Yahi asli sona hai β€” sirf locker ki zarurat nahi.
Kahan kharidein: Paytm, PhonePe, Google Pay, Groww β€” sab par available.
Price: Market rate pe milta hai β€” physical gold jaisa hi.
Purity: 24 karat, 99.9% pure guaranteed.
Storage: Company secure vault mein rakhti hai.
Sell karna: Jab chahiye tab bech sakte ho, paisa turant account mein aata hai.
Festival pe physical gold mein convert bhi kar sakte ho.
Return: Gold historically 8-10% annual return deta hai.
Risk: Gold price upar neeche hota hai β€” par long term mein safe hai.
Minimum investment: Rs.1 β€” koi bhi shuru kar sakta hai.
Teachers aur daily wage workers ke liye: Har mahine Rs.200-500 ka gold kharidna shuru karo.
""",
"keywords": ["gold", "sona", "digital gold", "paytm gold", "phonepe gold", "har mahine sona"]
},
# ── EMERGENCY FUND ────────────────────────────────────────────────────────
{
"id": "emergency_fund_1",
"topic": "Emergency Fund",
"content": """
Emergency Fund kya hai: Aapke paas 3-6 mahine ke kharche ke barabar cash ready rehna chahiye.
Kyun zaroori: Hospital, job jaana, ghar ki tameer, accident β€” koi bhi time aa sakta hai.
Emergency fund savings account mein rakhein β€” FD ya investment mein nahi.
Kitna chahiye: Monthly kharche ka 3 guna. Example: Rs.10,000/mahine kharche hain to Rs.30,000 emergency fund.
Kahan rakhein: SBI ya Post Office savings account β€” easily nikal sake.
Emergency fund ko kabhi invest mat karo β€” yeh aapka safety net hai.
Ghar ka kiraya, bijli, khana β€” in sab ke liye 3 mahine ka paisa hona chahiye.
Agar emergency fund nahi hai to pehle yahi banao β€” baad mein invest karo.
""",
"keywords": ["emergency", "achanak", "hospital", "zarurat", "cash", "safety net", "reserve"]
},
# ── INVESTMENT BASICS ─────────────────────────────────────────────────────
{
"id": "investment_basics_1",
"topic": "Investment Basics for Beginners",
"content": """
Investment kya hai: Apna paisa aisi jagah lagana jo zyada paisa bana sake.
Kyun invest karna chahiye: Sirf bank mein rakhne se inflation ki wajah se paison ki value kam hoti hai.
Inflation matlab: Jo cheez aaj Rs.100 mein milti hai, 10 saal baad Rs.170 ki ho jaati hai.
Isliye invest karo warna paisa ghatta hai.
3 Bucket Rule:
Bucket 1 (Safety): 10% RD mein β€” guaranteed return.
Bucket 2 (Growth): 5% Digital Gold mein β€” inflation se bachao.
Bucket 3 (Emergency): Baaki bachat savings account mein.
Kab shuru karein: Aaj se β€” chahe Rs.100 hi ho.
Kitna invest karein: Jitna invest karo β€” woh amount 3 saal mein double hone ki chance hai.
Common mistake: Log sochte hain bahut paisa chahiye invest karne ke liye β€” galat hai, Rs.100 se shuru karo.
""",
"keywords": ["invest kaise", "investment", "paisa lagana", "shuru kaise karein", "beginner", "pehli baar"]
},
# ── NIFTY / STOCKS ────────────────────────────────────────────────────────
{
"id": "stocks_basics_1",
"topic": "Stocks and Mutual Funds Basics",
"content": """
Stock kya hai: Kisi company ka ek chhota sa hissa kharidna.
Example: SBI ka ek share kharidne par aap SBI ke chhote se malik ban jaate ho.
Index Fund kya hai: Ek sath 50 companies mein invest karna β€” Nifty 50 index fund.
Index Fund kyun safe hai: Agar ek company doobi to baaki 49 bachayengi.
Return: Nifty 50 ne historically 12% annual return diya hai.
Mutual Fund: Professional log aapka paisa invest karte hain β€” SIP Rs.500/mahine se shuru.
SIP kya hai: Systematic Investment Plan β€” har mahine fixed amount mutual fund mein jaata hai.
Risk: Short term mein upar neeche β€” 5+ saal mein safe hai.
Kahan shuru karein: Groww, Zerodha Coin, Paytm Money β€” sab free hain.
Teacher ke liye suggestion: Rs.500/mahine Nifty 50 Index Fund SIP β€” 10 saal mein Rs.1.1 lakh bane Rs.1.2 lakh.
Stocks SIRF emergency fund aur FD ke baad β€” agar extra paisa ho tab.
""",
"keywords": ["stock", "share", "mutual fund", "sip", "nifty", "index fund", "market mein lagana"]
},
# ── SAVINGS TIPS ──────────────────────────────────────────────────────────
{
"id": "savings_tips_1",
"topic": "Savings Tips for Low Income",
"content": """
Kam income mein savings kaise karein β€” practical tips:
Tip 1: Pay Yourself First β€” salary aate hi pehle RD mein daalo, baad mein kharch karo.
Tip 2: 50-30-20 Rule: 50% zaroorat, 30% chahat, 20% savings.
Tip 3: Kirana store ki weekly list banao β€” Rs.100-200 bachenge.
Tip 4: LED bulbs lagao β€” bijli bill Rs.150-200 kam hoga.
Tip 5: Jan Aushadhi store se generic medicines β€” 50-60% sasta.
Tip 6: Monthly bus pass β€” daily auto se sasta.
Tip 7: Mobile recharge plan 3 mahine ka lena β€” per month sasta padta hai.
Tip 8: Ghar ka khana tiffin mein le jaao β€” Rs.500-1000/mahine bachega.
Agar Rs.15,000 income hai: Rs.1,500 RD (10%) + Rs.750 gold (5%) + Rs.1,000 emergency = Rs.3,250 savings possible.
""",
"keywords": ["savings tips", "bachat kaise karein", "kam paison mein", "budget", "kharcha kam karo"]
},
# ── POST OFFICE SCHEMES ───────────────────────────────────────────────────
{
"id": "post_office_1",
"topic": "Post Office Savings Schemes",
"content": """
Post Office schemes β€” government guaranteed, sabse safe:
1. Post Office RD: Rs.100/mahine minimum, 6.7% byaaj, 5 saal.
2. Post Office FD: 6.9% - 7.5% byaaj, 1-5 saal.
3. PPF (Public Provident Fund): 7.1% byaaj, tax free return, 15 saal.
4. NSC (National Savings Certificate): 7.7% byaaj, 5 saal, tax benefit.
5. Sukanya Samriddhi: Beti ke liye β€” 8.2% byaaj, tax free.
6. Kisan Vikas Patra: Paisa double β€” 7.5% byaaj.
Post Office schemes ki khas baat: Government guarantee β€” kabhi doob nahi sakti.
Gaon aur chhote sheher mein post office sabse aasaan option hai.
PPF sabse accha long term option hai β€” 15 saal mein paisa lagbhag double hota hai.
""",
"keywords": ["post office", "ppf", "nsc", "sukanya", "sarkari yojana", "government scheme", "dak ghar"]
},
# ── UPI / DIGITAL PAYMENTS ────────────────────────────────────────────────
{
"id": "upi_digital_1",
"topic": "UPI and Digital Payments",
"content": """
UPI kya hai: Mobile se seedha bank account se payment karna.
Apps: PhonePe, Google Pay, Paytm, BHIM β€” sab free hain.
Investment ke liye UPI: Directly bank account se RD, gold, ya mutual fund mein paisa ja sakta hai.
UPI se digital gold kharidna: PhonePe ya Google Pay mein Gold section jaao.
UPI se RD: SBI YONO app mein seedha RD khol sakte ho aur UPI se payment kar sakte ho.
Safe hai ya nahi: Haan, NPCI (government) regulate karta hai β€” bilkul safe.
Transaction limit: Rs.1 lakh per transaction by default.
Koi charge nahi: UPI transactions free hain.
""",
"keywords": ["upi", "phonepe", "google pay", "paytm", "digital payment", "online payment"]
},
# ── INCOME TAX BASICS ─────────────────────────────────────────────────────
{
"id": "tax_basics_1",
"topic": "Income Tax Basics",
"content": """
Income tax β€” aapko kitna dena hoga:
Rs.3 lakh tak: Koi tax nahi (annual income).
Rs.3-6 lakh: 5% tax (par rebate milti hai, effectively zero).
Rs.6-9 lakh: 10% tax.
Rs.9-12 lakh: 15% tax.
Tax bachane ke tarike:
Section 80C: Rs.1.5 lakh tak investment β€” PPF, ELSS, LIC β€” tax free.
Section 80D: Health insurance premium β€” tax benefit.
Standard Deduction: Rs.75,000 automatically milti hai salaried logo ko.
Teacher ki salary Rs.15,000/mahine (Rs.1.8 lakh/saal) β€” koi tax nahi.
PAN card zaroor banwao β€” banking aur investment ke liye zaroori.
""",
"keywords": ["tax", "income tax", "80c", "ppf tax", "tax bachana", "pan card"]
},
# ── BLOSTEM / FINTECH ─────────────────────────────────────────────────────
{
"id": "blostem_fintech_1",
"topic": "Fintech and Digital Banking",
"content": """
Fintech kya hai: Technology se financial services β€” bank nahi jaana padta.
Digital banking advantages: 24x7 available, ghar baithe sab kaam.
Jan Dhan account: Zero balance account β€” koi bhi khol sakta hai.
PMJJBY: Rs.330/saal mein Rs.2 lakh life insurance.
PMSBY: Rs.20/saal mein Rs.2 lakh accident insurance β€” bahut sasta.
Atal Pension Yojana: Rs.210/mahine par Rs.5,000/mahine pension milegi retirement mein.
PM Mudra Loan: Chhote business ke liye Rs.10 lakh tak loan β€” bina guarantee ke.
Loan types: Home loan, education loan, personal loan β€” bank se le sakte ho.
Credit score: CIBIL score β€” 750+ hona chahiye loan ke liye.
""",
"keywords": ["jan dhan", "pmjjby", "atal pension", "mudra loan", "digital banking", "fintech"]
},
]
# ── CHROMA DB SETUP ────────────────────────────────────────────────────────────
def setup_chromadb(persist_dir: str = "./rag_db"):
"""
Initialize ChromaDB with financial knowledge.
Thread-safe singleton β€” safe to call from multiple threads.
Pin chromadb==0.4.24 in requirements.txt to avoid Rust backend errors.
"""
global _chroma_collection
with _chroma_lock:
if _chroma_collection is not None:
return _chroma_collection
import chromadb
print("[RAG] Setting up ChromaDB...")
# Ensure directory exists
Path(persist_dir).mkdir(parents=True, exist_ok=True)
# Create persistent client
client = chromadb.PersistentClient(path=persist_dir)
# Build embedding function
emb_fn = _get_embedding_function()
# Create or get collection
collection = client.get_or_create_collection(
name="financial_knowledge",
embedding_function=emb_fn,
metadata={"description": "NiveshSaathi financial knowledge base"}
)
# Check if already populated
if collection.count() >= len(FINANCIAL_KNOWLEDGE):
print(f"[RAG] ChromaDB already has {collection.count()} documents βœ…")
_chroma_collection = collection
return collection
# Add all documents
print(f"[RAG] Adding {len(FINANCIAL_KNOWLEDGE)} documents...")
collection.add(
ids=[doc["id"] for doc in FINANCIAL_KNOWLEDGE],
documents=[doc["content"] for doc in FINANCIAL_KNOWLEDGE],
metadatas=[{"topic": doc["topic"], "keywords": ",".join(doc["keywords"])} for doc in FINANCIAL_KNOWLEDGE]
)
print(f"[RAG] ChromaDB setup complete βœ… β€” {collection.count()} documents indexed")
_chroma_collection = collection
return collection
def _get_embedding_function():
"""
Get embedding function β€” handles different chromadb versions.
Uses multilingual model that supports Hindi.
"""
model_name = "paraphrase-multilingual-MiniLM-L12-v2"
# Try chromadb 0.4.x style
try:
from chromadb.utils import embedding_functions
emb_fn = embedding_functions.SentenceTransformerEmbeddingFunction(
model_name=model_name
)
print(f"[RAG] Using embedding model: {model_name} (chromadb 0.4.x style)")
return emb_fn
except Exception:
pass
# Try chromadb 0.5.x style
try:
from chromadb.utils.embedding_functions import SentenceTransformerEmbeddingFunction
emb_fn = SentenceTransformerEmbeddingFunction(model_name=model_name)
print(f"[RAG] Using embedding model: {model_name} (chromadb 0.5.x style)")
return emb_fn
except Exception:
pass
# Fallback: manual sentence-transformers
try:
from sentence_transformers import SentenceTransformer
model = SentenceTransformer(model_name)
class ManualEmbeddingFn:
def __call__(self, input):
return model.encode(input).tolist()
print(f"[RAG] Using manual embedding function with {model_name}")
return ManualEmbeddingFn()
except Exception as e:
raise RuntimeError(f"Could not load any embedding function: {e}")
# ── RETRIEVAL ──────────────────────────────────────────────────────────────────
def retrieve_context(query: str, collection, n_results: int = 3) -> str:
"""Retrieve relevant financial documents for a query"""
results = collection.query(
query_texts=[query],
n_results=n_results
)
if not results["documents"] or not results["documents"][0]:
return ""
# Combine top results
context_parts = []
for i, doc in enumerate(results["documents"][0]):
topic = results["metadatas"][0][i].get("topic", "")
context_parts.append(f"[{topic}]\n{doc.strip()}")
return "\n\n---\n\n".join(context_parts)
# ── LLM β€” GROQ API (FREE) ─────────────────────────────────────────────────────
def ask_groq(question: str, context: str, profession: str = "user") -> str:
"""
Use Groq API (free) with Llama 3 to generate Hindi answers.
Get free API key at: console.groq.com (no credit card needed)
"""
import requests
groq_api_key = os.environ.get("GROQ_API_KEY", "")
if not groq_api_key:
return _fallback_answer(question, context)
system_prompt = f"""Aap NiveshSaathi ke AI financial advisor hain.
Aapka kaam hai {profession} ko simple Hindi mein financial guidance dena.
Rules:
- HAMESHA Hindi mein jawab do (Hinglish chalega)
- Simple bhasha use karo β€” jaise family member ko samjhate ho
- Specific numbers aur examples do (Rs. mein)
- Chhota aur clear jawab do β€” 3-5 sentences maximum
- Encourage karo β€” positively bolna
- Agar koi advanced cheez ho to simple analogy use karo
Context (yahi information use karo jawab ke liye):
{context}
"""
user_message = f"Mera sawaal: {question}"
try:
response = requests.post(
"https://api.groq.com/openai/v1/chat/completions",
headers={
"Authorization": f"Bearer {groq_api_key}",
"Content-Type": "application/json"
},
json={
"model": "llama-3.1-8b-instant", # Free Groq model
"messages": [
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_message}
],
"max_tokens": 300,
"temperature": 0.7,
},
timeout=15
)
data = response.json()
if "choices" in data and data["choices"]:
return data["choices"][0]["message"]["content"].strip()
else:
print(f"[RAG] Groq error: {data}")
return _fallback_answer(question, context)
except Exception as e:
print(f"[RAG] Groq API error: {e}")
return _fallback_answer(question, context)
def _fallback_answer(question: str, context: str) -> str:
"""Rule-based fallback when Groq API not available"""
q = question.lower()
# Simple keyword-based responses
if any(w in q for w in ["rd", "recurring", "deposit"]):
return "RD (Recurring Deposit) mein aap bank mein har mahine ek fixed amount jama karte ho. Bank aapko 6.5-7% byaaj deta hai. SBI mein sirf Rs.100/mahine se shuru kar sakte ho β€” bilkul safe hai! 🏦"
elif any(w in q for w in ["gold", "sona", "digital gold"]):
return "Digital Gold mein aap Rs.1 se bhi sona khareed sakte ho PhonePe ya Google Pay se. Yahi asli 24 karat sona hai β€” sirf locker ki zarurat nahi. Festival pe physical gold mein convert bhi kar sakte ho! ✨"
elif any(w in q for w in ["emergency", "achanak", "hospital"]):
return "Emergency Fund bahut zaroori hai! Apne 3 mahine ke kharche ke barabar cash savings account mein rakhein. Example: Agar Rs.10,000/mahine kharche hain to Rs.30,000 emergency fund banao. Yeh aapka safety net hai! πŸ†˜"
elif any(w in q for w in ["invest", "paise lagana", "stock", "mutual fund"]):
return "Investment ke liye 3 bucket rule follow karo: 10% RD mein (safe), 5% Digital Gold mein (growth), baaki emergency fund mein. Rs.100 se bhi shuru kar sakte ho β€” aaj hi shuru karo! 🌱"
elif any(w in q for w in ["tax", "income tax", "80c"]):
return "Agar aapki salary Rs.15,000/mahine (Rs.1.8 lakh/saal) hai to koi income tax nahi lagega! PPF aur ELSS mein invest karne se 80C ke under Rs.1.5 lakh tak tax bhi bachta hai. πŸ“Š"
elif any(w in q for w in ["post office", "ppf", "nsc"]):
return "Post Office schemes sabse safe hain β€” government guarantee hoti hai! PPF mein 7.1% byaaj milta hai aur yeh tax-free bhi hai. 15 saal mein paisa lagbhag double hota hai. Gaon mein bhi asaani se available hai! 🏀"
else:
# Extract first relevant sentence from context
if context:
lines = [l.strip() for l in context.split('\n') if len(l.strip()) > 30]
if lines:
return lines[0] + " Zyada jankari ke liye apne bank ya post office mein jaayein. πŸ’‘"
return "Yeh ek achha sawaal hai! Investment ke baare mein: pehle emergency fund banao (3 mahine ka kharcha), phir RD shuru karo (10% income), phir digital gold (5% income). Chhote kadam se bada fark padta hai! 🌱"
# ── MAIN RAG FUNCTION ─────────────────────────────────────────────────────────
_collection = None
def get_collection():
global _collection
if _collection is None:
_collection = setup_chromadb()
return _collection
def ask_financial_question(
question: str,
profession: str = "user",
income: float = 15000,
expenses: float = 11000
) -> dict:
"""
Main RAG function: Question β†’ Retrieve β†’ Generate Answer
Returns answer + source topics used
"""
try:
collection = get_collection()
# Retrieve relevant context
context = retrieve_context(question, collection, n_results=3)
# Add user context to make answers personalized
user_context = f"\nUser info: {profession}, monthly income Rs.{income:.0f}, expenses Rs.{expenses:.0f}, savings Rs.{income-expenses:.0f}/month"
full_context = context + user_context
# Generate answer with Groq LLM
answer = ask_groq(question, full_context, profession)
# Get source topics
results = collection.query(query_texts=[question], n_results=3)
sources = [m.get("topic", "") for m in results["metadatas"][0]] if results["metadatas"] else []
return {
"success": True,
"question": question,
"answer": answer,
"sources": sources,
"method": "groq_rag" if os.environ.get("GROQ_API_KEY") else "fallback_rag"
}
except Exception as e:
print(f"[RAG] Error: {e}")
return {
"success": False,
"question": question,
"answer": "Maafi chahta hoon, abhi jawab nahi de pa raha. Kripya dobara try karein. πŸ™",
"sources": [],
"method": "error"
}
# ── TEST ───────────────────────────────────────────────────────────────────────
if __name__ == "__main__":
print("Testing RAG module...\n")
test_questions = [
"RD kya hota hai?",
"Mujhe digital gold mein invest karna chahiye?",
"Emergency fund kitna hona chahiye?",
"Post office schemes safe hain kya?",
"Rs.15000 salary mein kaise bachat karein?",
]
for q in test_questions:
print(f"Q: {q}")
result = ask_financial_question(q, profession="teacher", income=15000, expenses=11000)
print(f"A: {result['answer']}")
print(f"Sources: {result['sources']}")
print("-" * 50)