derkaal's picture
Upload folder using huggingface_hub
c7eca3d verified
#!/usr/bin/env python3
"""
API interaction module for GAIA Benchmark Agent.
This module handles all interactions with the GAIA benchmark API,
including fetching questions, downloading files, and submitting answers.
"""
import json
import requests
from typing import Dict, List, Any, Optional
from pathlib import Path
from gaiaX.config import logger, API_BASE_URL
def get_all_questions(api_base_url: str = API_BASE_URL) -> List[Dict[str, Any]]:
"""
Retrieve all available questions from the GAIA benchmark.
Args:
api_base_url: Base URL for the GAIA API
Returns:
List of question dictionaries
Raises:
requests.RequestException: If the API request fails
ValueError: If the response is not valid JSON or doesn't contain expected data
"""
try:
response = requests.get(f"{api_base_url}/questions")
response.raise_for_status() # Raise exception for 4XX/5XX responses
questions = response.json()
if not isinstance(questions, list):
raise ValueError("Expected a list of questions but received a different format")
return questions
except requests.RequestException as e:
logger.error(f"Error fetching questions: {e}")
raise
except json.JSONDecodeError:
logger.error("Error decoding response as JSON")
raise ValueError("Invalid JSON response from the API")
def get_random_question(api_base_url: str = API_BASE_URL) -> Dict[str, Any]:
"""
Retrieve a random question from the GAIA benchmark.
Args:
api_base_url: Base URL for the GAIA API
Returns:
A single question dictionary
Raises:
requests.RequestException: If the API request fails
ValueError: If the response is not valid JSON or doesn't contain expected data
"""
try:
response = requests.get(f"{api_base_url}/questions/random")
response.raise_for_status()
question = response.json()
if not isinstance(question, dict):
raise ValueError("Expected a question dictionary but received a different format")
return question
except requests.RequestException as e:
logger.error(f"Error fetching random question: {e}")
raise
except json.JSONDecodeError:
logger.error("Error decoding response as JSON")
raise ValueError("Invalid JSON response from the API")
def download_file_for_task(api_base_url: str, task_id: str, download_path: str) -> str:
"""
Download a file associated with a specific task.
Args:
api_base_url: Base URL for the GAIA API
task_id: ID of the task to download files for
download_path: Directory path where the file should be saved
Returns:
Path to the downloaded file
Raises:
requests.RequestException: If the API request fails
IOError: If there's an error writing the file
ValueError: If the task_id is invalid or the response is unexpected
"""
if not task_id:
raise ValueError("Task ID cannot be empty")
# Ensure download directory exists
download_dir = Path(download_path)
download_dir.mkdir(parents=True, exist_ok=True)
try:
response = requests.get(
f"{api_base_url}/tasks/{task_id}/file",
stream=True # Stream the response for large files
)
response.raise_for_status()
# Get filename from Content-Disposition header or use task_id as fallback
content_disposition = response.headers.get('Content-Disposition', '')
filename = None
if 'filename=' in content_disposition:
filename = content_disposition.split('filename=')[1].strip('"\'')
if not filename:
filename = f"{task_id}_file.txt"
file_path = download_dir / filename
# Write the file
with open(file_path, 'wb') as f:
for chunk in response.iter_content(chunk_size=8192):
f.write(chunk)
return str(file_path)
except requests.RequestException as e:
logger.error(f"Error downloading file for task {task_id}: {e}")
raise
except IOError as e:
logger.error(f"Error writing file to {download_path}: {e}")
raise
def submit_answers(
api_base_url: str,
username: str,
agent_code_link: str,
answers: Dict[str, Any]
) -> Dict[str, Any]:
"""
Submit answers to the GAIA benchmark.
Args:
api_base_url: Base URL for the GAIA API
username: Hugging Face username
agent_code_link: Link to the agent code (e.g., GitHub repository)
answers: Dictionary of answers to submit
Returns:
Response from the API containing submission results
Raises:
requests.RequestException: If the API request fails
ValueError: If the response is not valid JSON or contains an error message
"""
if not username:
raise ValueError("Username cannot be empty")
if not agent_code_link:
raise ValueError("Agent code link cannot be empty")
if not answers or not isinstance(answers, dict):
raise ValueError("Answers must be a non-empty dictionary")
payload = {
"username": username,
"agent_code_link": agent_code_link,
"answers": answers
}
try:
response = requests.post(
f"{api_base_url}/submit",
json=payload,
headers={"Content-Type": "application/json"}
)
response.raise_for_status()
result = response.json()
# Check if the response contains an error message
if isinstance(result, dict) and result.get("error"):
raise ValueError(f"API returned an error: {result['error']}")
return result
except requests.RequestException as e:
logger.error(f"Error submitting answers: {e}")
raise
except json.JSONDecodeError:
logger.error("Error decoding response as JSON")
raise ValueError("Invalid JSON response from the API")
def get_question_details(task_id: str, api_base_url: str = API_BASE_URL) -> Dict[str, Any]:
"""
Get detailed information about a specific question/task.
Args:
task_id: The ID of the task to get details for
api_base_url: Base URL for the GAIA API
Returns:
Dictionary containing question details
"""
try:
response = requests.get(f"{api_base_url}/questions/{task_id}")
response.raise_for_status()
return response.json()
except requests.RequestException as e:
logger.error(f"Failed to get question details: {str(e)}")
return {"error": f"Failed to get question details: {str(e)}"}
except json.JSONDecodeError:
logger.error("Invalid JSON response from the API")
return {"error": "Invalid JSON response from the API"}