Spaces:
Running
Running
Priyanshi Saxena
commited on
Commit
Β·
2fe0e75
1
Parent(s):
6bf47a1
new
Browse files- app.py +1 -1
- src/agent/research_agent.py +96 -64
- 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.
|
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-
|
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 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
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 |
-
|
277 |
-
|
278 |
-
|
279 |
-
chart_type = "
|
280 |
-
|
281 |
-
chart_type = "gas_tracker"
|
282 |
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
288 |
|
289 |
-
result
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
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 |
-
|
420 |
-
|
421 |
-
|
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 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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-
|
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 |
-
|
54 |
-
"""
|
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 |
-
|
|
|
|
|
|
|
63 |
elif chart_type == "market_overview":
|
64 |
-
|
65 |
elif chart_type == "defi_tvl":
|
66 |
-
|
67 |
elif chart_type == "portfolio_pie":
|
68 |
-
|
69 |
elif chart_type == "gas_tracker":
|
70 |
-
|
71 |
else:
|
72 |
-
|
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
|
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:
|