Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
|
@@ -249,6 +249,7 @@
|
|
| 249 |
#
|
| 250 |
import os
|
| 251 |
import io
|
|
|
|
| 252 |
import requests
|
| 253 |
import pandas as pd
|
| 254 |
import gradio as gr
|
|
@@ -256,12 +257,11 @@ from contextlib import redirect_stdout
|
|
| 256 |
from typing import TypedDict, Annotated, List
|
| 257 |
import operator
|
| 258 |
|
| 259 |
-
# --- LangChain & LangGraph Imports
|
| 260 |
-
from langchain_core.messages import BaseMessage, HumanMessage, ToolMessage
|
| 261 |
from langchain_core.tools import tool
|
| 262 |
-
from
|
| 263 |
from langgraph.graph import StateGraph, END
|
| 264 |
-
from langgraph.prebuilt import ToolNode
|
| 265 |
from tavily import TavilyClient
|
| 266 |
import pypdf
|
| 267 |
|
|
@@ -270,198 +270,240 @@ DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
|
|
| 270 |
FILES_DIR = "./files"
|
| 271 |
os.makedirs(FILES_DIR, exist_ok=True)
|
| 272 |
|
| 273 |
-
# --- System Prompt (
|
|
|
|
| 274 |
AGENT_SYSTEM_PROMPT = """You are a world-class AI agent, specialized in solving complex problems from the GAIA benchmark.
|
| 275 |
Your task is to analyze the user's question, think step-by-step, and use the provided tools to find the correct answer.
|
| 276 |
-
|
| 277 |
-
|
| 278 |
-
|
| 279 |
-
|
| 280 |
-
|
| 281 |
-
|
| 282 |
-
|
| 283 |
-
|
| 284 |
-
|
| 285 |
-
|
| 286 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 287 |
Think, use your tools, and then provide ONLY the final, precise answer.
|
| 288 |
"""
|
| 289 |
-
|
| 290 |
-
#
|
| 291 |
-
# ================================================================================================
|
| 292 |
-
# ✅ 1. DEFINE THE AGENT'S TOOLS (Unchanged)
|
| 293 |
-
# ================================================================================================
|
| 294 |
-
#
|
| 295 |
tavily = TavilyClient(api_key=os.getenv("TAVILY_API_KEY"))
|
| 296 |
-
|
| 297 |
@tool
|
| 298 |
def tavily_search(query: str) -> str:
|
| 299 |
-
|
| 300 |
-
|
| 301 |
-
|
| 302 |
-
|
| 303 |
-
|
| 304 |
-
|
| 305 |
-
|
| 306 |
@tool
|
| 307 |
def read_file(url: str) -> str:
|
| 308 |
-
|
| 309 |
-
|
| 310 |
-
|
| 311 |
-
|
| 312 |
-
|
| 313 |
-
|
| 314 |
-
|
| 315 |
-
|
| 316 |
-
|
| 317 |
-
|
| 318 |
-
|
| 319 |
-
|
| 320 |
-
|
| 321 |
-
|
| 322 |
-
|
| 323 |
-
|
| 324 |
-
|
| 325 |
-
|
| 326 |
@tool
|
| 327 |
def python_interpreter(code: str) -> str:
|
| 328 |
-
|
| 329 |
-
|
| 330 |
-
|
| 331 |
-
|
| 332 |
-
|
| 333 |
-
|
| 334 |
-
|
| 335 |
-
|
| 336 |
-
|
| 337 |
-
|
| 338 |
-
# ✅ 2. CONFIGURE AND BUILD THE AGENT (Stable LangGraph Method)
|
| 339 |
-
# ================================================================================================
|
| 340 |
-
#
|
| 341 |
class AgentState(TypedDict):
|
| 342 |
-
|
| 343 |
-
|
| 344 |
def build_agent_graph():
|
| 345 |
-
|
| 346 |
-
|
| 347 |
-
|
| 348 |
-
|
| 349 |
-
|
| 350 |
-
|
| 351 |
-
|
| 352 |
-
|
| 353 |
-
|
| 354 |
-
|
| 355 |
-
|
| 356 |
-
|
| 357 |
-
|
| 358 |
-
|
| 359 |
-
|
| 360 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 361 |
return "action"
|
|
|
|
|
|
|
|
|
|
| 362 |
return "end"
|
| 363 |
|
| 364 |
-
|
| 365 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 366 |
|
| 367 |
-
|
| 368 |
-
|
| 369 |
-
|
| 370 |
-
|
| 371 |
-
|
| 372 |
-
|
| 373 |
-
|
| 374 |
-
|
| 375 |
-
|
| 376 |
-
|
| 377 |
-
|
| 378 |
-
|
| 379 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 380 |
class GaiaAgent:
|
| 381 |
-
|
| 382 |
-
|
| 383 |
-
|
| 384 |
-
|
| 385 |
-
|
| 386 |
-
|
| 387 |
-
try:
|
| 388 |
-
initial_input = {"messages": [HumanMessage(content=f"{AGENT_SYSTEM_PROMPT}\n\nUSER QUESTION: {question}")]}
|
| 389 |
-
final_state = None
|
| 390 |
-
for step in self.agent_app.stream(initial_input, {"recursion_limit": 15}):
|
| 391 |
-
final_state = step
|
| 392 |
-
|
| 393 |
-
# The final answer is in the last 'agent' step's AIMessage
|
| 394 |
-
final_answer = final_state['agent']['messages'][-1].content
|
| 395 |
-
print(f"\n--- Agent finished. Final Answer: {final_answer} ---\n")
|
| 396 |
-
return str(final_answer).strip()
|
| 397 |
-
except Exception as e:
|
| 398 |
-
print(f"An error occurred during agent execution: {e}")
|
| 399 |
-
return f"AGENT_EXECUTION_ERROR: {e}"
|
| 400 |
-
|
| 401 |
-
# --- The rest of the file is unchanged ---
|
| 402 |
-
def run_and_submit_all( profile: gr.OAuthProfile | None):
|
| 403 |
-
space_id = os.getenv("SPACE_ID")
|
| 404 |
-
if not profile: return "Please Login to Hugging Face with the button.", None
|
| 405 |
-
username = f"{profile.username}"
|
| 406 |
-
print(f"User logged in: {username}")
|
| 407 |
-
api_url = DEFAULT_API_URL
|
| 408 |
-
questions_url = f"{api_url}/questions"
|
| 409 |
-
submit_url = f"{api_url}/submit"
|
| 410 |
-
agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
|
| 411 |
-
|
| 412 |
try:
|
| 413 |
-
|
| 414 |
-
|
| 415 |
-
|
| 416 |
-
|
| 417 |
-
|
| 418 |
-
|
| 419 |
-
|
| 420 |
-
|
| 421 |
-
|
| 422 |
-
|
| 423 |
-
|
| 424 |
-
|
| 425 |
-
|
| 426 |
-
|
| 427 |
-
|
| 428 |
-
|
| 429 |
-
|
| 430 |
-
|
| 431 |
-
|
| 432 |
-
|
| 433 |
-
|
| 434 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 435 |
try:
|
| 436 |
-
|
| 437 |
-
|
| 438 |
-
|
| 439 |
-
|
| 440 |
-
|
| 441 |
-
|
| 442 |
-
|
| 443 |
-
|
| 444 |
-
|
| 445 |
-
|
| 446 |
-
|
| 447 |
-
|
| 448 |
-
|
| 449 |
-
|
| 450 |
-
|
| 451 |
-
|
| 452 |
-
""
|
| 453 |
-
|
| 454 |
-
|
| 455 |
-
|
| 456 |
-
2. Ensure you have a **`COHERE_API_KEY`** and a **`TAVILY_API_KEY`** set in your Space secrets.
|
| 457 |
-
"""
|
| 458 |
)
|
| 459 |
-
|
| 460 |
-
|
| 461 |
-
|
| 462 |
-
|
| 463 |
-
|
| 464 |
-
|
| 465 |
-
|
| 466 |
-
|
| 467 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 249 |
#
|
| 250 |
import os
|
| 251 |
import io
|
| 252 |
+
import json
|
| 253 |
import requests
|
| 254 |
import pandas as pd
|
| 255 |
import gradio as gr
|
|
|
|
| 257 |
from typing import TypedDict, Annotated, List
|
| 258 |
import operator
|
| 259 |
|
| 260 |
+
# --- LangChain & LangGraph Imports ---
|
| 261 |
+
from langchain_core.messages import BaseMessage, HumanMessage, ToolMessage, AIMessage, SystemMessage
|
| 262 |
from langchain_core.tools import tool
|
| 263 |
+
from langchain_huggingface import HuggingFaceEndpoint
|
| 264 |
from langgraph.graph import StateGraph, END
|
|
|
|
| 265 |
from tavily import TavilyClient
|
| 266 |
import pypdf
|
| 267 |
|
|
|
|
| 270 |
FILES_DIR = "./files"
|
| 271 |
os.makedirs(FILES_DIR, exist_ok=True)
|
| 272 |
|
| 273 |
+
# --- System Prompt (Updated for Manual JSON Tool Calling) ---
|
| 274 |
+
# This prompt instructs the model to generate JSON, a robust method for tool calls.
|
| 275 |
AGENT_SYSTEM_PROMPT = """You are a world-class AI agent, specialized in solving complex problems from the GAIA benchmark.
|
| 276 |
Your task is to analyze the user's question, think step-by-step, and use the provided tools to find the correct answer.
|
| 277 |
+
|
| 278 |
+
**TOOL USAGE INSTRUCTIONS:**
|
| 279 |
+
When you need to use a tool, you MUST respond with a JSON object containing the tool name and its arguments. The JSON object should have two keys: "tool_name" and "parameters".
|
| 280 |
+
|
| 281 |
+
Here is an example of how to call the `tavily_search` tool:
|
| 282 |
+
```json
|
| 283 |
+
{
|
| 284 |
+
"tool_name": "tavily_search",
|
| 285 |
+
"parameters": {
|
| 286 |
+
"query": "Who won the last FIFA World Cup?"
|
| 287 |
+
}
|
| 288 |
+
}
|
| 289 |
+
Use code with caution.
|
| 290 |
+
Python
|
| 291 |
+
CRITICAL FINAL ANSWER INSTRUCTIONS:
|
| 292 |
+
Once you have gathered all the necessary information and are absolutely certain of the answer, you MUST provide it directly and concisely.
|
| 293 |
+
Your final response must ONLY be the answer itself.
|
| 294 |
+
DO NOT wrap the final answer in a JSON object or include any conversational text.
|
| 295 |
Think, use your tools, and then provide ONLY the final, precise answer.
|
| 296 |
"""
|
| 297 |
+
###===============================================================================================
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 298 |
tavily = TavilyClient(api_key=os.getenv("TAVILY_API_KEY"))
|
|
|
|
| 299 |
@tool
|
| 300 |
def tavily_search(query: str) -> str:
|
| 301 |
+
"""Uses the Tavily Search API to find information on the web."""
|
| 302 |
+
print(f"--- Calling Tavily Search Tool with query: {query} ---")
|
| 303 |
+
try:
|
| 304 |
+
result = tavily.search(query=query, search_depth="advanced")
|
| 305 |
+
return f"Search results for '{query}':\n" + "\n".join([f"- {r['content']}" for r in result['results']])
|
| 306 |
+
except Exception as e: return f"Error during Tavily search: {e}"
|
|
|
|
| 307 |
@tool
|
| 308 |
def read_file(url: str) -> str:
|
| 309 |
+
"""Downloads and reads the content of a file (text or PDF) from a URL."""
|
| 310 |
+
print(f"--- Calling Read File Tool with URL: {url} ---")
|
| 311 |
+
try:
|
| 312 |
+
filename = os.path.join(FILES_DIR, os.path.basename(url))
|
| 313 |
+
response = requests.get(url)
|
| 314 |
+
response.raise_for_status()
|
| 315 |
+
with open(filename, 'wb') as f: f.write(response.content)
|
| 316 |
+
if url.lower().endswith('.pdf'):
|
| 317 |
+
try:
|
| 318 |
+
pdf_reader = pypdf.PdfReader(filename)
|
| 319 |
+
return f"Successfully read PDF file '{filename}'. Content:\n\n{''.join(p.extract_text() for p in pdf_reader.pages)}"
|
| 320 |
+
except Exception as e: return f"Error reading PDF file: {e}"
|
| 321 |
+
else:
|
| 322 |
+
try:
|
| 323 |
+
with open(filename, 'r', encoding='utf-8') as f: return f"Successfully read text file '{filename}'. Content:\n\n{f.read()}"
|
| 324 |
+
except UnicodeDecodeError: return f"Successfully downloaded binary file '{filename}'. Cannot display content as text."
|
| 325 |
+
except requests.exceptions.RequestException as e: return f"Error downloading or reading file: {e}"
|
|
|
|
| 326 |
@tool
|
| 327 |
def python_interpreter(code: str) -> str:
|
| 328 |
+
"""Executes Python code and returns its stdout."""
|
| 329 |
+
print(f"--- Calling Python Interpreter Tool with code:\n{code} ---")
|
| 330 |
+
output_buffer = io.StringIO()
|
| 331 |
+
try:
|
| 332 |
+
with redirect_stdout(output_buffer): exec(code, globals())
|
| 333 |
+
return f"Code executed successfully. Output:\n{output_buffer.getvalue()}"
|
| 334 |
+
except Exception as e: return f"Error executing Python code: {e}"
|
| 335 |
+
##================================================================================================
|
| 336 |
+
#✅ 2. CONFIGURE AND BUILD THE AGENT (with Qwen2 and Manual Tool Calling)
|
| 337 |
+
#================================================================================================
|
|
|
|
|
|
|
|
|
|
| 338 |
class AgentState(TypedDict):
|
| 339 |
+
messages: Annotated[List[BaseMessage], operator.add]
|
|
|
|
| 340 |
def build_agent_graph():
|
| 341 |
+
"""Builds the agent using a manual LangGraph loop with the HuggingFaceEndpoint."""
|
| 342 |
+
tools = [tavily_search, read_file, python_interpreter]
|
| 343 |
+
tool_map = {tool.name: tool for tool in tools}
|
| 344 |
+
Generated code
|
| 345 |
+
# Using Qwen2-72B-Instruct model via HuggingFaceEndpoint
|
| 346 |
+
repo_id = "Qwen/Qwen2-72B-Instruct"
|
| 347 |
+
llm = HuggingFaceEndpoint(
|
| 348 |
+
repo_id=repo_id,
|
| 349 |
+
max_new_tokens=1024,
|
| 350 |
+
temperature=0.1,
|
| 351 |
+
huggingfacehub_api_token=os.getenv("HUGGINGFACEHUB_API_TOKEN")
|
| 352 |
+
)
|
| 353 |
+
|
| 354 |
+
def call_model(state: AgentState):
|
| 355 |
+
"""Invokes the LLM and wraps the response in an AIMessage."""
|
| 356 |
+
# Qwen2 Instruct uses a specific chat template. We build it manually.
|
| 357 |
+
prompt_str = ""
|
| 358 |
+
for msg in state['messages']:
|
| 359 |
+
role = ""
|
| 360 |
+
if isinstance(msg, SystemMessage): role = "system"
|
| 361 |
+
elif isinstance(msg, HumanMessage): role = "user"
|
| 362 |
+
elif isinstance(msg, AIMessage): role = "assistant"
|
| 363 |
+
elif isinstance(msg, ToolMessage): continue # We'll handle tool results differently
|
| 364 |
+
|
| 365 |
+
if role: prompt_str += f"<|im_start|>{role}\n{msg.content}<|im_end|>\n"
|
| 366 |
+
|
| 367 |
+
# Add results from the last tool call, if any
|
| 368 |
+
if isinstance(state['messages'][-1], ToolMessage):
|
| 369 |
+
prompt_str += f"<|im_start|>user\nTool output:\n{state['messages'][-1].content}<|im_end|>\n"
|
| 370 |
+
|
| 371 |
+
prompt_str += "<|im_start|>assistant\n"
|
| 372 |
+
|
| 373 |
+
response_text = llm.invoke(prompt_str)
|
| 374 |
+
return {"messages": [AIMessage(content=response_text)]}
|
| 375 |
+
|
| 376 |
+
def should_continue(state: AgentState) -> str:
|
| 377 |
+
"""Determines whether to call a tool or end the loop."""
|
| 378 |
+
last_message_content = state['messages'][-1].content.strip()
|
| 379 |
+
# A simple check for JSON is a reliable way to detect tool calls.
|
| 380 |
+
if "```json" in last_message_content:
|
| 381 |
+
return "action"
|
| 382 |
+
if last_message_content.startswith('{') and last_message_content.endswith('}'):
|
| 383 |
+
try:
|
| 384 |
+
json.loads(last_message_content)
|
| 385 |
return "action"
|
| 386 |
+
except json.JSONDecodeError:
|
| 387 |
+
return "end" # Not valid JSON, must be the final answer
|
| 388 |
+
else:
|
| 389 |
return "end"
|
| 390 |
|
| 391 |
+
def call_tool_node(state: AgentState):
|
| 392 |
+
"""Parses the JSON tool call from the LLM and executes it."""
|
| 393 |
+
last_message_content = state['messages'][-1].content.strip()
|
| 394 |
+
|
| 395 |
+
# Extract JSON from markdown code block if present
|
| 396 |
+
if "```json" in last_message_content:
|
| 397 |
+
json_str = last_message_content.split("```json").split("```")[0].strip()
|
| 398 |
+
else:
|
| 399 |
+
json_str = last_message_content
|
| 400 |
|
| 401 |
+
try:
|
| 402 |
+
tool_call_data = json.loads(json_str)
|
| 403 |
+
tool_name = tool_call_data.get("tool_name")
|
| 404 |
+
parameters = tool_call_data.get("parameters", {})
|
| 405 |
+
if tool_name not in tool_map:
|
| 406 |
+
return {"messages": [ToolMessage(content=f"Error: Tool '{tool_name}' not found.", tool_call_id="error")]}
|
| 407 |
+
|
| 408 |
+
selected_tool = tool_map[tool_name]
|
| 409 |
+
tool_output = selected_tool.invoke(parameters)
|
| 410 |
+
return {"messages": [ToolMessage(content=str(tool_output), tool_call_id=tool_name)]}
|
| 411 |
+
except Exception as e:
|
| 412 |
+
return {"messages": [ToolMessage(content=f"Error parsing tool call: {e}. Content: '{last_message_content}'", tool_call_id="error")]}
|
| 413 |
+
|
| 414 |
+
workflow = StateGraph(AgentState)
|
| 415 |
+
workflow.add_node("agent", call_model)
|
| 416 |
+
workflow.add_node("action", call_tool_node)
|
| 417 |
+
workflow.set_entry_point("agent")
|
| 418 |
+
workflow.add_conditional_edges("agent", should_continue, {"action": "action", "end": END})
|
| 419 |
+
workflow.add_edge('action', 'agent')
|
| 420 |
+
return workflow.compile()
|
| 421 |
+
Use code with caution.
|
| 422 |
+
#================================================================================================
|
| 423 |
+
#✅ 3. AGENT CLASS AND EVALUATION LOGIC
|
| 424 |
+
#================================================================================================
|
| 425 |
class GaiaAgent:
|
| 426 |
+
def init(self):
|
| 427 |
+
print("GaiaAgent initialized. Building agent with Qwen/Qwen2-72B-Instruct...")
|
| 428 |
+
self.agent_app = build_agent_graph()
|
| 429 |
+
Generated code
|
| 430 |
+
def __call__(self, question: str) -> str:
|
| 431 |
+
print(f"\n{'='*60}\nAgent received question: {question[:100]}...\n{'='*60}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 432 |
try:
|
| 433 |
+
initial_input = {"messages": [SystemMessage(content=AGENT_SYSTEM_PROMPT), HumanMessage(content=question)]}
|
| 434 |
+
final_state = None
|
| 435 |
+
for step in self.agent_app.stream(initial_input, {"recursion_limit": 15}):
|
| 436 |
+
final_state = list(step.values())[0]
|
| 437 |
+
|
| 438 |
+
final_answer = final_state['messages'][-1].content
|
| 439 |
+
return str(final_answer).strip()
|
| 440 |
+
except Exception as e:
|
| 441 |
+
print(f"An error occurred during agent execution: {e}")
|
| 442 |
+
return f"AGENT_EXECUTION_ERROR: {e}"
|
| 443 |
+
Use code with caution.
|
| 444 |
+
--- The rest of the file is unchanged ---
|
| 445 |
+
def run_and_submit_all( profile: gr.OAuthProfile | None):
|
| 446 |
+
space_id = os.getenv("SPACE_ID")
|
| 447 |
+
if not profile: return "Please Login to Hugging Face with the button.", None
|
| 448 |
+
username = f"{profile.username}"
|
| 449 |
+
print(f"User logged in: {username}")
|
| 450 |
+
api_url = DEFAULT_API_URL
|
| 451 |
+
questions_url = f"{api_url}/questions"
|
| 452 |
+
submit_url = f"{api_url}/submit"
|
| 453 |
+
agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
|
| 454 |
+
Generated code
|
| 455 |
+
try:
|
| 456 |
+
response = requests.get(questions_url, timeout=15)
|
| 457 |
+
response.raise_for_status()
|
| 458 |
+
questions_data = response.json()
|
| 459 |
+
except Exception as e: return f"An unexpected error occurred fetching questions: {e}", None
|
| 460 |
+
|
| 461 |
+
results_log, answers_payload = [], []
|
| 462 |
+
agent_instance = GaiaAgent()
|
| 463 |
+
|
| 464 |
+
for item in questions_data:
|
| 465 |
+
task_id, question_text = item.get("task_id"), item.get("question")
|
| 466 |
+
if not task_id or question_text is None: continue
|
| 467 |
try:
|
| 468 |
+
submitted_answer = agent_instance(question_text)
|
| 469 |
+
answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
|
| 470 |
+
results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
|
| 471 |
+
except Exception as e:
|
| 472 |
+
print(f"Error running agent on task {task_id}: {e}")
|
| 473 |
+
results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": f"AGENT ERROR: {e}"})
|
| 474 |
+
|
| 475 |
+
if not answers_payload: return "Agent did not produce any answers to submit.", pd.DataFrame(results_log)
|
| 476 |
+
submission_data = {"username": username.strip(), "agent_code": agent_code, "answers": answers_payload}
|
| 477 |
+
|
| 478 |
+
try:
|
| 479 |
+
response = requests.post(submit_url, json=submission_data, timeout=90)
|
| 480 |
+
response.raise_for_status()
|
| 481 |
+
result_data = response.json()
|
| 482 |
+
final_status = (
|
| 483 |
+
f"Submission Successful!\n"
|
| 484 |
+
f"User: {result_data.get('username')}\n"
|
| 485 |
+
f"Overall Score: {result_data.get('score', 'N/A')}% "
|
| 486 |
+
f"({result_data.get('correct_count', '?')}/{result_data.get('total_attempted', '?')} correct)\n"
|
| 487 |
+
f"Message: {result_data.get('message', 'No message received.')}"
|
|
|
|
|
|
|
| 488 |
)
|
| 489 |
+
return final_status, pd.DataFrame(results_log)
|
| 490 |
+
except Exception as e: return f"An unexpected error in submission: {e}", pd.DataFrame(results_log)
|
| 491 |
+
Use code with caution.
|
| 492 |
+
with gr.Blocks() as demo:
|
| 493 |
+
gr.Markdown("# GAIA Agent Final Assessment (Qwen2-72B-Instruct)")
|
| 494 |
+
gr.Markdown(
|
| 495 |
+
"""
|
| 496 |
+
Instructor's Note: This version uses the powerful Qwen/Qwen2-72B-Instruct model from the Hugging Face Hub.
|
| 497 |
+
It relies on a robust manual LangGraph loop to handle tool calls by instructing the model to generate JSON.
|
| 498 |
+
1. Ensure you have a HUGGINGFACEHUB_API_TOKEN and TAVILY_API_KEY set in your secrets.
|
| 499 |
+
2. Ensure your requirements.txt is updated. Good luck!
|
| 500 |
+
"""
|
| 501 |
+
)
|
| 502 |
+
gr.LoginButton()
|
| 503 |
+
run_button = gr.Button("Run Evaluation & Submit All Answers")
|
| 504 |
+
status_output = gr.Textbox(label="Run Status / Submission Result", lines=5, interactive=False)
|
| 505 |
+
results_table = gr.DataFrame(label="Questions and Agent Answers", wrap=True)
|
| 506 |
+
run_button.click(fn=run_and_submit_all, outputs=[status_output, results_table])
|
| 507 |
+
if name == "main":
|
| 508 |
+
print("\n" + "-"*30 + " App Starting " + "-"*30)
|
| 509 |
+
demo.launch(debug=True, share=False, ssr_mode=False)
|