---
title: Integração Avançada de Ferramentas
slug: integracao-avancada-de-ferramentas
createdAt: 2024-09-04T13:45:35.574Z
---

Antes de iniciar este guia avançado, certifique-se de ter uma compreensão básica do processo de integração de ferramentas no Paragraph. Confira a Integração Rápida para uma visão geral rápida.

## Interface de Ferramentas

Definimos uma série de métodos auxiliares na classe *Tool* para ajudar os desenvolvedores a construir ferramentas mais complexas rapidamente.

### Retorno de Mensagens

O Paragraph suporta vários tipos de mensagens, como texto, link, imagem e arquivo BLOB. Você pode retornar diferentes tipos de mensagens para o LLM e os usuários por meio das seguintes interfaces.

Observe que alguns parâmetros nas interfaces a seguir serão apresentados nas seções posteriores.

### URL da Imagem

Você só precisa passar o URL da imagem, e o Paragraph fará o download da imagem automaticamente e a retornará ao usuário.

```python
    def create_image_message(self, image: str, save_as: str = '') -> ToolInvokeMessage:
        """
            criar uma mensagem de imagem

            :param image: o URL da imagem
            :return: a mensagem de imagem
        """
```

### Link

Se precisar retornar um link, você pode usar a seguinte interface:

```python
    def create_link_message(self, link: str, save_as: str = '') -> ToolInvokeMessage:
        """
            criar uma mensagem de link

            :param link: o URL do link
            :return: a mensagem de link
        """
```

### Texto

Se precisar retornar uma mensagem de texto, você pode usar a seguinte interface:

```python
    def create_text_message(self, text: str, save_as: str = '') -> ToolInvokeMessage:
        """
            criar uma mensagem de texto

            :param text: o texto da mensagem
            :return: a mensagem de texto
        """
```

### Arquivo BLOB

Se precisar retornar os dados brutos de um arquivo, como imagens, áudio, vídeo, PPT, Word, Excel, etc., você pode usar a seguinte interface.

- **blob**: os dados brutos do arquivo, do tipo *bytes*
- **meta**: os metadados do arquivo; se você souber o tipo do arquivo, é melhor passar um *mime\_type*, caso contrário, o Paragraph usará *octet/stream* como tipo padrão.

```python
    def create_blob_message(self, blob: bytes, meta: dict = None, save_as: str = '') -> ToolInvokeMessage:
        """
            criar uma mensagem de blob

            :param blob: o blob
            :return: a mensagem de blob
        """
```

### Ferramentas Atalhos

Em aplicações de grande modelo, temos duas necessidades comuns:

1. Resumir um texto longo antes de passá-lo ao LLM, evitando que o texto original seja muito longo para o LLM processar.
2. O conteúdo obtido pela ferramenta é um link, e as informações da página web precisam ser rastreadas antes de serem retornadas ao LLM.

Para ajudar os desenvolvedores a implementar rapidamente essas duas necessidades, fornecemos as seguintes ferramentas de atalho:

### Ferramenta de Resumo de Texto

Essa ferramenta recebe um *user\_id* e o texto a ser resumido, retornando o texto resumido. O Paragraph usará o modelo padrão do espaço de trabalho atual para resumir o texto longo.

```python
    def summary(self, user_id: str, content: str) -> str:
        """
            resumir o conteúdo

            :param user_id: o id do usuário
            :param content: o conteúdo
            :return: o resumo
        """
```

**Ferramenta de Rastreamento de Página Web**

Essa ferramenta recebe o link da página web a ser rastreada e um *user\_agent* (que pode ser vazio), retornando uma string contendo as informações da página web.

```python
    def get_url(self, url: str, user_agent: str = None) -> str:
        """
            obter url
        """ o resultado rastreado
```

### Pool de Variáveis

Introduzimos um *pool* de variáveis na ferramenta para armazenar variáveis, arquivos, etc., gerados durante a operação da ferramenta. Essas variáveis podem ser usadas por outras ferramentas durante a execução da ferramenta.

A seguir, usaremos *DallE3* e *Vectorizer.AI* como exemplos para demonstrar como usar o *pool* de variáveis.

### DallE3

Primeiro, usamos o *DallE3*. Após criar a imagem, salvamos a imagem no *pool* de variáveis. O código é o seguinte:

```python
from typing import Any, Dict, List, Union
from core.tools.entities.tool_entities import ToolInvokeMessage
from core.tools.tool.builtin_tool import BuiltinTool

from base64 import b64decode

from openai import OpenAI

class DallE3Tool(BuiltinTool):
    def _invoke(self, 
                user_id: str, 
               tool_paramters: Dict[str, Any], 
        ) -> Union[ToolInvokeMessage, List[ToolInvokeMessage]]:
        """
            invocar ferramentas
        """
        client = OpenAI(
            api_key=self.runtime.credentials['openai_api_key'],
        )

        # prompt
        prompt = tool_paramters.get('prompt', '')
        if not prompt:
            return self.create_text_message('Por favor, insira um prompt')

        # chamar openapi dalle3
        response = client.images.generate(
            prompt=prompt, model='dall-e-3',
            size='1024x1024', n=1, style='vivid', quality='standard',
            response_format='b64_json'
        )

        result = []
        for image in response.data:
            # Salvar todas as imagens no pool de variáveis por meio do parâmetro save_as. O nome da variável é self.VARIABLE_KEY.IMAGE.value. Se novas imagens forem geradas posteriormente, elas substituirão as anteriores.
            result.append(self.create_blob_message(blob=b64decode(image.b64_json), 
                                                   meta={ 'mime_type': 'image/png' },
                                                    save_as=self.VARIABLE_KEY.IMAGE.value))

        return result
```

Observe que usamos `self.VARIABLE_KEY.IMAGE.value` como o nome da variável da imagem. Para que as ferramentas dos desenvolvedores cooperem entre si, definimos esta CHAVE. Você pode usá-la livremente, ou escolher não usá-la. Passar uma CHAVE personalizada também é aceitável.

### Vectorizer.AI

Em seguida, usamos o *Vectorizer.AI* para converter o ícone PNG gerado pelo *DallE3* em uma imagem vetorial. Vamos examinar as funções que definimos aqui. O código é o seguinte:

```python
from core.tools.tool.builtin_tool import BuiltinTool
from core.tools.entities.tool_entities import ToolInvokeMessage, ToolParamter
from core.tools.errors import ToolProviderCredentialValidationError

from typing import Any, Dict, List, Union
from httpx import post
from base64 import b64decode

class VectorizerTool(BuiltinTool):
    def _invoke(self, user_id: str, tool_paramters: Dict[str, Any]) \
        -> Union[ToolInvokeMessage, List[ToolInvokeMessage]]:
        """
        Invocação da ferramenta, o nome da variável de imagem precisa ser passado aqui para que possamos obter a imagem do pool de variáveis
        """
        
    
    def get_runtime_parameters(self) -> List[ToolParamter]:
        """
        Sobrescreva a lista de parâmetros da ferramenta, podemos gerar dinamicamente a lista de parâmetros com base na situação atual no pool de variáveis, para que o LLM possa gerar o formulário com base na lista de parâmetros
        """
        
    
    def is_tool_avaliable(self) -> bool:
        """
        Se a ferramenta atual está disponível, se não houver imagem no pool de variáveis, então não precisamos exibir essa ferramenta, apenas retornar False aqui
        """     
```

Em seguida, vamos implementar essas três funções:

```python
from core.tools.tool.builtin_tool import BuiltinTool
from core.tools.entities.tool_entities import ToolInvokeMessage, ToolParamter
from core.tools.errors import ToolProviderCredentialValidationError

from typing import Any, Dict, List, Union
from httpx import post
from base64 import b64decode

class VectorizerTool(BuiltinTool):
    def _invoke(self, user_id: str, tool_paramters: Dict[str, Any]) \
        -> Union[ToolInvokeMessage, List[ToolInvokeMessage]]:
        """
            invocar ferramentas
        """
        api_key_name = self.runtime.credentials.get('api_key_name', None)
        api_key_value = self.runtime.credentials.get('api_key_value', None)

        if not api_key_name ou not api_key_value:
            raise ToolProviderCredentialValidationError('Por favor, insira o nome e valor da chave da API')

        # Obter o image_id, a definição de image_id pode ser encontrada em get_runtime_parameters
        image_id = tool_paramters.get('image_id', '')
        if not image_id:
            return self.create_text_message('Por favor, insira o ID da imagem')

        # Obter a imagem gerada pelo DallE do pool de variáveis
        image_binary = self.get_variable_file(self.VARIABLE_KEY.IMAGE)
        if not image_binary:
            return self.create_text_message('Imagem não encontrada, por favor, solicite ao usuário que gere a imagem primeiro.')

        # Gerar a imagem vetorial
        response = post(
            'https://vectorizer.ai/api/v1/vectorize',
            files={ 'image': image_binary },
            data={ 'mode': 'test' },
            auth=(api_key_name, api_key_value), 
            timeout=30
        )

        if response.status_code != 200:
            raise Exception(response.text)
        
        return [
            self.create_text_message('O SVG vetorizado foi salvo como uma imagem.'),
            self.create_blob_message(blob=response.content,
                                    meta={'mime_type': 'image/svg+xml'})
        ]
    
    def get_runtime_parameters(self) -> List[ToolParamter]:
        """
        sobrescrever os parâmetros de tempo de execução
        """
        # Aqui, sobrescrevemos a lista de parâmetros da ferramenta, definimos o image_id e configuramos sua lista de opções para todas as imagens no pool de variáveis atual. A configuração aqui é consistente com a configuração no yaml.
        return [
            ToolParamter.get_simple_instance(
                name='image_id',
                llm_description=f'o ID da imagem que você deseja vetorizar, \
                    e o ID da imagem deve ser especificado em \
                        {[i.name for i in self.list_default_image_variables()]}',
                type=ToolParamter.ToolParameterType.SELECT,
                required=True,
                options=[i.name for i in self.list_default_image_variables()]
            )
        ]
    
    def is_tool_avaliable(self) -> bool:
        # Apenas quando houver imagens no pool de variáveis, o LLM precisará usar essa ferramenta
        return len(self.list_default_image_variables()) > 0
```

Vale notar que, na verdade, não usamos o *image\_id* aqui. Supomos que deve haver uma imagem no pool de variáveis padrão ao chamar essa ferramenta, então usamos diretamente `image_binary = self.get_variable_file(self.VARIABLE_KEY.IMAGE)` para obter a imagem. Em casos em que as capacidades do modelo são fracas, recomendamos que os desenvolvedores façam o mesmo, o que pode melhorar efetivamente a tolerância a falhas e evitar que o modelo passe parâmetros incorretos.
