Spaces:
Sleeping
Sleeping
Commit ·
1b34f03
1
Parent(s): 24d5bb0
Refactored + Added prompts + Added Tools (Calculator, FileDownloader, ImageReader, Pandas, WebSearch) + NebiusAI inference added
Browse files- __pycache__/agent.cpython-313.pyc +0 -0
- agent.py +38 -0
- agent_models/__pycache__/models.cpython-313.pyc +0 -0
- agent_models/models.py +22 -0
- agent_prompts/SystemPrompt.py +9 -1
- agent_prompts/__pycache__/SystemPrompt.cpython-313.pyc +0 -0
- agent_tools/CalculatorTool.py +29 -0
- agent_tools/FileDownloaderTool.py +56 -0
- agent_tools/ImageReaderTool.py +56 -0
- agent_tools/PandasTool.py +39 -0
- agent_tools/WebSearchTool.py +1 -1
- agent_tools/__pycache__/CalculatorTool.cpython-313.pyc +0 -0
- agent_tools/__pycache__/FileDownloaderTool.cpython-313.pyc +0 -0
- agent_tools/__pycache__/ImageReaderTool.cpython-313.pyc +0 -0
- agent_tools/__pycache__/PandasTool.cpython-313.pyc +0 -0
- agent_tools/__pycache__/WebSearchTool.cpython-313.pyc +0 -0
- app.py +25 -69
- requirements.txt +10 -2
__pycache__/agent.cpython-313.pyc
ADDED
|
Binary file (2.5 kB). View file
|
|
|
agent.py
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import sys
|
| 2 |
+
import inspect
|
| 3 |
+
import logging
|
| 4 |
+
from llama_index.core.agent import ReActAgent
|
| 5 |
+
from agent_models.models import get_language_model
|
| 6 |
+
from agent_tools.WebSearchTool import web_search_tools
|
| 7 |
+
from agent_tools.FileDownloaderTool import get_downloader_tool
|
| 8 |
+
from agent_tools.ImageReaderTool import get_image_interpreter_tool
|
| 9 |
+
from agent_tools.CalculatorTool import get_calculator_tool
|
| 10 |
+
from agent_tools.PandasTool import get_pandas_tool
|
| 11 |
+
from agent_prompts.SystemPrompt import gaia_system_prompt
|
| 12 |
+
|
| 13 |
+
#Logging
|
| 14 |
+
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
|
| 15 |
+
logging.getLogger().addHandler(logging.StreamHandler(stream=sys.stdout))
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
# Agent Definition
|
| 19 |
+
class GaiaAgent:
|
| 20 |
+
def __init__(self):
|
| 21 |
+
# print(f"ReAct Agent signature--------------------------------------- \n {inspect.signature(ReActAgent.from_tools)} \n ReAct Agent signature--------------------------------------- \n" )
|
| 22 |
+
list_of_search_tools = web_search_tools()
|
| 23 |
+
list_of_other_tools = [get_downloader_tool(), get_image_interpreter_tool(), get_calculator_tool(), get_pandas_tool()]
|
| 24 |
+
|
| 25 |
+
self.llm = get_language_model()
|
| 26 |
+
self.tools = list_of_search_tools + list_of_other_tools
|
| 27 |
+
self.agent = ReActAgent.from_tools(tools=self.tools, llm=self.llm, context=gaia_system_prompt, verbose=True)
|
| 28 |
+
|
| 29 |
+
async def __call__(self, question: str) -> str:
|
| 30 |
+
response_object = self.agent.chat(question)
|
| 31 |
+
full_response_text = str(response_object)
|
| 32 |
+
|
| 33 |
+
final_answer_prefix = "FINAL ANSWER:"
|
| 34 |
+
if final_answer_prefix in full_response_text:
|
| 35 |
+
clean_answer = full_response_text.split(final_answer_prefix, 1)[1].strip()
|
| 36 |
+
return clean_answer
|
| 37 |
+
else:
|
| 38 |
+
return full_response_text
|
agent_models/__pycache__/models.cpython-313.pyc
ADDED
|
Binary file (1.65 kB). View file
|
|
|
agent_models/models.py
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
from llama_index.llms.nebius import NebiusLLM
|
| 3 |
+
from llama_index.llms.huggingface_api import HuggingFaceInferenceAPI
|
| 4 |
+
from openai import OpenAI
|
| 5 |
+
|
| 6 |
+
# NebiusAI API Key
|
| 7 |
+
os.environ["NEBIUS_API_KEY"] = ""
|
| 8 |
+
|
| 9 |
+
# Model config variable
|
| 10 |
+
llm_Id = "Qwen/Qwen2.5-32B-Instruct"
|
| 11 |
+
|
| 12 |
+
def get_language_model():
|
| 13 |
+
'''Initializes and returns the LLM for Agent's core functionality'''
|
| 14 |
+
return NebiusLLM(api_key=os.getenv("NEBIUS_API_KEY"), model=llm_Id) # To use HuggingFaceInferenceAPI -> return HuggingFaceInferenceAPI(model_name=llm_Id)
|
| 15 |
+
|
| 16 |
+
def get_vision_model_client():
|
| 17 |
+
'''Initializes and returns the vision model for analyzing images'''
|
| 18 |
+
|
| 19 |
+
return OpenAI(
|
| 20 |
+
api_key=os.getenv("NEBIUS_API_KEY"),
|
| 21 |
+
base_url="https://api.studio.nebius.com/v1/"
|
| 22 |
+
)
|
agent_prompts/SystemPrompt.py
CHANGED
|
@@ -49,4 +49,12 @@ Action: calculate["20 divided by 80 times 100"]
|
|
| 49 |
Observation: 20/80 × 100 = 25.
|
| 50 |
Thought: That is twenty‑five percent.
|
| 51 |
FINAL ANSWER: twenty-five percent
|
| 52 |
-
'''
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 49 |
Observation: 20/80 × 100 = 25.
|
| 50 |
Thought: That is twenty‑five percent.
|
| 51 |
FINAL ANSWER: twenty-five percent
|
| 52 |
+
'''
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
vision_model_system_prompt = '''
|
| 56 |
+
You are an expert image analyst. Describe the contents of this image in detail. Focus on the minute details present in the image that might be important to the overall context.
|
| 57 |
+
If it is a chess board, describe the exact position of all pieces for both black and white (Pay very close attention to the numbers and letters to determine position).
|
| 58 |
+
|
| 59 |
+
You MUST ALWAYS VERIFY that your output is correct before sending it to the user.
|
| 60 |
+
'''
|
agent_prompts/__pycache__/SystemPrompt.cpython-313.pyc
CHANGED
|
Binary files a/agent_prompts/__pycache__/SystemPrompt.cpython-313.pyc and b/agent_prompts/__pycache__/SystemPrompt.cpython-313.pyc differ
|
|
|
agent_tools/CalculatorTool.py
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import numexpr
|
| 2 |
+
from llama_index.core.tools import FunctionTool
|
| 3 |
+
|
| 4 |
+
def calculate(expression: str) -> str:
|
| 5 |
+
"""
|
| 6 |
+
A safe calculator that evaluates a mathematical string expression.
|
| 7 |
+
This tool can handle complex expressions with parentheses, addition,
|
| 8 |
+
subtraction, multiplication, and division.
|
| 9 |
+
Args:
|
| 10 |
+
expression (str): The mathematical expression to evaluate (e.g., "2 * (3 + 4)").
|
| 11 |
+
"""
|
| 12 |
+
print(f"Calculating expression: {expression}")
|
| 13 |
+
try:
|
| 14 |
+
# Use the numexpr library to safely evaluate the string.
|
| 15 |
+
result = numexpr.evaluate(expression).item()
|
| 16 |
+
|
| 17 |
+
# Return the result as a string for the agent to process.
|
| 18 |
+
return str(result)
|
| 19 |
+
except Exception as e:
|
| 20 |
+
# If the expression is invalid, return a descriptive error.
|
| 21 |
+
return f"Error: Invalid mathematical expression. Please check your syntax. Details: {e}"
|
| 22 |
+
|
| 23 |
+
def get_calculator_tool() -> FunctionTool:
|
| 24 |
+
"""Initializes and returns our custom-built, safe calculator tool."""
|
| 25 |
+
return FunctionTool.from_defaults(
|
| 26 |
+
fn=calculate,
|
| 27 |
+
name="calculator",
|
| 28 |
+
description="A tool for evaluating mathematical expressions. Use this for any math calculations, like addition, subtraction, multiplication, division, etc. Example input: '(25 * 4) + 15 - 5'"
|
| 29 |
+
)
|
agent_tools/FileDownloaderTool.py
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import requests
|
| 2 |
+
import os
|
| 3 |
+
from llama_index.core.tools import FunctionTool
|
| 4 |
+
|
| 5 |
+
BASE_API_URL = "https://agents-course-unit4-scoring.hf.space"
|
| 6 |
+
|
| 7 |
+
def download_file(task_id: str, file_name: str) -> str:
|
| 8 |
+
"""
|
| 9 |
+
Downloads a file for a given task_id from the GAIA API.
|
| 10 |
+
Args:
|
| 11 |
+
task_id (str): The ID of the task to download the file for.
|
| 12 |
+
file_name (str): The name to save the file as.
|
| 13 |
+
Returns:
|
| 14 |
+
str: The local path to the downloaded file.
|
| 15 |
+
"""
|
| 16 |
+
|
| 17 |
+
print(f"Attempting to download file for task: {task_id}")
|
| 18 |
+
|
| 19 |
+
# 1. Construct the full URL for the file endpoint.
|
| 20 |
+
file_url = f"{BASE_API_URL}/files/{task_id}"
|
| 21 |
+
|
| 22 |
+
# 2. Define the local directory to save downloads.
|
| 23 |
+
download_dir = "downloads"
|
| 24 |
+
os.makedirs(download_dir, exist_ok=True)
|
| 25 |
+
|
| 26 |
+
# 3. Construct the full local path for the file.
|
| 27 |
+
local_filepath = os.path.join(download_dir, file_name)
|
| 28 |
+
|
| 29 |
+
# 4. Make a GET request to the file_url.
|
| 30 |
+
try:
|
| 31 |
+
response = requests.get(file_url, timeout=20)
|
| 32 |
+
# This will raise an exception for bad status codes (like 404).
|
| 33 |
+
response.raise_for_status()
|
| 34 |
+
|
| 35 |
+
# 5. Save the content of the response to the local file.
|
| 36 |
+
with open(local_filepath, 'wb') as f:
|
| 37 |
+
f.write(response.content)
|
| 38 |
+
|
| 39 |
+
print(f"Successfully downloaded file to: {local_filepath}")
|
| 40 |
+
|
| 41 |
+
# 6. Return the local file path.
|
| 42 |
+
return local_filepath
|
| 43 |
+
|
| 44 |
+
except requests.exceptions.RequestException as e:
|
| 45 |
+
error_message = f"Failed to download file for task {task_id}. Error: {e}"
|
| 46 |
+
print(error_message)
|
| 47 |
+
return error_message
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
# Wrapper function to create the tool
|
| 51 |
+
def get_downloader_tool() -> FunctionTool:
|
| 52 |
+
return FunctionTool.from_defaults(
|
| 53 |
+
fn=download_file,
|
| 54 |
+
name="file_downloader",
|
| 55 |
+
description="A tool to download files associated with a specific task ID. Use this when a question mentions an image, audio file, or other document."
|
| 56 |
+
)
|
agent_tools/ImageReaderTool.py
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import base64
|
| 3 |
+
from llama_index.core.tools import FunctionTool
|
| 4 |
+
from llama_index.readers.file.image import ImageReader
|
| 5 |
+
from agent_models.models import get_vision_model_client
|
| 6 |
+
from agent_prompts.SystemPrompt import vision_model_system_prompt
|
| 7 |
+
|
| 8 |
+
def get_image_description(image_path: str) -> str:
|
| 9 |
+
"""
|
| 10 |
+
Analyzes a local image and returns a text description. This tool is used to "see" what is in an image file.
|
| 11 |
+
Args:
|
| 12 |
+
image_path (str): The local file path of the image to analyze.
|
| 13 |
+
"""
|
| 14 |
+
try:
|
| 15 |
+
print(f"Analyzing image at path: {image_path}")
|
| 16 |
+
|
| 17 |
+
# Read and encode the image
|
| 18 |
+
with open(image_path, "rb") as img_file:
|
| 19 |
+
b64_image = base64.b64encode(img_file.read()).decode("utf-8")
|
| 20 |
+
b64_url = f"data:image/png;base64,{b64_image}"
|
| 21 |
+
|
| 22 |
+
# Get Nebius client
|
| 23 |
+
client = get_vision_model_client()
|
| 24 |
+
|
| 25 |
+
# Call Nebius API
|
| 26 |
+
response = client.chat.completions.create(
|
| 27 |
+
model="Qwen/Qwen2-VL-72B-Instruct",
|
| 28 |
+
messages=[
|
| 29 |
+
{
|
| 30 |
+
"role": "system",
|
| 31 |
+
"content": vision_model_system_prompt
|
| 32 |
+
},
|
| 33 |
+
{
|
| 34 |
+
"role": "user",
|
| 35 |
+
"content": [
|
| 36 |
+
{"type": "text", "text": "Here is an image."},
|
| 37 |
+
{"type": "image_url", "image_url": {"url": b64_url}}
|
| 38 |
+
]
|
| 39 |
+
}
|
| 40 |
+
]
|
| 41 |
+
)
|
| 42 |
+
|
| 43 |
+
description = response.choices[0].message.content
|
| 44 |
+
print(f"Vision model response: {description}")
|
| 45 |
+
return description
|
| 46 |
+
|
| 47 |
+
except Exception as e:
|
| 48 |
+
return f"Error analyzing image: {e}"
|
| 49 |
+
|
| 50 |
+
# Wrapper function to create the tool for our agent
|
| 51 |
+
def get_image_interpreter_tool() -> FunctionTool:
|
| 52 |
+
return FunctionTool.from_defaults(
|
| 53 |
+
fn=get_image_description,
|
| 54 |
+
name="image_interpreter",
|
| 55 |
+
description="A tool to analyze an image from a local file path and return a detailed text description. Use this to 'see' what is in an image file that has already been downloaded."
|
| 56 |
+
)
|
agent_tools/PandasTool.py
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pandas as pd
|
| 2 |
+
from llama_index.experimental.query_engine import PandasQueryEngine
|
| 3 |
+
from llama_index.core.tools import FunctionTool
|
| 4 |
+
from agent_models.models import get_language_model
|
| 5 |
+
|
| 6 |
+
def analyze_spreadsheet(file_path: str, question: str) -> str:
|
| 7 |
+
"""
|
| 8 |
+
Analyzes a spreadsheet (Excel/CSV) to answer a specific question about its data.
|
| 9 |
+
This is a powerful tool for data analysis on structured files.
|
| 10 |
+
Args:
|
| 11 |
+
file_path (str): The local path to the .xlsx or .csv file.
|
| 12 |
+
question (str): The question to ask about the data in the file.
|
| 13 |
+
"""
|
| 14 |
+
print(f"Analyzing spreadsheet '{file_path}' for question: '{question}'")
|
| 15 |
+
try:
|
| 16 |
+
# Load the spreadsheet into a Pandas DataFrame
|
| 17 |
+
df = pd.read_excel(file_path)
|
| 18 |
+
|
| 19 |
+
# The PandasQueryEngine needs a LLM to translate natural language into Pandas commands.
|
| 20 |
+
llm = get_language_model()
|
| 21 |
+
|
| 22 |
+
# Create the query engine
|
| 23 |
+
query_engine = PandasQueryEngine(df=df, llm=llm, verbose=True)
|
| 24 |
+
|
| 25 |
+
# Ask the question and get the response
|
| 26 |
+
response = query_engine.query(question)
|
| 27 |
+
|
| 28 |
+
return str(response)
|
| 29 |
+
|
| 30 |
+
except Exception as e:
|
| 31 |
+
return f"Error analyzing spreadsheet: {e}"
|
| 32 |
+
|
| 33 |
+
# Wrapper function to create the LlamaIndex tool
|
| 34 |
+
def get_pandas_tool() -> FunctionTool:
|
| 35 |
+
return FunctionTool.from_defaults(
|
| 36 |
+
fn=analyze_spreadsheet,
|
| 37 |
+
name="spreadsheet_analyzer",
|
| 38 |
+
description="A tool to answer questions about data stored in a spreadsheet (.xlsx or .csv). It takes two arguments: the 'file_path' to the spreadsheet and the 'question' to ask about the data."
|
| 39 |
+
)
|
agent_tools/WebSearchTool.py
CHANGED
|
@@ -6,6 +6,6 @@ from llama_index.tools.tavily_research import TavilyToolSpec
|
|
| 6 |
def web_search_tools()->List[FunctionTool]:
|
| 7 |
"Tool to search the web with Tavily (search + scraping)"
|
| 8 |
|
| 9 |
-
os.environ["TAVILY_API_KEY"] = "
|
| 10 |
tavily_spec = TavilyToolSpec(api_key=os.getenv("TAVILY_API_KEY"))
|
| 11 |
return tavily_spec.to_tool_list()
|
|
|
|
| 6 |
def web_search_tools()->List[FunctionTool]:
|
| 7 |
"Tool to search the web with Tavily (search + scraping)"
|
| 8 |
|
| 9 |
+
os.environ["TAVILY_API_KEY"] = ""
|
| 10 |
tavily_spec = TavilyToolSpec(api_key=os.getenv("TAVILY_API_KEY"))
|
| 11 |
return tavily_spec.to_tool_list()
|
agent_tools/__pycache__/CalculatorTool.cpython-313.pyc
ADDED
|
Binary file (1.65 kB). View file
|
|
|
agent_tools/__pycache__/FileDownloaderTool.cpython-313.pyc
ADDED
|
Binary file (2.36 kB). View file
|
|
|
agent_tools/__pycache__/ImageReaderTool.cpython-313.pyc
ADDED
|
Binary file (2.56 kB). View file
|
|
|
agent_tools/__pycache__/PandasTool.cpython-313.pyc
ADDED
|
Binary file (1.91 kB). View file
|
|
|
agent_tools/__pycache__/WebSearchTool.cpython-313.pyc
CHANGED
|
Binary files a/agent_tools/__pycache__/WebSearchTool.cpython-313.pyc and b/agent_tools/__pycache__/WebSearchTool.cpython-313.pyc differ
|
|
|
app.py
CHANGED
|
@@ -1,35 +1,23 @@
|
|
| 1 |
-
import logging
|
| 2 |
-
import sys
|
| 3 |
-
# logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
|
| 4 |
-
# logging.getLogger().addHandler(logging.StreamHandler(stream=sys.stdout))
|
| 5 |
-
|
| 6 |
import os
|
| 7 |
-
import
|
| 8 |
-
import requests
|
| 9 |
import inspect
|
|
|
|
|
|
|
|
|
|
| 10 |
import pandas as pd
|
| 11 |
-
from
|
| 12 |
-
from llama_index.core.agent import ReActAgent
|
| 13 |
-
from agent_tools.WebSearchTool import web_search_tools
|
| 14 |
-
from agent_prompts.SystemPrompt import gaia_system_prompt
|
| 15 |
|
| 16 |
-
#
|
| 17 |
-
|
|
|
|
| 18 |
|
| 19 |
-
#
|
| 20 |
-
|
| 21 |
-
def __init__(self):
|
| 22 |
-
self.llm = HuggingFaceInferenceAPI(model_name = "Qwen/Qwen2.5-72B-Instruct")
|
| 23 |
-
# print(f"ReAct Agent signature--------------------------------------- \n {inspect.signature(ReActAgent.from_tools)} \n ReAct Agent signature--------------------------------------- \n" )
|
| 24 |
-
self.agent = ReActAgent.from_tools(tools=web_search_tools(), llm=self.llm, context=gaia_system_prompt, verbose=True)
|
| 25 |
-
|
| 26 |
-
async def __call__(self, question: str) -> str:
|
| 27 |
-
response = self.agent.chat(question)
|
| 28 |
-
return str(response)
|
| 29 |
|
|
|
|
| 30 |
async def run_and_submit_all( profile: gr.OAuthProfile | None):
|
| 31 |
"""
|
| 32 |
-
Fetches all questions, runs the
|
| 33 |
"""
|
| 34 |
# --- Determine HF Space Runtime URL and Repo URL ---
|
| 35 |
space_id = os.getenv("SPACE_ID") # Get the SPACE_ID for sending link to the code
|
|
@@ -41,13 +29,13 @@ async def run_and_submit_all( profile: gr.OAuthProfile | None):
|
|
| 41 |
print("User not logged in.")
|
| 42 |
return "Please Login to Hugging Face with the button.", None
|
| 43 |
|
| 44 |
-
api_url =
|
| 45 |
questions_url = f"{api_url}/questions"
|
| 46 |
submit_url = f"{api_url}/submit"
|
| 47 |
|
| 48 |
-
# 1. Instantiate Agent
|
| 49 |
try:
|
| 50 |
-
agent =
|
| 51 |
except Exception as e:
|
| 52 |
print(f"Error instantiating agent: {e}")
|
| 53 |
return f"Error initializing agent: {e}", None
|
|
@@ -55,36 +43,6 @@ async def run_and_submit_all( profile: gr.OAuthProfile | None):
|
|
| 55 |
agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
|
| 56 |
print(agent_code)
|
| 57 |
|
| 58 |
-
# 2. Test Case
|
| 59 |
-
test_question = "How many studio albums were published by Mercedes Sosa between 2000 and 2009 (included)?"
|
| 60 |
-
print(f"--- RUNNING SINGLE TEST ---")
|
| 61 |
-
print(f"Question: {test_question}")
|
| 62 |
-
|
| 63 |
-
# 3. Run the agent and display the result
|
| 64 |
-
try:
|
| 65 |
-
# This calls your agent's __call__ method
|
| 66 |
-
submitted_answer = await agent(test_question)
|
| 67 |
-
|
| 68 |
-
# Print the final answer clearly in the terminal
|
| 69 |
-
print("-" * 50)
|
| 70 |
-
print(f">>> AGENT'S FINAL ANSWER: {submitted_answer}")
|
| 71 |
-
print("-" * 50)
|
| 72 |
-
|
| 73 |
-
# Prepare a simple status message and table for the Gradio UI
|
| 74 |
-
status_message = "Test Finished Successfully."
|
| 75 |
-
results_df = pd.DataFrame([
|
| 76 |
-
{"Question": test_question, "Submitted Answer": submitted_answer}
|
| 77 |
-
])
|
| 78 |
-
|
| 79 |
-
except Exception as e:
|
| 80 |
-
print(f"Error during single test run: {e}")
|
| 81 |
-
status_message = f"Agent returned an error: {e}"
|
| 82 |
-
results_df = pd.DataFrame()
|
| 83 |
-
|
| 84 |
-
# 4. Return early to prevent fetching all questions or submitting
|
| 85 |
-
return status_message, results_df
|
| 86 |
-
|
| 87 |
-
'''
|
| 88 |
# 2. Fetch Questions
|
| 89 |
print(f"Fetching questions from: {questions_url}")
|
| 90 |
try:
|
|
@@ -113,11 +71,18 @@ async def run_and_submit_all( profile: gr.OAuthProfile | None):
|
|
| 113 |
for item in questions_data:
|
| 114 |
task_id = item.get("task_id")
|
| 115 |
question_text = item.get("question")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 116 |
if not task_id or question_text is None:
|
| 117 |
print(f"Skipping item with missing task_id or question: {item}")
|
| 118 |
continue
|
| 119 |
try:
|
| 120 |
-
submitted_answer = agent(
|
| 121 |
answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
|
| 122 |
results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
|
| 123 |
except Exception as e:
|
|
@@ -174,24 +139,15 @@ async def run_and_submit_all( profile: gr.OAuthProfile | None):
|
|
| 174 |
status_message = f"An unexpected error occurred during submission: {e}"
|
| 175 |
print(status_message)
|
| 176 |
results_df = pd.DataFrame(results_log)
|
| 177 |
-
return status_message, results_df
|
| 178 |
-
'''
|
| 179 |
|
| 180 |
# --- Build Gradio Interface using Blocks ---
|
| 181 |
with gr.Blocks() as demo:
|
| 182 |
-
gr.Markdown("#
|
| 183 |
gr.Markdown(
|
| 184 |
"""
|
| 185 |
-
**Instructions:**
|
| 186 |
-
|
| 187 |
-
1. Please clone this space, then modify the code to define your agent's logic, the tools, the necessary packages, etc ...
|
| 188 |
-
2. Log in to your Hugging Face account using the button below. This uses your HF username for submission.
|
| 189 |
-
3. Click 'Run Evaluation & Submit All Answers' to fetch questions, run your agent, submit answers, and see the score.
|
| 190 |
-
|
| 191 |
-
---
|
| 192 |
**Disclaimers:**
|
| 193 |
Once clicking on the "submit button, it can take quite some time ( this is the time for the agent to go through all the questions).
|
| 194 |
-
This space provides a basic setup and is intentionally sub-optimal to encourage you to develop your own, more robust solution. For instance for the delay process of the submit button, a solution could be to cache the answers and submit in a seperate action or even to answer the questions in async.
|
| 195 |
"""
|
| 196 |
)
|
| 197 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
import os
|
| 2 |
+
import sys
|
|
|
|
| 3 |
import inspect
|
| 4 |
+
import requests
|
| 5 |
+
import logging
|
| 6 |
+
import gradio as gr
|
| 7 |
import pandas as pd
|
| 8 |
+
from agent import GaiaAgent
|
|
|
|
|
|
|
|
|
|
| 9 |
|
| 10 |
+
# Logging
|
| 11 |
+
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
|
| 12 |
+
logging.getLogger().addHandler(logging.StreamHandler(stream=sys.stdout))
|
| 13 |
|
| 14 |
+
# Constants
|
| 15 |
+
BASE_API_URL = "https://agents-course-unit4-scoring.hf.space"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
|
| 17 |
+
# Function to run GAIA dataset questions
|
| 18 |
async def run_and_submit_all( profile: gr.OAuthProfile | None):
|
| 19 |
"""
|
| 20 |
+
Fetches all questions, runs the GaiaAgent on them, submits all answers, and displays the results.
|
| 21 |
"""
|
| 22 |
# --- Determine HF Space Runtime URL and Repo URL ---
|
| 23 |
space_id = os.getenv("SPACE_ID") # Get the SPACE_ID for sending link to the code
|
|
|
|
| 29 |
print("User not logged in.")
|
| 30 |
return "Please Login to Hugging Face with the button.", None
|
| 31 |
|
| 32 |
+
api_url = BASE_API_URL
|
| 33 |
questions_url = f"{api_url}/questions"
|
| 34 |
submit_url = f"{api_url}/submit"
|
| 35 |
|
| 36 |
+
# 1. Instantiate Agent
|
| 37 |
try:
|
| 38 |
+
agent = GaiaAgent()
|
| 39 |
except Exception as e:
|
| 40 |
print(f"Error instantiating agent: {e}")
|
| 41 |
return f"Error initializing agent: {e}", None
|
|
|
|
| 43 |
agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
|
| 44 |
print(agent_code)
|
| 45 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 46 |
# 2. Fetch Questions
|
| 47 |
print(f"Fetching questions from: {questions_url}")
|
| 48 |
try:
|
|
|
|
| 71 |
for item in questions_data:
|
| 72 |
task_id = item.get("task_id")
|
| 73 |
question_text = item.get("question")
|
| 74 |
+
file_name = item.get("file_name")
|
| 75 |
+
|
| 76 |
+
full_input=f"""
|
| 77 |
+
Task ID: {task_id}
|
| 78 |
+
File Name: {file_name}
|
| 79 |
+
Question: {question_text}
|
| 80 |
+
"""
|
| 81 |
if not task_id or question_text is None:
|
| 82 |
print(f"Skipping item with missing task_id or question: {item}")
|
| 83 |
continue
|
| 84 |
try:
|
| 85 |
+
submitted_answer = await agent(full_input)
|
| 86 |
answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
|
| 87 |
results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
|
| 88 |
except Exception as e:
|
|
|
|
| 139 |
status_message = f"An unexpected error occurred during submission: {e}"
|
| 140 |
print(status_message)
|
| 141 |
results_df = pd.DataFrame(results_log)
|
| 142 |
+
return status_message, results_df
|
|
|
|
| 143 |
|
| 144 |
# --- Build Gradio Interface using Blocks ---
|
| 145 |
with gr.Blocks() as demo:
|
| 146 |
+
gr.Markdown("# GAIA Agent Evaluation Runner")
|
| 147 |
gr.Markdown(
|
| 148 |
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 149 |
**Disclaimers:**
|
| 150 |
Once clicking on the "submit button, it can take quite some time ( this is the time for the agent to go through all the questions).
|
|
|
|
| 151 |
"""
|
| 152 |
)
|
| 153 |
|
requirements.txt
CHANGED
|
@@ -1,6 +1,14 @@
|
|
| 1 |
gradio
|
| 2 |
requests
|
| 3 |
llama-index
|
| 4 |
-
llama-index-llms-huggingface-api
|
| 5 |
llama-index-tools-tavily-research
|
| 6 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
gradio
|
| 2 |
requests
|
| 3 |
llama-index
|
| 4 |
+
# llama-index-llms-huggingface-api
|
| 5 |
llama-index-tools-tavily-research
|
| 6 |
+
llama-index-llms-nebius
|
| 7 |
+
llama-index-multi-modal-llms-nebius
|
| 8 |
+
tavily-python
|
| 9 |
+
llama-index-readers-file
|
| 10 |
+
openai
|
| 11 |
+
numexpr # calculator
|
| 12 |
+
pandas
|
| 13 |
+
openpyxl
|
| 14 |
+
llama-index-experimental
|