Spaces:
Running
Running
Priyanshi Saxena
commited on
Commit
Β·
a4b05e9
1
Parent(s):
faf01ab
fix: Clean LLM responses and fix variable scope errors
Browse files- Fixed Gemini response cleaning to extract content properly from LangChain objects
- Fixed Ollama response cleaning to handle string conversion
- Fixed variable scope error in timeout handler (btc_data -> summary_data)
- Fixed DeFi TVL sorting error by filtering out None values
- Enhanced error handling in fallback response mechanism
- Improved response content extraction for both LLMs
- src/agent/research_agent.py +22 -8
- src/tools/chart_data_tool.py +3 -3
- test_tool_selection.py +0 -69
src/agent/research_agent.py
CHANGED
@@ -202,6 +202,7 @@ class Web3ResearchAgent:
|
|
202 |
"metadata": {"llm": "ollama", "mode": "simple", "timestamp": datetime.now().isoformat()}
|
203 |
}
|
204 |
except Exception as fallback_error:
|
|
|
205 |
return {
|
206 |
"success": False,
|
207 |
"query": query,
|
@@ -333,8 +334,11 @@ Just list the tool names:"""
|
|
333 |
)
|
334 |
logger.info(f"π― Ollama final response preview: {str(final_response)[:300]}...")
|
335 |
|
|
|
|
|
|
|
336 |
# AI Safety Check: Validate response
|
337 |
-
clean_response, response_safe, response_reason = ai_safety.validate_ollama_response(
|
338 |
if not response_safe:
|
339 |
ai_safety.log_safety_event("blocked_ollama_response", {
|
340 |
"reason": response_reason,
|
@@ -355,16 +359,20 @@ Based on the available data:
|
|
355 |
except asyncio.TimeoutError:
|
356 |
logger.warning("β±οΈ Ollama final response timed out, using tool data directly")
|
357 |
# Create a summary from the tool results directly
|
358 |
-
|
359 |
-
|
|
|
|
|
|
|
|
|
360 |
elif "defillama_data" in suggested_tools:
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
|
365 |
final_response = f"""## {query.split()[0]} Analysis
|
366 |
|
367 |
-
**Quick Summary**: {
|
368 |
|
369 |
The system successfully gathered data from {len(suggested_tools)} tools:
|
370 |
{', '.join(suggested_tools)}
|
@@ -502,8 +510,14 @@ Respond with only the tool names, comma-separated (no explanations)."""
|
|
502 |
)
|
503 |
logger.info(f"π― Gemini final response preview: {str(final_response)[:300]}...")
|
504 |
|
|
|
|
|
|
|
|
|
|
|
|
|
505 |
# AI Safety Check: Validate response
|
506 |
-
clean_response, response_safe, response_reason = ai_safety.validate_gemini_response(
|
507 |
if not response_safe:
|
508 |
ai_safety.log_safety_event("blocked_gemini_response", {
|
509 |
"reason": response_reason,
|
|
|
202 |
"metadata": {"llm": "ollama", "mode": "simple", "timestamp": datetime.now().isoformat()}
|
203 |
}
|
204 |
except Exception as fallback_error:
|
205 |
+
logger.error(f"Fallback response failed: {fallback_error}")
|
206 |
return {
|
207 |
"success": False,
|
208 |
"query": query,
|
|
|
334 |
)
|
335 |
logger.info(f"π― Ollama final response preview: {str(final_response)[:300]}...")
|
336 |
|
337 |
+
# Extract content from Ollama response
|
338 |
+
response_content = str(final_response)
|
339 |
+
|
340 |
# AI Safety Check: Validate response
|
341 |
+
clean_response, response_safe, response_reason = ai_safety.validate_ollama_response(response_content)
|
342 |
if not response_safe:
|
343 |
ai_safety.log_safety_event("blocked_ollama_response", {
|
344 |
"reason": response_reason,
|
|
|
359 |
except asyncio.TimeoutError:
|
360 |
logger.warning("β±οΈ Ollama final response timed out, using tool data directly")
|
361 |
# Create a summary from the tool results directly
|
362 |
+
summary_data = "Tool data available"
|
363 |
+
if "cryptocompare_data" in suggested_tools:
|
364 |
+
if "bitcoin" in query.lower() or "btc" in query.lower():
|
365 |
+
summary_data = "Bitcoin price data retrieved"
|
366 |
+
else:
|
367 |
+
summary_data = "Cryptocurrency price data retrieved"
|
368 |
elif "defillama_data" in suggested_tools:
|
369 |
+
summary_data = "DeFi protocols data available"
|
370 |
+
elif "etherscan_data" in suggested_tools:
|
371 |
+
summary_data = "Ethereum blockchain data available"
|
372 |
|
373 |
final_response = f"""## {query.split()[0]} Analysis
|
374 |
|
375 |
+
**Quick Summary**: {summary_data}
|
376 |
|
377 |
The system successfully gathered data from {len(suggested_tools)} tools:
|
378 |
{', '.join(suggested_tools)}
|
|
|
510 |
)
|
511 |
logger.info(f"π― Gemini final response preview: {str(final_response)[:300]}...")
|
512 |
|
513 |
+
# Extract content from Gemini response object
|
514 |
+
if hasattr(final_response, 'content'):
|
515 |
+
response_content = final_response.content
|
516 |
+
else:
|
517 |
+
response_content = str(final_response)
|
518 |
+
|
519 |
# AI Safety Check: Validate response
|
520 |
+
clean_response, response_safe, response_reason = ai_safety.validate_gemini_response(response_content)
|
521 |
if not response_safe:
|
522 |
ai_safety.log_safety_event("blocked_gemini_response", {
|
523 |
"reason": response_reason,
|
src/tools/chart_data_tool.py
CHANGED
@@ -271,9 +271,9 @@ class ChartDataTool(BaseTool):
|
|
271 |
break
|
272 |
protocols_data = filtered_protocols[:8] # Limit to 8
|
273 |
else:
|
274 |
-
# Get top protocols by TVL
|
275 |
-
|
276 |
-
|
277 |
|
278 |
if not protocols_data:
|
279 |
return await self._get_mock_defi_data(protocols)
|
|
|
271 |
break
|
272 |
protocols_data = filtered_protocols[:8] # Limit to 8
|
273 |
else:
|
274 |
+
# Get top protocols by TVL (filter out None values)
|
275 |
+
valid_protocols = [p for p in data if p.get("tvl") is not None and p.get("tvl", 0) > 0]
|
276 |
+
protocols_data = sorted(valid_protocols, key=lambda x: x.get("tvl", 0), reverse=True)[:8]
|
277 |
|
278 |
if not protocols_data:
|
279 |
return await self._get_mock_defi_data(protocols)
|
test_tool_selection.py
DELETED
@@ -1,69 +0,0 @@
|
|
1 |
-
#!/usr/bin/env python3
|
2 |
-
"""
|
3 |
-
Test the updated tool selection to ensure we use CryptoCompare/Etherscan instead of CoinGecko
|
4 |
-
"""
|
5 |
-
|
6 |
-
import asyncio
|
7 |
-
import sys
|
8 |
-
import os
|
9 |
-
|
10 |
-
# Add src to path
|
11 |
-
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src'))
|
12 |
-
|
13 |
-
from src.agent.research_agent import Web3ResearchAgent
|
14 |
-
|
15 |
-
async def test_tool_selection():
|
16 |
-
"""Test that the system prioritizes CryptoCompare and Etherscan over CoinGecko"""
|
17 |
-
print("π§ͺ Testing tool selection...")
|
18 |
-
|
19 |
-
agent = Web3ResearchAgent()
|
20 |
-
|
21 |
-
if not agent.enabled:
|
22 |
-
print("β Agent not enabled")
|
23 |
-
return False
|
24 |
-
|
25 |
-
# Check which tools are initialized
|
26 |
-
tool_names = [tool.name for tool in agent.tools]
|
27 |
-
print(f"π οΈ Available tools: {tool_names}")
|
28 |
-
|
29 |
-
# Verify CoinGecko is not in tools (since no API key)
|
30 |
-
if 'coingecko_data' in tool_names:
|
31 |
-
print("β οΈ CoinGecko tool is still initialized - this may cause API failures")
|
32 |
-
else:
|
33 |
-
print("β
CoinGecko tool properly skipped (no API key)")
|
34 |
-
|
35 |
-
# Verify we have the working tools
|
36 |
-
expected_tools = ['cryptocompare_data', 'etherscan_data', 'defillama_data', 'chart_data_provider']
|
37 |
-
working_tools = [tool for tool in expected_tools if tool in tool_names]
|
38 |
-
print(f"β
Working tools available: {working_tools}")
|
39 |
-
|
40 |
-
# Test a simple query
|
41 |
-
try:
|
42 |
-
print("\nπ Testing Bitcoin price query...")
|
43 |
-
result = await agent.research_query("Analyze Bitcoin price trends", use_gemini=True)
|
44 |
-
|
45 |
-
if result['success']:
|
46 |
-
print("β
Query successful!")
|
47 |
-
print(f"π Result preview: {result['result'][:200]}...")
|
48 |
-
print(f"π§ Tools used: {result.get('metadata', {}).get('tools_used', 'N/A')}")
|
49 |
-
return True
|
50 |
-
else:
|
51 |
-
print(f"β Query failed: {result.get('error', 'Unknown error')}")
|
52 |
-
return False
|
53 |
-
|
54 |
-
except Exception as e:
|
55 |
-
print(f"β Test failed with exception: {e}")
|
56 |
-
return False
|
57 |
-
|
58 |
-
async def main():
|
59 |
-
success = await test_tool_selection()
|
60 |
-
if success:
|
61 |
-
print("\nπ Tool selection test passed!")
|
62 |
-
return 0
|
63 |
-
else:
|
64 |
-
print("\nβ Tool selection test failed!")
|
65 |
-
return 1
|
66 |
-
|
67 |
-
if __name__ == "__main__":
|
68 |
-
exit_code = asyncio.run(main())
|
69 |
-
sys.exit(exit_code)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|