Native CLI i18n: The TrustGraph CLI has built-in translation support that dynamically loads language strings. You can test and use different languages by simply passing the --lang flag (e.g., --lang es for Spanish, --lang ru for Russian) or by configuring your environment's LANG variable. Automated Docs Translations: This PR introduces autonomously translated Markdown documentation into several target languages, including Spanish, Swahili, Portuguese, Turkish, Hindi, Hebrew, Arabic, Simplified Chinese, and Russian.
23 KiB
| layout | title | parent |
|---|---|---|
| default | Сервисы инструментов: Динамически подключаемые инструменты для агентов | Russian (Beta) |
Сервисы инструментов: Динамически подключаемые инструменты для агентов
Beta Translation: This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
Статус
Реализовано
Обзор
Эта спецификация определяет механизм динамически подключаемых инструментов для агентов, называемых "сервисами инструментов". В отличие от существующих встроенных типов инструментов (KnowledgeQueryImpl, McpToolImpl и т.д.), сервисы инструментов позволяют добавлять новые инструменты путем:
- Развертывания нового сервиса на базе Pulsar
- Добавления описания конфигурации, которое сообщает агенту, как его вызывать
Это обеспечивает расширяемость без изменения основной структуры агента.
Терминология
| Термин | Определение |
|---|---|
| Встроенный инструмент | Существующие типы инструментов с жестко закодированными реализациями в tools.py |
| Сервис инструмента | Сервис Pulsar, который может быть вызван как инструмент для агента, определенный описанием сервиса |
| Инструмент | Настроенный экземпляр, который ссылается на сервис инструмента и предоставляется агенту/LLM |
Это двухзвенная модель, аналогичная инструментам MCP: MCP: MCP-сервер определяет интерфейс инструмента → Конфигурация инструмента ссылается на него Сервисы инструментов: Сервис инструмента определяет интерфейс Pulsar → Конфигурация инструмента ссылается на него
Обзор: Существующие инструменты
Реализация встроенного инструмента
Инструменты в настоящее время определены в trustgraph-flow/trustgraph/agent/react/tools.py с типизированными реализациями:
class KnowledgeQueryImpl:
async def invoke(self, question):
client = self.context("graph-rag-request")
return await client.rag(question, self.collection)
Каждый тип инструмента:
Имеет жестко заданный сервис Pulsar, к которому он обращается (например, graph-rag-request)
Знает точный метод, который нужно вызвать у клиента (например, client.rag())
Имеет типизированные аргументы, определенные в реализации
Регистрация инструментов (service.py:105-214)
Инструменты загружаются из конфигурации с помощью поля type, которое сопоставляется с реализацией:
if impl_id == "knowledge-query":
impl = functools.partial(KnowledgeQueryImpl, collection=data.get("collection"))
elif impl_id == "text-completion":
impl = TextCompletionImpl
# ... etc
Архитектура
Двухуровневая модель
Уровень 1: Описание сервиса инструмента
Сервис инструмента определяет интерфейс сервиса Pulsar. Он объявляет: Очереди Pulsar для запросов/ответов Параметры конфигурации, которые он требует от инструментов, использующих его
{
"id": "custom-rag",
"request-queue": "non-persistent://tg/request/custom-rag",
"response-queue": "non-persistent://tg/response/custom-rag",
"config-params": [
{"name": "collection", "required": true}
]
}
Сервис, который не требует параметров конфигурации:
{
"id": "calculator",
"request-queue": "non-persistent://tg/request/calc",
"response-queue": "non-persistent://tg/response/calc",
"config-params": []
}
Уровень 2: Описание инструмента
Инструмент ссылается на сервис инструмента и предоставляет: Значения параметров конфигурации (соответствующие требованиям сервиса) Метаданные инструмента для агента (название, описание) Определения аргументов для LLM
{
"type": "tool-service",
"name": "query-customers",
"description": "Query the customer knowledge base",
"service": "custom-rag",
"collection": "customers",
"arguments": [
{
"name": "question",
"type": "string",
"description": "The question to ask about customers"
}
]
}
Несколько инструментов могут ссылаться на один и тот же сервис с разными конфигурациями:
{
"type": "tool-service",
"name": "query-products",
"description": "Query the product knowledge base",
"service": "custom-rag",
"collection": "products",
"arguments": [
{
"name": "question",
"type": "string",
"description": "The question to ask about products"
}
]
}
Формат запроса
Когда вызывается инструмент, запрос к службе инструмента включает в себя:
user: Из запроса агента (многопользовательский режим)
config: Значения конфигурации, закодированные в формате JSON, из описания инструмента
arguments: Аргументы, закодированные в формате JSON, из LLM
{
"user": "alice",
"config": "{\"collection\": \"customers\"}",
"arguments": "{\"question\": \"What are the top customer complaints?\"}"
}
Сервис инструментов получает это в виде разобранных словарей в методе invoke.
Общая реализация сервиса инструментов
Класс ToolServiceImpl вызывает сервисы инструментов на основе конфигурации:
class ToolServiceImpl:
def __init__(self, context, request_queue, response_queue, config_values, arguments, processor):
self.request_queue = request_queue
self.response_queue = response_queue
self.config_values = config_values # e.g., {"collection": "customers"}
# ...
async def invoke(self, **arguments):
client = await self._get_or_create_client()
response = await client.call(user, self.config_values, arguments)
if isinstance(response, str):
return response
else:
return json.dumps(response)
Принятые решения по проектированию
Модель конфигурации с двумя уровнями
Сервисы инструментов следуют двухслойной модели, аналогичной инструментам MCP:
- Сервис инструмента: Определяет интерфейс сервиса Pulsar (тема, необходимые параметры конфигурации).
- Инструмент: Ссылается на сервис инструмента, предоставляет значения конфигурации, определяет аргументы LLM.
Это разделение позволяет: Использовать один сервис инструмента несколькими инструментами с разными конфигурациями. Четко различать интерфейс сервиса и конфигурацию инструмента. Повторное использование определений сервисов.
Отображение запросов: Прямая передача с оболочкой
Запрос к сервису инструмента представляет собой структурированную оболочку, содержащую:
user: Передается из запроса агента для поддержки многопользовательской среды.
Значения конфигурации: Из описателя инструмента (например, collection).
arguments: Аргументы, предоставленные LLM, передаются в виде словаря.
Менеджер агента анализирует ответ LLM в act.arguments в виде словаря (agent_manager.py:117-154). Этот словарь включается в оболочку запроса.
Обработка схем: Без типов
Запросы и ответы используют нетипизированные словари. Отсутствует проверка схемы на уровне агента - сервис инструмента отвечает за проверку своих входных данных. Это обеспечивает максимальную гибкость при определении новых сервисов.
Клиентский интерфейс: Прямые темы Pulsar
Сервисы инструментов используют прямые темы Pulsar без необходимости настройки потоков. Описатель сервиса инструмента указывает полные имена очередей:
{
"id": "joke-service",
"request-queue": "non-persistent://tg/request/joke",
"response-queue": "non-persistent://tg/response/joke",
"config-params": [...]
}
Это позволяет размещать сервисы в любом пространстве имен.
Обработка ошибок: Стандартная конвенция для ошибок
Ответы сервисов инструментов соответствуют существующей схеме с полем error:
@dataclass
class Error:
type: str = ""
message: str = ""
Структура ответа:
Успех: error имеет значение None, ответ содержит результат
Ошибка: error заполняется значениями type и message
Это соответствует шаблону, используемому во всех существующих схемах сервисов (например, PromptResponse, QueryResponse, AgentResponse).
Корреляция запросов и ответов
Корреляция запросов и ответов осуществляется с использованием id в свойствах сообщения Pulsar:
Запрос включает id в свойствах: properties={"id": id}
Ответы включают тот же id: properties={"id": id}
Это соответствует существующему шаблону, используемому во всей кодовой базе (например, agent_service.py, llm_service.py).
Поддержка потоковой передачи
Сервисы инструментов могут возвращать потоковые ответы:
Несколько сообщений ответа с тем же id в свойствах
Каждый ответ включает поле end_of_stream: bool
Заключительный ответ имеет end_of_stream: True
Это соответствует шаблону, используемому в AgentResponse и других сервисах потоковой передачи.
Обработка ответов: Возврат строки
Все существующие инструменты следуют одному и тому же шаблону: получение аргументов в виде словаря, возврат наблюдения в виде строки.
| Инструмент | Обработка ответов |
|---|---|
KnowledgeQueryImpl |
Возвращает client.rag() напрямую (строка) |
TextCompletionImpl |
Возвращает client.question() напрямую (строка) |
McpToolImpl |
Возвращает строку, или json.dumps(output), если это не строка |
StructuredQueryImpl |
Форматирует результат в строку |
PromptImpl |
Возвращает client.prompt() напрямую (строка) |
Сервисы инструментов следуют тому же контракту:
Сервис возвращает строковый ответ (наблюдение)
Если ответ не является строкой, он преобразуется с помощью json.dumps()
Не требуется конфигурация извлечения в дескрипторе
Это упрощает дескриптор и возлагает ответственность на сервис по возврату соответствующего текстового ответа для агента.
Руководство по настройке
Для добавления нового сервиса инструмента требуются два элемента конфигурации:
1. Конфигурация сервиса инструмента
Хранится под ключом конфигурации tool-service. Определяет очереди Pulsar и доступные параметры конфигурации.
| Поле | Обязательно | Описание |
|---|---|---|
id |
Да | Уникальный идентификатор для сервиса инструмента |
request-queue |
Да | Полная тема Pulsar для запросов (например, non-persistent://tg/request/joke) |
response-queue |
Да | Полная тема Pulsar для ответов (например, non-persistent://tg/response/joke) |
config-params |
Нет | Массив параметров конфигурации, которые принимает сервис |
Каждый параметр конфигурации может указывать:
name: Имя параметра (обязательно)
required: Должен ли параметр предоставляться инструментами (по умолчанию: false)
Пример:
{
"id": "joke-service",
"request-queue": "non-persistent://tg/request/joke",
"response-queue": "non-persistent://tg/response/joke",
"config-params": [
{"name": "style", "required": false}
]
}
2. Конфигурация инструмента
Хранится под ключом конфигурации tool. Определяет инструмент, которым может пользоваться агент.
| Поле | Обязательно | Описание |
|---|---|---|
type |
Да | Должно быть "tool-service" |
name |
Да | Название инструмента, доступное для LLM |
description |
Да | Описание того, что делает инструмент (отображается для LLM) |
service |
Да | ID сервиса инструмента, который необходимо вызвать |
arguments |
Нет | Массив определений аргументов для LLM |
| (параметры конфигурации) | Зависит | Любые параметры конфигурации, определенные сервисом |
Каждый аргумент может содержать:
name: Имя аргумента (обязательно)
type: Тип данных, например, "string" (обязательно)
description: Описание, отображаемое для LLM (обязательно)
Пример:
{
"type": "tool-service",
"name": "tell-joke",
"description": "Tell a joke on a given topic",
"service": "joke-service",
"style": "pun",
"arguments": [
{
"name": "topic",
"type": "string",
"description": "The topic for the joke (e.g., programming, animals, food)"
}
]
}
Загрузка конфигурации
Используйте tg-put-config-item для загрузки конфигураций:
# Load tool-service config
tg-put-config-item tool-service/joke-service < joke-service.json
# Load tool config
tg-put-config-item tool/tell-joke < tell-joke.json
Агент-менеджер должен быть перезапущен для применения новых конфигураций.
Детали реализации
Схема
Типы запросов и ответов в trustgraph-base/trustgraph/schema/services/tool_service.py:
@dataclass
class ToolServiceRequest:
user: str = "" # User context for multi-tenancy
config: str = "" # JSON-encoded config values from tool descriptor
arguments: str = "" # JSON-encoded arguments from LLM
@dataclass
class ToolServiceResponse:
error: Error | None = None
response: str = "" # String response (the observation)
end_of_stream: bool = False
Серверная часть: DynamicToolService
Базовый класс в trustgraph-base/trustgraph/base/dynamic_tool_service.py:
class DynamicToolService(AsyncProcessor):
"""Base class for implementing tool services."""
def __init__(self, **params):
topic = params.get("topic", default_topic)
# Constructs topics: non-persistent://tg/request/{topic}, non-persistent://tg/response/{topic}
# Sets up Consumer and Producer
async def invoke(self, user, config, arguments):
"""Override this method to implement the tool's logic."""
raise NotImplementedError()
Клиентская часть: ToolServiceImpl
Реализация в trustgraph-flow/trustgraph/agent/react/tools.py:
class ToolServiceImpl:
def __init__(self, context, request_queue, response_queue, config_values, arguments, processor):
# Uses the provided queue paths directly
# Creates ToolServiceClient on first use
async def invoke(self, **arguments):
client = await self._get_or_create_client()
response = await client.call(user, config_values, arguments)
return response if isinstance(response, str) else json.dumps(response)
Файлы
| Файл | Назначение |
|---|---|
trustgraph-base/trustgraph/schema/services/tool_service.py |
Схемы запросов/ответов |
trustgraph-base/trustgraph/base/tool_service_client.py |
Клиент для вызова сервисов |
trustgraph-base/trustgraph/base/dynamic_tool_service.py |
Базовый класс для реализации сервиса |
trustgraph-flow/trustgraph/agent/react/tools.py |
Класс ToolServiceImpl |
trustgraph-flow/trustgraph/agent/react/service.py |
Загрузка конфигурации |
Пример: Сервис шуток
Пример сервиса на trustgraph-flow/trustgraph/tool_service/joke/:
class Processor(DynamicToolService):
async def invoke(self, user, config, arguments):
style = config.get("style", "pun")
topic = arguments.get("topic", "")
joke = pick_joke(topic, style)
return f"Hey {user}! Here's a {style} for you:\n\n{joke}"
Конфигурация сервиса инструментов:
{
"id": "joke-service",
"request-queue": "non-persistent://tg/request/joke",
"response-queue": "non-persistent://tg/response/joke",
"config-params": [{"name": "style", "required": false}]
}
Конфигурация инструмента:
{
"type": "tool-service",
"name": "tell-joke",
"description": "Tell a joke on a given topic",
"service": "joke-service",
"style": "pun",
"arguments": [
{"name": "topic", "type": "string", "description": "The topic for the joke"}
]
}
Обратная совместимость
Существующие встроенные типы инструментов продолжают работать без изменений.
tool-service - это новый тип инструмента, который существует наряду с существующими типами (knowledge-query, mcp-tool и т.д.).
Будущие соображения
Сервисы с автоматическим оповещением
В будущем можно будет реализовать функцию, позволяющую сервисам публиковать свои собственные описания:
Сервисы публикуют информацию при запуске в определенной теме tool-descriptors.
Агент подписывается и динамически регистрирует инструменты.
Это обеспечивает возможность подключения и использования без изменения конфигурации.
Это выходит за рамки первоначальной реализации.
Ссылки
Текущая реализация инструментов: trustgraph-flow/trustgraph/agent/react/tools.py
Регистрация инструментов: trustgraph-flow/trustgraph/agent/react/service.py:105-214
Схемы агента: trustgraph-base/trustgraph/schema/services/agent.py