Coool2 commited on
Commit
5adab1e
·
verified ·
1 Parent(s): 7307bbf

Update agent.py

Browse files
Files changed (1) hide show
  1. agent.py +141 -115
agent.py CHANGED
@@ -9,7 +9,6 @@ from llama_index.core.query_engine import RetrieverQueryEngine
9
  from llama_index.readers.file import PDFReader, DocxReader, CSVReader, ImageReader
10
  import os
11
  from typing import List, Dict, Any
12
- from llama_index.readers.web import SimpleWebPageReader
13
  from llama_index.core.tools.ondemand_loader_tool import OnDemandLoaderTool
14
  from llama_index.tools.arxiv import ArxivToolSpec
15
  import duckduckgo_search as ddg
@@ -20,6 +19,7 @@ from llama_index.callbacks.wandb import WandbCallbackHandler
20
  from llama_index.core.callbacks.base import CallbackManager
21
  from llama_index.core.callbacks.llama_debug import LlamaDebugHandler
22
  from llama_index.core import Settings
 
23
 
24
  from transformers import AutoModelForCausalLM, AutoTokenizer
25
  from llama_index.llms.huggingface import HuggingFaceLLM
@@ -240,170 +240,197 @@ analysis_agent = FunctionAgent(
240
  )
241
 
242
 
 
 
 
243
  class IntelligentSourceRouter:
244
  def __init__(self):
245
- # Initialize tools - only ArXiv and web search
246
- self.arxiv_spec = ArxivToolSpec()
247
-
248
- # Add web content loader
249
- self.web_reader = SimpleWebPageReader()
250
-
251
- # Create OnDemandLoaderTool for web content
252
- self.web_loader_tool = OnDemandLoaderTool.from_defaults(
253
- self.web_reader,
254
- name="Web Content Loader",
255
- description="Load and analyze web page content with intelligent chunking and search"
256
- )
257
-
258
- def web_search_fallback(self, query: str, max_results: int = 5) -> str:
259
- try:
260
- results = ddg.DDGS().text(query, max_results=max_results)
261
- return "\n".join([f"{i}. **{r['title']}**\n URL: {r['href']}\n {r['body']}" for i, r in enumerate(results, 1)])
262
- except Exception as e:
263
- return f"Search failed: {str(e)}"
264
-
265
- def extract_web_content(self, urls: List[str], query: str) -> str:
266
- """Extract and analyze content from web URLs"""
267
- try:
268
- content_results = []
269
- for url in urls[:3]: # Limit to top 3 URLs
270
- try:
271
- result = self.web_loader_tool.call(
272
- urls=[url],
273
- query=f"Extract information relevant to: {query}"
274
- )
275
- content_results.append(f"**Content from {url}:**\n{result}")
276
- except Exception as e:
277
- content_results.append(f"**Failed to load {url}**: {str(e)}")
278
-
279
- return "\n\n".join(content_results)
280
- except Exception as e:
281
- return f"Content extraction failed: {str(e)}"
282
-
283
  def detect_intent_and_route(self, query: str) -> str:
284
- # Simple LLM-based discrimination: scientific vs non-scientific
285
  intent_prompt = f"""
286
  Analyze this query and determine if it's scientific research or general information:
287
  Query: "{query}"
288
-
289
  Choose ONE source:
290
  - arxiv: For scientific research, academic papers, technical studies, algorithms, experiments
291
  - web_search: For all other information (current events, general facts, weather, how-to guides, etc.)
292
-
293
  Respond with ONLY "arxiv" or "web_search".
294
  """
295
-
296
- response = proj_llm.complete(intent_prompt)
297
  selected_source = response.text.strip().lower()
298
-
299
- # Execute search and extract content
300
  results = [f"**Query**: {query}", f"**Selected Source**: {selected_source}", "="*50]
301
-
302
  try:
303
  if selected_source == 'arxiv':
304
- result = self.arxiv_spec.to_tool_list()[0].call(query=query, max_results=3)
305
  results.append(f"**ArXiv Research:**\n{result}")
306
-
307
- else: # Default to web_search for everything else
308
- # Get search results
309
- search_results = self.web_search_fallback(query, 5)
310
- results.append(f"**Web Search Results:**\n{search_results}")
311
-
312
- # Extract URLs and load content
313
- urls = re.findall(r'URL: (https?://[^\s]+)', search_results)
314
- if urls:
315
- web_content = self.extract_web_content(urls, query)
316
- results.append(f"**Extracted Web Content:**\n{web_content}")
317
-
318
  except Exception as e:
319
  results.append(f"**Search failed**: {str(e)}")
320
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
321
  return "\n\n".join(results)
322
 
323
  # Initialize router
324
  intelligent_router = IntelligentSourceRouter()
325
 
326
  # Create enhanced research tool
327
- def enhanced_smart_research_tool(query: str, task_context: str = "", max_results: int = 5) -> str:
328
  full_query = f"{query} {task_context}".strip()
329
- return intelligent_router.detect_intent_and_route(full_query)
330
 
331
  research_tool = FunctionTool.from_defaults(
332
  fn=enhanced_smart_research_tool,
333
- name="Enhanced Research Tool",
334
- description="Intelligent research tool that discriminates between scientific (ArXiv) and general (web) research with deep content extraction"
335
- )
336
-
337
- def execute_python_code(code: str) -> str:
338
- try:
339
- safe_globals = {
340
- "__builtins__": {
341
- "len": len, "str": str, "int": int, "float": float,
342
- "list": list, "dict": dict, "sum": sum, "max": max, "min": min,
343
- "round": round, "abs": abs, "sorted": sorted
344
- },
345
- "math": __import__("math"),
346
- "datetime": __import__("datetime"),
347
- "re": __import__("re")
348
- }
349
-
350
- exec_locals = {}
351
- exec(code, safe_globals, exec_locals)
352
-
353
- if 'result' in exec_locals:
354
- return str(exec_locals['result'])
355
- else:
356
- return "Code executed successfully"
357
-
358
- except Exception as e:
359
- return f"Code execution failed: {str(e)}"
360
-
361
- code_execution_tool = FunctionTool.from_defaults(
362
- fn=execute_python_code,
363
- name="Python Code Execution",
364
- description="Execute Python code safely for calculations and data processing"
365
  )
366
 
367
- # Code Agent as ReActAgent
368
- code_agent = ReActAgent(
369
  name="CodeAgent",
370
  description="Advanced calculations, data processing, and final answer synthesis using ReAct reasoning",
371
  system_prompt="""
372
  You are a coding and reasoning specialist using ReAct methodology.
373
-
374
  For each task:
375
  1. THINK: Analyze what needs to be calculated or processed
376
  2. ACT: Execute appropriate code or calculations
377
  3. OBSERVE: Review results and determine if more work is needed
378
  4. REPEAT: Continue until you have the final answer
379
-
380
  Always show your reasoning process clearly and provide exact answers as required by GAIA.
381
  """,
382
- llm=proj_llm,
383
- tools=[code_execution_tool],
384
- max_steps = 5
385
  )
386
 
387
- # Créer des outils à partir des agents
388
- def analysis_function(query: str, files=None):
389
- ctx = Context(analysis_agent)
390
- return analysis_agent.run(query, ctx=ctx)
391
-
392
-
393
- def code_function(query: str):
394
- ctx = Context(code_agent)
395
- return code_agent.run(query, ctx=ctx)
396
-
397
  analysis_tool = FunctionTool.from_defaults(
398
  fn=analysis_function,
399
  name="AnalysisAgent",
400
- description="Advanced multimodal analysis using enhanced RAG"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
401
  )
402
 
 
403
  code_tool = FunctionTool.from_defaults(
404
  fn=code_function,
405
  name="CodeAgent",
406
- description="Advanced calculations and data processing"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
407
  )
408
 
409
  class EnhancedGAIAAgent:
@@ -428,7 +455,6 @@ class EnhancedGAIAAgent:
428
  3. OBSERVE: Review results from specialist tools
429
  4. REPEAT: Continue until you have the final answer. If you give a final answer, FORMAT: Ensure answer is EXACT GAIA format (number only, word only, etc.)
430
 
431
-
432
  IMPORTANT: Use tools strategically - only when their specific expertise is needed.
433
  For simple questions, you can answer directly without using any tools.
434
 
 
9
  from llama_index.readers.file import PDFReader, DocxReader, CSVReader, ImageReader
10
  import os
11
  from typing import List, Dict, Any
 
12
  from llama_index.core.tools.ondemand_loader_tool import OnDemandLoaderTool
13
  from llama_index.tools.arxiv import ArxivToolSpec
14
  import duckduckgo_search as ddg
 
19
  from llama_index.core.callbacks.base import CallbackManager
20
  from llama_index.core.callbacks.llama_debug import LlamaDebugHandler
21
  from llama_index.core import Settings
22
+ from llama_index.core.agent.workflow import CodeActAgent
23
 
24
  from transformers import AutoModelForCausalLM, AutoTokenizer
25
  from llama_index.llms.huggingface import HuggingFaceLLM
 
240
  )
241
 
242
 
243
+ from llama_index.tools.arxiv import ArxivToolSpec
244
+ from llama_index.tools.duckduckgo import DuckDuckGoSearchToolSpec
245
+
246
  class IntelligentSourceRouter:
247
  def __init__(self):
248
+ # Initialize ArXiv and DuckDuckGo as LlamaIndex tools
249
+ self.arxiv_tool = ArxivToolSpec().to_tool_list()[0]
250
+ self.duckduckgo_tool = DuckDuckGoSearchToolSpec().to_tool_list()[0]
251
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
252
  def detect_intent_and_route(self, query: str) -> str:
253
+ # Use your LLM to decide between arxiv and web_search
254
  intent_prompt = f"""
255
  Analyze this query and determine if it's scientific research or general information:
256
  Query: "{query}"
 
257
  Choose ONE source:
258
  - arxiv: For scientific research, academic papers, technical studies, algorithms, experiments
259
  - web_search: For all other information (current events, general facts, weather, how-to guides, etc.)
 
260
  Respond with ONLY "arxiv" or "web_search".
261
  """
262
+ response = text_llm.complete(intent_prompt)
 
263
  selected_source = response.text.strip().lower()
264
+
 
265
  results = [f"**Query**: {query}", f"**Selected Source**: {selected_source}", "="*50]
 
266
  try:
267
  if selected_source == 'arxiv':
268
+ result = self.arxiv_tool.call(query=query, max_results=3)
269
  results.append(f"**ArXiv Research:**\n{result}")
270
+ else:
271
+ result = self.duckduckgo_tool.call(query=query, max_results=5)
272
+ # Format results if needed
273
+ if isinstance(result, list):
274
+ formatted = []
275
+ for i, r in enumerate(result, 1):
276
+ formatted.append(
277
+ f"{i}. **{r.get('title', '')}**\n URL: {r.get('href', '')}\n {r.get('body', '')}"
278
+ )
279
+ result = "\n".join(formatted)
280
+ results.append(f"**Web Search Results:**\n{result}")
 
281
  except Exception as e:
282
  results.append(f"**Search failed**: {str(e)}")
283
+ return "\n\n".join(results)
284
+
285
+ class IntelligentSourceRouter:
286
+ def __init__(self):
287
+ # Initialize Arxiv and DuckDuckGo tools
288
+ self.arxiv_tool = ArxivToolSpec().to_tool_list()[0]
289
+ self.duckduckgo_tool = DuckDuckGoSearchToolSpec().to_tool_list()[0]
290
+
291
+ def detect_intent_and_extract_content(self, query: str, max_results: int = 3) -> str:
292
+ # Use your LLM to decide between arxiv and web_search
293
+ intent_prompt = f"""
294
+ Analyze this query and determine if it's scientific research or general information:
295
+ Query: "{query}"
296
+ Choose ONE source:
297
+ - arxiv: For scientific research, academic papers, technical studies, algorithms, experiments
298
+ - web_search: For all other information (current events, general facts, weather, how-to guides, etc.)
299
+ Respond with ONLY "arxiv" or "web_search".
300
+ """
301
+ response = text_llm.complete(intent_prompt)
302
+ selected_source = response.text.strip().lower()
303
+
304
+ results = [f"**Query**: {query}", f"**Selected Source**: {selected_source}", "="*50]
305
+ try:
306
+ if selected_source == 'arxiv':
307
+ # Extract abstracts and paper summaries (deep content)
308
+ arxiv_results = self.arxiv_tool.call(query=query, max_results=max_results)
309
+ results.append(f"**Extracted ArXiv Content:**\n{arxiv_results}")
310
+ else:
311
+ # DuckDuckGo returns a list of dicts with 'href', 'title', 'body'
312
+ web_results = self.duckduckgo_tool.call(query=query, max_results=max_results)
313
+ if isinstance(web_results, list):
314
+ formatted = []
315
+ for i, r in enumerate(web_results, 1):
316
+ formatted.append(
317
+ f"{i}. **{r.get('title', '')}**\n URL: {r.get('href', '')}\n {r.get('body', '')}"
318
+ )
319
+ web_content = "\n".join(formatted)
320
+ else:
321
+ web_content = str(web_results)
322
+ results.append(f"**Extracted Web Content:**\n{web_content}")
323
+ except Exception as e:
324
+ results.append(f"**Extraction failed**: {str(e)}")
325
  return "\n\n".join(results)
326
 
327
  # Initialize router
328
  intelligent_router = IntelligentSourceRouter()
329
 
330
  # Create enhanced research tool
331
+ def enhanced_smart_research_tool(query: str, task_context: str = "", max_results: int = 3) -> str:
332
  full_query = f"{query} {task_context}".strip()
333
+ return intelligent_router.detect_intent_and_extract_content(full_query, max_results=max_results)
334
 
335
  research_tool = FunctionTool.from_defaults(
336
  fn=enhanced_smart_research_tool,
337
+ name="Research Tool",
338
+ description="""Intelligent research specialist that automatically routes between scientific and general sources. Use this tool when you need:
339
+
340
+ **Scientific Research (ArXiv):**
341
+ - Academic papers, research studies, technical algorithms
342
+ - Scientific experiments, theories, mathematical concepts
343
+ - Recent developments in AI, ML, physics, chemistry, etc.
344
+
345
+ **General Research (Web + Content Extraction):**
346
+ - Current events, news, real-time information
347
+ - Biographical information, company details, locations
348
+ - How-to guides, technical documentation
349
+ - Weather data, sports results, cultural information
350
+ - Product specifications, reviews, comparisons
351
+
352
+ **Automatic Features:**
353
+ - Intelligently selects between ArXiv and web search
354
+ - Extracts full content from web pages (not just snippets)
355
+ - Provides source attribution and detailed information
356
+
357
+ **When to use:** Questions requiring external knowledge not in your training data, current events, scientific research, or factual verification.
358
+
359
+ **Input format:** Provide the research query with any relevant context."""
 
 
 
 
 
 
 
 
 
360
  )
361
 
362
+ code_agent = CodeActAgent(
 
363
  name="CodeAgent",
364
  description="Advanced calculations, data processing, and final answer synthesis using ReAct reasoning",
365
  system_prompt="""
366
  You are a coding and reasoning specialist using ReAct methodology.
367
+
368
  For each task:
369
  1. THINK: Analyze what needs to be calculated or processed
370
  2. ACT: Execute appropriate code or calculations
371
  3. OBSERVE: Review results and determine if more work is needed
372
  4. REPEAT: Continue until you have the final answer
373
+
374
  Always show your reasoning process clearly and provide exact answers as required by GAIA.
375
  """,
376
+ llm=proj_llm, # Your language model instance
377
+ max_steps=5 # Optional: limit the number of reasoning steps
 
378
  )
379
 
 
 
 
 
 
 
 
 
 
 
380
  analysis_tool = FunctionTool.from_defaults(
381
  fn=analysis_function,
382
  name="AnalysisAgent",
383
+ description="""Advanced multimodal document analysis specialist. Use this tool when you need to:
384
+
385
+ **Document Processing:**
386
+ - Analyze PDF, Word, CSV, or image files provided with the question
387
+ - Extract specific information from tables, charts, or structured documents
388
+ - Cross-reference information across multiple documents
389
+ - Perform semantic search within document collections
390
+
391
+ **Content Analysis:**
392
+ - Summarize long documents or extract key facts
393
+ - Find specific data points, numbers, or text within files
394
+ - Analyze visual content in images (charts, graphs, diagrams)
395
+ - Compare information between different document sources
396
+
397
+ **When to use:** Questions involving file attachments, document analysis, data extraction from PDFs/images, or when you need to process structured/unstructured content.
398
+
399
+ **Input format:** Provide the query and mention any relevant files or context."""
400
  )
401
 
402
+
403
  code_tool = FunctionTool.from_defaults(
404
  fn=code_function,
405
  name="CodeAgent",
406
+ description="""Advanced computational specialist using ReAct reasoning. Use this tool when you need:
407
+
408
+ **Mathematical Calculations:**
409
+ - Complex arithmetic, algebra, statistics, probability
410
+ - Unit conversions, percentage calculations
411
+ - Financial calculations (interest, loans, investments)
412
+ - Scientific calculations (physics, chemistry formulas)
413
+
414
+ **Data Processing:**
415
+ - Parsing and analyzing numerical data
416
+ - String manipulation and text processing
417
+ - Date/time calculations and conversions
418
+ - List operations, sorting, filtering
419
+
420
+ **Logical Operations:**
421
+ - Step-by-step problem solving with code
422
+ - Verification of calculations or logic
423
+ - Pattern analysis and data validation
424
+ - Algorithm implementation for specific problems
425
+
426
+ **Programming Tasks:**
427
+ - Code generation for specific computational needs
428
+ - Data structure manipulation
429
+ - Regular expression operations
430
+
431
+ **When to use:** Questions requiring precise calculations, data manipulation, logical reasoning with code, or when you need to verify numerical results.
432
+
433
+ **Input format:** Describe the calculation or processing task clearly, including any specific requirements or constraints."""
434
  )
435
 
436
  class EnhancedGAIAAgent:
 
455
  3. OBSERVE: Review results from specialist tools
456
  4. REPEAT: Continue until you have the final answer. If you give a final answer, FORMAT: Ensure answer is EXACT GAIA format (number only, word only, etc.)
457
 
 
458
  IMPORTANT: Use tools strategically - only when their specific expertise is needed.
459
  For simple questions, you can answer directly without using any tools.
460