Skip to content

Commit

Permalink
Merge pull request #104 from alipay/dev_request_tool
Browse files Browse the repository at this point in the history
requst tool
  • Loading branch information
LandJerry authored Jun 28, 2024
2 parents 4389882 + b5957cd commit c4ec0b6
Show file tree
Hide file tree
Showing 14 changed files with 477 additions and 4 deletions.
83 changes: 83 additions & 0 deletions docs/guidebook/en/2_2_3_Integrated_LangChain_Tools.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Integrated LangChain Tool

Based on the level of difficulty in initializing tool objects in LangChain, they can be divided into two categories:
The first category involves simple initialization, where initialization can be completed with basic parameter configuration.
The second category involves complex initialization with intricate internal objects that need to be set up.
For the first category of tools, you can use configuration files in aU to directly perform initialization, such as initializing the DuDuckGo search tool.
For the second category of tools, we have implemented a LangChainTool base class. You only need to implement the init_langchain_tool method of this class to initialize the corresponding LangChain tool objects, with reference to the initialization method of Wikipedia.

Note: If you want to directly use the description from LangChain, the description in the configuration file must be set to empty.

An Example of Tool Initialization:
[Tool Address](../../../sample_standard_app/app/core/tool/langchain_tool/human_input_run.yaml)
```yaml
name: 'human_input_run'
description: ''
tool_type: 'api'
input_keys: ['input']
langchain:
module: langchain_community.tools
class_name: HumanInputRun
metadata:
type: 'TOOL'
module: 'sample_standard_app.app.core.tool.langchain_tool'
class: 'LangChainTool'
```
Parameter Description:
langchain: The LangChain tool you intend to use, which requires the configuration of module and class_name.
langchain.module: The name of the LangChain module, e.g., langchain_community.tools.
langchain.class_name: The name of the LangChain class, e.g., HumanInputRun.
langchain.init_params: The initialization parameters for LangChain, such as:
```yaml
langchain:
module: langchain_community.tools
class_name: HumanInputRun
init_params:
prompt: 'please Input your question'
```
If you completely override the `init_langchain_tool` method, then you do not need to configure this part.

## 1. Integrate the DuckDuckGo Tool from LangChain
[Tool Address](../../../sample_standard_app/app/core/tool/langchain_tool/duckduckgo_search.yaml)
```yaml
name: 'duckduckgo_search'
description: 'DuckDuckGo Search tool'
tool_type: 'api'
input_keys: ['input']
langchain:
module: langchain.tools
class_name: DuckDuckGoSearchResults
init_params:
backend: news
metadata:
type: 'TOOL'
module: 'sample_standard_app.app.core.tool.langchain_tool.langchain_tool'
class: 'LangChainTool'
```
This tool can be used directly without any keys.

## 2.Integrate Wikipedia Search
Since the definition of LangChain includes an api_wrapper object, define the object file and override the initialization method:
```python
from langchain_community.tools import WikipediaQueryRun
from langchain_community.utilities import WikipediaAPIWrapper
from sample_standard_app.app.core.tool.langchain_tool.langchain_tool import LangChainTool
class WikipediaTool(LangChainTool):
def init_langchain_tool(self, component_configer):
wrapper = WikipediaAPIWrapper()
return WikipediaQueryRun(api_wrapper=wrapper)
```
Define Configuration:
```yaml
name: 'wikipedia_query'
description: ''
tool_type: 'api'
input_keys: ['input']
metadata:
type: 'TOOL'
module: 'sample_standard_app.app.core.tool.langchain_tool.wikipedia_query'
class: 'WikipediaTool'
```
53 changes: 52 additions & 1 deletion docs/guidebook/en/2_2_3_Integrated_Tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ SEARCHAPI_API_KEY="xxxxxx"
```


## 2. 代码工具
## 2. Code Tool

### 2.1 PythonRepl
[Tool address](../../../sample_standard_app/app/core/tool/python_repl_tool.yaml)
Expand Down Expand Up @@ -134,5 +134,56 @@ metadata:
This tool can be used directly without any key, but for system security, please do not use this tool in production environments.
## 3.HTTP Tool
### 3.1 HTTP GET
[Tool address](../../../sample_standard_app/app/core/tool/request_get_tool.yaml)
The tool can send a GET request, with its configuration information being:
```yaml
name: 'requests_get'
description: 'A portal to the internet. Use this when you need to get specific
content from a website. Input should be a url (i.e. https://www.google.com).
The output will be the text response of the GET request.
```'
headers:
content-type: 'application/json'
method: 'POST'
json_parser: true
response_content_type: json
tool_type: 'api'
input_keys: ['input']
metadata:
type: 'TOOL'
module: 'sample_standard_app.app.core.tool.request_tool'
class: 'RequestTool'
```
Configuration to Refer to When Sending a POST Request:
```yaml
name: 'requests_post'
# description copy from langchain RequestPOSTTool
description: 'Use this when you want to POST to a website.
Input should be a json string with two keys: "url" and "data".
The value of "url" should be a string, and the value of "data" should be a dictionary of
key-value pairs you want to POST to the url.
Be careful to always use double quotes for strings in the json string
The output will be the text response of the POST request.
```'
headers:
content-type: 'application/json'
method: 'POST'
json_parser: true
response_content_type: json
tool_type: 'api'
input_keys: ['input']
metadata:
type: 'TOOL'
module: 'sample_standard_app.app.core.tool.request_tool'
class: 'RequestTool'
```
Parameter Description:
method: The method of the request, such as GET, POST, PUT, etc.
headers: The HTTP headers required for sending the request.
json_parse: Specifies whether the input parameters need to be parsed by HTTP. It should be set to True for POST requests and False for GET requests.
response_content_type: The parsing method for the HTTP request result. If set to 'json', the result will be returned in JSON format; if set to 'text', the result will be returned as text.
This tool can be used directly without any keys required.
84 changes: 84 additions & 0 deletions docs/guidebook/zh/2_2_3_集成LangChain工具.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# 集成LangChain工具

根据langchain中工具对象的初始化的难易程度,可以将其分为两类:
第一类,简单初始化,只需要简单的参数配置即可完成初始化。
第二类,复杂初始化,内部包含一些复杂的对象需要进行初始化。
对于一类工具,你可以在aU中直接使用配置文件进行初始化,如DuDuckGo搜索工具的初始化。
对于第二类工具,我们实现了一个LangChainTool基础类,你只需要实现该类的init_langchain_tool方法,初始化对应的langchain工具对象即可,参考维基百科的初始化方法。

注意,如果你想直接使用LangChain中的description,在配置文件中description必须要配置为空

一个工具初始化示例:
[工具地址](../../../sample_standard_app/app/core/tool/langchain_tool/human_input_run.yaml)
```yaml
name: 'human_input_run'
description: ''
tool_type: 'api'
input_keys: ['input']
langchain:
module: langchain_community.tools
class_name: HumanInputRun
metadata:
type: 'TOOL'
module: 'sample_standard_app.app.core.tool.langchain_tool'
class: 'LangChainTool'
```
参数说明:
langchain: 你打算使用的langchain工具,需要配置module和class_name
langchain.module: langchain的模块名,例如langchain_community.tools
langchain.class_name: langchain的类名,例如HumanInputRun
langchain.init_params: langchain的初始化参数,例如:
```yaml
langchain:
module: langchain_community.tools
class_name: HumanInputRun
init_params:
prompt: '请输入你的问题'
```
如果需要使用你完全重写了init_langchain_tool方法,那么你不需要配置该部分
该工具可以直接使用,无需任何keys
## 1. 集成LangChain中的DuckDuckGo工具
[工具地址](../../../sample_standard_app/app/core/tool/langchain_tool/duckduckgo_search.yaml)
```yaml
name: 'duckduckgo_search'
description: 'DuckDuckGo Search tool'
tool_type: 'api'
input_keys: ['input']
langchain:
module: langchain.tools
class_name: DuckDuckGoSearchResults
init_params:
backend: news
metadata:
type: 'TOOL'
module: 'sample_standard_app.app.core.tool.langchain_tool.langchain_tool'
class: 'LangChainTool'
```
该工具可以直接使用,无需任何keys
## 2.集成维基百科搜索
因为LangChain的定义当中,包含一个api_wrapper对象,因此定义对象文件,并重写初始化方法:
```python
from langchain_community.tools import WikipediaQueryRun
from langchain_community.utilities import WikipediaAPIWrapper

from sample_standard_app.app.core.tool.langchain_tool.langchain_tool import LangChainTool


class WikipediaTool(LangChainTool):
def init_langchain_tool(self, component_configer):
wrapper = WikipediaAPIWrapper()
return WikipediaQueryRun(api_wrapper=wrapper)
```
定义配置
```yaml
name: 'wikipedia_query'
description: ''
tool_type: 'api'
input_keys: ['input']
metadata:
type: 'TOOL'
module: 'sample_standard_app.app.core.tool.langchain_tool.wikipedia_query'
class: 'WikipediaTool'
```
54 changes: 51 additions & 3 deletions docs/guidebook/zh/2_2_3_集成的工具.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,54 @@ metadata:
该工具可以直接使用,无需任何key,但是为了系统安全,请不要在生产环境使用该工具
## 3.HTTP 工具
[工具地址](../../../sample_standard_app/app/core/tool/request_get_tool.yaml)
该工具可以发送一个GET请求,工具的配置信息 :
```yaml
name: 'requests_get'
# description copy from langchain RequestGetTool
description: 'A portal to the internet. Use this when you need to get specific
content from a website. Input should be a url (i.e. https://www.google.com).
The output will be the text response of the GET request.
```'
headers:
content-type: 'application/json'
method: 'POST'
json_parser: false
response_content_type: json
tool_type: 'api'
input_keys: ['input']
metadata:
type: 'TOOL'
module: 'sample_standard_app.app.core.tool.request_tool'
class: 'RequestTool'
```
发送POST请求时可以参考的配置:
```yaml
name: 'requests_post'
# description copy from langchain RequestPOSTTool
description: 'Use this when you want to POST to a website.
Input should be a json string with two keys: "url" and "data".
The value of "url" should be a string, and the value of "data" should be a dictionary of
key-value pairs you want to POST to the url.
Be careful to always use double quotes for strings in the json string
The output will be the text response of the POST request.
```'
headers:
content-type: 'application/json'
method: 'POST'
json_parser: true
response_content_type: json
tool_type: 'api'
input_keys: ['input']
metadata:
type: 'TOOL'
module: 'sample_standard_app.app.core.tool.request_tool'
class: 'RequestTool'
```
参数说明:
method 请求的方式GET/POST/PUT等
headers 发送请求需要使用的 http的header,
json_parse 输入参数是否需要是要HTTP解析,POST请求时需要设置为True,GET请求需要设置为False
response_content_type http请求结果的解析方式,设置为json时,会返回json结果,设置为text时会返回text结果
该工具可以直接使用,无需任何keys
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ langchain-anthropic = '^0.1.13'
numpy = '^1.26.0'
pandas = "^2.2.2"
pyarrow = "^16.1.0"
duckduckgo-search = "^6.1.7"
wikipedia= "^1.4.0"

[tool.poetry.extras]
log_ext = ["aliyun-log-python-sdk"]
Expand Down
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name: 'duckduckgo_search'
description: ''
tool_type: 'api'
input_keys: ['input']
langchain:
module: langchain.tools
class_name: DuckDuckGoSearchResults
init_params:
backend: news
metadata:
type: 'TOOL'
module: 'sample_standard_app.app.core.tool.langchain_tool.langchain_tool'
class: 'LangChainTool'
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
name: 'human_input_run'
description: ''
tool_type: 'api'
input_keys: ['input']
langchain:
module: langchain_community.tools
class_name: HumanInputRun
metadata:
type: 'TOOL'
module: 'sample_standard_app.app.core.tool.langchain_tool.langchain_tool'
class: 'LangChainTool'
50 changes: 50 additions & 0 deletions sample_standard_app/app/core/tool/langchain_tool/langchain_tool.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# !/usr/bin/env python3
# -*- coding:utf-8 -*-
import importlib
import json
# @Time : 2024/6/24 11:42
# @Author : weizjajj
# @Email : weizhongjie.wzj@antgroup.com
# @FileName: langchain_tool.py

from typing import Optional, Type

from langchain_community.tools import DuckDuckGoSearchResults
from langchain_core.tools import BaseTool

from agentuniverse.agent.action.tool.tool import Tool, ToolInput
from agentuniverse.base.config.component_configer.configers.tool_configer import ToolConfiger


class LangChainTool(Tool):
name: Optional[str] = ""
description: Optional[str] = ""
tool: Optional[BaseTool] = None

def execute(self, tool_input: ToolInput):
input = tool_input.get_data("input")
callbacks = tool_input.get_data("callbacks", None)
return self.tool.run(input, callbacks=callbacks)

def initialize_by_component_configer(self, component_configer: ToolConfiger) -> 'Tool':
super().initialize_by_component_configer(component_configer)
self.tool = self.init_langchain_tool(component_configer)
if not component_configer.description:
self.description = self.tool.description
return self

def init_langchain_tool(self, component_configer):
langchain_info = component_configer.configer.value.get('langchain')
module = langchain_info.get("module")
class_name = langchain_info.get("class_name")
module = importlib.import_module(module)
clz = getattr(module, class_name)
init_params = langchain_info.get("init_params")
self.get_langchain_tool(init_params, clz)
return self.tool

def get_langchain_tool(self, init_params: dict, clz: Type[BaseTool]):
if init_params:
self.tool = clz(**init_params)
else:
self.tool = clz()
Loading

0 comments on commit c4ec0b6

Please sign in to comment.