from abc import ABC, abstractmethod from dataclasses import dataclass from typing import Any, Dict, List, Optional from openrouter.components import ChatMessageContentItemTypedDict, ToolDefinitionJSONTypedDict class Tool(ABC): """Интерфейс функции""" @property @abstractmethod def name(self) -> str: """Имя функции (snake_case)""" pass @property @abstractmethod def description(self) -> str: """Текстовое описание функции""" pass @property @abstractmethod def parameters(self) -> Dict[str, Any]: """Описание параметров функции""" pass def to_dict(self) -> ToolDefinitionJSONTypedDict: """JSON-представление инструмента для OpenRouter""" return { "type": "function", "function": { "name": self.name, "description": self.description, "parameters": self.parameters } } @abstractmethod async def execute(self, args: Dict[str, Any], artifacts: Dict[str, Any]) -> List[ChatMessageContentItemTypedDict]: """Вызов функции. :param args: Параметры из JSON :param artifacts: Словарь для хранения артефактов :return: Содержимое JSON-ответа на вызов функции """ pass @dataclass class ToolSet: """Набор логически объединенных функций""" functions: List[Tool] """Список функций, входящих в набор""" system_prompt: str """Дополнение к системному запросу, описывающее, как пользоваться функциями""" def get_function_by_name(self, name: str) -> Optional[Tool]: """Поиск инструмента по имени""" return next((t for t in self.functions if t.name == name), None) def get_all_tools_description(self) -> List[ToolDefinitionJSONTypedDict]: """Получить JSON-описание всех инструментов""" return [tool.to_dict() for tool in self.functions]