sasio06 / agent_implementation.py
Sasa06's picture
Upload 7 files
1fa212d verified
"""
Модульная реализация ИИ-агента для GAIA benchmark.
Этот файл содержит основные компоненты архитектуры агента.
"""
import os
import json
import logging
import requests
from typing import Dict, List, Any, Optional, Union, Callable
from dataclasses import dataclass, field
from enum import Enum
import time
from datetime import datetime
import random
# Настройка логирования
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler("agent.log"),
logging.StreamHandler()
]
)
logger = logging.getLogger("gaia_agent")
# Определение типов и структур данных
class ToolType(Enum):
"""Типы инструментов, доступных агенту."""
BROWSER = "browser"
SEARCH = "search"
IMAGE = "image"
CODE = "code"
CALCULATOR = "calculator"
FILE = "file"
@dataclass
class ToolResult:
"""Результат выполнения инструмента."""
success: bool
data: Any
error: Optional[str] = None
@dataclass
class MemoryItem:
"""Элемент памяти агента."""
content: Any
source: str
timestamp: float = field(default_factory=time.time)
relevance: float = 1.0
@dataclass
class Task:
"""Задача для агента."""
task_id: str
question: str
level: int
files: List[str] = field(default_factory=list)
context: Dict[str, Any] = field(default_factory=dict)
@dataclass
class AgentResponse:
"""Ответ агента на задачу."""
task_id: str
submitted_answer: str
confidence: float
reasoning: str
tools_used: List[str]
class LLMInterface:
"""Интерфейс для взаимодействия с языковыми моделями."""
def __init__(self, model_name: str = "gpt-3.5-turbo", api_key: Optional[str] = None):
"""
Инициализация интерфейса LLM.
Args:
model_name: Имя модели для использования
api_key: API ключ для доступа к модели (если требуется)
"""
self.model_name = model_name
self.api_key = api_key or os.environ.get("OPENAI_API_KEY")
self.max_tokens = 4096
self.temperature = 0.7
logger.info(f"Initialized LLM interface with model: {model_name}")
def generate(self, prompt: str, system_message: Optional[str] = None,
temperature: Optional[float] = None, max_tokens: Optional[int] = None) -> str:
"""
Генерация текста с помощью LLM.
Args:
prompt: Основной текст запроса
system_message: Системное сообщение для установки контекста
temperature: Параметр температуры (разнообразие ответов)
max_tokens: Максимальное количество токенов в ответе
Returns:
Сгенерированный текст
"""
# Здесь должна быть реализация вызова API конкретной модели
# В данном примере используется заглушка
logger.info(f"Generating text with prompt length: {len(prompt)}")
# Имитация вызова API
response = f"This is a simulated response from {self.model_name}"
return response
def generate_with_tools(self, prompt: str, tools: List[Dict[str, Any]],
system_message: Optional[str] = None) -> Dict[str, Any]:
"""
Генерация текста с возможностью вызова инструментов.
Args:
prompt: Основной текст запроса
tools: Список доступных инструментов в формате OpenAI
system_message: Системное сообщение для установки контекста
Returns:
Результат генерации с возможным вызовом инструмента
"""
# Здесь должна быть реализация вызова API с поддержкой инструментов
# В данном примере используется заглушка
logger.info(f"Generating text with {len(tools)} available tools")
# Имитация вызова API
response = {
"content": f"This is a simulated response with tools from {self.model_name}",
"tool_calls": []
}
return response
class Tool:
"""Базовый класс для инструментов агента."""
def __init__(self, name: str, description: str, tool_type: ToolType):
"""
Инициализация инструмента.
Args:
name: Имя инструмента
description: Описание инструмента
tool_type: Тип инструмента
"""
self.name = name
self.description = description
self.tool_type = tool_type
logger.info(f"Initialized tool: {name} ({tool_type.value})")
def execute(self, **kwargs) -> ToolResult:
"""
Выполнение инструмента.
Args:
**kwargs: Параметры для выполнения
Returns:
Результат выполнения
"""
raise NotImplementedError("Tool execution not implemented")
def to_openai_format(self) -> Dict[str, Any]:
"""
Преобразование инструмента в формат OpenAI.
Returns:
Словарь с описанием инструмента в формате OpenAI
"""
return {
"type": "function",
"function": {
"name": self.name,
"description": self.description,
"parameters": {
"type": "object",
"properties": {},
"required": []
}
}
}
class SearchTool(Tool):
"""Инструмент для поиска информации."""
def __init__(self):
"""Инициализация инструмента поиска."""
super().__init__(
name="search",
description="Search for information on the web",
tool_type=ToolType.SEARCH
)
def execute(self, query: str) -> ToolResult:
"""
Выполнение поиска.
Args:
query: Поисковый запрос
Returns:
Результат поиска
"""
logger.info(f"Executing search with query: {query}")
try:
# Здесь должна быть реализация поиска
# В данном примере используется заглушка
results = [
{"title": "Sample result 1", "snippet": "This is a sample search result"},
{"title": "Sample result 2", "snippet": "Another sample search result"}
]
return ToolResult(success=True, data=results)
except Exception as e:
logger.error(f"Search error: {e}")
return ToolResult(success=False, data=None, error=str(e))
def to_openai_format(self) -> Dict[str, Any]:
"""
Преобразование инструмента в формат OpenAI.
Returns:
Словарь с описанием инструмента в формате OpenAI
"""
return {
"type": "function",
"function": {
"name": self.name,
"description": self.description,
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "The search query"
}
},
"required": ["query"]
}
}
}
class BrowserTool(Tool):
"""Инструмент для работы с браузером."""
def __init__(self):
"""Инициализация инструмента браузера."""
super().__init__(
name="browser",
description="Browse websites and extract information",
tool_type=ToolType.BROWSER
)
def execute(self, url: str) -> ToolResult:
"""
Выполнение запроса к веб-странице.
Args:
url: URL страницы
Returns:
Содержимое страницы
"""
logger.info(f"Browsing URL: {url}")
try:
# Здесь должна быть реализация запроса к веб-странице
# В данном примере используется заглушка
content = f"Sample content from {url}"
return ToolResult(success=True, data={"url": url, "content": content})
except Exception as e:
logger.error(f"Browser error: {e}")
return ToolResult(success=False, data=None, error=str(e))
def to_openai_format(self) -> Dict[str, Any]:
"""
Преобразование инструмента в формат OpenAI.
Returns:
Словарь с описанием инструмента в формате OpenAI
"""
return {
"type": "function",
"function": {
"name": self.name,
"description": self.description,
"parameters": {
"type": "object",
"properties": {
"url": {
"type": "string",
"description": "The URL to browse"
}
},
"required": ["url"]
}
}
}
class ImageTool(Tool):
"""Инструмент для работы с изображениями."""
def __init__(self):
"""Инициализация инструмента для работы с изображениями."""
super().__init__(
name="image",
description="Process and analyze images",
tool_type=ToolType.IMAGE
)
def execute(self, image_url: str, task: str = "describe") -> ToolResult:
"""
Обработка изображения.
Args:
image_url: URL изображения
task: Задача для выполнения (describe, analyze, etc.)
Returns:
Результат обработки изображения
"""
logger.info(f"Processing image: {image_url}, task: {task}")
try:
# Здесь должна быть реализация обработки изображения
# В данном примере используется заглушка
description = f"Sample description of image at {image_url}"
return ToolResult(success=True, data={"description": description})
except Exception as e:
logger.error(f"Image processing error: {e}")
return ToolResult(success=False, data=None, error=str(e))
def to_openai_format(self) -> Dict[str, Any]:
"""
Преобразование инструмента в формат OpenAI.
Returns:
Словарь с описанием инструмента в формате OpenAI
"""
return {
"type": "function",
"function": {
"name": self.name,
"description": self.description,
"parameters": {
"type": "object",
"properties": {
"image_url": {
"type": "string",
"description": "The URL of the image to process"
},
"task": {
"type": "string",
"description": "The task to perform on the image (describe, analyze, etc.)",
"enum": ["describe", "analyze", "extract_text", "identify_objects"]
}
},
"required": ["image_url"]
}
}
}
class CodeTool(Tool):
"""Инструмент для выполнения кода."""
def __init__(self):
"""Инициализация инструмента для выполнения кода."""
super().__init__(
name="code",
description="Execute code and return results",
tool_type=ToolType.CODE
)
def execute(self, code: str, language: str = "python") -> ToolResult:
"""
Выполнение кода.
Args:
code: Код для выполнения
language: Язык программирования
Returns:
Результат выполнения кода
"""
logger.info(f"Executing {language} code, length: {len(code)}")
try:
# Здесь должна быть реализация выполнения кода
# В данном примере используется заглушка
result = f"Sample result of executing {language} code"
return ToolResult(success=True, data={"result": result})
except Exception as e:
logger.error(f"Code execution error: {e}")
return ToolResult(success=False, data=None, error=str(e))
def to_openai_format(self) -> Dict[str, Any]:
"""
Преобразование инструмента в формат OpenAI.
Returns:
Словарь с описанием инструмента в формате OpenAI
"""
return {
"type": "function",
"function": {
"name": self.name,
"description": self.description,
"parameters": {
"type": "object",
"properties": {
"code": {
"type": "string",
"description": "The code to execute"
},
"language": {
"type": "string",
"description": "The programming language",
"enum": ["python", "javascript", "bash"]
}
},
"required": ["code"]
}
}
}
class ToolRegistry:
"""Реестр инструментов агента."""
def __init__(self):
"""Инициализация реестра инструментов."""
self.tools: Dict[str, Tool] = {}
logger.info("Initialized tool registry")
def register(self, tool: Tool) -> None:
"""
Регистрация инструмента.
Args:
tool: Инструмент для регистрации
"""
self.tools[tool.name] = tool
logger.info(f"Registered tool: {tool.name}")
def get(self, name: str) -> Optional[Tool]:
"""
Получение инструмента по имени.
Args:
name: Имя инструмента
Returns:
Инструмент или None, если не найден
"""
return self.tools.get(name)
def list_tools(self) -> List[Tool]:
"""
Получение списка всех инструментов.
Returns:
Список инструментов
"""
return list(self.tools.values())
def to_openai_format(self) -> List[Dict[str, Any]]:
"""
Преобразование всех инструментов в формат OpenAI.
Returns:
Список инструментов в формате OpenAI
"""
return [tool.to_openai_format() for tool in self.tools.values()]
class Memory:
"""Система памяти агента."""
def __init__(self, max_items: int = 100):
"""
Инициализация системы памяти.
Args:
max_items: Максимальное количество элементов в памяти
"""
self.items: List[MemoryItem] = []
self.max_items = max_items
logger.info(f"Initialized memory system with max_items={max_items}")
def add(self, content: Any, source: str, relevance: float = 1.0) -> None:
"""
Добавление элемента в память.
Args:
content: Содержимое элемента
source: Источник информации
relevance: Релевантность элемента (0.0-1.0)
"""
item = MemoryItem(content=content, source=source, relevance=relevance)
self.items.append(item)
# Удаление старых элементов, если превышен лимит
if len(self.items) > self.max_items:
# Сортировка по релевантности и времени
self.items.sort(key=lambda x: (x.relevance, x.timestamp), reverse=True)
self.items = self.items[:self.max_items]
logger.info(f"Added memory item from source: {source}")
def get_relevant(self, query: str, limit: int = 5) -> List[MemoryItem]:
"""
Получение релевантных элементов памяти.
Args:
query: Запрос для поиска релевантных элементов
limit: Максимальное количество возвращаемых элементов
Returns:
Список релевантных элементов памяти
"""
# Здесь должна быть реализация поиска релевантных элементов
# В данном примере возвращаются последние элементы
return sorted(self.items, key=lambda x: x.timestamp, reverse=True)[:limit]
def clear(self) -> None:
"""Очистка памяти."""
self.items = []
logger.info("Memory cleared")
class ReasoningEngine:
"""Движок рассуждений агента."""
def __init__(self, llm: LLMInterface, tool_registry: ToolRegistry, memory: Memory):
"""
Инициализация движка рассуждений.
Args:
llm: Интерфейс языковой модели
tool_registry: Реестр инструментов
memory: Система памяти
"""
self.llm = llm
self.tool_registry = tool_registry
self.memory = memory
logger.info("Initialized reasoning engine")
def solve(self, task: Task) -> AgentResponse:
"""
Решение задачи.
Args:
task: Задача для решения
Returns:
Ответ агента
"""
logger.info(f"Starting to solve task: {task.task_id}")
# Подготовка контекста
context = self._prepare_context(task)
# Планирование решения
plan = self._create_plan(task, context)
# Выполнение плана
tools_used = []
reasoning_steps = []
for step in plan:
step_result = self._execute_step(step, context)
reasoning_steps.append(step_result)
if step_result.get("tool_used"):
tools_used.append(step_result["tool_used"])
# Обновление контекста
context["steps"].append(step_result)
# Формирование финального ответа
answer = self._formulate_answer(task, context)
# Создание ответа агента
response = AgentResponse(
task_id=task.task_id,
submitted_answer=answer["answer"],
confidence=answer["confidence"],
reasoning="\n".join([step["reasoning"] for step in reasoning_steps]),
tools_used=tools_used
)
logger.info(f"Completed task: {task.task_id}, confidence: {answer['confidence']}")
return response
def _prepare_context(self, task: Task) -> Dict[str, Any]:
"""
Подготовка контекста для решения задачи.
Args:
task: Задача для решения
Returns:
Контекст для решения задачи
"""
context = {
"task_id": task.task_id,
"question": task.question,
"level": task.level,
"files": task.files,
"steps": [],
"memory_items": self.memory.get_relevant(task.question)
}
# Добавление дополнительного контекста из задачи
context.update(task.context)
return context
def _create_plan(self, task: Task, context: Dict[str, Any]) -> List[Dict[str, Any]]:
"""
Создание плана решения задачи.
Args:
task: Задача для решения
context: Контекст решения
Returns:
План решения задачи
"""
# Формирование промпта для планирования
prompt = f"""
Task: {task.question}
Create a step-by-step plan to solve this task. Each step should be specific and actionable.
"""
# Генерация плана с помощью LLM
plan_text = self.llm.generate(prompt)
# Парсинг плана (в реальной реализации нужно более надежное решение)
# В данном примере используется заглушка
plan = [
{"step": 1, "action": "Analyze the question", "tool": None},
{"step": 2, "action": "Search for relevant information", "tool": "search"},
{"step": 3, "action": "Process and synthesize information", "tool": None},
{"step": 4, "action": "Formulate the answer", "tool": None}
]
logger.info(f"Created plan with {len(plan)} steps")
return plan
def _execute_step(self, step: Dict[str, Any], context: Dict[str, Any]) -> Dict[str, Any]:
"""
Выполнение шага плана.
Args:
step: Шаг плана
context: Контекст решения
Returns:
Результат выполнения шага
"""
logger.info(f"Executing step {step['step']}: {step['action']}")
result = {
"step": step["step"],
"action": step["action"],
"tool_used": None,
"reasoning": "",
"result": None
}
# Если шаг требует использования инструмента
if step["tool"]:
tool = self.tool_registry.get(step["tool"])
if tool:
# Формирование параметров для инструмента
# В реальной реализации нужно более надежное решение
tool_params = {"query": context["question"]} if step["tool"] == "search" else {}
# Выполнение инструмента
tool_result = tool.execute(**tool_params)
result["tool_used"] = step["tool"]
result["result"] = tool_result.data if tool_result.success else {"error": tool_result.error}
# Добавление результата в память
if tool_result.success:
self.memory.add(tool_result.data, f"tool:{step['tool']}")
# Рассуждение о результате шага
reasoning_prompt = f"""
Step {step['step']}: {step['action']}
{result['result'] if result['result'] else 'No tool was used in this step.'}
Based on this information, what can we conclude? How does this help us solve the task?
"""
result["reasoning"] = self.llm.generate(reasoning_prompt)
return result
def _formulate_answer(self, task: Task, context: Dict[str, Any]) -> Dict[str, Any]:
"""
Формулирование финального ответа.
Args:
task: Задача
context: Контекст решения
Returns:
Финальный ответ и уверенность
"""
# Формирование промпта для финального ответа
steps_text = "\n".join([
f"Step {step['step']}: {step['action']}\n{step['reasoning']}"
for step in context["steps"]
])
prompt = f"""
Task: {task.question}
Steps taken:
{steps_text}
Based on the above steps, provide the final answer to the task. Be concise and precise.
The answer should be in the exact format required by the task.
"""
# Генерация ответа с помощью LLM
answer_text = self.llm.generate(prompt)
# В реальной реализации нужно извлечь ответ из текста
# и оценить уверенность
return {
"answer": answer_text,
"confidence": 0.85 # Заглушка
}
class GAIAAPIClient:
"""Клиент для взаимодействия с API GAIA benchmark."""
def __init__(self, api_url: str, username: str):
"""
Инициализация клиента API GAIA.
Args:
api_url: URL API GAIA
username: Имя пользователя Hugging Face
"""
self.api_url = api_url
self.username = username
logger.info(f"Initialized GAIA API client for user: {username}")
def get_questions(self) -> List[Dict[str, Any]]:
"""
Получение списка вопросов.
Returns:
Список вопросов
"""
logger.info("Fetching questions from GAIA API")
try:
# Здесь должен быть запрос к API
# В данном примере используется расширенная заглушка с большим количеством вопросов
questions = []
# Генерация вопросов для уровня 1
for i in range(1, 21):
questions.append({
"task_id": f"task_level1_{i}",
"question": f"Sample level 1 question {i}",
"level": 1
})
# Генерация вопросов для уровня 2
for i in range(1, 21):
questions.append({
"task_id": f"task_level2_{i}",
"question": f"Sample level 2 question {i}",
"level": 2
})
# Генерация вопросов для уровня 3
for i in range(1, 21):
questions.append({
"task_id": f"task_level3_{i}",
"question": f"Sample level 3 question {i}",
"level": 3
})
# Перемешивание вопросов для более реалистичного поведения
random.shuffle(questions)
logger.info(f"Fetched {len(questions)} questions")
return questions
except Exception as e:
logger.error(f"Error fetching questions: {e}")
return []
def get_random_question(self) -> Optional[Dict[str, Any]]:
"""
Получение случайного вопроса.
Returns:
Случайный вопрос или None в случае ошибки
"""
logger.info("Fetching random question from GAIA API")
try:
# Здесь должен быть запрос к API
# В данном примере используется заглушка с выбором случайного уровня
level = random.choice([1, 2, 3])
question = {
"task_id": f"task_random_{int(time.time())}",
"question": f"Sample random question for level {level}",
"level": level
}
logger.info(f"Fetched random question: {question['task_id']}")
return question
except Exception as e:
logger.error(f"Error fetching random question: {e}")
return None
def get_file(self, task_id: str, file_path: str) -> Optional[bytes]:
"""
Получение файла, связанного с заданием.
Args:
task_id: ID задания
file_path: Путь к файлу
Returns:
Содержимое файла или None в случае ошибки
"""
logger.info(f"Fetching file for task: {task_id}, path: {file_path}")
try:
# Здесь должен быть запрос к API
# В данном примере используется заглушка
file_content = b"Sample file content"
logger.info(f"Fetched file: {file_path}")
return file_content
except Exception as e:
logger.error(f"Error fetching file: {e}")
return None
def submit_answer(self, task_id: str, answer: str) -> Dict[str, Any]:
"""
Отправка ответа на задание.
Args:
task_id: ID задания
answer: Ответ на задание
Returns:
Результат отправки
"""
logger.info(f"Submitting answer for task: {task_id}")
try:
# Здесь должен быть запрос к API
# В данном примере используется заглушка
result = {
"success": True,
"is_correct": True,
"score": 1.0
}
logger.info(f"Answer submitted, result: {result}")
return result
except Exception as e:
logger.error(f"Error submitting answer: {e}")
return {"success": False, "error": str(e)}
def submit_batch(self, answers: List[Dict[str, str]], code_link: str) -> Dict[str, Any]:
"""
Отправка пакета ответов.
Args:
answers: Список ответов в формате [{"task_id": "...", "submitted_answer": "..."}]
code_link: Ссылка на код агента
Returns:
Результат отправки
"""
logger.info(f"Submitting batch of {len(answers)} answers")
try:
# Подготовка данных для отправки
payload = {
"username": self.username,
"agent_code": code_link,
"answers": answers
}
# Здесь должен быть запрос к API
# В данном примере используется заглушка с более реалистичными результатами
correct_answers = random.randint(len(answers) // 3, len(answers) // 2)
score = correct_answers / len(answers)
result = {
"success": True,
"score": score,
"correct_answers": correct_answers,
"total_questions": len(answers)
}
logger.info(f"Batch submitted, score: {result['score']}")
return result
except Exception as e:
logger.error(f"Error submitting batch: {e}")
return {"success": False, "error": str(e)}
class AgentController:
"""Основной контроллер агента."""
def __init__(self, model_name: str = "gpt-3.5-turbo", api_key: Optional[str] = None,
gaia_api_url: str = "https://api.example.com/gaia",
username: str = "default_user"):
"""
Инициализация контроллера агента.
Args:
model_name: Имя модели для использования
api_key: API ключ для доступа к модели
gaia_api_url: URL API GAIA
username: Имя пользователя Hugging Face
"""
# Инициализация компонентов
self.llm = LLMInterface(model_name=model_name, api_key=api_key)
self.tool_registry = ToolRegistry()
self.memory = Memory()
self.reasoning_engine = ReasoningEngine(self.llm, self.tool_registry, self.memory)
self.gaia_client = GAIAAPIClient(api_url=gaia_api_url, username=username)
# Регистрация стандартных инструментов
self._register_default_tools()
logger.info(f"Initialized agent controller with model: {model_name}")
def _register_default_tools(self) -> None:
"""Регистрация стандартных инструментов."""
self.tool_registry.register(SearchTool())
self.tool_registry.register(BrowserTool())
self.tool_registry.register(ImageTool())
self.tool_registry.register(CodeTool())
logger.info("Registered default tools")
def process_question(self, question: str) -> str:
"""
Обработка отдельного вопроса.
Args:
question: Вопрос для обработки
Returns:
Ответ на вопрос
"""
logger.info(f"Processing question: {question}")
# Создание задачи
task = Task(
task_id=f"manual_{int(time.time())}",
question=question,
level=1
)
# Решение задачи
response = self.reasoning_engine.solve(task)
return response.submitted_answer
def run_benchmark(self, num_questions: int = 20, level: Optional[int] = 1,
code_link: str = "") -> Dict[str, Any]:
"""
Запуск бенчмарка GAIA.
Args:
num_questions: Количество вопросов
level: Уровень сложности (None для всех уровней)
code_link: Ссылка на код агента
Returns:
Результаты бенчмарка
"""
logger.info(f"Running GAIA benchmark with {num_questions} questions, level: {level}")
# Получение вопросов
questions_data = self.gaia_client.get_questions()
# Фильтрация по уровню
if level is not None:
questions_data = [q for q in questions_data if q.get("level") == level]
logger.info(f"Filtered questions by level {level}, remaining: {len(questions_data)}")
# Проверка наличия вопросов после фильтрации
if not questions_data:
logger.warning(f"No questions available for level {level}, using all levels")
questions_data = self.gaia_client.get_questions()
# Ограничение количества вопросов
if num_questions > 0 and num_questions < len(questions_data):
questions_data = questions_data[:num_questions]
logger.info(f"Selected {len(questions_data)} questions for benchmark")
if not questions_data:
logger.error("No questions available for benchmark")
return {
"success": False,
"error": "No questions available",
"score": 0.0,
"results": []
}
# Обработка вопросов
results = []
answers = []
for q_data in questions_data:
task = Task(
task_id=q_data["task_id"],
question=q_data["question"],
level=q_data.get("level", 1)
)
# Решение задачи
response = self.reasoning_engine.solve(task)
# Сохранение результата
results.append({
"task_id": task.task_id,
"question": task.question,
"answer": response.submitted_answer,
"confidence": response.confidence
})
# Подготовка ответа для отправки
answers.append({
"task_id": task.task_id,
"submitted_answer": response.submitted_answer
})
# Отправка результатов
submission_result = self.gaia_client.submit_batch(answers, code_link)
# Формирование итогового результата
benchmark_result = {
"success": submission_result.get("success", False),
"score": submission_result.get("score", 0.0),
"correct_answers": submission_result.get("correct_answers", 0),
"total_questions": len(questions_data),
"results": results
}
logger.info(f"Benchmark completed, score: {benchmark_result['score']}")
return benchmark_result
# Пример использования
if __name__ == "__main__":
# Инициализация агента
agent = AgentController(
model_name="gpt-3.5-turbo",
username="your_username"
)
# Обработка вопроса
answer = agent.process_question("What is the capital of France?")
print(f"Answer: {answer}")
# Запуск бенчмарка
results = agent.run_benchmark(
num_questions=5,
level=1,
code_link="https://huggingface.co/spaces/your_username/your_space/tree/main"
)
print(f"Benchmark score: {results['score']}")