File size: 3,583 Bytes
018a940
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81

import gradio as gr
from sentence_transformers import SentenceTransformer, CrossEncoder
import chromadb
from rank_bm25 import BM25Okapi
from groq import Groq
import json, os

# Load corpus
with open("corpus.json", "r", encoding="utf-8") as f:
    final_corpus = json.load(f)

# Setup models
embed_model = SentenceTransformer("intfloat/multilingual-e5-base")
chroma_client = chromadb.Client()
collection = chroma_client.create_collection(name="hindi_finrag")

for doc in final_corpus:
    embedding = embed_model.encode(doc["text"]).tolist()
    collection.add(ids=[doc["id"]], embeddings=[embedding], documents=[doc["text"]])

tokenized_corpus = [doc["text"].split() for doc in final_corpus]
bm25 = BM25Okapi(tokenized_corpus)
reranker = CrossEncoder("cross-encoder/mmarco-mMiniLMv2-L12-H384-v1")

GROQ_API_KEY = os.environ.get("GROQ_API_KEY")
groq_client = Groq(api_key=GROQ_API_KEY)

def rrf_fusion(dense_ids, sparse_ids, k=60):
    scores = {}
    for rank, doc_id in enumerate(dense_ids):
        scores[doc_id] = scores.get(doc_id, 0) + 1/(k+rank+1)
    for rank, doc_id in enumerate(sparse_ids):
        scores[doc_id] = scores.get(doc_id, 0) + 1/(k+rank+1)
    return sorted(scores.keys(), key=lambda x: scores[x], reverse=True)

def hybrid_retrieve_reranked(question, top_k=3):
    query_emb = embed_model.encode(question).tolist()
    dense = collection.query(query_embeddings=[query_emb], n_results=len(final_corpus))
    dense_ids = dense["ids"][0]
    bm25_scores = bm25.get_scores(question.split())
    sparse_ids = [final_corpus[i]["id"] for i in sorted(range(len(bm25_scores)), key=lambda i: bm25_scores[i], reverse=True)]
    fused = rrf_fusion(dense_ids, sparse_ids)
    id_to_text = {doc["id"]: doc["text"] for doc in final_corpus}
    candidates = [id_to_text[i] for i in fused[:10]]
    scores = reranker.predict([(question, doc) for doc in candidates])
    ranked = sorted(zip(candidates, scores), key=lambda x: x[1], reverse=True)
    return [doc for doc, _ in ranked[:top_k]]

def rag_query(question):
    if not question.strip():
        return "कृपया एक प्रश्न लिखें।", ""
    contexts = hybrid_retrieve_reranked(question)
    context_text = " ".join(contexts)[:1200]
    prompt = f"""आप एक वित्तीय सहायक हैं। नीचे दिए गए संदर्भ के आधार पर प्रश्न का उत्तर दें।

संदर्भ:
{context_text}

प्रश्न: {question}

उत्तर (हिंदी में, संक्षिप्त):"""
    response = groq_client.chat.completions.create(
        model="llama-3.3-70b-versatile",
        messages=[{"role": "user", "content": prompt}],
        temperature=0.1
    )
    answer = response.choices[0].message.content
    sources = "\n\n".join([f"स्रोत {i+1}: {c[:200]}..." for i, c in enumerate(contexts)])
    return answer, sources

demo = gr.Interface(
    fn=rag_query,
    inputs=gr.Textbox(label="अपना प्रश्न हिंदी में लिखें", placeholder="उदाहरण: पीएम-किसान योजना क्या है?"),
    outputs=[gr.Textbox(label="उत्तर"), gr.Textbox(label="स्रोत दस्तावेज़")],
    title="HindiFinRAG — Hindi Financial RAG System",
    description="भारतीय वित्तीय और सरकारी योजनाओं के बारे में हिंदी में प्रश्न पूछें।"
)

demo.launch()