Priyanshi Saxena commited on
Commit
2fe0e75
Β·
1 Parent(s): 6bf47a1
Files changed (3) hide show
  1. app.py +1 -1
  2. src/agent/research_agent.py +96 -64
  3. src/tools/chart_data_tool.py +19 -14
app.py CHANGED
@@ -513,7 +513,7 @@ async def process_query_stream(request: QueryRequest):
513
  await asyncio.sleep(0.5)
514
 
515
  # Send final result
516
- yield f"data: {json.dumps({'type': 'result', 'data': result.dict(), 'progress': 100})}\n\n"
517
 
518
  except asyncio.TimeoutError:
519
  processing_time = (datetime.now() - start_time).total_seconds()
 
513
  await asyncio.sleep(0.5)
514
 
515
  # Send final result
516
+ yield f"data: {json.dumps({'type': 'result', 'data': result.model_dump(), 'progress': 100})}\n\n"
517
 
518
  except asyncio.TimeoutError:
519
  processing_time = (datetime.now() - start_time).total_seconds()
src/agent/research_agent.py CHANGED
@@ -58,12 +58,12 @@ class Web3ResearchAgent:
58
  """Initialize Gemini LLM"""
59
  try:
60
  self.llm = ChatGoogleGenerativeAI(
61
- model="gemini-pro",
62
  google_api_key=config.GEMINI_API_KEY,
63
  temperature=0.1
64
  )
65
  self.gemini_available = True
66
- logger.info("βœ… Gemini initialized")
67
  except Exception as e:
68
  logger.warning(f"Gemini initialization failed: {e}")
69
  self.gemini_available = False
@@ -261,41 +261,57 @@ Just list the tool names:"""
261
 
262
  # Step 2: Execute relevant tools
263
  tool_results = []
264
- for tool_name in suggested_tools:
265
- tool = next((t for t in self.tools if t.name == tool_name), None)
266
- if tool:
267
- try:
268
- logger.info(f"πŸ”§ Executing {tool_name}")
269
-
270
- # Handle chart_data_provider with proper parameters
271
- if tool_name == "chart_data_provider":
272
- # Extract chart type from query or default to price_chart
273
- chart_type = "price_chart" # Default
274
- symbol = "bitcoin" # Default
275
 
276
- if "defi" in query.lower() or "tvl" in query.lower():
277
- chart_type = "defi_tvl"
278
- elif "market" in query.lower() or "overview" in query.lower():
279
- chart_type = "market_overview"
280
- elif "gas" in query.lower():
281
- chart_type = "gas_tracker"
282
 
283
- # Extract symbol if mentioned
284
- if "ethereum" in query.lower() or "eth" in query.lower():
285
- symbol = "ethereum"
286
- elif "bitcoin" in query.lower() or "btc" in query.lower():
287
- symbol = "bitcoin"
 
 
 
 
 
 
 
 
 
 
 
 
288
 
289
- result = await tool._arun(chart_type=chart_type, symbol=symbol)
290
- else:
291
- # Other tools use the query directly
292
- result = await tool._arun(query)
293
-
294
- logger.info(f"πŸ“Š {tool_name} result preview: {str(result)[:200]}...")
295
- tool_results.append(f"=== {tool_name} Results ===\n{result}\n")
296
- except Exception as e:
297
- logger.error(f"Tool {tool_name} failed: {e}")
298
- tool_results.append(f"=== {tool_name} Error ===\nTool failed: {str(e)}\n")
 
 
 
 
 
 
 
 
 
 
299
 
300
  # Step 3: Generate final response with tool results using AI Safety
301
  context = "\n".join(tool_results) if tool_results else "No tool data available - provide general information."
@@ -405,38 +421,54 @@ Respond with only the tool names, comma-separated (no explanations)."""
405
 
406
  # Step 2: Execute tools (same logic as Ollama version)
407
  tool_results = []
408
- for tool_name in suggested_tools:
409
- tool = next((t for t in self.tools if t.name == tool_name), None)
410
- if tool:
411
- try:
412
- logger.info(f"πŸ”§ Executing {tool_name}")
413
-
414
- # Handle chart_data_provider with proper parameters
415
- if tool_name == "chart_data_provider":
416
- chart_type = "price_chart"
417
- symbol = "bitcoin"
418
 
419
- if "defi" in query.lower() or "tvl" in query.lower():
420
- chart_type = "defi_tvl"
421
- elif "market" in query.lower() or "overview" in query.lower():
422
- chart_type = "market_overview"
423
- elif "gas" in query.lower():
424
- chart_type = "gas_tracker"
425
-
426
- if "ethereum" in query.lower() or "eth" in query.lower():
427
- symbol = "ethereum"
428
- elif "bitcoin" in query.lower() or "btc" in query.lower():
429
  symbol = "bitcoin"
430
 
431
- result = await tool._arun(chart_type=chart_type, symbol=symbol)
432
- else:
433
- result = await tool._arun(query)
434
-
435
- logger.info(f"πŸ“Š {tool_name} result preview: {str(result)[:200]}...")
436
- tool_results.append(f"=== {tool_name} Results ===\n{result}\n")
437
- except Exception as e:
438
- logger.error(f"Tool {tool_name} failed: {e}")
439
- tool_results.append(f"=== {tool_name} Error ===\nTool failed: {str(e)}\n")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
440
 
441
  # Step 3: Generate final response with Gemini
442
  context = "\n".join(tool_results) if tool_results else "No tool data available - provide general information."
@@ -474,7 +506,7 @@ Respond with only the tool names, comma-separated (no explanations)."""
474
  "result": final_response,
475
  "sources": [],
476
  "metadata": {
477
- "llm_used": f"Gemini ({self.llm.model_name if hasattr(self.llm, 'model_name') else 'gemini-pro'})",
478
  "tools_used": suggested_tools,
479
  "timestamp": datetime.now().isoformat()
480
  }
 
58
  """Initialize Gemini LLM"""
59
  try:
60
  self.llm = ChatGoogleGenerativeAI(
61
+ model="gemini-2.0-flash-lite", # Updated to Gemini 2.0 Flash-Lite
62
  google_api_key=config.GEMINI_API_KEY,
63
  temperature=0.1
64
  )
65
  self.gemini_available = True
66
+ logger.info("βœ… Gemini initialized with gemini-2.0-flash-lite")
67
  except Exception as e:
68
  logger.warning(f"Gemini initialization failed: {e}")
69
  self.gemini_available = False
 
261
 
262
  # Step 2: Execute relevant tools
263
  tool_results = []
264
+ try:
265
+ for tool_name in suggested_tools:
266
+ tool = next((t for t in self.tools if t.name == tool_name), None)
267
+ if tool:
268
+ try:
269
+ logger.info(f"πŸ”§ Executing {tool_name}")
 
 
 
 
 
270
 
271
+ # Handle chart_data_provider with proper parameters
272
+ if tool_name == "chart_data_provider":
273
+ # Extract chart type from query or default to price_chart
274
+ chart_type = "price_chart" # Default
275
+ symbol = "bitcoin" # Default
 
276
 
277
+ if "defi" in query.lower() or "tvl" in query.lower():
278
+ chart_type = "defi_tvl"
279
+ elif "market" in query.lower() or "overview" in query.lower():
280
+ chart_type = "market_overview"
281
+ elif "gas" in query.lower():
282
+ chart_type = "gas_tracker"
283
+
284
+ # Extract symbol if mentioned
285
+ if "ethereum" in query.lower() or "eth" in query.lower():
286
+ symbol = "ethereum"
287
+ elif "bitcoin" in query.lower() or "btc" in query.lower():
288
+ symbol = "bitcoin"
289
+
290
+ result = await tool._arun(chart_type=chart_type, symbol=symbol)
291
+ else:
292
+ # Other tools use the query directly
293
+ result = await tool._arun(query)
294
 
295
+ logger.info(f"πŸ“Š {tool_name} result preview: {str(result)[:200]}...")
296
+ tool_results.append(f"=== {tool_name} Results ===\n{result}\n")
297
+ except Exception as e:
298
+ logger.error(f"Tool {tool_name} failed: {e}")
299
+ tool_results.append(f"=== {tool_name} Error ===\nTool failed: {str(e)}\n")
300
+ finally:
301
+ # Cleanup tool session if available
302
+ if hasattr(tool, 'cleanup'):
303
+ try:
304
+ await tool.cleanup()
305
+ except Exception:
306
+ pass # Ignore cleanup errors
307
+ finally:
308
+ # Ensure all tools are cleaned up
309
+ for tool in self.tools:
310
+ if hasattr(tool, 'cleanup'):
311
+ try:
312
+ await tool.cleanup()
313
+ except Exception:
314
+ pass
315
 
316
  # Step 3: Generate final response with tool results using AI Safety
317
  context = "\n".join(tool_results) if tool_results else "No tool data available - provide general information."
 
421
 
422
  # Step 2: Execute tools (same logic as Ollama version)
423
  tool_results = []
424
+ try:
425
+ for tool_name in suggested_tools:
426
+ tool = next((t for t in self.tools if t.name == tool_name), None)
427
+ if tool:
428
+ try:
429
+ logger.info(f"πŸ”§ Executing {tool_name}")
 
 
 
 
430
 
431
+ # Handle chart_data_provider with proper parameters
432
+ if tool_name == "chart_data_provider":
433
+ chart_type = "price_chart"
 
 
 
 
 
 
 
434
  symbol = "bitcoin"
435
 
436
+ if "defi" in query.lower() or "tvl" in query.lower():
437
+ chart_type = "defi_tvl"
438
+ elif "market" in query.lower() or "overview" in query.lower():
439
+ chart_type = "market_overview"
440
+ elif "gas" in query.lower():
441
+ chart_type = "gas_tracker"
442
+
443
+ if "ethereum" in query.lower() or "eth" in query.lower():
444
+ symbol = "ethereum"
445
+ elif "bitcoin" in query.lower() or "btc" in query.lower():
446
+ symbol = "bitcoin"
447
+
448
+ result = await tool._arun(chart_type=chart_type, symbol=symbol)
449
+ else:
450
+ result = await tool._arun(query)
451
+
452
+ logger.info(f"πŸ“Š {tool_name} result preview: {str(result)[:200]}...")
453
+ tool_results.append(f"=== {tool_name} Results ===\n{result}\n")
454
+ except Exception as e:
455
+ logger.error(f"Tool {tool_name} failed: {e}")
456
+ tool_results.append(f"=== {tool_name} Error ===\nTool failed: {str(e)}\n")
457
+ finally:
458
+ # Cleanup tool session if available
459
+ if hasattr(tool, 'cleanup'):
460
+ try:
461
+ await tool.cleanup()
462
+ except Exception:
463
+ pass # Ignore cleanup errors
464
+ finally:
465
+ # Ensure all tools are cleaned up
466
+ for tool in self.tools:
467
+ if hasattr(tool, 'cleanup'):
468
+ try:
469
+ await tool.cleanup()
470
+ except Exception:
471
+ pass
472
 
473
  # Step 3: Generate final response with Gemini
474
  context = "\n".join(tool_results) if tool_results else "No tool data available - provide general information."
 
506
  "result": final_response,
507
  "sources": [],
508
  "metadata": {
509
+ "llm_used": f"Gemini ({self.llm.model_name if hasattr(self.llm, 'model_name') else 'gemini-1.5-flash'})",
510
  "tools_used": suggested_tools,
511
  "timestamp": datetime.now().isoformat()
512
  }
src/tools/chart_data_tool.py CHANGED
@@ -50,39 +50,44 @@ class ChartDataTool(BaseTool):
50
  return asyncio.run(self._arun(chart_type, symbol, timeframe, protocols, network))
51
 
52
  async def _arun(self, chart_type: str, symbol: str = None, timeframe: str = "30d",
53
- protocols: List[str] = None, network: str = "ethereum") -> str:
54
- """Provide chart data based on request"""
55
  try:
56
  logger.info(f"Providing {chart_type} data for {symbol or 'general'}")
57
 
58
- # Convert timeframe to days
59
- days = self._parse_timeframe(timeframe)
60
-
61
  if chart_type == "price_chart":
62
- return await self._get_price_chart_data(symbol or "bitcoin", days)
 
 
 
63
  elif chart_type == "market_overview":
64
- return await self._get_market_overview_data()
65
  elif chart_type == "defi_tvl":
66
- return await self._get_defi_tvl_data(protocols or ["uniswap", "aave", "compound"])
67
  elif chart_type == "portfolio_pie":
68
- return await self._get_portfolio_data()
69
  elif chart_type == "gas_tracker":
70
- return await self._get_gas_data(network)
71
  else:
72
- return json.dumps({
73
  "chart_type": "error",
74
  "error": f"Unknown chart type: {chart_type}",
75
  "available_types": ["price_chart", "market_overview", "defi_tvl", "portfolio_pie", "gas_tracker"]
76
  })
77
-
 
 
78
  except Exception as e:
79
- logger.error(f"Chart data error: {e}")
80
  return json.dumps({
81
  "chart_type": "error",
82
  "error": str(e),
83
  "message": "Failed to generate chart data"
84
  })
85
-
 
 
 
86
  async def _get_price_chart_data(self, symbol: str, days: int) -> str:
87
  """Get price chart data with fallback for API failures"""
88
  try:
 
50
  return asyncio.run(self._arun(chart_type, symbol, timeframe, protocols, network))
51
 
52
  async def _arun(self, chart_type: str, symbol: str = None, timeframe: str = "30d",
53
+ protocols: List[str] = None, network: str = "ethereum") -> str:
54
+ """Asynchronous execution with proper session cleanup"""
55
  try:
56
  logger.info(f"Providing {chart_type} data for {symbol or 'general'}")
57
 
 
 
 
58
  if chart_type == "price_chart":
59
+ if not symbol:
60
+ symbol = "bitcoin" # Default symbol
61
+ days = {"1d": 1, "7d": 7, "30d": 30, "90d": 90, "365d": 365}.get(timeframe, 30)
62
+ result = await self._get_price_chart_data(symbol, days)
63
  elif chart_type == "market_overview":
64
+ result = await self._get_market_overview_data()
65
  elif chart_type == "defi_tvl":
66
+ result = await self._get_defi_tvl_data(protocols)
67
  elif chart_type == "portfolio_pie":
68
+ result = await self._get_portfolio_data()
69
  elif chart_type == "gas_tracker":
70
+ result = await self._get_gas_tracker_data(network)
71
  else:
72
+ result = json.dumps({
73
  "chart_type": "error",
74
  "error": f"Unknown chart type: {chart_type}",
75
  "available_types": ["price_chart", "market_overview", "defi_tvl", "portfolio_pie", "gas_tracker"]
76
  })
77
+
78
+ return result
79
+
80
  except Exception as e:
81
+ logger.error(f"Chart data generation failed: {e}")
82
  return json.dumps({
83
  "chart_type": "error",
84
  "error": str(e),
85
  "message": "Failed to generate chart data"
86
  })
87
+ finally:
88
+ # Ensure session cleanup
89
+ await self.cleanup()
90
+
91
  async def _get_price_chart_data(self, symbol: str, days: int) -> str:
92
  """Get price chart data with fallback for API failures"""
93
  try: