chore: remove useless doc and font (#15838)
parent
98bd79f548
commit
cf72e53a10
@ -1,25 +0,0 @@
|
||||
# Tools
|
||||
|
||||
This module implements built-in tools used in Agent Assistants and Workflows within Dify. You could define and display your own tools in this module, without modifying the frontend logic. This decoupling allows for easier horizontal scaling of Dify's capabilities.
|
||||
|
||||
## Feature Introduction
|
||||
|
||||
The tools provided for Agents and Workflows are currently divided into two categories:
|
||||
- `Built-in Tools` are internally implemented within our product and are hardcoded for use in Agents and Workflows.
|
||||
- `Api-Based Tools` leverage third-party APIs for implementation. You don't need to code to integrate these -- simply provide interface definitions in formats like `OpenAPI` , `Swagger`, or the `OpenAI-plugin` on the front-end.
|
||||
|
||||
### Built-in Tool Providers
|
||||

|
||||
|
||||
### API Tool Providers
|
||||

|
||||
|
||||
## Tool Integration
|
||||
|
||||
To enable developers to build flexible and powerful tools, we provide two guides:
|
||||
|
||||
### [Quick Integration 👈🏻](./docs/en_US/tool_scale_out.md)
|
||||
Quick integration aims at quickly getting you up to speed with tool integration by walking over an example Google Search tool.
|
||||
|
||||
### [Advanced Integration 👈🏻](./docs/en_US/advanced_scale_out.md)
|
||||
Advanced integration will offer a deeper dive into the module interfaces, and explain how to implement more complex capabilities, such as generating images, combining multiple tools, and managing the flow of parameters, images, and files between different tools.
|
||||
@ -1,31 +0,0 @@
|
||||
# Tools
|
||||
|
||||
このモジュールは、Difyのエージェントアシスタントやワークフローで使用される組み込みツールを実装しています。このモジュールでは、フロントエンドのロジックを変更することなく、独自のツールを定義し表示することができます。この分離により、Difyの機能を容易に水平方向にスケールアウトできます。
|
||||
|
||||
## 機能紹介
|
||||
|
||||
エージェントとワークフロー向けに提供されるツールは、現在2つのカテゴリーに分類されています。
|
||||
|
||||
- `Built-in Tools`はDify内部で実装され、エージェントとワークフローで使用するためにハードコードされています。
|
||||
- `Api-Based Tools`はサードパーティのAPIを利用して実装されています。これらを統合するためのコーディングは不要で、フロントエンドで
|
||||
`OpenAPI`, `Swagger`または`OpenAI-plugin`などの形式でインターフェース定義を提供するだけです。
|
||||
|
||||
### 組み込みツールプロバイダー
|
||||
|
||||

|
||||
|
||||
### APIツールプロバイダー
|
||||
|
||||

|
||||
|
||||
## ツールの統合
|
||||
|
||||
開発者が柔軟で強力なツールを構築できるよう、2つのガイドを提供しています。
|
||||
|
||||
### [クイック統合 👈🏻](./docs/ja_JP/tool_scale_out.md)
|
||||
|
||||
クイック統合は、Google検索ツールの例を通じて、ツール統合の基本をすばやく理解できるようにすることを目的としています。
|
||||
|
||||
### [高度な統合 👈🏻](./docs/ja_JP/advanced_scale_out.md)
|
||||
|
||||
高度な統合では、モジュールインターフェースについてより深く掘り下げ、画像生成、複数ツールの組み合わせ、異なるツール間でのパラメーター、画像、ファイルのフロー管理など、より複雑な機能の実装方法を説明します。
|
||||
@ -1,278 +0,0 @@
|
||||
# Advanced Tool Integration
|
||||
|
||||
Before starting with this advanced guide, please make sure you have a basic understanding of the tool integration process in Dify. Check out [Quick Integration](./tool_scale_out.md) for a quick runthrough.
|
||||
|
||||
## Tool Interface
|
||||
|
||||
We have defined a series of helper methods in the `Tool` class to help developers quickly build more complex tools.
|
||||
|
||||
### Message Return
|
||||
|
||||
Dify supports various message types such as `text`, `link`, `json`, `image`, and `file BLOB`. You can return different types of messages to the LLM and users through the following interfaces.
|
||||
|
||||
Please note, some parameters in the following interfaces will be introduced in later sections.
|
||||
|
||||
#### Image URL
|
||||
You only need to pass the URL of the image, and Dify will automatically download the image and return it to the user.
|
||||
|
||||
```python
|
||||
def create_image_message(self, image: str, save_as: str = '') -> ToolInvokeMessage:
|
||||
"""
|
||||
create an image message
|
||||
|
||||
:param image: the url of the image
|
||||
:return: the image message
|
||||
"""
|
||||
```
|
||||
|
||||
#### Link
|
||||
If you need to return a link, you can use the following interface.
|
||||
|
||||
```python
|
||||
def create_link_message(self, link: str, save_as: str = '') -> ToolInvokeMessage:
|
||||
"""
|
||||
create a link message
|
||||
|
||||
:param link: the url of the link
|
||||
:return: the link message
|
||||
"""
|
||||
```
|
||||
|
||||
#### Text
|
||||
If you need to return a text message, you can use the following interface.
|
||||
|
||||
```python
|
||||
def create_text_message(self, text: str, save_as: str = '') -> ToolInvokeMessage:
|
||||
"""
|
||||
create a text message
|
||||
|
||||
:param text: the text of the message
|
||||
:return: the text message
|
||||
"""
|
||||
```
|
||||
|
||||
#### File BLOB
|
||||
If you need to return the raw data of a file, such as images, audio, video, PPT, Word, Excel, etc., you can use the following interface.
|
||||
|
||||
- `blob` The raw data of the file, of bytes type
|
||||
- `meta` The metadata of the file, if you know the type of the file, it is best to pass a `mime_type`, otherwise Dify will use `application/octet-stream` as the default type
|
||||
|
||||
```python
|
||||
def create_blob_message(self, blob: bytes, meta: dict = None, save_as: str = '') -> ToolInvokeMessage:
|
||||
"""
|
||||
create a blob message
|
||||
|
||||
:param blob: the blob
|
||||
:return: the blob message
|
||||
"""
|
||||
```
|
||||
|
||||
#### JSON
|
||||
If you need to return a formatted JSON, you can use the following interface. This is commonly used for data transmission between nodes in a workflow, of course, in agent mode, most LLM are also able to read and understand JSON.
|
||||
|
||||
- `object` A Python dictionary object will be automatically serialized into JSON
|
||||
|
||||
```python
|
||||
def create_json_message(self, object: dict) -> ToolInvokeMessage:
|
||||
"""
|
||||
create a json message
|
||||
"""
|
||||
```
|
||||
|
||||
### Shortcut Tools
|
||||
|
||||
In large model applications, we have two common needs:
|
||||
- First, summarize a long text in advance, and then pass the summary content to the LLM to prevent the original text from being too long for the LLM to handle
|
||||
- The content obtained by the tool is a link, and the web page information needs to be crawled before it can be returned to the LLM
|
||||
|
||||
To help developers quickly implement these two needs, we provide the following two shortcut tools.
|
||||
|
||||
#### Text Summary Tool
|
||||
|
||||
This tool takes in an user_id and the text to be summarized, and returns the summarized text. Dify will use the default model of the current workspace to summarize the long text.
|
||||
|
||||
```python
|
||||
def summary(self, user_id: str, content: str) -> str:
|
||||
"""
|
||||
summary the content
|
||||
|
||||
:param user_id: the user id
|
||||
:param content: the content
|
||||
:return: the summary
|
||||
"""
|
||||
```
|
||||
|
||||
#### Web Page Crawling Tool
|
||||
|
||||
This tool takes in web page link to be crawled and a user_agent (which can be empty), and returns a string containing the information of the web page. The `user_agent` is an optional parameter that can be used to identify the tool. If not passed, Dify will use the default `user_agent`.
|
||||
|
||||
```python
|
||||
def get_url(self, url: str, user_agent: str = None) -> str:
|
||||
"""
|
||||
get url
|
||||
""" the crawled result
|
||||
```
|
||||
|
||||
### Variable Pool
|
||||
|
||||
We have introduced a variable pool in `Tool` to store variables, files, etc. generated during the tool's operation. These variables can be used by other tools during the tool's operation.
|
||||
|
||||
Next, we will use `DallE3` and `Vectorizer.AI` as examples to introduce how to use the variable pool.
|
||||
|
||||
- `DallE3` is an image generation tool that can generate images based on text. Here, we will let `DallE3` generate a logo for a coffee shop
|
||||
- `Vectorizer.AI` is a vector image conversion tool that can convert images into vector images, so that the images can be infinitely enlarged without distortion. Here, we will convert the PNG icon generated by `DallE3` into a vector image, so that it can be truly used by designers.
|
||||
|
||||
#### DallE3
|
||||
First, we use DallE3. After creating the image, we save the image to the variable pool. The code is as follows:
|
||||
|
||||
```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_parameters: Dict[str, Any],
|
||||
) -> Union[ToolInvokeMessage, List[ToolInvokeMessage]]:
|
||||
"""
|
||||
invoke tools
|
||||
"""
|
||||
client = OpenAI(
|
||||
api_key=self.runtime.credentials['openai_api_key'],
|
||||
)
|
||||
|
||||
# prompt
|
||||
prompt = tool_parameters.get('prompt', '')
|
||||
if not prompt:
|
||||
return self.create_text_message('Please input prompt')
|
||||
|
||||
# call 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:
|
||||
# Save all images to the variable pool through the save_as parameter. The variable name is self.VARIABLE_KEY.IMAGE.value. If new images are generated later, they will overwrite the previous images.
|
||||
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
|
||||
```
|
||||
|
||||
Note that we used `self.VARIABLE_KEY.IMAGE.value` as the variable name of the image. In order for developers' tools to cooperate with each other, we defined this `KEY`. You can use it freely, or you can choose not to use this `KEY`. Passing a custom KEY is also acceptable.
|
||||
|
||||
#### Vectorizer.AI
|
||||
Next, we use Vectorizer.AI to convert the PNG icon generated by DallE3 into a vector image. Let's go through the functions we defined here. The code is as follows:
|
||||
|
||||
```python
|
||||
from core.tools.tool.builtin_tool import BuiltinTool
|
||||
from core.tools.entities.tool_entities import ToolInvokeMessage, ToolParameter
|
||||
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_parameters: Dict[str, Any]) \
|
||||
-> Union[ToolInvokeMessage, List[ToolInvokeMessage]]:
|
||||
"""
|
||||
Tool invocation, the image variable name needs to be passed in from here, so that we can get the image from the variable pool
|
||||
"""
|
||||
|
||||
|
||||
def get_runtime_parameters(self) -> List[ToolParameter]:
|
||||
"""
|
||||
Override the tool parameter list, we can dynamically generate the parameter list based on the actual situation in the current variable pool, so that the LLM can generate the form based on the parameter list
|
||||
"""
|
||||
|
||||
|
||||
def is_tool_available(self) -> bool:
|
||||
"""
|
||||
Whether the current tool is available, if there is no image in the current variable pool, then we don't need to display this tool, just return False here
|
||||
"""
|
||||
```
|
||||
|
||||
Next, let's implement these three functions
|
||||
|
||||
```python
|
||||
from core.tools.tool.builtin_tool import BuiltinTool
|
||||
from core.tools.entities.tool_entities import ToolInvokeMessage, ToolParameter
|
||||
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_parameters: Dict[str, Any]) \
|
||||
-> Union[ToolInvokeMessage, List[ToolInvokeMessage]]:
|
||||
"""
|
||||
invoke tools
|
||||
"""
|
||||
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 or not api_key_value:
|
||||
raise ToolProviderCredentialValidationError('Please input api key name and value')
|
||||
|
||||
# Get image_id, the definition of image_id can be found in get_runtime_parameters
|
||||
image_id = tool_parameters.get('image_id', '')
|
||||
if not image_id:
|
||||
return self.create_text_message('Please input image id')
|
||||
|
||||
# Get the image generated by DallE from the variable pool
|
||||
image_binary = self.get_variable_file(self.VARIABLE_KEY.IMAGE)
|
||||
if not image_binary:
|
||||
return self.create_text_message('Image not found, please request user to generate image firstly.')
|
||||
|
||||
# Generate vector image
|
||||
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('the vectorized svg is saved as an image.'),
|
||||
self.create_blob_message(blob=response.content,
|
||||
meta={'mime_type': 'image/svg+xml'})
|
||||
]
|
||||
|
||||
def get_runtime_parameters(self) -> List[ToolParameter]:
|
||||
"""
|
||||
override the runtime parameters
|
||||
"""
|
||||
# Here, we override the tool parameter list, define the image_id, and set its option list to all images in the current variable pool. The configuration here is consistent with the configuration in yaml.
|
||||
return [
|
||||
ToolParameter.get_simple_instance(
|
||||
name='image_id',
|
||||
llm_description=f'the image id that you want to vectorize, \
|
||||
and the image id should be specified in \
|
||||
{[i.name for i in self.list_default_image_variables()]}',
|
||||
type=ToolParameter.ToolParameterType.SELECT,
|
||||
required=True,
|
||||
options=[i.name for i in self.list_default_image_variables()]
|
||||
)
|
||||
]
|
||||
|
||||
def is_tool_available(self) -> bool:
|
||||
# Only when there are images in the variable pool, the LLM needs to use this tool
|
||||
return len(self.list_default_image_variables()) > 0
|
||||
```
|
||||
|
||||
It's worth noting that we didn't actually use `image_id` here. We assumed that there must be an image in the default variable pool when calling this tool, so we directly used `image_binary = self.get_variable_file(self.VARIABLE_KEY.IMAGE)` to get the image. In cases where the model's capabilities are weak, we recommend developers to do the same, which can effectively improve fault tolerance and avoid the model passing incorrect parameters.
|
||||
@ -1,248 +0,0 @@
|
||||
# Quick Tool Integration
|
||||
|
||||
Here, we will use GoogleSearch as an example to demonstrate how to quickly integrate a tool.
|
||||
|
||||
## 1. Prepare the Tool Provider yaml
|
||||
|
||||
### Introduction
|
||||
|
||||
This yaml declares a new tool provider, and includes information like the provider's name, icon, author, and other details that are fetched by the frontend for display.
|
||||
|
||||
### Example
|
||||
|
||||
We need to create a `google` module (folder) under `core/tools/provider/builtin`, and create `google.yaml`. The name must be consistent with the module name.
|
||||
|
||||
Subsequently, all operations related to this tool will be carried out under this module.
|
||||
|
||||
```yaml
|
||||
identity: # Basic information of the tool provider
|
||||
author: Dify # Author
|
||||
name: google # Name, unique, no duplication with other providers
|
||||
label: # Label for frontend display
|
||||
en_US: Google # English label
|
||||
zh_Hans: Google # Chinese label
|
||||
description: # Description for frontend display
|
||||
en_US: Google # English description
|
||||
zh_Hans: Google # Chinese description
|
||||
icon: icon.svg # Icon, needs to be placed in the _assets folder of the current module
|
||||
tags:
|
||||
- search
|
||||
|
||||
```
|
||||
|
||||
- The `identity` field is mandatory, it contains the basic information of the tool provider, including author, name, label, description, icon, etc.
|
||||
- The icon needs to be placed in the `_assets` folder of the current module, you can refer to [here](../../provider/builtin/google/_assets/icon.svg).
|
||||
- The `tags` field is optional, it is used to classify the provider, and the frontend can filter the provider according to the tag, for all tags, they have been listed below:
|
||||
|
||||
```python
|
||||
class ToolLabelEnum(Enum):
|
||||
SEARCH = 'search'
|
||||
IMAGE = 'image'
|
||||
VIDEOS = 'videos'
|
||||
WEATHER = 'weather'
|
||||
FINANCE = 'finance'
|
||||
DESIGN = 'design'
|
||||
TRAVEL = 'travel'
|
||||
SOCIAL = 'social'
|
||||
NEWS = 'news'
|
||||
MEDICAL = 'medical'
|
||||
PRODUCTIVITY = 'productivity'
|
||||
EDUCATION = 'education'
|
||||
BUSINESS = 'business'
|
||||
ENTERTAINMENT = 'entertainment'
|
||||
UTILITIES = 'utilities'
|
||||
OTHER = 'other'
|
||||
```
|
||||
|
||||
## 2. Prepare Provider Credentials
|
||||
|
||||
Google, as a third-party tool, uses the API provided by SerpApi, which requires an API Key to use. This means that this tool needs a credential to use. For tools like `wikipedia`, there is no need to fill in the credential field, you can refer to [here](../../provider/builtin/wikipedia/wikipedia.yaml).
|
||||
|
||||
After configuring the credential field, the effect is as follows:
|
||||
|
||||
```yaml
|
||||
identity:
|
||||
author: Dify
|
||||
name: google
|
||||
label:
|
||||
en_US: Google
|
||||
zh_Hans: Google
|
||||
description:
|
||||
en_US: Google
|
||||
zh_Hans: Google
|
||||
icon: icon.svg
|
||||
credentials_for_provider: # Credential field
|
||||
serpapi_api_key: # Credential field name
|
||||
type: secret-input # Credential field type
|
||||
required: true # Required or not
|
||||
label: # Credential field label
|
||||
en_US: SerpApi API key # English label
|
||||
zh_Hans: SerpApi API key # Chinese label
|
||||
placeholder: # Credential field placeholder
|
||||
en_US: Please input your SerpApi API key # English placeholder
|
||||
zh_Hans: 请输入你的 SerpApi API key # Chinese placeholder
|
||||
help: # Credential field help text
|
||||
en_US: Get your SerpApi API key from SerpApi # English help text
|
||||
zh_Hans: 从 SerpApi 获取您的 SerpApi API key # Chinese help text
|
||||
url: https://serpapi.com/manage-api-key # Credential field help link
|
||||
|
||||
```
|
||||
|
||||
- `type`: Credential field type, currently can be either `secret-input`, `text-input`, or `select` , corresponding to password input box, text input box, and drop-down box, respectively. If set to `secret-input`, it will mask the input content on the frontend, and the backend will encrypt the input content.
|
||||
|
||||
## 3. Prepare Tool yaml
|
||||
|
||||
A provider can have multiple tools, each tool needs a yaml file to describe, this file contains the basic information, parameters, output, etc. of the tool.
|
||||
|
||||
Still taking GoogleSearch as an example, we need to create a `tools` module under the `google` module, and create `tools/google_search.yaml`, the content is as follows.
|
||||
|
||||
```yaml
|
||||
identity: # Basic information of the tool
|
||||
name: google_search # Tool name, unique, no duplication with other tools
|
||||
author: Dify # Author
|
||||
label: # Label for frontend display
|
||||
en_US: GoogleSearch # English label
|
||||
zh_Hans: 谷歌搜索 # Chinese label
|
||||
description: # Description for frontend display
|
||||
human: # Introduction for frontend display, supports multiple languages
|
||||
en_US: A tool for performing a Google SERP search and extracting snippets and webpages.Input should be a search query.
|
||||
zh_Hans: 一个用于执行 Google SERP 搜索并提取片段和网页的工具。输入应该是一个搜索查询。
|
||||
llm: A tool for performing a Google SERP search and extracting snippets and webpages.Input should be a search query. # Introduction passed to LLM, in order to make LLM better understand this tool, we suggest to write as detailed information about this tool as possible here, so that LLM can understand and use this tool
|
||||
parameters: # Parameter list
|
||||
- name: query # Parameter name
|
||||
type: string # Parameter type
|
||||
required: true # Required or not
|
||||
label: # Parameter label
|
||||
en_US: Query string # English label
|
||||
zh_Hans: 查询语句 # Chinese label
|
||||
human_description: # Introduction for frontend display, supports multiple languages
|
||||
en_US: used for searching
|
||||
zh_Hans: 用于搜索网页内容
|
||||
llm_description: key words for searching # Introduction passed to LLM, similarly, in order to make LLM better understand this parameter, we suggest to write as detailed information about this parameter as possible here, so that LLM can understand this parameter
|
||||
form: llm # Form type, llm means this parameter needs to be inferred by Agent, the frontend will not display this parameter
|
||||
- name: result_type
|
||||
type: select # Parameter type
|
||||
required: true
|
||||
options: # Drop-down box options
|
||||
- value: text
|
||||
label:
|
||||
en_US: text
|
||||
zh_Hans: 文本
|
||||
- value: link
|
||||
label:
|
||||
en_US: link
|
||||
zh_Hans: 链接
|
||||
default: link
|
||||
label:
|
||||
en_US: Result type
|
||||
zh_Hans: 结果类型
|
||||
human_description:
|
||||
en_US: used for selecting the result type, text or link
|
||||
zh_Hans: 用于选择结果类型,使用文本还是链接进行展示
|
||||
form: form # Form type, form means this parameter needs to be filled in by the user on the frontend before the conversation starts
|
||||
|
||||
```
|
||||
|
||||
- The `identity` field is mandatory, it contains the basic information of the tool, including name, author, label, description, etc.
|
||||
- `parameters` Parameter list
|
||||
- `name` (Mandatory) Parameter name, must be unique and not duplicate with other parameters.
|
||||
- `type` (Mandatory) Parameter type, currently supports `string`, `number`, `boolean`, `select`, `secret-input` five types, corresponding to string, number, boolean, drop-down box, and encrypted input box, respectively. For sensitive information, we recommend using the `secret-input` type
|
||||
- `label` (Mandatory) Parameter label, for frontend display
|
||||
- `form` (Mandatory) Form type, currently supports `llm`, `form` two types.
|
||||
- In an agent app, `llm` indicates that the parameter is inferred by the LLM itself, while `form` indicates that the parameter can be pre-set for the tool.
|
||||
- In a workflow app, both `llm` and `form` need to be filled out by the front end, but the parameters of `llm` will be used as input variables for the tool node.
|
||||
- `required` Indicates whether the parameter is required or not
|
||||
- In `llm` mode, if the parameter is required, the Agent is required to infer this parameter
|
||||
- In `form` mode, if the parameter is required, the user is required to fill in this parameter on the frontend before the conversation starts
|
||||
- `options` Parameter options
|
||||
- In `llm` mode, Dify will pass all options to LLM, LLM can infer based on these options
|
||||
- In `form` mode, when `type` is `select`, the frontend will display these options
|
||||
- `default` Default value
|
||||
- `min` Minimum value, can be set when the parameter type is `number`.
|
||||
- `max` Maximum value, can be set when the parameter type is `number`.
|
||||
- `placeholder` The prompt text for input boxes. It can be set when the form type is `form`, and the parameter type is `string`, `number`, or `secret-input`. It supports multiple languages.
|
||||
- `human_description` Introduction for frontend display, supports multiple languages
|
||||
- `llm_description` Introduction passed to LLM, in order to make LLM better understand this parameter, we suggest to write as detailed information about this parameter as possible here, so that LLM can understand this parameter
|
||||
|
||||
|
||||
## 4. Add Tool Logic
|
||||
|
||||
After completing the tool configuration, we can start writing the tool code that defines how it is invoked.
|
||||
|
||||
Create `google_search.py` under the `google/tools` module, the content is as follows.
|
||||
|
||||
```python
|
||||
from core.tools.tool.builtin_tool import BuiltinTool
|
||||
from core.tools.entities.tool_entities import ToolInvokeMessage
|
||||
|
||||
from typing import Any, Dict, List, Union
|
||||
|
||||
class GoogleSearchTool(BuiltinTool):
|
||||
def _invoke(self,
|
||||
user_id: str,
|
||||
tool_parameters: Dict[str, Any],
|
||||
) -> Union[ToolInvokeMessage, List[ToolInvokeMessage]]:
|
||||
"""
|
||||
invoke tools
|
||||
"""
|
||||
query = tool_parameters['query']
|
||||
result_type = tool_parameters['result_type']
|
||||
api_key = self.runtime.credentials['serpapi_api_key']
|
||||
# Search with serpapi
|
||||
result = SerpAPI(api_key).run(query, result_type=result_type)
|
||||
|
||||
if result_type == 'text':
|
||||
return self.create_text_message(text=result)
|
||||
return self.create_link_message(link=result)
|
||||
```
|
||||
|
||||
### Parameters
|
||||
|
||||
The overall logic of the tool is in the `_invoke` method, this method accepts two parameters: `user_id` and `tool_parameters`, which represent the user ID and tool parameters respectively
|
||||
|
||||
### Return Data
|
||||
|
||||
When the tool returns, you can choose to return one message or multiple messages, here we return one message, using `create_text_message` and `create_link_message` can create a text message or a link message. If you want to return multiple messages, you can use `[self.create_text_message('msg1'), self.create_text_message('msg2')]` to create a list of messages.
|
||||
|
||||
## 5. Add Provider Code
|
||||
|
||||
Finally, we need to create a provider class under the provider module to implement the provider's credential verification logic. If the credential verification fails, it will throw a `ToolProviderCredentialValidationError` exception.
|
||||
|
||||
Create `google.py` under the `google` module, the content is as follows.
|
||||
|
||||
```python
|
||||
from core.tools.provider.builtin_tool_provider import BuiltinToolProviderController
|
||||
from core.tools.errors import ToolProviderCredentialValidationError
|
||||
|
||||
from core.tools.provider.builtin.google.tools.google_search import GoogleSearchTool
|
||||
|
||||
from typing import Any, Dict
|
||||
|
||||
class GoogleProvider(BuiltinToolProviderController):
|
||||
def _validate_credentials(self, credentials: Dict[str, Any]) -> None:
|
||||
try:
|
||||
# 1. Here you need to instantiate a GoogleSearchTool with GoogleSearchTool(), it will automatically load the yaml configuration of GoogleSearchTool, but at this time it does not have credential information inside
|
||||
# 2. Then you need to use the fork_tool_runtime method to pass the current credential information to GoogleSearchTool
|
||||
# 3. Finally, invoke it, the parameters need to be passed according to the parameter rules configured in the yaml of GoogleSearchTool
|
||||
GoogleSearchTool().fork_tool_runtime(
|
||||
meta={
|
||||
"credentials": credentials,
|
||||
}
|
||||
).invoke(
|
||||
user_id='',
|
||||
tool_parameters={
|
||||
"query": "test",
|
||||
"result_type": "link"
|
||||
},
|
||||
)
|
||||
except Exception as e:
|
||||
raise ToolProviderCredentialValidationError(str(e))
|
||||
```
|
||||
|
||||
## Completion
|
||||
|
||||
After the above steps are completed, we can see this tool on the frontend, and it can be used in the Agent.
|
||||
|
||||
Of course, because google_search needs a credential, before using it, you also need to input your credentials on the frontend.
|
||||
|
||||

|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 242 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 407 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 266 KiB |
Loading…
Reference in New Issue