benjipeng commited on
Commit
f605e9a
·
verified ·
1 Parent(s): fb79f9d

Update agent.py

Browse files
Files changed (1) hide show
  1. agent.py +28 -33
agent.py CHANGED
@@ -3,32 +3,25 @@ import re
3
  import google.generativeai as genai
4
  from tools import web_search, read_file_from_api, python_interpreter
5
 
6
- # --- NEW, MORE ADVANCED REACT PROMPT ---
7
  REACT_PROMPT = """
8
  You are a state-of-the-art, helpful AI agent designed to solve complex, multi-step problems.
9
 
10
  **Your Task:**
11
- Your goal is to answer the user's question with 100% accuracy. To do this, you will operate in a loop of Thought, Action, and Observation. You must break down the problem into a series of smaller steps.
12
 
13
  **Your Tools:**
14
  You have access to the following tools. Choose ONE tool per turn.
15
  1. `web_search[query]`: Use this to find current information, facts, or to research topics.
16
- 2. `read_file_from_api[task_id]`: Use this ONLY when the question or an agent note explicitly mentions an attached file. It reads the raw content of that file.
17
- 3. `python_interpreter[code]`: Use this for all calculations, data processing, and complex logic.
18
- - **This tool is powerful.** It has the `pandas` and `openpyxl` libraries installed.
19
- - You can use it to analyze data from files. For example, after using `read_file_from_api`, you can pass the raw content into a Python script for processing.
20
- - For Excel files, it's often better to use `pandas.read_excel(file_url)` directly within the python tool, where `file_url` can be constructed from the task_id.
21
 
22
- **Reasoning Process:**
23
- 1. **Thought:** Carefully analyze the question. Identify the required information and devise a step-by-step plan.
24
- 2. **Action:** Choose the appropriate tool and input to execute the current step of your plan. Your action MUST be in the format `Action: tool_name[input]`.
25
- 3. **Observation:** You will receive the result of your action.
26
- 4. **Repeat:** Analyze the observation and continue with the next step in your plan until you have the final answer.
27
-
28
- **CRITICAL SUBMISSION RULE:**
29
- When you have the final, definitive answer, you MUST format your response as:
30
  `Final Answer: [The single, exact answer]`
31
- The system will automatically extract only the text after this prefix for submission. Do not add any other text or explanation.
32
 
33
  ---
34
  Here is the problem:
@@ -38,10 +31,9 @@ Question: {question}
38
  class GeminiAgent:
39
  def __init__(self):
40
  print("Initializing GeminiAgent (Advanced ReAct)...")
41
- # ... (init logic remains the same: api_key, model, tools)
42
  api_key = os.getenv("GEMINI_API_KEY")
43
  if not api_key:
44
- raise ValueError("GEMINI_API_KEY secret not found! Please set it in your Space's settings.")
45
  genai.configure(api_key=api_key)
46
  self.model = genai.GenerativeModel('gemini-2.5-pro')
47
  self.tools = {
@@ -51,32 +43,35 @@ class GeminiAgent:
51
  }
52
  print("GeminiAgent initialized successfully with model 'gemini-2.5-pro'.")
53
 
54
-
55
- # MODIFIED to accept task_id
56
  def __call__(self, question: str, task_id: str) -> str:
57
  prompt = REACT_PROMPT.format(question=question)
58
 
59
- # ReAct loop
60
  for turn in range(10): # Max 10 turns
61
  print(f"\n--- Turn {turn + 1} for Task ID: {task_id} ---\n")
62
 
63
  response = self.model.generate_content(prompt)
64
  if not response.parts:
65
- print("Warning: Model returned an empty response.")
66
  prompt += "\nObservation: The model returned an empty response. Please try again."
67
  continue
68
 
69
  response_text = response.text
70
  print(f"LLM Response:\n{response_text}\n")
71
 
72
- # Check for Final Answer
73
- final_answer_match = re.search(r"Final Answer: (.*)", response_text, re.DOTALL)
74
- if final_answer_match:
75
- answer = final_answer_match.group(1).strip()
76
- print(f"Final Answer extracted: '{answer}'")
77
- return answer
 
 
 
 
 
 
 
 
78
 
79
- # Look for an Action
80
  action_match = re.search(r"Action: (\w+)\[(.*)\]", response_text, re.DOTALL)
81
  if not action_match:
82
  observation = "No valid 'Action:' or 'Final Answer:' found. Please think step-by-step and select a tool or provide the final answer."
@@ -88,14 +83,14 @@ class GeminiAgent:
88
  observation = f"Error: Unknown tool '{tool_name}'."
89
  else:
90
  try:
91
- # Pass the task_id to the tool function, which can then use it if needed
92
  observation = self.tools[tool_name](tool_input if tool_name != 'read_file_from_api' else task_id)
93
  except Exception as e:
94
  observation = f"Error executing tool {tool_name}: {e}"
95
 
96
  print(f"Observation:\n{observation}\n")
97
-
98
- # Append the full turn to the prompt
99
  prompt += f"{response_text}\nObservation: {observation}\n"
100
 
101
- return "Agent failed to find an answer within 10 turns."
 
 
 
 
3
  import google.generativeai as genai
4
  from tools import web_search, read_file_from_api, python_interpreter
5
 
6
+ # --- UPGRADED REACT PROMPT ---
7
  REACT_PROMPT = """
8
  You are a state-of-the-art, helpful AI agent designed to solve complex, multi-step problems.
9
 
10
  **Your Task:**
11
+ Your goal is to answer the user's question with 100% accuracy. You must operate in a loop of Thought, Action, and Observation. Break the problem down into a series of smaller steps.
12
 
13
  **Your Tools:**
14
  You have access to the following tools. Choose ONE tool per turn.
15
  1. `web_search[query]`: Use this to find current information, facts, or to research topics.
16
+ 2. `read_file_from_api[task_id]`: Use this ONLY when the question explicitly mentions an attached file.
17
+ 3. `python_interpreter[code]`: Use this for all calculations, data processing (with pandas), and complex logic.
 
 
 
18
 
19
+ **CRITICAL INSTRUCTIONS:**
20
+ 1. Your reasoning process is: Thought -> Action -> Observation.
21
+ 2. You MUST continue this loop until you are certain of the answer.
22
+ 3. When you have the final, definitive answer, your ABSOLUTELY LAST output line MUST be in the format:
 
 
 
 
23
  `Final Answer: [The single, exact answer]`
24
+ 4. Do not output any other text or explanation after the `Final Answer:` line.
25
 
26
  ---
27
  Here is the problem:
 
31
  class GeminiAgent:
32
  def __init__(self):
33
  print("Initializing GeminiAgent (Advanced ReAct)...")
 
34
  api_key = os.getenv("GEMINI_API_KEY")
35
  if not api_key:
36
+ raise ValueError("GEMINI_API_KEY secret not found!")
37
  genai.configure(api_key=api_key)
38
  self.model = genai.GenerativeModel('gemini-2.5-pro')
39
  self.tools = {
 
43
  }
44
  print("GeminiAgent initialized successfully with model 'gemini-2.5-pro'.")
45
 
 
 
46
  def __call__(self, question: str, task_id: str) -> str:
47
  prompt = REACT_PROMPT.format(question=question)
48
 
 
49
  for turn in range(10): # Max 10 turns
50
  print(f"\n--- Turn {turn + 1} for Task ID: {task_id} ---\n")
51
 
52
  response = self.model.generate_content(prompt)
53
  if not response.parts:
 
54
  prompt += "\nObservation: The model returned an empty response. Please try again."
55
  continue
56
 
57
  response_text = response.text
58
  print(f"LLM Response:\n{response_text}\n")
59
 
60
+ # Use re.findall to get ALL occurrences of Final Answer
61
+ final_answer_matches = re.findall(r"Final Answer: (.*)", response_text, re.DOTALL)
62
+ if final_answer_matches:
63
+ # The model sometimes outputs multiple 'Final Answer' lines. The last one is the most correct.
64
+ final_answer = final_answer_matches[-1].strip()
65
+
66
+ # --- NEW: Robust cleaning of the final answer ---
67
+ # Remove common trailing punctuation that isn't part of the answer itself.
68
+ # This handles cases like 'Claus.' but preserves '1759.70'.
69
+ if not final_answer.isnumeric():
70
+ final_answer = final_answer.rstrip('.?!,')
71
+
72
+ print(f"Final Answer extracted and cleaned: '{final_answer}'")
73
+ return final_answer
74
 
 
75
  action_match = re.search(r"Action: (\w+)\[(.*)\]", response_text, re.DOTALL)
76
  if not action_match:
77
  observation = "No valid 'Action:' or 'Final Answer:' found. Please think step-by-step and select a tool or provide the final answer."
 
83
  observation = f"Error: Unknown tool '{tool_name}'."
84
  else:
85
  try:
 
86
  observation = self.tools[tool_name](tool_input if tool_name != 'read_file_from_api' else task_id)
87
  except Exception as e:
88
  observation = f"Error executing tool {tool_name}: {e}"
89
 
90
  print(f"Observation:\n{observation}\n")
 
 
91
  prompt += f"{response_text}\nObservation: {observation}\n"
92
 
93
+ # Fallback if the agent gets stuck
94
+ last_guess = response_text.split("Final Answer:")[-1].strip()
95
+ print(f"Agent failed to find a 'Final Answer:' signal. Returning last guess: {last_guess}")
96
+ return last_guess