chatpaper / src /agent /agent.py
Shafagh99's picture
add chatpaper project
c003cc2
import os
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage, AIMessage, BaseMessage
from langgraph.prebuilt import create_react_agent
from typing import List
from src.agent.tools import search_papers, compare_papers, generate_literature_review
SYSTEM_PROMPT = """You are ChatPaper, an expert AI research assistant. You have access to a database of research papers.
CRITICAL RULES — NEVER BREAK THESE:
1. You MUST call search_papers tool FIRST before answering ANY question. No exceptions.
2. NEVER say you don't have enough information before searching. Always search first.
3. NEVER ask the user for clarification before searching. Search with what you have.
4. Base your answer ONLY on what the search_papers tool returns.
5. If the tool returns no relevant results, then say the paper does not contain that information.
Your tools:
- search_papers: search the indexed papers — call this IMMEDIATELY for every question
- compare_papers: compare topics across multiple papers
- generate_literature_review: write a literature review from the papers
Answer format:
- Be concise and specific
- Always mention which paper and page your answer comes from
- Use bullet points for lists
"""
class ChatPaperAgent:
def __init__(self):
print("Initializing ChatPaper agent...")
self.llm = ChatOpenAI(
model="anthropic/claude-3-haiku",
api_key=os.getenv("OPENROUTER_API_KEY"),
base_url="https://openrouter.ai/api/v1",
temperature=0,
max_tokens=4096,
)
self.tools = [
search_papers,
compare_papers,
generate_literature_review,
]
self.graph = create_react_agent(
model=self.llm,
tools=self.tools,
prompt=SYSTEM_PROMPT,
)
self.conversation_history: List[BaseMessage] = []
print("Agent ready!")
def chat(self, user_message: str) -> str:
#Send a message and get the agent's response.
self.conversation_history.append(
HumanMessage(content=user_message)
)
try:
result = self.graph.invoke(
{"messages": self.conversation_history}
)
response_text = ""
for message in reversed(result["messages"]):
content = message.content
if isinstance(content, str):
if content.strip():
response_text = content.strip()
break
elif isinstance(content, list):
text_parts = []
for block in content:
if isinstance(block, dict):
if block.get("type") == "text" and block.get("text", "").strip():
text_parts.append(block["text"].strip())
elif isinstance(block, str) and block.strip():
text_parts.append(block.strip())
if text_parts:
response_text = " ".join(text_parts)
break
if not response_text:
response_text = "I could not generate a response. Please try again."
self.conversation_history.append(
AIMessage(content=response_text)
)
return response_text
except Exception as e:
error_msg = f"Agent error: {str(e)}\n\nPlease try rephrasing your question."
return error_msg
def reset(self) -> None:
"""
Clear conversation history to start a fresh session.
Call this when the user clicks "New Conversation" or
when switching to a different set of papers.
"""
self.conversation_history = []
print("Conversation reset")