naman1102 commited on
Commit
67017c3
Β·
1 Parent(s): 1ae0aa0

react_removed

Browse files
Files changed (3) hide show
  1. agent.py +34 -15
  2. app.py +43 -50
  3. tools.py +1 -10
agent.py CHANGED
@@ -1,13 +1,10 @@
1
  from __future__ import annotations
2
  import os
3
  from langchain_openai import ChatOpenAI
4
- from langgraph.graph import StateGraph, START, END
5
- from langchain.schema import HumanMessage, SystemMessage, AIMessage
6
- from state import AgentState
7
  from typing import Any, Dict, List, Optional
8
  import json
9
- from langgraph.prebuilt import create_react_agent
10
- import signal
11
 
12
  # ─────────────────────────── External tools ──────────────────────────────
13
  from tools import (
@@ -26,21 +23,43 @@ from tools import (
26
  # ─────────────────────────── Configuration ───────────────────────────────
27
  MAX_TOOL_CALLS = 5
28
 
29
- # ─────────────────────────── Helper utilities ────────────────────────────
 
 
 
30
 
31
- # ─────────────────────────── Agent state ⬇ ───────────────────────────────
 
 
 
 
32
 
33
- # ───────────────────────────── Nodes ⬇ ───────────────────────────────────
 
 
 
34
 
35
- # ------------- tool adapters -------------
 
 
36
 
 
 
 
 
 
 
 
 
 
 
 
37
 
38
- # ─────────────────────────── Graph wiring ───────────────────────────────
39
 
40
  def build_graph():
41
- """Build and return a create_react_agent."""
42
- llm = ChatOpenAI(model_name="gpt-4o-mini", temperature=0.3)
43
-
44
  llm_tools = [
45
  wikipedia_search_tool,
46
  arxiv_search_tool,
@@ -54,7 +73,7 @@ def build_graph():
54
  divide_tool
55
  ]
56
 
57
- # Create the react agent - it will use the system prompt from the messages
58
- agent = create_react_agent(model=llm, tools=llm_tools)
59
 
60
  return agent
 
1
  from __future__ import annotations
2
  import os
3
  from langchain_openai import ChatOpenAI
4
+ from langchain_core.messages import AIMessage, HumanMessage, SystemMessage
5
+ from langgraph.prebuilt import ToolExecutor
 
6
  from typing import Any, Dict, List, Optional
7
  import json
 
 
8
 
9
  # ─────────────────────────── External tools ──────────────────────────────
10
  from tools import (
 
23
  # ─────────────────────────── Configuration ───────────────────────────────
24
  MAX_TOOL_CALLS = 5
25
 
26
+ class CustomReActAgent:
27
+ def __init__(self, tools: List, model_name="gpt-4o-mini"):
28
+ self.llm = ChatOpenAI(model_name=model_name, temperature=0.3)
29
+ self.tool_executor = ToolExecutor(tools)
30
 
31
+ def run(self, question: str, task_id: Optional[str] = None, max_turns: int = 15, system_prompt: str = "") -> str:
32
+ messages = [SystemMessage(content=system_prompt)]
33
+ if task_id:
34
+ messages[0].content += f"\n\nIMPORTANT: Your current task_id is: {task_id}."
35
+ messages.append(HumanMessage(content=question))
36
 
37
+ for _ in range(max_turns):
38
+ ai_response = self.llm.invoke(messages)
39
+ messages.append(ai_response)
40
+ print("AI said:", ai_response.content)
41
 
42
+ # Final answer?
43
+ if "FINAL ANSWER:" in ai_response.content.upper():
44
+ return ai_response.content.split("FINAL ANSWER:")[-1].strip()
45
 
46
+ # Tool call expected
47
+ if "Action:" in ai_response.content and "Action Input:" in ai_response.content:
48
+ try:
49
+ tool_name = ai_response.content.split("Action:")[1].split("Action Input:")[0].strip()
50
+ tool_input = ai_response.content.split("Action Input:")[1].strip()
51
+ tool_result = self.tool_executor.run(tool_name, tool_input)
52
+ messages.append(HumanMessage(content=f"Observation: {tool_result}"))
53
+ except Exception as e:
54
+ messages.append(HumanMessage(content=f"Observation: Tool execution failed: {str(e)}"))
55
+ else:
56
+ messages.append(HumanMessage(content="Observation: No valid action. Please clarify."))
57
 
58
+ return "No FINAL ANSWER found within allowed steps."
59
 
60
  def build_graph():
61
+ """Build and return a CustomReActAgent."""
62
+
 
63
  llm_tools = [
64
  wikipedia_search_tool,
65
  arxiv_search_tool,
 
73
  divide_tool
74
  ]
75
 
76
+ # Create the custom react agent
77
+ agent = CustomReActAgent(tools=llm_tools)
78
 
79
  return agent
app.py CHANGED
@@ -14,20 +14,46 @@ from state import AgentState
14
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
15
 
16
  SYSTEM_PROMPT = """
17
- You are a general AI assistant. I will ask you a question. Report your thoughts, and finish your answer with the following template: FINAL ANSWER: [YOUR FINAL ANSWER]. YOUR FINAL ANSWER should be a number OR as few words as possible OR a comma separated list of numbers and/or strings. If you are asked for a number, don't use comma to write your number neither use units such as $ or percent sign unless specified otherwise. If you are asked for a string, don't use articles, neither abbreviations (e.g. for cities), and write the digits in plain text unless specified otherwise. If you are asked for a comma separated list, apply the above rules depending of whether the element to be put in the list is a number or a string.
18
 
19
- IMPORTANT: When using tools that require file access (such as audio_transcriber_tool, excel_tool, analyze_code_tool, or image_tool), ALWAYS use the task_id parameter only. Do NOT use any file names mentioned by the user - ignore them completely and only pass the task_id.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
 
21
  SEARCH STRATEGY:
22
- - If wikipedia_search_tool fails or returns insufficient/irrelevant results, try these fallback strategies:
23
- 1. Try wikipedia_search_tool again with a broader, more general query (remove specific terms, use synonyms)
24
- 2. If Wikipedia still doesn't help, try arxiv_search_tool for academic/research topics
25
- 3. You can use multiple search attempts with different keywords to find better information
26
- - Always evaluate if the search results are relevant and sufficient before proceeding to your final answer
27
- - IMPORTANT: When you see [END_OF_SEARCH] in tool results, this means the search is complete and you have all available information
28
- - Do NOT perform additional searches after seeing [END_OF_SEARCH] - immediately proceed to analyze the provided information and give your final answer
29
-
30
- You MUST always provide a FINAL ANSWER. If you reach the recursion limit or tools fail, provide the best answer possible with available information.
31
  """
32
 
33
 
@@ -37,48 +63,15 @@ class BasicAgent:
37
  self.graph = build_graph()
38
 
39
  def __call__(self, question: str, task_id: Optional[str] = None) -> str:
40
- """Run the agent and return whatever FINAL_ANSWER the graph produces."""
41
  print(f"Agent received question: {question}")
42
 
43
  try:
44
- # Create system prompt with task_id included
45
- system_prompt_with_task = SYSTEM_PROMPT
46
- if task_id:
47
- system_prompt_with_task += f"\n\nIMPORTANT: Your current task_id is: {task_id}. When using any tools that require a task_id parameter (audio_transcriber_tool, excel_tool, analyze_code_tool, image_tool), use this exact task_id: {task_id}"
48
-
49
- # Initialize the state properly with all required fields
50
- init_state = {
51
- "messages": [
52
- SystemMessage(content=system_prompt_with_task),
53
- HumanMessage(content=question)
54
- ]
55
- }
56
-
57
- # Run the agent with increased steps
58
- out_state = self.graph.invoke(init_state, {"recursion_limit": 15})
59
-
60
- # Extract the final answer from the last message
61
- if out_state and "messages" in out_state:
62
- last_message = out_state["messages"][-1]
63
- if hasattr(last_message, 'content') and last_message.content:
64
- content = last_message.content
65
- print("content: ", content)
66
- print("\n\n\n\n")
67
-
68
- # Look for FINAL ANSWER: pattern (case insensitive)
69
- if "FINAL ANSWER:" in content.upper():
70
- # Find the last occurrence of FINAL ANSWER
71
- parts = content.upper().split("FINAL ANSWER:")
72
- if len(parts) > 1:
73
- # Get the original case version
74
- answer_start = content.upper().rfind("FINAL ANSWER:") + len("FINAL ANSWER:")
75
- final_answer = content[answer_start:].strip()
76
- return final_answer
77
-
78
- # If no FINAL ANSWER found, return the whole content
79
- return content
80
-
81
- return "No valid response generated."
82
 
83
  except Exception as e:
84
  print(f"Agent execution error: {e}")
 
14
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
15
 
16
  SYSTEM_PROMPT = """
17
+ You are a general AI assistant using the ReAct (Reasoning and Acting) approach. I will ask you a question, and you should think step by step and use tools when needed.
18
 
19
+ FORMAT:
20
+ For each step, use this exact format:
21
+ Thought: [your reasoning about what to do next]
22
+ Action: [tool name]
23
+ Action Input: [input to the tool]
24
+
25
+ After using a tool, you'll receive:
26
+ Observation: [tool result]
27
+
28
+ Continue this cycle until you have enough information, then provide:
29
+ FINAL ANSWER: [YOUR FINAL ANSWER]
30
+
31
+ ANSWER FORMAT:
32
+ YOUR FINAL ANSWER should be a number OR as few words as possible OR a comma separated list of numbers and/or strings. If you are asked for a number, don't use comma to write your number neither use units such as $ or percent sign unless specified otherwise. If you are asked for a string, don't use articles, neither abbreviations (e.g. for cities), and write the digits in plain text unless specified otherwise.
33
+
34
+ IMPORTANT: When using tools that require file access (such as audio_transcriber_tool, excel_tool, analyze_code_tool, or image_tool), ALWAYS use the task_id parameter only. Do NOT use any file names mentioned by the user.
35
+
36
+ AVAILABLE TOOLS:
37
+ - wikipedia_search_tool: For historical, biographical, scientific facts
38
+ - arxiv_search_tool: For academic research papers
39
+ - audio_transcriber_tool: For transcribing audio files
40
+ - excel_tool: For analyzing spreadsheet data
41
+ - analyze_code_tool: For understanding code files
42
+ - image_tool: For describing images
43
+ - add_tool: For adding numbers
44
+ - subtract_tool: For subtracting numbers
45
+ - multiply_tool: For multiplying numbers
46
+ - divide_tool: For dividing numbers
47
 
48
  SEARCH STRATEGY:
49
+ - If wikipedia_search_tool fails, try with broader queries or use arxiv_search_tool for academic topics
50
+ - When you see [END_OF_SEARCH] in results, stop searching and provide your final answer
51
+ - You MUST always provide a FINAL ANSWER, even if tools fail
52
+
53
+ Example:
54
+ Thought: I need to find information about quantum computing.
55
+ Action: wikipedia_search_tool
56
+ Action Input: quantum computing
 
57
  """
58
 
59
 
 
63
  self.graph = build_graph()
64
 
65
  def __call__(self, question: str, task_id: Optional[str] = None) -> str:
66
+ """Run the agent and return whatever FINAL_ANSWER the agent produces."""
67
  print(f"Agent received question: {question}")
68
 
69
  try:
70
+ # Run the custom react agent
71
+ result = self.graph.run(question=question, task_id=task_id, max_turns=15, system_prompt=SYSTEM_PROMPT)
72
+ print("Final result: ", result)
73
+ print("\n\n\n\n")
74
+ return result
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
 
76
  except Exception as e:
77
  print(f"Agent execution error: {e}")
tools.py CHANGED
@@ -219,18 +219,12 @@ def wikipedia_search_tool(wiki_query: str) -> str:
219
  - "Explain quantum entanglement"
220
  - "Tell me about the French Revolution"
221
  """
222
- print(f"DEBUG: reached wikipedia_search_tool with query: {wiki_query}")
223
  try:
224
  docs = WikipediaLoader(query=wiki_query, load_max_docs=3).load() # Reduced from 5 to 3
225
- print(f"DEBUG: WikipediaLoader returned {len(docs)} documents")
226
 
227
  result = ""
228
  counter = 1
229
  for doc in docs:
230
- print(f"DEBUG: Processing Wikipedia document {counter}")
231
- print(f"DEBUG: Document metadata: {doc.metadata}")
232
- print(f"DEBUG: Document content length: {len(doc.page_content)}")
233
-
234
  # Handle different metadata structures
235
  title = "Unknown Title"
236
  if hasattr(doc, 'metadata') and doc.metadata:
@@ -247,8 +241,6 @@ def wikipedia_search_tool(wiki_query: str) -> str:
247
  first_key = list(doc.metadata.keys())[0]
248
  title = f"Wikipedia: {doc.metadata[first_key]}"
249
 
250
- print(f"DEBUG: Using Wikipedia title: {title}")
251
-
252
  # Trim content to key information only (reduced from 2000 to 800 characters)
253
  content = doc.page_content[:800] if len(doc.page_content) > 800 else doc.page_content
254
 
@@ -266,12 +258,11 @@ def wikipedia_search_tool(wiki_query: str) -> str:
266
  # Add clear end marker
267
  result += "\n\n[END_OF_SEARCH] - Wikipedia search complete. Use this information to answer the question."
268
 
269
- print(f"DEBUG: Final Wikipedia result length: {len(result)}")
270
  return result
271
 
272
  except Exception as e:
273
  error_msg = f"Error during Wikipedia search: {str(e)} [END_OF_SEARCH]"
274
- print(f"DEBUG: {error_msg}")
275
  return error_msg
276
 
277
  @tool
 
219
  - "Explain quantum entanglement"
220
  - "Tell me about the French Revolution"
221
  """
 
222
  try:
223
  docs = WikipediaLoader(query=wiki_query, load_max_docs=3).load() # Reduced from 5 to 3
 
224
 
225
  result = ""
226
  counter = 1
227
  for doc in docs:
 
 
 
 
228
  # Handle different metadata structures
229
  title = "Unknown Title"
230
  if hasattr(doc, 'metadata') and doc.metadata:
 
241
  first_key = list(doc.metadata.keys())[0]
242
  title = f"Wikipedia: {doc.metadata[first_key]}"
243
 
 
 
244
  # Trim content to key information only (reduced from 2000 to 800 characters)
245
  content = doc.page_content[:800] if len(doc.page_content) > 800 else doc.page_content
246
 
 
258
  # Add clear end marker
259
  result += "\n\n[END_OF_SEARCH] - Wikipedia search complete. Use this information to answer the question."
260
 
261
+ print("Wikipedia search completed successfully")
262
  return result
263
 
264
  except Exception as e:
265
  error_msg = f"Error during Wikipedia search: {str(e)} [END_OF_SEARCH]"
 
266
  return error_msg
267
 
268
  @tool