Mayank2027 commited on
Commit
eeeb5ac
·
verified ·
1 Parent(s): 11f87a6

Update agents.py

Browse files
Files changed (1) hide show
  1. agents.py +54 -47
agents.py CHANGED
@@ -1,4 +1,4 @@
1
- # agents.py – Complete with full history and forced done
2
 
3
  import json
4
  import logging
@@ -15,7 +15,7 @@ class BaseAgent:
15
  def __init__(self, name: str, role: str, system_prompt: str, tools: ToolRegistry, state: Any):
16
  self.name = name
17
  self.role = role
18
- self.system_prompt = system_prompt[:800] # Keep essential
19
  self.tools = tools
20
  self.state = state
21
  self.history = []
@@ -25,20 +25,19 @@ class BaseAgent:
25
  self.plan_index = 0
26
 
27
  async def think(self, context: str) -> Dict:
28
- # Build context with full history (last 3 steps, summarized)
29
  history_text = ""
30
  if self.history:
31
- last_entries = self.history[-3:]
32
  history_text = "\n".join([
33
- f"Step {i+1}: Action {entry['action'].get('tool')} -> Result: {self._summarize_result(entry['result'])}"
34
- for i, entry in enumerate(last_entries)
35
  ])
36
 
37
- full_context = f"Task: {self.state.task}\nHistory:\n{history_text}\nCurrent instruction: {context}"
38
- if len(full_context) > 1200:
39
- full_context = full_context[:1200] + "\n... (truncated)"
40
 
41
- # Short system prompt
42
  short_prompt = self.system_prompt + """
43
  Output ONLY JSON. Format: {"thought":"...","action":{"tool":"...","params":{...}}}
44
  """
@@ -49,6 +48,14 @@ Output ONLY JSON. Format: {"thought":"...","action":{"tool":"...","params":{...}
49
  raw, meta = await LLMClient.chat(messages, temperature=0.1, response_format="json")
50
  logger.info(f"Raw LLM response: {raw[:150]}...")
51
 
 
 
 
 
 
 
 
 
52
  json_data = self._extract_json(raw)
53
  if json_data:
54
  try:
@@ -64,15 +71,13 @@ Output ONLY JSON. Format: {"thought":"...","action":{"tool":"...","params":{...}
64
  except Exception as e:
65
  logger.error(f"JSON parse error: {e}")
66
 
67
- # If we have completed all steps in the plan, force done
68
- if self.plan and self.plan_index >= len(self.plan):
69
- logger.info("Plan completed, forcing done")
70
  return {
71
- "thought": "Plan completed",
72
- "action": {"tool": "done", "params": {"result": "Task completed by plan"}}
73
  }
74
-
75
- logger.warning("Using fallback navigate")
76
  return {
77
  "thought": "Fallback",
78
  "action": {"tool": "navigate", "params": {"url": "https://example.com"}}
@@ -80,8 +85,8 @@ Output ONLY JSON. Format: {"thought":"...","action":{"tool":"...","params":{...}
80
 
81
  def _summarize_result(self, result):
82
  if isinstance(result, dict):
83
- return result.get("result", "") or result.get("data", "") or str(result)[:100]
84
- return str(result)[:100]
85
 
86
  def _extract_json(self, text: str) -> str:
87
  start = text.find('{')
@@ -103,8 +108,8 @@ Output ONLY JSON. Format: {"thought":"...","action":{"tool":"...","params":{...}
103
  if tool_name == "done":
104
  self.done = True
105
  self.result = params.get("result", "Task completed.")
 
106
  try:
107
- await asyncio.sleep(0.2)
108
  screenshot = await self.tools("screenshot")
109
  return {"result": self.result, "screenshot": screenshot.get("result", "")}
110
  except:
@@ -112,16 +117,24 @@ Output ONLY JSON. Format: {"thought":"...","action":{"tool":"...","params":{...}
112
 
113
  try:
114
  result = await self.tools(tool_name, **params)
115
- await asyncio.sleep(0.1)
116
- screenshot = await self.tools("screenshot")
117
- result["screenshot"] = screenshot.get("result", "")
 
 
 
118
  # Truncate large data
119
- if "data" in result and isinstance(result["data"], str) and len(result["data"]) > 300:
120
- result["data"] = result["data"][:300] + "... (truncated)"
121
  return result
122
  except Exception as e:
123
  logger.error(f"Action failed: {e}")
124
- return {"error": str(e)}
 
 
 
 
 
125
 
126
  async def run(self, context: str) -> Dict:
127
  self.history = []
@@ -130,10 +143,9 @@ Output ONLY JSON. Format: {"thought":"...","action":{"tool":"...","params":{...}
130
  self.plan = []
131
  self.plan_index = 0
132
  steps = 0
133
- max_steps = 10
134
 
135
  while not self.done and steps < max_steps:
136
- # Build context with current step info
137
  data = await self.think(context)
138
  thought = data.get("thought", "")
139
  action = data.get("action", {"tool": "done", "params": {"result": "No action"}})
@@ -149,9 +161,13 @@ Output ONLY JSON. Format: {"thought":"...","action":{"tool":"...","params":{...}
149
  if self.done:
150
  break
151
 
152
- # If loop ended without done, set a default result
153
- if not self.done:
154
- self.result = self.history[-1].get("result", {}).get("result", "Task incomplete") if self.history else "No action taken"
 
 
 
 
155
  return {
156
  "agent": self.name,
157
  "result": self.result,
@@ -170,42 +186,33 @@ Output ONLY JSON. Format: {"thought":"...","action":{"tool":"...","params":{...}
170
  }
171
 
172
 
173
- # ---------- Specialist Agents with clear step-by-step instructions ----------
174
  class ResearchAgent(BaseAgent):
175
  def __init__(self, tools: ToolRegistry, state: Any):
176
- prompt = """
177
- You are a Research Agent. Task: Go to wikipedia and search for AI.
178
- Follow these steps exactly:
179
- 1. Navigate to https://www.wikipedia.org
180
- 2. Fill #searchInput with "AI"
181
- 3. Click button[type='submit']
182
- 4. Extract text from #firstHeading
183
- 5. Done with result: "Article title is: " + title.
184
- Only output one action per JSON.
185
- """
186
  super().__init__("Research Agent", "Gather", prompt, tools, state)
187
 
188
  class SalesAgent(BaseAgent):
189
  def __init__(self, tools: ToolRegistry, state: Any):
190
- prompt = "You are a Sales Agent. Generate proposals and emails. Output JSON actions only."
191
  super().__init__("Sales Agent", "Sales", prompt, tools, state)
192
 
193
  class SupportAgent(BaseAgent):
194
  def __init__(self, tools: ToolRegistry, state: Any):
195
- prompt = "You are a Support Agent. Search knowledge base and generate FAQs. Output JSON actions only."
196
  super().__init__("Support Agent", "Support", prompt, tools, state)
197
 
198
  class DataAgent(BaseAgent):
199
  def __init__(self, tools: ToolRegistry, state: Any):
200
- prompt = "You are a Data Agent. Analyse data and create plots. Output JSON actions only."
201
  super().__init__("Data Agent", "Data", prompt, tools, state)
202
 
203
  class CodeAgent(BaseAgent):
204
  def __init__(self, tools: ToolRegistry, state: Any):
205
- prompt = "You are a Code Agent. Write and execute Python code. Output JSON actions only."
206
  super().__init__("Code Agent", "Code", prompt, tools, state)
207
 
208
  class ContentAgent(BaseAgent):
209
  def __init__(self, tools: ToolRegistry, state: Any):
210
- prompt = "You are a Content Agent. Summarise and translate text. Output JSON actions only."
211
  super().__init__("Content Agent", "Content", prompt, tools, state)
 
1
+ # agents.py – FIXED: forced done, screenshot on error, truncated context
2
 
3
  import json
4
  import logging
 
15
  def __init__(self, name: str, role: str, system_prompt: str, tools: ToolRegistry, state: Any):
16
  self.name = name
17
  self.role = role
18
+ self.system_prompt = system_prompt[:400] # Keep short
19
  self.tools = tools
20
  self.state = state
21
  self.history = []
 
25
  self.plan_index = 0
26
 
27
  async def think(self, context: str) -> Dict:
28
+ # Build context with last 2 actions only, heavily truncated
29
  history_text = ""
30
  if self.history:
31
+ last_entries = self.history[-2:]
32
  history_text = "\n".join([
33
+ f"Action: {entry['action'].get('tool')} -> Result: {self._summarize_result(entry['result'])}"
34
+ for entry in last_entries
35
  ])
36
 
37
+ full_context = f"Task: {self.state.task}\nHistory:\n{history_text}\nInstruction: {context}"
38
+ if len(full_context) > 800:
39
+ full_context = full_context[:800] + "\n... (truncated)"
40
 
 
41
  short_prompt = self.system_prompt + """
42
  Output ONLY JSON. Format: {"thought":"...","action":{"tool":"...","params":{...}}}
43
  """
 
48
  raw, meta = await LLMClient.chat(messages, temperature=0.1, response_format="json")
49
  logger.info(f"Raw LLM response: {raw[:150]}...")
50
 
51
+ # If we already have a plan and all steps executed, force done
52
+ if self.plan and self.plan_index >= len(self.plan):
53
+ logger.info("Plan completed, forcing done")
54
+ return {
55
+ "thought": "Plan completed",
56
+ "action": {"tool": "done", "params": {"result": "Task completed by plan"}}
57
+ }
58
+
59
  json_data = self._extract_json(raw)
60
  if json_data:
61
  try:
 
71
  except Exception as e:
72
  logger.error(f"JSON parse error: {e}")
73
 
74
+ # Fallback: if we have a plan, execute next step; else navigate
75
+ if self.plan and self.plan_index < len(self.plan):
76
+ # We don't have a specific action for the next step, so fallback to navigate
77
  return {
78
+ "thought": "Fallback to navigate",
79
+ "action": {"tool": "navigate", "params": {"url": "https://example.com"}}
80
  }
 
 
81
  return {
82
  "thought": "Fallback",
83
  "action": {"tool": "navigate", "params": {"url": "https://example.com"}}
 
85
 
86
  def _summarize_result(self, result):
87
  if isinstance(result, dict):
88
+ return result.get("result", "") or result.get("data", "") or str(result)[:80]
89
+ return str(result)[:80]
90
 
91
  def _extract_json(self, text: str) -> str:
92
  start = text.find('{')
 
108
  if tool_name == "done":
109
  self.done = True
110
  self.result = params.get("result", "Task completed.")
111
+ # Always capture a final screenshot
112
  try:
 
113
  screenshot = await self.tools("screenshot")
114
  return {"result": self.result, "screenshot": screenshot.get("result", "")}
115
  except:
 
117
 
118
  try:
119
  result = await self.tools(tool_name, **params)
120
+ # Capture screenshot after action
121
+ try:
122
+ screenshot = await self.tools("screenshot")
123
+ result["screenshot"] = screenshot.get("result", "")
124
+ except:
125
+ result["screenshot"] = ""
126
  # Truncate large data
127
+ if "data" in result and isinstance(result["data"], str) and len(result["data"]) > 200:
128
+ result["data"] = result["data"][:200] + "... (truncated)"
129
  return result
130
  except Exception as e:
131
  logger.error(f"Action failed: {e}")
132
+ # Even on error, try to capture screenshot
133
+ try:
134
+ screenshot = await self.tools("screenshot")
135
+ return {"error": str(e), "screenshot": screenshot.get("result", "")}
136
+ except:
137
+ return {"error": str(e)}
138
 
139
  async def run(self, context: str) -> Dict:
140
  self.history = []
 
143
  self.plan = []
144
  self.plan_index = 0
145
  steps = 0
146
+ max_steps = 8 # Reduce to speed up
147
 
148
  while not self.done and steps < max_steps:
 
149
  data = await self.think(context)
150
  thought = data.get("thought", "")
151
  action = data.get("action", {"tool": "done", "params": {"result": "No action"}})
 
161
  if self.done:
162
  break
163
 
164
+ # If loop ended without done, mark done with last result
165
+ if not self.done and self.history:
166
+ self.result = self.history[-1].get("result", {}).get("result", "Task incomplete")
167
+ elif not self.done:
168
+ self.result = "No actions executed"
169
+ self.done = True # Force completion to avoid infinite loop
170
+
171
  return {
172
  "agent": self.name,
173
  "result": self.result,
 
186
  }
187
 
188
 
189
+ # ---------- Specialist Agents ----------
190
  class ResearchAgent(BaseAgent):
191
  def __init__(self, tools: ToolRegistry, state: Any):
192
+ prompt = "You are a Research Agent. Task: Go to wikipedia and search for AI. Steps: navigate, fill search, click, extract title, done."
 
 
 
 
 
 
 
 
 
193
  super().__init__("Research Agent", "Gather", prompt, tools, state)
194
 
195
  class SalesAgent(BaseAgent):
196
  def __init__(self, tools: ToolRegistry, state: Any):
197
+ prompt = "You are a Sales Agent. Generate proposals and emails."
198
  super().__init__("Sales Agent", "Sales", prompt, tools, state)
199
 
200
  class SupportAgent(BaseAgent):
201
  def __init__(self, tools: ToolRegistry, state: Any):
202
+ prompt = "You are a Support Agent. Search knowledge base and generate FAQs."
203
  super().__init__("Support Agent", "Support", prompt, tools, state)
204
 
205
  class DataAgent(BaseAgent):
206
  def __init__(self, tools: ToolRegistry, state: Any):
207
+ prompt = "You are a Data Agent. Analyse data and create plots."
208
  super().__init__("Data Agent", "Data", prompt, tools, state)
209
 
210
  class CodeAgent(BaseAgent):
211
  def __init__(self, tools: ToolRegistry, state: Any):
212
+ prompt = "You are a Code Agent. Write and execute Python code."
213
  super().__init__("Code Agent", "Code", prompt, tools, state)
214
 
215
  class ContentAgent(BaseAgent):
216
  def __init__(self, tools: ToolRegistry, state: Any):
217
+ prompt = "You are a Content Agent. Summarise and translate text."
218
  super().__init__("Content Agent", "Content", prompt, tools, state)