mirror of
https://github.com/trustgraph-ai/trustgraph.git
synced 2026-04-25 08:26:21 +02:00
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.
479 lines
17 KiB
Markdown
479 lines
17 KiB
Markdown
---
|
|
layout: default
|
|
title: "Serviços de Ferramentas: Ferramentas de Agente Dinamicamente Plugáveis"
|
|
parent: "Portuguese (Beta)"
|
|
---
|
|
|
|
# Serviços de Ferramentas: Ferramentas de Agente Dinamicamente Plugáveis
|
|
|
|
> **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.
|
|
|
|
## Status
|
|
|
|
Implementado
|
|
|
|
## Visão Geral
|
|
|
|
Esta especificação define um mecanismo para ferramentas de agente dinamicamente plugáveis, chamadas "serviços de ferramentas". Ao contrário dos tipos de ferramentas integradas existentes (`KnowledgeQueryImpl`, `McpToolImpl`, etc.), os serviços de ferramentas permitem que novas ferramentas sejam introduzidas por:
|
|
|
|
1. Implantando um novo serviço baseado em Pulsar
|
|
2. Adicionando um descritor de configuração que informa ao agente como invocá-lo
|
|
|
|
Isso permite a extensibilidade sem modificar o framework de resposta do agente principal.
|
|
|
|
## Terminologia
|
|
|
|
| Termo | Definição |
|
|
|------|------------|
|
|
| **Ferramenta Integrada** | Tipos de ferramentas existentes com implementações codificadas em `tools.py` |
|
|
| **Serviço de Ferramenta** | Um serviço Pulsar que pode ser invocado como uma ferramenta de agente, definido por um descritor de serviço |
|
|
| **Ferramenta** | Uma instância configurada que referencia um serviço de ferramenta, exposta ao agente/LLM |
|
|
|
|
Este é um modelo de duas camadas, análogo às ferramentas MCP:
|
|
MCP: O servidor MCP define a interface da ferramenta → A configuração da ferramenta a referencia
|
|
Serviços de Ferramenta: O serviço de ferramenta define a interface Pulsar → A configuração da ferramenta a referencia
|
|
|
|
## Contexto: Ferramentas Existentes
|
|
|
|
### Implementação de Ferramenta Integrada
|
|
|
|
As ferramentas são atualmente definidas em `trustgraph-flow/trustgraph/agent/react/tools.py` com implementações tipadas:
|
|
|
|
```python
|
|
class KnowledgeQueryImpl:
|
|
async def invoke(self, question):
|
|
client = self.context("graph-rag-request")
|
|
return await client.rag(question, self.collection)
|
|
```
|
|
|
|
Cada tipo de ferramenta:
|
|
Possui um serviço Pulsar pré-definido que ele chama (por exemplo, `graph-rag-request`)
|
|
Conhece o método exato a ser chamado no cliente (por exemplo, `client.rag()`)
|
|
Possui argumentos tipados definidos na implementação
|
|
|
|
### Registro de Ferramentas (service.py:105-214)
|
|
|
|
As ferramentas são carregadas da configuração com um campo `type` que mapeia para uma implementação:
|
|
|
|
```python
|
|
if impl_id == "knowledge-query":
|
|
impl = functools.partial(KnowledgeQueryImpl, collection=data.get("collection"))
|
|
elif impl_id == "text-completion":
|
|
impl = TextCompletionImpl
|
|
# ... etc
|
|
```
|
|
|
|
## Arquitetura
|
|
|
|
### Modelo de Duas Camadas
|
|
|
|
#### Camada 1: Descritor do Serviço de Ferramenta
|
|
|
|
Um serviço de ferramenta define uma interface de serviço Pulsar. Ele declara:
|
|
As filas Pulsar para solicitação/resposta
|
|
Os parâmetros de configuração que ele requer das ferramentas que o utilizam
|
|
|
|
```json
|
|
{
|
|
"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}
|
|
]
|
|
}
|
|
```
|
|
|
|
Um serviço de ferramenta que não requer parâmetros de configuração:
|
|
|
|
```json
|
|
{
|
|
"id": "calculator",
|
|
"request-queue": "non-persistent://tg/request/calc",
|
|
"response-queue": "non-persistent://tg/response/calc",
|
|
"config-params": []
|
|
}
|
|
```
|
|
|
|
#### Nível 2: Descritor de Ferramenta
|
|
|
|
Uma ferramenta referencia um serviço de ferramenta e fornece:
|
|
Valores de parâmetros de configuração (que satisfazem os requisitos do serviço)
|
|
Metadados da ferramenta para o agente (nome, descrição)
|
|
Definições de argumentos para o LLM
|
|
|
|
```json
|
|
{
|
|
"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"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
Múltiplas ferramentas podem referenciar o mesmo serviço com diferentes configurações:
|
|
|
|
```json
|
|
{
|
|
"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"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### Formato da Requisição
|
|
|
|
Quando uma ferramenta é invocada, a requisição ao serviço da ferramenta inclui:
|
|
`user`: Do pedido do agente (multi-tenência)
|
|
`config`: Valores de configuração codificados em JSON, provenientes da descrição da ferramenta
|
|
`arguments`: Argumentos codificados em JSON, provenientes do LLM
|
|
|
|
```json
|
|
{
|
|
"user": "alice",
|
|
"config": "{\"collection\": \"customers\"}",
|
|
"arguments": "{\"question\": \"What are the top customer complaints?\"}"
|
|
}
|
|
```
|
|
|
|
O serviço de ferramenta recebe estes como dicionários analisados no método `invoke`.
|
|
|
|
### Implementação Genérica do Serviço de Ferramenta
|
|
|
|
Uma classe `ToolServiceImpl` invoca serviços de ferramenta com base na configuração:
|
|
|
|
```python
|
|
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)
|
|
```
|
|
|
|
## Decisões de Design
|
|
|
|
### Modelo de Configuração de Duas Camadas
|
|
|
|
Os serviços de ferramentas seguem um modelo de duas camadas semelhante às ferramentas MCP:
|
|
|
|
1. **Serviço de Ferramenta**: Define a interface do serviço Pulsar (tópico, parâmetros de configuração necessários)
|
|
2. **Ferramenta**: Referencia um serviço de ferramenta, fornece valores de configuração, define argumentos do LLM
|
|
|
|
Essa separação permite:
|
|
Que um único serviço de ferramenta seja usado por várias ferramentas com diferentes configurações
|
|
Uma distinção clara entre a interface do serviço e a configuração da ferramenta
|
|
A reutilização das definições de serviço
|
|
|
|
### Mapeamento de Solicitações: Transmissão com Envelope
|
|
|
|
A solicitação a um serviço de ferramenta é um envelope estruturado contendo:
|
|
`user`: Propagado do pedido do agente para multi-inquilinato
|
|
Valores de configuração: Do descritor da ferramenta (por exemplo, `collection`)
|
|
`arguments`: Argumentos fornecidos pelo LLM, transmitidos como um dicionário
|
|
|
|
O gerenciador de agente analisa a resposta do LLM em `act.arguments` como um dicionário (`agent_manager.py:117-154`). Este dicionário é incluído no envelope da solicitação.
|
|
|
|
### Tratamento de Esquemas: Não Tipados
|
|
|
|
As solicitações e respostas usam dicionários não tipados. Não há validação de esquema no nível do agente - o serviço de ferramenta é responsável por validar suas entradas. Isso fornece o máximo de flexibilidade para definir novos serviços.
|
|
|
|
### Interface do Cliente: Tópicos Pulsar Diretos
|
|
|
|
Os serviços de ferramentas usam tópicos Pulsar diretos, sem a necessidade de configuração de fluxo. O descritor do serviço de ferramenta especifica os nomes completos das filas:
|
|
|
|
```json
|
|
{
|
|
"id": "joke-service",
|
|
"request-queue": "non-persistent://tg/request/joke",
|
|
"response-queue": "non-persistent://tg/response/joke",
|
|
"config-params": [...]
|
|
}
|
|
```
|
|
|
|
Isso permite que os serviços sejam hospedados em qualquer namespace.
|
|
|
|
### Tratamento de Erros: Convenção de Erro Padrão
|
|
|
|
As respostas do serviço de ferramenta seguem a convenção de esquema existente com um campo `error`:
|
|
|
|
```python
|
|
@dataclass
|
|
class Error:
|
|
type: str = ""
|
|
message: str = ""
|
|
```
|
|
|
|
Estrutura da resposta:
|
|
Sucesso: `error` é `None`, a resposta contém o resultado
|
|
Erro: `error` é preenchido com `type` e `message`
|
|
|
|
Isso corresponde ao padrão usado em todo o serviço existente (por exemplo, `PromptResponse`, `QueryResponse`, `AgentResponse`).
|
|
|
|
### Correlação de Requisições/Respostas
|
|
|
|
As requisições e respostas são correlacionadas usando um `id` nas propriedades da mensagem Pulsar:
|
|
|
|
A requisição inclui `id` nas propriedades: `properties={"id": id}`
|
|
A(s) resposta(s) incluem o mesmo `id`: `properties={"id": id}`
|
|
|
|
Isso segue o padrão existente usado em todo o código-fonte (por exemplo, `agent_service.py`, `llm_service.py`).
|
|
|
|
### Suporte a Streaming
|
|
|
|
Os serviços de ferramenta podem retornar respostas em streaming:
|
|
|
|
Múltiplas mensagens de resposta com o mesmo `id` nas propriedades
|
|
Cada resposta inclui o campo `end_of_stream: bool`
|
|
A resposta final tem `end_of_stream: True`
|
|
|
|
Isso corresponde ao padrão usado em `AgentResponse` e outros serviços de streaming.
|
|
|
|
### Tratamento da Resposta: Retorno de String
|
|
|
|
Todas as ferramentas existentes seguem o mesmo padrão: **receber argumentos como um dicionário, retornar a observação como uma string**.
|
|
|
|
| Ferramenta | Tratamento da Resposta |
|
|
|------|------------------|
|
|
| `KnowledgeQueryImpl` | Retorna `client.rag()` diretamente (string) |
|
|
| `TextCompletionImpl` | Retorna `client.question()` diretamente (string) |
|
|
| `McpToolImpl` | Retorna uma string, ou `json.dumps(output)` se não for uma string |
|
|
| `StructuredQueryImpl` | Formata o resultado para uma string |
|
|
| `PromptImpl` | Retorna `client.prompt()` diretamente (string) |
|
|
|
|
Os serviços de ferramenta seguem o mesmo contrato:
|
|
O serviço retorna uma resposta em string (a observação)
|
|
Se a resposta não for uma string, ela é convertida via `json.dumps()`
|
|
Nenhuma configuração de extração é necessária no descritor
|
|
|
|
Isso mantém o descritor simples e coloca a responsabilidade de retornar uma resposta de texto apropriada para o agente no serviço.
|
|
|
|
## Guia de Configuração
|
|
|
|
Para adicionar um novo serviço de ferramenta, são necessários dois itens de configuração:
|
|
|
|
### 1. Configuração do Serviço de Ferramenta
|
|
|
|
Armazenado sob a chave de configuração `tool-service`. Define as filas Pulsar e os parâmetros de configuração disponíveis.
|
|
|
|
| Campo | Obrigatório | Descrição |
|
|
|-------|----------|-------------|
|
|
| `id` | Sim | Identificador único para o serviço de ferramenta |
|
|
| `request-queue` | Sim | Tópico Pulsar completo para requisições (por exemplo, `non-persistent://tg/request/joke`) |
|
|
| `response-queue` | Sim | Tópico Pulsar completo para respostas (por exemplo, `non-persistent://tg/response/joke`) |
|
|
| `config-params` | Não | Array de parâmetros de configuração que o serviço aceita |
|
|
|
|
Cada parâmetro de configuração pode especificar:
|
|
`name`: Nome do parâmetro (obrigatório)
|
|
`required`: Se o parâmetro deve ser fornecido pelas ferramentas (padrão: falso)
|
|
|
|
Exemplo:
|
|
```json
|
|
{
|
|
"id": "joke-service",
|
|
"request-queue": "non-persistent://tg/request/joke",
|
|
"response-queue": "non-persistent://tg/response/joke",
|
|
"config-params": [
|
|
{"name": "style", "required": false}
|
|
]
|
|
}
|
|
```
|
|
|
|
### 2. Configuração da Ferramenta
|
|
|
|
Armazenado sob a chave de configuração `tool`. Define uma ferramenta que o agente pode usar.
|
|
|
|
| Campo | Obrigatório | Descrição |
|
|
|-------|----------|-------------|
|
|
| `type` | Sim | Deve ser `"tool-service"` |
|
|
| `name` | Sim | Nome da ferramenta exposto para o LLM |
|
|
| `description` | Sim | Descrição do que a ferramenta faz (mostrada para o LLM) |
|
|
| `service` | Sim | ID do serviço de ferramenta a ser invocado |
|
|
| `arguments` | Não | Array de definições de argumentos para o LLM |
|
|
| *(parâmetros de configuração)* | Varia | Quaisquer parâmetros de configuração definidos pelo serviço |
|
|
|
|
Cada argumento pode especificar:
|
|
`name`: Nome do argumento (obrigatório)
|
|
`type`: Tipo de dados, por exemplo, `"string"` (obrigatório)
|
|
`description`: Descrição mostrada para o LLM (obrigatório)
|
|
|
|
Exemplo:
|
|
```json
|
|
{
|
|
"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)"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### Carregando a Configuração
|
|
|
|
Use `tg-put-config-item` para carregar as configurações:
|
|
|
|
```bash
|
|
# 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
|
|
```
|
|
|
|
O agente-gerenciador deve ser reiniciado para aplicar novas configurações.
|
|
|
|
## Detalhes da Implementação
|
|
|
|
### Esquema
|
|
|
|
Tipos de requisição e resposta em `trustgraph-base/trustgraph/schema/services/tool_service.py`:
|
|
|
|
```python
|
|
@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
|
|
```
|
|
|
|
### Servidor: DynamicToolService
|
|
|
|
Classe base em `trustgraph-base/trustgraph/base/dynamic_tool_service.py`:
|
|
|
|
```python
|
|
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()
|
|
```
|
|
|
|
### Cliente: ToolServiceImpl
|
|
|
|
Implementação em `trustgraph-flow/trustgraph/agent/react/tools.py`:
|
|
|
|
```python
|
|
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)
|
|
```
|
|
|
|
### Arquivos
|
|
|
|
| Arquivo | Propósito |
|
|
|------|---------|
|
|
| `trustgraph-base/trustgraph/schema/services/tool_service.py` | Esquemas de requisição/resposta |
|
|
| `trustgraph-base/trustgraph/base/tool_service_client.py` | Cliente para invocar serviços |
|
|
| `trustgraph-base/trustgraph/base/dynamic_tool_service.py` | Classe base para implementação de serviço |
|
|
| `trustgraph-flow/trustgraph/agent/react/tools.py` | Classe `ToolServiceImpl` |
|
|
| `trustgraph-flow/trustgraph/agent/react/service.py` | Carregamento de configuração |
|
|
|
|
### Exemplo: Serviço de Piadas
|
|
|
|
Um exemplo de serviço em `trustgraph-flow/trustgraph/tool_service/joke/`:
|
|
|
|
```python
|
|
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}"
|
|
```
|
|
|
|
Configuração do serviço de ferramenta:
|
|
```json
|
|
{
|
|
"id": "joke-service",
|
|
"request-queue": "non-persistent://tg/request/joke",
|
|
"response-queue": "non-persistent://tg/response/joke",
|
|
"config-params": [{"name": "style", "required": false}]
|
|
}
|
|
```
|
|
|
|
Configuração da ferramenta:
|
|
```json
|
|
{
|
|
"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"}
|
|
]
|
|
}
|
|
```
|
|
|
|
### Compatibilidade com versões anteriores
|
|
|
|
Os tipos de ferramentas integradas existentes continuam a funcionar sem alterações.
|
|
`tool-service` é um novo tipo de ferramenta, juntamente com os tipos existentes (`knowledge-query`, `mcp-tool`, etc.).
|
|
|
|
## Considerações futuras
|
|
|
|
### Serviços de autoanúncio
|
|
|
|
Uma melhoria futura poderia permitir que os serviços publicassem seus próprios descritores:
|
|
|
|
Os serviços publicam em um tópico `tool-descriptors` conhecido na inicialização.
|
|
O agente se inscreve e registra dinamicamente as ferramentas.
|
|
Permite um verdadeiro sistema de plug-and-play sem alterações de configuração.
|
|
|
|
Isso está fora do escopo da implementação inicial.
|
|
|
|
## Referências
|
|
|
|
Implementação atual da ferramenta: `trustgraph-flow/trustgraph/agent/react/tools.py`
|
|
Registro de ferramentas: `trustgraph-flow/trustgraph/agent/react/service.py:105-214`
|
|
Esquemas do agente: `trustgraph-base/trustgraph/schema/services/agent.py`
|