Update agent.py
Browse files
agent.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
| 1 |
import os
|
| 2 |
import re
|
| 3 |
from groq import Groq
|
| 4 |
-
from
|
| 5 |
from bs4 import BeautifulSoup
|
| 6 |
import requests
|
| 7 |
from utils import BaseAgent, SimpleRateLimiter
|
|
@@ -11,21 +11,28 @@ class GaiaAgent(BaseAgent):
|
|
| 11 |
|
| 12 |
def __init__(self):
|
| 13 |
self.client = Groq(api_key=os.environ.get("GROQ_API_KEY"))
|
| 14 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
self.rate_limiter = SimpleRateLimiter()
|
|
|
|
| 16 |
|
| 17 |
def web_search(self, query, max_results=3):
|
| 18 |
-
"""Search the web using DuckDuckGo"""
|
| 19 |
print(f"[web_search] query: {query[:80]}...")
|
| 20 |
results = []
|
| 21 |
try:
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
except Exception as e:
|
| 30 |
print(f"[web_search] error: {e}")
|
| 31 |
return results
|
|
@@ -104,7 +111,7 @@ IMPORTANT: Your response MUST end with a line starting with "FINAL ANSWER:" foll
|
|
| 104 |
- For numbers, use exact format requested
|
| 105 |
- For names, use exact spelling
|
| 106 |
|
| 107 |
-
|
| 108 |
{question}
|
| 109 |
|
| 110 |
Context:
|
|
@@ -114,34 +121,52 @@ Remember to end with:
|
|
| 114 |
FINAL ANSWER: <answer>
|
| 115 |
"""
|
| 116 |
|
| 117 |
-
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
|
| 127 |
-
|
| 128 |
-
|
| 129 |
-
|
| 130 |
-
|
| 131 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 132 |
|
| 133 |
-
# Retry without context if empty
|
| 134 |
if not answer or len(answer) == 0:
|
| 135 |
-
print(f"[agent] retrying
|
| 136 |
self.rate_limiter.wait_if_needed()
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
|
| 142 |
-
|
| 143 |
-
|
| 144 |
-
|
|
|
|
|
|
|
|
|
|
| 145 |
|
| 146 |
if not answer:
|
| 147 |
answer = "I am unable to answer"
|
|
@@ -151,4 +176,4 @@ FINAL ANSWER: <answer>
|
|
| 151 |
return answer
|
| 152 |
|
| 153 |
def __call__(self, question: str, file_content: str = "") -> str:
|
| 154 |
-
return self.run(question, file_content)
|
|
|
|
| 1 |
import os
|
| 2 |
import re
|
| 3 |
from groq import Groq
|
| 4 |
+
from ddgs import DDGS
|
| 5 |
from bs4 import BeautifulSoup
|
| 6 |
import requests
|
| 7 |
from utils import BaseAgent, SimpleRateLimiter
|
|
|
|
| 11 |
|
| 12 |
def __init__(self):
|
| 13 |
self.client = Groq(api_key=os.environ.get("GROQ_API_KEY"))
|
| 14 |
+
# Modèles Groq valides (en ordre de préférence)
|
| 15 |
+
self.models = [
|
| 16 |
+
"openai/gpt-oss-120b", # ← en priorité
|
| 17 |
+
"qwen/qwen3.6-27b", # fallback 1
|
| 18 |
+
"llama-3.3-70b-versatile", # fallback 2
|
| 19 |
+
"llama-3.1-8b-instant" # fallback 3
|
| 20 |
+
]
|
| 21 |
self.rate_limiter = SimpleRateLimiter()
|
| 22 |
+
self.current_model = self.models[0]
|
| 23 |
|
| 24 |
def web_search(self, query, max_results=3):
|
| 25 |
+
"""Search the web using DDGS (DuckDuckGo)"""
|
| 26 |
print(f"[web_search] query: {query[:80]}...")
|
| 27 |
results = []
|
| 28 |
try:
|
| 29 |
+
ddgs = DDGS()
|
| 30 |
+
for r in ddgs.text(query, max_results=max_results):
|
| 31 |
+
results.append({
|
| 32 |
+
"title": r.get("title"),
|
| 33 |
+
"url": r.get("href"),
|
| 34 |
+
"snippet": r.get("body")
|
| 35 |
+
})
|
| 36 |
except Exception as e:
|
| 37 |
print(f"[web_search] error: {e}")
|
| 38 |
return results
|
|
|
|
| 111 |
- For numbers, use exact format requested
|
| 112 |
- For names, use exact spelling
|
| 113 |
|
| 114 |
+
Question:
|
| 115 |
{question}
|
| 116 |
|
| 117 |
Context:
|
|
|
|
| 121 |
FINAL ANSWER: <answer>
|
| 122 |
"""
|
| 123 |
|
| 124 |
+
# Try models in order with fallback
|
| 125 |
+
answer = ""
|
| 126 |
+
for model in self.models:
|
| 127 |
+
self.current_model = model
|
| 128 |
+
print(f"[agent] trying model: {model}...")
|
| 129 |
+
try:
|
| 130 |
+
response = self.client.chat.completions.create(
|
| 131 |
+
model=model,
|
| 132 |
+
messages=[{"role": "user", "content": prompt}],
|
| 133 |
+
temperature=0,
|
| 134 |
+
max_tokens=1000
|
| 135 |
+
)
|
| 136 |
+
output = response.choices[0].message.content
|
| 137 |
+
print(f"[agent] ✓ got response ({len(output)} chars)")
|
| 138 |
+
answer = self.extract_answer(output)
|
| 139 |
+
|
| 140 |
+
if answer and len(answer) > 0:
|
| 141 |
+
print(f"[agent] ✓ got answer from {model}")
|
| 142 |
+
break
|
| 143 |
+
else:
|
| 144 |
+
print(f"[agent] ✗ model {model} returned empty answer, trying next...")
|
| 145 |
+
|
| 146 |
+
except Exception as e:
|
| 147 |
+
error_msg = str(e)
|
| 148 |
+
if "does not exist" in error_msg or "not found" in error_msg:
|
| 149 |
+
print(f"[agent] ✗ model {model} not found, trying next...")
|
| 150 |
+
elif "overload" in error_msg.lower() or "rate limit" in error_msg.lower():
|
| 151 |
+
print(f"[agent] ✗ rate limit on {model}, trying next...")
|
| 152 |
+
else:
|
| 153 |
+
print(f"[agent] ✗ error with {model}: {e}")
|
| 154 |
+
continue
|
| 155 |
|
|
|
|
| 156 |
if not answer or len(answer) == 0:
|
| 157 |
+
print(f"[agent] retrying with shorter prompt...")
|
| 158 |
self.rate_limiter.wait_if_needed()
|
| 159 |
+
try:
|
| 160 |
+
response = self.client.chat.completions.create(
|
| 161 |
+
model=self.models[0],
|
| 162 |
+
messages=[{"role": "user", "content": f"Answer briefly:\n{question}\n\nFINAL ANSWER:"}],
|
| 163 |
+
temperature=0,
|
| 164 |
+
max_tokens=200
|
| 165 |
+
)
|
| 166 |
+
output = response.choices[0].message.content
|
| 167 |
+
answer = self.extract_answer(output)
|
| 168 |
+
except Exception as e:
|
| 169 |
+
print(f"[agent] retry error: {e}")
|
| 170 |
|
| 171 |
if not answer:
|
| 172 |
answer = "I am unable to answer"
|
|
|
|
| 176 |
return answer
|
| 177 |
|
| 178 |
def __call__(self, question: str, file_content: str = "") -> str:
|
| 179 |
+
return self.run(question, file_content)
|