multi-pdf-chatbot / agent.py
artistica-004's picture
Update: Add agent.py, modify app.py and rag_engine.py, remove deprecated streamlit_app.py
248e6eb
Raw
History Blame Contribute Delete
4.12 kB
import os
from dotenv import load_dotenv
from groq import Groq
from rag_engine import (
search_relevant_chunks,
generate_answer,
generate_followup_questions
)
load_dotenv()
client = Groq(api_key=os.getenv("GROQ_API_KEY"))
def analyze_question(question):
prompt = f"""Analyze this question.
Question: {question}
Reply in this exact format only:
TYPE: [simple/complex]
NEEDS_COMPARISON: [yes/no]"""
try:
response = client.chat.completions.create(
model="llama-3.3-70b-versatile",
messages=[{"role": "user", "content": prompt}],
temperature=0.1,
max_tokens=50
)
return response.choices[0].message.content
except Exception:
return "TYPE: simple"
def break_into_subquestions(question):
prompt = f"""Break this question into 2-3 smaller sub-questions
that can be answered from a PDF document.
Only ask questions that can be found in documents.
Do not ask personal questions.
Question: {question}
Reply with only the sub-questions, one per line. Nothing else."""
try:
response = client.chat.completions.create(
model="llama-3.3-70b-versatile",
messages=[{"role": "user", "content": prompt}],
temperature=0.1,
max_tokens=200
)
subquestions = response.choices[0].message.content.strip().split('\n')
return [q.strip() for q in subquestions if q.strip()]
except Exception:
return [question]
def check_answer_quality(answer):
prompt = f"""Does this answer contain actual information or does it say information is not available?
Answer: {answer}
Reply with only: FOUND or NOT_FOUND"""
try:
response = client.chat.completions.create(
model="llama-3.3-70b-versatile",
messages=[{"role": "user", "content": prompt}],
temperature=0.1,
max_tokens=10
)
return response.choices[0].message.content.strip()
except Exception:
return "FOUND"
def run_agent(vector_store, question, pdf_names):
# Step 1 β€” Adaptive behavior
greetings = ["hi", "hello", "hey", "thanks", "thank you", "okay", "ok"]
if question.lower().strip() in greetings:
return "Please ask a question related to your uploaded PDFs!", [], []
try:
# Step 2 β€” Decision making
analysis = analyze_question(question)
is_complex = "complex" in analysis.lower()
if is_complex:
# Step 3 β€” Break into sub-questions
subquestions = break_into_subquestions(question)
all_chunks = []
all_answers = []
# Step 4 β€” Multi-step execution
for subq in subquestions:
chunks = search_relevant_chunks(vector_store, subq, k=6)
all_chunks.extend(chunks)
answer, _ = generate_answer(subq, chunks, pdf_names)
all_answers.append(f"**{subq}**\n{answer}")
# Step 5 β€” Combine
combined = "\n\n".join(all_answers)
# Step 6 β€” Gap detection
quality = check_answer_quality(combined)
if quality == "NOT_FOUND":
return "This information is not available in the uploaded documents.", all_chunks, []
# Step 7 β€” Follow-up questions
followups = generate_followup_questions(question, combined)
return combined, all_chunks, followups
else:
# Simple question
chunks = search_relevant_chunks(vector_store, question, k=6)
answer, _ = generate_answer(question, chunks, pdf_names)
# Gap detection
quality = check_answer_quality(answer)
if quality == "NOT_FOUND":
return "This information is not available in the uploaded documents.", chunks, []
# Follow-up questions
followups = generate_followup_questions(question, answer)
return answer, chunks, followups
except Exception as e:
return f"Something went wrong: {str(e)}", [], []