naman1102 commited on
Commit
3872131
Β·
1 Parent(s): 0fb8f08
Files changed (2) hide show
  1. app.py +28 -10
  2. tools.py +38 -0
app.py CHANGED
@@ -25,11 +25,12 @@ from tools import (
25
  wikipedia_search_tool,
26
  ocr_image_tool,
27
  audio_transcriber_tool,
28
- parse_excel_tool
 
29
  )
30
 
31
  # ─────────────────────────── Configuration ───────────────────────────────
32
- LLM = ChatOpenAI(model_name="gpt-4.1", temperature=0.0)
33
  MAX_TOOL_CALLS = 5
34
 
35
  # ─────────────────────────── Helper utilities ────────────────────────────
@@ -92,21 +93,25 @@ def tool_selector(state: AgentState) -> AgentState:
92
 
93
  prompt = SystemMessage(
94
  content=(
 
 
 
 
 
 
95
  "Reply with ONE JSON only (no markdown). Choices:\n"
96
  " {'action':'wiki','query':'…'}\n"
97
  " {'action':'ocr'}\n"
98
  " {'action':'audio'}\n"
99
  " {'action':'excel'}\n"
 
 
100
  " {'action':'final'}\n"
101
- "if the tool you want isnt listed above, return {'action':'final'} \n"
102
- "Use wiki if you need to search online for information. Keep the query short and concise and accurate. The query should not be a prompt but instad you should search for the relevant information rather than asking for the answer directly.\n"
103
- "If the question is about any image, you have to use ocr tool. It will tell you about the image also\n"
104
- "Use audio if the question is about an audio file\n"
105
- "Use excel if the question is about an excel file\n"
106
 
107
  )
108
  )
109
- raw = LLM(state.messages + [prompt]).content.strip()
110
  print(f"Tool selector response: {raw}")
111
  state.add(AIMessage(content=raw))
112
  parsed = safe_json(raw)
@@ -157,6 +162,16 @@ def excel_tool(state: AgentState) -> AgentState:
157
  state.next_action = None
158
  return state
159
 
 
 
 
 
 
 
 
 
 
 
160
 
161
  # ------------- final answer -------------
162
 
@@ -167,7 +182,7 @@ def final_node(state: AgentState) -> AgentState:
167
  "reply **only** with "
168
  "{\"final_answer\":\"…\"} (no markdown, no commentary)."
169
  )
170
- raw = LLM(state.messages + [wrap]).content.strip()
171
  # print("raw : ", raw)
172
  state.add(AIMessage(content=raw))
173
  parsed = safe_json(raw)
@@ -187,6 +202,7 @@ for name, fn in [
187
  ("ocr_tool", ocr_tool),
188
  ("audio_tool", audio_tool),
189
  ("excel_tool", excel_tool),
 
190
  ("final_node", final_node),
191
  ]:
192
  graph.add_node(name, fn)
@@ -200,6 +216,7 @@ def dispatch(state: AgentState) -> str:
200
  "ocr": "ocr_tool",
201
  "audio": "audio_tool",
202
  "excel": "excel_tool",
 
203
  "final": "final_node",
204
  }.get(state.next_action, "final_node")
205
 
@@ -211,12 +228,13 @@ graph.add_conditional_edges(
211
  "ocr_tool": "ocr_tool",
212
  "audio_tool": "audio_tool",
213
  "excel_tool": "excel_tool",
 
214
  "final_node": "final_node",
215
  },
216
  )
217
 
218
  # tools loop back to selector
219
- for tool_name in ("wiki_tool", "ocr_tool", "audio_tool", "excel_tool"):
220
  graph.add_edge(tool_name, "tool_selector")
221
 
222
  # final_answer β†’ END
 
25
  wikipedia_search_tool,
26
  ocr_image_tool,
27
  audio_transcriber_tool,
28
+ parse_excel_tool,
29
+ analyze_code_tool
30
  )
31
 
32
  # ─────────────────────────── Configuration ───────────────────────────────
33
+ LLM = ChatOpenAI(model_name="gpt-4.1-mini", temperature=0.3)
34
  MAX_TOOL_CALLS = 5
35
 
36
  # ─────────────────────────── Helper utilities ────────────────────────────
 
93
 
94
  prompt = SystemMessage(
95
  content=(
96
+ "if the tool you want isnt listed below, return {'action':'final'} \n"
97
+ "Use wiki if you need to search online for information. Keep the query short and concise and accurate. The query should not be a prompt but instad you should search for the relevant information rather than asking for the answer directly.\n"
98
+ "If the question is about any image, you have to use ocr tool. It will tell you about the image also\n"
99
+ "Use audio if the question is about an audio file\n"
100
+ "Use excel if the question is about an excel file\n"
101
+ "Use code if the question is about a code file, or if you want to run your own code\n"
102
  "Reply with ONE JSON only (no markdown). Choices:\n"
103
  " {'action':'wiki','query':'…'}\n"
104
  " {'action':'ocr'}\n"
105
  " {'action':'audio'}\n"
106
  " {'action':'excel'}\n"
107
+ " {'action':'code', 'snippet':'<python code>'}\n"
108
+ " {'action':'code', 'file':'<name>.py'}\n"
109
  " {'action':'final'}\n"
110
+
 
 
 
 
111
 
112
  )
113
  )
114
+ raw = LLM.invoke(state.messages + [prompt]).content.strip()
115
  print(f"Tool selector response: {raw}")
116
  state.add(AIMessage(content=raw))
117
  parsed = safe_json(raw)
 
162
  state.next_action = None
163
  return state
164
 
165
+ def code_tool(state: AgentState) -> AgentState:
166
+ out = {"analysis": analyze_code_tool({
167
+ "task_id": state.task_id,
168
+ "snippet": state.snippet,
169
+ "file": state.file
170
+ })}
171
+ state.tool_calls += 1
172
+ state.add(SystemMessage(content=f"CODE_TOOL_OUT: {brief(out)}"))
173
+ state.next_action = None
174
+ return state
175
 
176
  # ------------- final answer -------------
177
 
 
182
  "reply **only** with "
183
  "{\"final_answer\":\"…\"} (no markdown, no commentary)."
184
  )
185
+ raw = LLM.invoke(state.messages + [wrap]).content.strip()
186
  # print("raw : ", raw)
187
  state.add(AIMessage(content=raw))
188
  parsed = safe_json(raw)
 
202
  ("ocr_tool", ocr_tool),
203
  ("audio_tool", audio_tool),
204
  ("excel_tool", excel_tool),
205
+ ("code_tool", code_tool),
206
  ("final_node", final_node),
207
  ]:
208
  graph.add_node(name, fn)
 
216
  "ocr": "ocr_tool",
217
  "audio": "audio_tool",
218
  "excel": "excel_tool",
219
+ "code": "code_tool",
220
  "final": "final_node",
221
  }.get(state.next_action, "final_node")
222
 
 
228
  "ocr_tool": "ocr_tool",
229
  "audio_tool": "audio_tool",
230
  "excel_tool": "excel_tool",
231
+ "code_tool": "code_tool",
232
  "final_node": "final_node",
233
  },
234
  )
235
 
236
  # tools loop back to selector
237
+ for tool_name in ("wiki_tool", "ocr_tool", "audio_tool", "excel_tool", "code_tool"):
238
  graph.add_edge(tool_name, "tool_selector")
239
 
240
  # final_answer β†’ END
tools.py CHANGED
@@ -146,6 +146,7 @@ def parse_excel_tool(args: dict) -> str:
146
  xls,
147
  sheet_name=sheet if sheet and sheet in xls.sheet_names else xls.sheet_names[0]
148
  )
 
149
  return str(df.to_dict(orient="records"))
150
  except Exception as e:
151
  return f"Error reading Excel file: {e}"
@@ -263,7 +264,44 @@ def wikipedia_search_tool(args: dict) -> str:
263
  return f"Unexpected error in wikipedia_search_tool: {e}"
264
 
265
 
 
 
 
266
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
267
 
268
 
269
  # def web_search_tool(state: AgentState) -> AgentState:
 
146
  xls,
147
  sheet_name=sheet if sheet and sheet in xls.sheet_names else xls.sheet_names[0]
148
  )
149
+ print(f"Excel file read successfully: {str(df.to_dict(orient='records'))}")
150
  return str(df.to_dict(orient="records"))
151
  except Exception as e:
152
  return f"Error reading Excel file: {e}"
 
264
  return f"Unexpected error in wikipedia_search_tool: {e}"
265
 
266
 
267
+ from langchain_openai import ChatOpenAI
268
+ from langchain.schema import SystemMessage, HumanMessage
269
+ LLM = ChatOpenAI(model_name="gpt-4.1-mini", temperature=0.2)
270
 
271
+ def analyze_code_tool(args: dict) -> str:
272
+ """
273
+ Either args['snippet'] OR (args['file'] + args['task_id'])
274
+ Reads the code (max 400 lines / 10 kB) and asks the LLM for:
275
+ β€’ plain-language summary
276
+ β€’ list of key functions/classes
277
+ β€’ obvious bugs or style smells
278
+ Returns that analysis as a string.
279
+ """
280
+ code_txt = ""
281
+ if args.get("snippet"):
282
+ code_txt = args["snippet"]
283
+ elif args.get("file") and args.get("task_id"):
284
+ path = _download_file_for_task(args["task_id"], "py")
285
+ if not path:
286
+ return "Error: .py file not found for this task."
287
+ code_txt = Path(path).read_text(encoding="utf-8", errors="ignore")
288
+ else:
289
+ return "Error: neither snippet nor file provided."
290
+
291
+ # Truncate for safety
292
+ lines = code_txt.splitlines()[:400]
293
+ code_sample = "\n".join(lines)[:10_000]
294
+
295
+ prompt = [
296
+ SystemMessage(content="You are a senior Python code reviewer."),
297
+ HumanMessage(content=(
298
+ "Please analyse the following code. "
299
+ "Summarise what it does, list key functions/classes, "
300
+ "and point out any obvious bugs, performance issues or style problems.\n\n"
301
+ f"```python\n{code_sample}\n```"
302
+ ))
303
+ ]
304
+ return LLM.invoke(prompt).content.strip()
305
 
306
 
307
  # def web_search_tool(state: AgentState) -> AgentState: