Ayat-Finder / main.py
Hammad712's picture
Update main.py
118b292 verified
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from langchain.chains import RetrievalQA
from langchain.prompts import PromptTemplate
from langchain_community.vectorstores import FAISS
from langchain_huggingface import HuggingFaceEmbeddings
from langchain_groq import ChatGroq
import zipfile
import os
app = FastAPI()
# === Startup config ===
class QueryRequest(BaseModel):
question: str
llm = None
retriever = None
chain = None
@app.on_event("startup")
def load_components():
global llm, retriever, chain
api_key = os.getenv('api_key')
# --- Load LLM ---
llm = ChatGroq(
model="meta-llama/llama-4-scout-17b-16e-instruct",
temperature=0,
max_tokens=1024,
api_key=api_key
)
# --- Load Embeddings ---
embeddings = HuggingFaceEmbeddings(
model_name="intfloat/multilingual-e5-large",
model_kwargs={"device": "cpu"},
encode_kwargs={"normalize_embeddings": True},
)
# --- Unzip Vectorstore if needed ---
zip_path = "faiss_index.zip"
extract_path = "faiss_index"
if not os.path.exists(extract_path):
with zipfile.ZipFile(zip_path, 'r') as z:
z.extractall(extract_path)
print("✅ Unzipped FAISS index.")
# --- Load FAISS Vectorstore & create retriever ---
vectorstore = FAISS.load_local(
extract_path,
embeddings,
allow_dangerous_deserialization=True
)
retriever = vectorstore.as_retriever(search_kwargs={"k": 3})
print("✅ FAISS index loaded.")
# --- Prepare prompt template ---
quiz_solving_prompt = """
You are a Quran Ayat Finder assistant.
Your goal is to provide an accurate and concise answer extracted directly from the provided context.
Output only the exact answer as it appears in the context; if it’s not there, say "I don't know."
Include the ayat reference (surah name, surah number and ayat number) only if present in the context.
Context:
{context}
Question:
{question}
Answer:
"""
prompt = PromptTemplate(
template=quiz_solving_prompt,
input_variables=["context", "question"]
)
# --- Assemble a stateless RetrievalQA chain (no memory) ---
chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff",
retriever=retriever,
return_source_documents=False,
chain_type_kwargs={"prompt": prompt},
verbose=False,
)
@app.get("/")
def root():
return {"message": "English Quran Ayat Finder API is up."}
@app.post("/query")
def query(request: QueryRequest):
try:
result = chain.invoke({"query": request.question})
return {"answer": result["result"]}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))