umar-100's picture
minor bug fix
791900c
from fastapi import FastAPI, File, UploadFile, HTTPException, Form
from backend.pydantic_models import QueryInput, QueryResponse, DocumentInfo, DeleteFileRequest, ChallengeRequest, EvaluateAnswer
from backend.langchain_utils import generate_response, retrieve
from backend.db_utils import insert_application_logs, get_chat_history, get_all_documents, insert_document_record, delete_document_record, get_file_content
from backend.pinecone_utilis import index_document_to_pinecone, delete_doc_from_pinecone, load_and_split_document
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.messages import SystemMessage, AIMessage, HumanMessage
import os
import uuid
import logging
import shutil
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
# Set up logging
logging.basicConfig(filename='app.log', level=logging.INFO)
# Initialize FastAPI app
app = FastAPI()
@app.post("/chat", response_model=QueryResponse)
def chat(query_input: QueryInput):
session_id = query_input.session_id or str(uuid.uuid4())
logging.info(f"Session ID: {session_id}, User Query: {query_input.question}, Model: {query_input.model.value}")
chat_history = get_chat_history(session_id)
print(chat_history)
state={"messages":chat_history} # test
messages_state = generate_response(query=query_input.question, state=state)
answer=messages_state["messages"][-1].content
insert_application_logs(session_id, query_input.question, answer, query_input.model.value)
logging.info(f"Session ID: {session_id}, AI Response: {answer}")
return QueryResponse(answer=answer, session_id=session_id, model=query_input.model)
@app.post('/challenge-me', response_model=list[str])
def challenge_me(request: ChallengeRequest):
file_id = request.file_id
content = get_file_content(file_id)
if content is None:
raise HTTPException(status_code=404, detail="Document not found")
llm = ChatOpenAI(
model='gpt-4.1',
api_key=OPENAI_API_KEY
)
prompt = ChatPromptTemplate.from_messages([
("system", "You are a helpful AI assistant. Generate three logic-based or comprehension-focused questions about the following document. Each question should require understanding or reasoning about the document content, not just simple recall. Provide each question on a new line."),
("human", "Document: {context}\n\nQuestions:")
])
chain = prompt | llm | StrOutputParser()
questions_str = chain.invoke({"context": content})
questions = [q.strip() for q in questions_str.split('\n') if q.strip()][:3]
return questions
@app.post('/evaluate-response')
def evaluate_response(request: EvaluateAnswer):
# get the file ralated to answers
file_id = request.file_id
question = request.question
user_answer=request.user_answer
# evaluate the useranswer according to the research paper
llm = ChatOpenAI(
model='gpt-4.1',
api_key=OPENAI_API_KEY
)
# get the context from doc
retrieved_docs=retrieve(query=question)
docs_content = "\n\n".join(doc.page_content for doc in retrieved_docs)
prompt = ChatPromptTemplate.from_messages([
("system", "You are a helpful AI assistant. Your task is to evaluate the user's answer to a question, using ONLY the information below as reference. If the answer is not correct, explain why and provide the correct answer with justification from the document. Do not make up information."),
("system", "Context: {context}"),
("human", "Question: {question}\nUser Answer: {user_answer}\nEvaluation:")
])
chain = prompt | llm | StrOutputParser()
evaluation = chain.invoke({
"context": docs_content,
"question": question,
"user_answer": user_answer
})
return {
"feedback": evaluation,
"file_id": file_id
}
@app.post("/upload-doc")
def upload_and_index_document(file: UploadFile = File(...), session_id: str = Form(None)):
if not session_id:
session_id = str(uuid.uuid4())
allowed_extensions = ['.pdf', '.txt']
file_extension = os.path.splitext(file.filename)[1].lower()
if file_extension not in allowed_extensions:
raise HTTPException(status_code=400, detail=f"Unsupported file type. Allowed types are: {', '.join(allowed_extensions)}")
temp_file_path = f"temp_{file.filename}"
try:
# Save the uploaded file to a temporary file
with open(temp_file_path, "wb") as buffer:
shutil.copyfileobj(file.file, buffer)
docs = load_and_split_document(temp_file_path)
docs_content = "\n\n".join(doc.page_content for doc in docs)
file_id = insert_document_record(session_id, file.filename, docs_content)
success = index_document_to_pinecone(temp_file_path, file_id)
if success:
# generate summary
llm = ChatOpenAI(
model='gpt-4.1',
api_key=OPENAI_API_KEY
)
prompt = ChatPromptTemplate.from_messages([
("system", "You are a helpful assistant. Summarize the following document in no more than 150 words. Focus on the main points and key findings. Do not include information not present in the document."),
("human", "{document}")
])
chain = prompt | llm | StrOutputParser()
summary = chain.invoke({"document": docs_content})
return {
"message": f"File {file.filename} has been successfully uploaded and indexed.",
"file_id": file_id,
"summary": summary
}
else:
delete_document_record(file_id)
raise HTTPException(status_code=500, detail=f"Failed to index {file.filename}.")
finally:
if os.path.exists(temp_file_path):
os.remove(temp_file_path)
@app.get("/list-docs", response_model=list[DocumentInfo])
def list_documents(session_id: str):
return get_all_documents(session_id)
@app.post("/delete-doc")
def delete_document(request: DeleteFileRequest):
pinecone_delete_success = delete_doc_from_pinecone(request.file_id)
if pinecone_delete_success:
db_delete_success = delete_document_record(request.file_id)
if db_delete_success:
return {"message": f"Successfully deleted document with file_id {request.file_id} from the system."}
else:
return {"error": f"Deleted from pinecone but failed to delete document with file_id {request.file_id} from the database."}
else:
return {"error": f"Failed to delete document with file_id {request.file_id} from pinecone."}