Spaces:
Running
Running
File size: 3,965 Bytes
2748d2d f64547d 2748d2d 87668f1 5ca56e1 f64547d 87668f1 f64547d 2748d2d 87668f1 f64547d 87668f1 2748d2d 87668f1 2748d2d 87668f1 2748d2d 87668f1 2748d2d 87668f1 2748d2d 87668f1 2748d2d 87668f1 2748d2d 87668f1 2748d2d 87668f1 2748d2d 87668f1 f64547d 2748d2d f64547d 5edff09 2748d2d 87668f1 2748d2d 87668f1 2748d2d 87668f1 |
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 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
import os
import zipfile
import logging
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from langchain_community.vectorstores import FAISS
from langchain_huggingface import HuggingFaceEmbeddings
from langchain_groq import ChatGroq
from langchain.chains import RetrievalQA
from langchain.prompts import PromptTemplate
# Configure logging
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)
logger = logging.getLogger(__name__)
app = FastAPI()
# === Globals ===
llm = None
embeddings = None
vectorstore = None
retriever = None
quiz_chain = None
grade_chain = None
class QuizRequest(BaseModel):
question: str
class GradeRequest(BaseModel):
question: str # string of Q/A pairs
@app.on_event("startup")
def load_components():
global llm, embeddings, vectorstore, retriever, quiz_chain, grade_chain
try:
api_key = os.getenv("api_key")
if not api_key:
logger.error("API_KEY environment variable is not set or empty.")
raise RuntimeError("API_KEY environment variable is not set or empty.")
logger.info("API_KEY is set.")
# 1) Init LLM & Embeddings
llm = ChatGroq(
model="meta-llama/llama-4-scout-17b-16e-instruct",
temperature=0,
max_tokens=1024,
api_key=api_key,
)
embeddings = HuggingFaceEmbeddings(
model_name="intfloat/multilingual-e5-large",
model_kwargs={"device": "cpu"},
encode_kwargs={"normalize_embeddings": True},
)
# 2) Load FAISS indexes
for zip_name, dir_name in [("faiss_index.zip", "faiss_index"), ("faiss_index(1).zip", "faiss_index_extra")]:
if not os.path.exists(dir_name):
with zipfile.ZipFile(zip_name, 'r') as z:
z.extractall(dir_name)
logger.info(f"Unzipped {zip_name} to {dir_name}.")
else:
logger.info(f"Directory {dir_name} already exists.")
vs1 = FAISS.load_local("faiss_index", embeddings, allow_dangerous_deserialization=True)
logger.info("FAISS index 1 loaded.")
vs2 = FAISS.load_local("faiss_index_extra", embeddings, allow_dangerous_deserialization=True)
logger.info("FAISS index 2 loaded.")
vs1.merge_from(vs2)
vectorstore = vs1
logger.info("Merged FAISS indexes into a single vectorstore.")
retriever = vectorstore.as_retriever(search_kwargs={"k": 10})
# Quiz generation chain
quiz_prompt = PromptTemplate(
template="""
Generate a quiz on the topic "{question}" using **only** the information in the "Retrieved context".
Include clear questions and multiple-choice options (A, B, C, D). Also provide the answers of the questions with them.
If context is insufficient, reply with "I don't know".
Retrieved context:
{context}
Quiz topic:
{question}
Quiz:
""",
input_variables=["context", "question"],
)
quiz_chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff",
retriever=retriever,
return_source_documents=False,
chain_type_kwargs={"prompt": quiz_prompt},
)
logger.info("Quiz chain ready.")
except Exception as e:
logger.error("Error loading components", exc_info=True)
raise
@app.get("/")
def root():
return {"message": "API is up and running!"}
@app.post("/quiz")
def create_quiz(request: QuizRequest):
try:
logger.info("Generating quiz for topic: %s", request.question)
result = quiz_chain.invoke({"query": request.question})
logger.info("Quiz generated successfully.")
return {"quiz": result.get("result")}
except Exception as e:
logger.error("Error generating quiz", exc_info=True)
raise HTTPException(status_code=500, detail=str(e))
|