Spaces:
Sleeping
Sleeping
| """ | |
| Модульная реализация ИИ-агента для 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" | |
| class ToolResult: | |
| """Результат выполнения инструмента.""" | |
| success: bool | |
| data: Any | |
| error: Optional[str] = None | |
| class MemoryItem: | |
| """Элемент памяти агента.""" | |
| content: Any | |
| source: str | |
| timestamp: float = field(default_factory=time.time) | |
| relevance: float = 1.0 | |
| class Task: | |
| """Задача для агента.""" | |
| task_id: str | |
| question: str | |
| level: int | |
| files: List[str] = field(default_factory=list) | |
| context: Dict[str, Any] = field(default_factory=dict) | |
| 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']}") | |