research-papers-rag / answer.py
akzz
added error handling and logs
2baf97f
Raw
History Blame Contribute Delete
2.37 kB
"""
Takes the top chunks from retriever, passes them to LLM along with query and conversation history, it returns answer with citations
"""
import os
from dotenv import load_dotenv
from google import genai
from config import LLM_MODEL
from memory import format_history_for_prompt
from logger import get_logger
load_dotenv()
logger = get_logger("answer")
llm = genai.Client(api_key=os.getenv("GEMINI_API_KEY"))
def answer(query:str, chunks:list, history:dict=None) -> str:
"""
Builds a prompt from top chunks + conversation memory and asks llm to answer
Args:
query: the user question
chunks: top ranked points from retrieve()
history: memory dict, pass None or new_memory() for first time
"""
if not chunks:
return "I couldn't find relevant information in the stored papers."
try:
# build context for chunks
context_parts = []
for i, chunk in enumerate(chunks):
p = chunk.payload
context_parts.append(
f"[Chunk No. {i+1} | Paper: {p["paper_name"]} | Page: {p["page_number"]} | Section: {p["section"]}]\n\n{p["text"]}"
)
context = "\n\n---\n\n".join(context_parts)
history_block = ""
if history and (history.get("summary") or history.get("recent")):
history_text = format_history_for_prompt(history)
history_block = f"""Previous conversation (for context only — do NOT use it to answer if the chunks don't support it):
{history_text}"""
prompt = f"""You are a research assistant. Answer the question using ONLY the provided context chunks.
For each piece of information you use for answer, cite the source at end like: (Paper: paper_name, Page: X, Section: Y)
If the answer is not in context, say so clearly.
{history_block}
Context:
{context}
Question: {query}
Answer:"""
response = llm.models.generate_content(
model=LLM_MODEL,
contents=prompt
)
logger.info("answer: generated response for query '%s'", query)
return response.text.strip()
except Exception as e:
logger.error("answer: LLM call failed for query '%s': %s", query, e)
return "Sorry, I couldn't generate an answer right now. Please try again."