multilingual-rag-chatbot / rag_pipeline.py
ِAkramtaha98
Add multilingual RAG chatbot
51168f3
Raw
History Blame Contribute Delete
2.93 kB
"""
RAG pipeline: loads the FAISS index and builds a ConversationalRetrievalChain
backed by Groq (llama-3.3-70b-versatile). Returns the answer and source chunks.
"""
import os
from pathlib import Path
from dotenv import load_dotenv
from langchain_huggingface import HuggingFaceEmbeddings
from langchain_community.vectorstores import FAISS
from langchain_classic.chains import ConversationalRetrievalChain
from langchain_classic.memory import ConversationBufferMemory
from langchain_groq import ChatGroq
load_dotenv()
EMBEDDING_MODEL = "sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2"
INDEX_DIR = Path("faiss_index")
GROQ_MODEL = "llama-3.3-70b-versatile"
TOP_K = 4
SYSTEM_PROMPT = (
"You are a helpful multilingual assistant that supports English, Arabic, and Malay. "
"Always reply in the same language the user used. "
"Base your answer strictly on the provided context. "
"If the context does not contain enough information, say so honestly."
)
def load_vectorstore() -> FAISS:
if not INDEX_DIR.exists():
raise FileNotFoundError(
"FAISS index not found. Run `python ingest.py` first."
)
embeddings = HuggingFaceEmbeddings(model_name=EMBEDDING_MODEL)
return FAISS.load_local(
str(INDEX_DIR), embeddings, allow_dangerous_deserialization=True
)
class RAGPipeline:
def __init__(self):
vectorstore = load_vectorstore()
retriever = vectorstore.as_retriever(search_kwargs={"k": TOP_K})
llm = ChatGroq(
model=GROQ_MODEL,
api_key=os.environ["GROQ_API_KEY"],
max_tokens=1024,
)
memory = ConversationBufferMemory(
memory_key="chat_history",
return_messages=True,
output_key="answer",
)
self.chain = ConversationalRetrievalChain.from_llm(
llm=llm,
retriever=retriever,
memory=memory,
return_source_documents=True,
output_key="answer",
combine_docs_chain_kwargs={"prompt": _build_prompt()},
)
def ask(self, question: str) -> dict:
"""
Returns:
{
"answer": str,
"sources": [{"content": str, "source": str}, ...]
}
"""
result = self.chain.invoke({"question": question})
sources = [
{
"content": doc.page_content,
"source": doc.metadata.get("source", "unknown"),
}
for doc in result.get("source_documents", [])
]
return {"answer": result["answer"], "sources": sources}
def _build_prompt():
from langchain_core.prompts import PromptTemplate
template = (
SYSTEM_PROMPT
+ "\n\nContext:\n{context}\n\nQuestion: {question}\n\nAnswer:"
)
return PromptTemplate(input_variables=["context", "question"], template=template)