Update app.py
Browse files
app.py
CHANGED
|
@@ -8,10 +8,10 @@ from duckduckgo_search import DDGS
|
|
| 8 |
|
| 9 |
# --- Constants ---
|
| 10 |
DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
|
| 11 |
-
TIMEOUT_PER_QUESTION = 30
|
| 12 |
|
| 13 |
# ============================================
|
| 14 |
-
#
|
| 15 |
# ============================================
|
| 16 |
|
| 17 |
def get_groq_client():
|
|
@@ -24,64 +24,146 @@ def get_groq_client():
|
|
| 24 |
# TOOL FUNCTIONS
|
| 25 |
# ============================================
|
| 26 |
|
| 27 |
-
def web_search(query: str) -> str:
|
| 28 |
-
"""Search the web"""
|
| 29 |
try:
|
| 30 |
with DDGS() as ddgs:
|
| 31 |
-
results = list(ddgs.text(query, max_results=
|
| 32 |
if not results:
|
| 33 |
-
return "No results"
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
|
| 38 |
|
| 39 |
def wikipedia_search(topic: str) -> str:
|
| 40 |
-
"""Get Wikipedia
|
| 41 |
try:
|
| 42 |
url = "https://en.wikipedia.org/w/api.php"
|
|
|
|
| 43 |
params = {"action": "query", "list": "search", "srsearch": topic, "format": "json", "srlimit": 1}
|
| 44 |
-
data = requests.get(url, params=params, timeout=
|
| 45 |
|
| 46 |
if not data.get("query", {}).get("search"):
|
| 47 |
-
return "
|
| 48 |
|
| 49 |
title = data["query"]["search"][0]["title"]
|
| 50 |
-
|
| 51 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
|
| 53 |
for page in pages.values():
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
|
|
|
| 58 |
|
| 59 |
|
| 60 |
-
def get_task_file(task_id: str) ->
|
| 61 |
-
"""Get GAIA task file"""
|
| 62 |
try:
|
| 63 |
url = f"https://agents-course-unit4-scoring.hf.space/files/{task_id}"
|
| 64 |
-
response = requests.get(url, timeout=
|
| 65 |
|
| 66 |
if response.status_code == 404:
|
| 67 |
-
return ""
|
| 68 |
|
| 69 |
content_type = response.headers.get('content-type', '').lower()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 70 |
|
| 71 |
-
|
| 72 |
-
return response.text[:4000]
|
| 73 |
|
| 74 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 75 |
try:
|
| 76 |
from io import BytesIO
|
| 77 |
df = pd.read_excel(BytesIO(response.content))
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 81 |
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 85 |
|
| 86 |
|
| 87 |
# ============================================
|
|
@@ -94,57 +176,121 @@ class BasicAgent:
|
|
| 94 |
self.client = get_groq_client()
|
| 95 |
print("β
Agent ready!")
|
| 96 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 97 |
def __call__(self, question: str, task_id: str = None) -> str:
|
| 98 |
try:
|
| 99 |
-
|
| 100 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 101 |
if task_id:
|
| 102 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 103 |
|
| 104 |
-
|
| 105 |
-
needs_search = any(word in question.lower() for word in
|
| 106 |
-
["who is", "what is", "when did", "where is", "current", "latest", "recent"])
|
| 107 |
|
| 108 |
-
|
| 109 |
-
if
|
| 110 |
-
|
| 111 |
-
search_results = web_search(question[:100])
|
| 112 |
|
| 113 |
-
#
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 119 |
|
| 120 |
-
#
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
|
| 124 |
|
| 125 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 126 |
|
| 127 |
-
|
| 128 |
|
| 129 |
-
|
| 130 |
-
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
|
| 135 |
-
)
|
| 136 |
-
|
| 137 |
-
answer = response.choices[0].message.content.strip()
|
| 138 |
-
|
| 139 |
-
# Clean up common prefixes
|
| 140 |
-
for prefix in ["Answer:", "The answer is:", "Final answer:", "A:"]:
|
| 141 |
-
if answer.lower().startswith(prefix.lower()):
|
| 142 |
-
answer = answer[len(prefix):].strip()
|
| 143 |
|
| 144 |
-
#
|
| 145 |
-
if
|
| 146 |
-
|
| 147 |
-
|
| 148 |
|
| 149 |
return answer
|
| 150 |
|
|
@@ -167,27 +313,23 @@ def run_and_submit_all(profile: gr.OAuthProfile | None):
|
|
| 167 |
print(f"\n{'='*50}")
|
| 168 |
print(f"User: {username}")
|
| 169 |
|
| 170 |
-
# Check API key
|
| 171 |
if not os.environ.get("GROQ_API_KEY"):
|
| 172 |
return "β ERROR: Add GROQ_API_KEY to Space secrets!", None
|
| 173 |
|
| 174 |
print("β
GROQ_API_KEY found")
|
| 175 |
print(f"{'='*50}\n")
|
| 176 |
|
| 177 |
-
# Init agent
|
| 178 |
try:
|
| 179 |
agent = BasicAgent()
|
| 180 |
except Exception as e:
|
| 181 |
return f"β Agent init failed: {e}", None
|
| 182 |
|
| 183 |
-
# Get questions
|
| 184 |
try:
|
| 185 |
questions = requests.get(f"{DEFAULT_API_URL}/questions", timeout=15).json()
|
| 186 |
print(f"π Got {len(questions)} questions\n")
|
| 187 |
except Exception as e:
|
| 188 |
return f"β Failed to fetch questions: {e}", None
|
| 189 |
|
| 190 |
-
# Process each question
|
| 191 |
results = []
|
| 192 |
answers = []
|
| 193 |
|
|
@@ -204,7 +346,7 @@ def run_and_submit_all(profile: gr.OAuthProfile | None):
|
|
| 204 |
try:
|
| 205 |
answer = agent(question, task_id)
|
| 206 |
q_time = time.time() - q_start
|
| 207 |
-
print(f" β {answer[:
|
| 208 |
except Exception as e:
|
| 209 |
answer = "unknown"
|
| 210 |
print(f" β Error: {e}")
|
|
@@ -212,14 +354,13 @@ def run_and_submit_all(profile: gr.OAuthProfile | None):
|
|
| 212 |
answers.append({"task_id": task_id, "submitted_answer": answer})
|
| 213 |
results.append({
|
| 214 |
"#": i+1,
|
| 215 |
-
"Question": question[:
|
| 216 |
-
"Answer": answer[:
|
| 217 |
})
|
| 218 |
|
| 219 |
total_time = time.time() - start_time
|
| 220 |
print(f"\nβ±οΈ Total time: {total_time:.1f}s ({total_time/60:.1f} min)")
|
| 221 |
|
| 222 |
-
# Submit
|
| 223 |
print(f"\nπ€ Submitting {len(answers)} answers...")
|
| 224 |
|
| 225 |
try:
|
|
@@ -257,16 +398,17 @@ def run_and_submit_all(profile: gr.OAuthProfile | None):
|
|
| 257 |
# ============================================
|
| 258 |
|
| 259 |
with gr.Blocks() as demo:
|
| 260 |
-
gr.Markdown("# π― GAIA Agent - Unit 4")
|
| 261 |
gr.Markdown("""
|
| 262 |
**Powered by Groq + Llama 3.3 70B**
|
| 263 |
|
| 264 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 265 |
|
| 266 |
-
**Setup:**
|
| 267 |
-
1. Add `GROQ_API_KEY` to Space secrets
|
| 268 |
-
2. Log in below
|
| 269 |
-
3. Click Run!
|
| 270 |
""")
|
| 271 |
|
| 272 |
gr.LoginButton()
|
|
@@ -278,12 +420,12 @@ with gr.Blocks() as demo:
|
|
| 278 |
|
| 279 |
if __name__ == "__main__":
|
| 280 |
print("="*50)
|
| 281 |
-
print("π― GAIA Agent -
|
| 282 |
print("="*50)
|
| 283 |
|
| 284 |
if os.environ.get("GROQ_API_KEY"):
|
| 285 |
print("β
GROQ_API_KEY found")
|
| 286 |
else:
|
| 287 |
-
print("β GROQ_API_KEY missing
|
| 288 |
|
| 289 |
demo.launch()
|
|
|
|
| 8 |
|
| 9 |
# --- Constants ---
|
| 10 |
DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
|
| 11 |
+
TIMEOUT_PER_QUESTION = 30
|
| 12 |
|
| 13 |
# ============================================
|
| 14 |
+
# GROQ CLIENT
|
| 15 |
# ============================================
|
| 16 |
|
| 17 |
def get_groq_client():
|
|
|
|
| 24 |
# TOOL FUNCTIONS
|
| 25 |
# ============================================
|
| 26 |
|
| 27 |
+
def web_search(query: str, num_results: int = 5) -> str:
|
| 28 |
+
"""Search the web with DuckDuckGo"""
|
| 29 |
try:
|
| 30 |
with DDGS() as ddgs:
|
| 31 |
+
results = list(ddgs.text(query, max_results=num_results))
|
| 32 |
if not results:
|
| 33 |
+
return "No results found"
|
| 34 |
+
output = []
|
| 35 |
+
for r in results:
|
| 36 |
+
output.append(f"Title: {r.get('title', '')}")
|
| 37 |
+
output.append(f"Content: {r.get('body', '')}")
|
| 38 |
+
output.append(f"URL: {r.get('href', '')}")
|
| 39 |
+
output.append("---")
|
| 40 |
+
return "\n".join(output)
|
| 41 |
+
except Exception as e:
|
| 42 |
+
return f"Search error: {e}"
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
def visit_webpage(url: str) -> str:
|
| 46 |
+
"""Get webpage content"""
|
| 47 |
+
try:
|
| 48 |
+
from bs4 import BeautifulSoup
|
| 49 |
+
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"}
|
| 50 |
+
response = requests.get(url, headers=headers, timeout=10)
|
| 51 |
+
soup = BeautifulSoup(response.text, 'html.parser')
|
| 52 |
+
for tag in soup(['script', 'style', 'nav', 'footer', 'header']):
|
| 53 |
+
tag.decompose()
|
| 54 |
+
text = soup.get_text(separator=' ', strip=True)
|
| 55 |
+
return text[:6000]
|
| 56 |
+
except Exception as e:
|
| 57 |
+
return f"Error: {e}"
|
| 58 |
|
| 59 |
|
| 60 |
def wikipedia_search(topic: str) -> str:
|
| 61 |
+
"""Get Wikipedia content"""
|
| 62 |
try:
|
| 63 |
url = "https://en.wikipedia.org/w/api.php"
|
| 64 |
+
# Search
|
| 65 |
params = {"action": "query", "list": "search", "srsearch": topic, "format": "json", "srlimit": 1}
|
| 66 |
+
data = requests.get(url, params=params, timeout=10).json()
|
| 67 |
|
| 68 |
if not data.get("query", {}).get("search"):
|
| 69 |
+
return "No Wikipedia article found"
|
| 70 |
|
| 71 |
title = data["query"]["search"][0]["title"]
|
| 72 |
+
|
| 73 |
+
# Get full content (not just intro)
|
| 74 |
+
params2 = {
|
| 75 |
+
"action": "query",
|
| 76 |
+
"titles": title,
|
| 77 |
+
"prop": "extracts",
|
| 78 |
+
"exintro": False, # Get full article
|
| 79 |
+
"explaintext": True,
|
| 80 |
+
"format": "json"
|
| 81 |
+
}
|
| 82 |
+
pages = requests.get(url, params=params2, timeout=10).json().get("query", {}).get("pages", {})
|
| 83 |
|
| 84 |
for page in pages.values():
|
| 85 |
+
content = page.get("extract", "")
|
| 86 |
+
return f"Wikipedia - {title}:\n{content[:5000]}"
|
| 87 |
+
return "No content found"
|
| 88 |
+
except Exception as e:
|
| 89 |
+
return f"Wikipedia error: {e}"
|
| 90 |
|
| 91 |
|
| 92 |
+
def get_task_file(task_id: str) -> dict:
|
| 93 |
+
"""Get GAIA task file - returns dict with content and type"""
|
| 94 |
try:
|
| 95 |
url = f"https://agents-course-unit4-scoring.hf.space/files/{task_id}"
|
| 96 |
+
response = requests.get(url, timeout=15)
|
| 97 |
|
| 98 |
if response.status_code == 404:
|
| 99 |
+
return {"has_file": False, "content": ""}
|
| 100 |
|
| 101 |
content_type = response.headers.get('content-type', '').lower()
|
| 102 |
+
disposition = response.headers.get('content-disposition', '')
|
| 103 |
+
|
| 104 |
+
# Get filename
|
| 105 |
+
filename = ""
|
| 106 |
+
if 'filename=' in disposition:
|
| 107 |
+
filename = disposition.split('filename=')[-1].strip('"\'')
|
| 108 |
|
| 109 |
+
result = {"has_file": True, "filename": filename, "type": content_type}
|
|
|
|
| 110 |
|
| 111 |
+
# Text files
|
| 112 |
+
if 'text' in content_type or filename.endswith(('.txt', '.py', '.md', '.csv')):
|
| 113 |
+
result["content"] = response.text[:8000]
|
| 114 |
+
return result
|
| 115 |
+
|
| 116 |
+
# JSON
|
| 117 |
+
if 'json' in content_type or filename.endswith('.json'):
|
| 118 |
+
result["content"] = response.text[:8000]
|
| 119 |
+
return result
|
| 120 |
+
|
| 121 |
+
# Excel files
|
| 122 |
+
if 'spreadsheet' in content_type or 'excel' in content_type or filename.endswith(('.xlsx', '.xls')):
|
| 123 |
try:
|
| 124 |
from io import BytesIO
|
| 125 |
df = pd.read_excel(BytesIO(response.content))
|
| 126 |
+
result["content"] = f"Excel file with {len(df)} rows:\n{df.to_string()}"
|
| 127 |
+
result["dataframe"] = df
|
| 128 |
+
return result
|
| 129 |
+
except Exception as e:
|
| 130 |
+
result["content"] = f"Excel file (parse error: {e})"
|
| 131 |
+
return result
|
| 132 |
+
|
| 133 |
+
# Images
|
| 134 |
+
if 'image' in content_type or filename.endswith(('.png', '.jpg', '.jpeg', '.gif')):
|
| 135 |
+
result["content"] = "IMAGE FILE - Cannot process images"
|
| 136 |
+
result["is_image"] = True
|
| 137 |
+
return result
|
| 138 |
|
| 139 |
+
# Audio/Video
|
| 140 |
+
if 'audio' in content_type or 'video' in content_type:
|
| 141 |
+
result["content"] = "AUDIO/VIDEO FILE - Cannot process"
|
| 142 |
+
return result
|
| 143 |
+
|
| 144 |
+
# PDF
|
| 145 |
+
if 'pdf' in content_type or filename.endswith('.pdf'):
|
| 146 |
+
result["content"] = "PDF FILE - Cannot read directly"
|
| 147 |
+
return result
|
| 148 |
+
|
| 149 |
+
result["content"] = f"Binary file: {content_type}, {len(response.content)} bytes"
|
| 150 |
+
return result
|
| 151 |
+
|
| 152 |
+
except Exception as e:
|
| 153 |
+
return {"has_file": False, "content": f"Error: {e}"}
|
| 154 |
+
|
| 155 |
+
|
| 156 |
+
def reverse_string(text: str) -> str:
|
| 157 |
+
"""Reverse a string"""
|
| 158 |
+
return text[::-1]
|
| 159 |
+
|
| 160 |
+
|
| 161 |
+
def is_reversed_text(text: str) -> bool:
|
| 162 |
+
"""Check if text appears to be reversed"""
|
| 163 |
+
# Common reversed patterns
|
| 164 |
+
reversed_indicators = ['.rewsna', '.txet', 'eht si', 'tahw', 'erehw', 'nehw', 'ohw']
|
| 165 |
+
text_lower = text.lower()
|
| 166 |
+
return any(ind in text_lower for ind in reversed_indicators)
|
| 167 |
|
| 168 |
|
| 169 |
# ============================================
|
|
|
|
| 176 |
self.client = get_groq_client()
|
| 177 |
print("β
Agent ready!")
|
| 178 |
|
| 179 |
+
def ask_llm(self, prompt: str, max_tokens: int = 300) -> str:
|
| 180 |
+
"""Ask Groq LLM"""
|
| 181 |
+
try:
|
| 182 |
+
response = self.client.chat.completions.create(
|
| 183 |
+
model="llama-3.3-70b-versatile",
|
| 184 |
+
messages=[{"role": "user", "content": prompt}],
|
| 185 |
+
temperature=0,
|
| 186 |
+
max_tokens=max_tokens,
|
| 187 |
+
timeout=TIMEOUT_PER_QUESTION,
|
| 188 |
+
)
|
| 189 |
+
return response.choices[0].message.content.strip()
|
| 190 |
+
except Exception as e:
|
| 191 |
+
return f"LLM Error: {e}"
|
| 192 |
+
|
| 193 |
+
def clean_answer(self, answer: str) -> str:
|
| 194 |
+
"""Clean up the answer"""
|
| 195 |
+
# Remove common prefixes
|
| 196 |
+
prefixes = [
|
| 197 |
+
"Answer:", "The answer is:", "Final answer:", "A:",
|
| 198 |
+
"The answer is", "Final answer", "Based on",
|
| 199 |
+
"According to", "The result is", "The result is:",
|
| 200 |
+
]
|
| 201 |
+
for prefix in prefixes:
|
| 202 |
+
if answer.lower().startswith(prefix.lower()):
|
| 203 |
+
answer = answer[len(prefix):].strip()
|
| 204 |
+
|
| 205 |
+
# Remove quotes
|
| 206 |
+
if (answer.startswith('"') and answer.endswith('"')) or \
|
| 207 |
+
(answer.startswith("'") and answer.endswith("'")):
|
| 208 |
+
answer = answer[1:-1]
|
| 209 |
+
|
| 210 |
+
# Remove trailing periods for single-word answers
|
| 211 |
+
if answer.endswith('.') and ' ' not in answer:
|
| 212 |
+
answer = answer[:-1]
|
| 213 |
+
|
| 214 |
+
return answer.strip()
|
| 215 |
+
|
| 216 |
def __call__(self, question: str, task_id: str = None) -> str:
|
| 217 |
try:
|
| 218 |
+
context_parts = []
|
| 219 |
+
|
| 220 |
+
# 1. Check for reversed text in question
|
| 221 |
+
if is_reversed_text(question):
|
| 222 |
+
reversed_q = reverse_string(question)
|
| 223 |
+
context_parts.append(f"NOTE: The question appears to be reversed. Original: {reversed_q}")
|
| 224 |
+
question = reversed_q
|
| 225 |
+
|
| 226 |
+
# 2. Check for file
|
| 227 |
+
file_info = {"has_file": False}
|
| 228 |
if task_id:
|
| 229 |
+
file_info = get_task_file(task_id)
|
| 230 |
+
if file_info.get("has_file"):
|
| 231 |
+
if file_info.get("is_image"):
|
| 232 |
+
context_parts.append("NOTE: This task has an IMAGE file which I cannot analyze.")
|
| 233 |
+
else:
|
| 234 |
+
context_parts.append(f"FILE CONTENT ({file_info.get('filename', 'file')}):\n{file_info.get('content', '')}")
|
| 235 |
+
|
| 236 |
+
# 3. Determine if web search needed
|
| 237 |
+
search_keywords = [
|
| 238 |
+
"who is", "who was", "who did", "who nominated",
|
| 239 |
+
"what is", "what was", "what are", "what did",
|
| 240 |
+
"when did", "when was",
|
| 241 |
+
"where is", "where was", "where were",
|
| 242 |
+
"how many", "how much",
|
| 243 |
+
"which", "name the", "find the",
|
| 244 |
+
"album", "movie", "actor", "actress", "singer", "artist",
|
| 245 |
+
"wikipedia", "article", "published",
|
| 246 |
+
"athlete", "player", "pitcher", "yankee",
|
| 247 |
+
"country", "city", "competition"
|
| 248 |
+
]
|
| 249 |
|
| 250 |
+
needs_search = any(kw in question.lower() for kw in search_keywords)
|
|
|
|
|
|
|
| 251 |
|
| 252 |
+
# Don't search if we have good file content
|
| 253 |
+
if file_info.get("has_file") and not file_info.get("is_image"):
|
| 254 |
+
needs_search = False
|
|
|
|
| 255 |
|
| 256 |
+
# 4. Do web search if needed
|
| 257 |
+
if needs_search:
|
| 258 |
+
# Extract key search terms
|
| 259 |
+
search_query = question[:150]
|
| 260 |
+
# Remove common question words for better search
|
| 261 |
+
for word in ["what is the", "who is the", "who was the", "what are the", "how many"]:
|
| 262 |
+
search_query = search_query.lower().replace(word, "")
|
| 263 |
+
|
| 264 |
+
search_results = web_search(search_query.strip(), num_results=5)
|
| 265 |
+
if search_results and "No results" not in search_results:
|
| 266 |
+
context_parts.append(f"WEB SEARCH RESULTS:\n{search_results}")
|
| 267 |
|
| 268 |
+
# 5. Build final prompt
|
| 269 |
+
context = "\n\n".join(context_parts) if context_parts else ""
|
| 270 |
+
|
| 271 |
+
prompt = f"""You are answering a GAIA benchmark question. Give ONLY the final answer.
|
| 272 |
|
| 273 |
+
RULES:
|
| 274 |
+
- Be PRECISE and CONCISE
|
| 275 |
+
- Give ONLY the answer, no explanation
|
| 276 |
+
- If asked for a name, give just the name
|
| 277 |
+
- If asked for a number, give just the number
|
| 278 |
+
- If asked for a list, give comma-separated items
|
| 279 |
+
- Match the format requested in the question
|
| 280 |
|
| 281 |
+
{f"CONTEXT:{chr(10)}{context}" if context else ""}
|
| 282 |
|
| 283 |
+
QUESTION: {question}
|
| 284 |
+
|
| 285 |
+
ANSWER (just the answer, nothing else):"""
|
| 286 |
+
|
| 287 |
+
answer = self.ask_llm(prompt)
|
| 288 |
+
answer = self.clean_answer(answer)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 289 |
|
| 290 |
+
# Special handling: if question asks for reversed text answer
|
| 291 |
+
if "reversed" in question.lower() and "spell" in question.lower():
|
| 292 |
+
# The answer might need to be reversed
|
| 293 |
+
pass # Keep as is, LLM should handle
|
| 294 |
|
| 295 |
return answer
|
| 296 |
|
|
|
|
| 313 |
print(f"\n{'='*50}")
|
| 314 |
print(f"User: {username}")
|
| 315 |
|
|
|
|
| 316 |
if not os.environ.get("GROQ_API_KEY"):
|
| 317 |
return "β ERROR: Add GROQ_API_KEY to Space secrets!", None
|
| 318 |
|
| 319 |
print("β
GROQ_API_KEY found")
|
| 320 |
print(f"{'='*50}\n")
|
| 321 |
|
|
|
|
| 322 |
try:
|
| 323 |
agent = BasicAgent()
|
| 324 |
except Exception as e:
|
| 325 |
return f"β Agent init failed: {e}", None
|
| 326 |
|
|
|
|
| 327 |
try:
|
| 328 |
questions = requests.get(f"{DEFAULT_API_URL}/questions", timeout=15).json()
|
| 329 |
print(f"π Got {len(questions)} questions\n")
|
| 330 |
except Exception as e:
|
| 331 |
return f"β Failed to fetch questions: {e}", None
|
| 332 |
|
|
|
|
| 333 |
results = []
|
| 334 |
answers = []
|
| 335 |
|
|
|
|
| 346 |
try:
|
| 347 |
answer = agent(question, task_id)
|
| 348 |
q_time = time.time() - q_start
|
| 349 |
+
print(f" β {answer[:60]}... ({q_time:.1f}s)")
|
| 350 |
except Exception as e:
|
| 351 |
answer = "unknown"
|
| 352 |
print(f" β Error: {e}")
|
|
|
|
| 354 |
answers.append({"task_id": task_id, "submitted_answer": answer})
|
| 355 |
results.append({
|
| 356 |
"#": i+1,
|
| 357 |
+
"Question": question[:60]+"...",
|
| 358 |
+
"Answer": answer[:80]
|
| 359 |
})
|
| 360 |
|
| 361 |
total_time = time.time() - start_time
|
| 362 |
print(f"\nβ±οΈ Total time: {total_time:.1f}s ({total_time/60:.1f} min)")
|
| 363 |
|
|
|
|
| 364 |
print(f"\nπ€ Submitting {len(answers)} answers...")
|
| 365 |
|
| 366 |
try:
|
|
|
|
| 398 |
# ============================================
|
| 399 |
|
| 400 |
with gr.Blocks() as demo:
|
| 401 |
+
gr.Markdown("# π― GAIA Agent - Unit 4 (Improved)")
|
| 402 |
gr.Markdown("""
|
| 403 |
**Powered by Groq + Llama 3.3 70B**
|
| 404 |
|
| 405 |
+
**Improvements:**
|
| 406 |
+
- β
Better web search
|
| 407 |
+
- β
Reversed text detection
|
| 408 |
+
- β
Excel file reading
|
| 409 |
+
- β
Smarter answer formatting
|
| 410 |
|
| 411 |
+
**Setup:** Add `GROQ_API_KEY` to Space secrets
|
|
|
|
|
|
|
|
|
|
| 412 |
""")
|
| 413 |
|
| 414 |
gr.LoginButton()
|
|
|
|
| 420 |
|
| 421 |
if __name__ == "__main__":
|
| 422 |
print("="*50)
|
| 423 |
+
print("π― GAIA Agent - Improved Version")
|
| 424 |
print("="*50)
|
| 425 |
|
| 426 |
if os.environ.get("GROQ_API_KEY"):
|
| 427 |
print("β
GROQ_API_KEY found")
|
| 428 |
else:
|
| 429 |
+
print("β GROQ_API_KEY missing!")
|
| 430 |
|
| 431 |
demo.launch()
|