文章目录
- 博客详细讲解视频
- 点击查看高清脑图
- 1. 搭建天气查询http服务
- 1.1. flask代码
- 1.2. 接口优化方法
- 2. 生成openapi json schema
- 2.1. 测试接口
- 2.2. 生成openapi schema
- 3. 在dify中创建自定义工具
- 3.1. 导入schema
- 3.2. 设置工具认证信息
- 3.3. 测试工具
- 4. 调用工具
- 4.1. Agent应用中调用工具
- 4.1.1. 创建agent应用
- 4.1.2. 添加工具
- 4.1.3. 测试工具
- 4.2. 聊天助手工作流中调用工具
- 4.2.1. 创建工作流应用
博客详细讲解视频
点击查看高清脑图
我们以一个天气查询工具为例子,介绍如何在dify平台创建自定义工具
1. 搭建天气查询http服务
1.1. flask代码
我们使用flask搭建简单的http服务,代码如下
from flask import Flask, request, jsonify
import random
app = Flask(__name__)
@app.route('/weather', methods=['POST'])
def get_weather():
auth_header = request.headers.get('Authorization')
if auth_header != 'Bearer hanfangyuan':
return {"msg": "Invalid Authorization header"}, 403
city = request.json.get('city', None)
if city is None:
return jsonify({
'status': 'error',
'errorInfo': 'No city provided',
'data': None
})
# 随机生成温度,风速和风向
temperature = f'{random.randint(10, 20)}℃'
windspeed = f'{random.randint(1, 5)}级'
winddirect = random.choice(['北风', '南风', '西风', '东风']) # 随机选择风向
# 返回JSON格式的响应
# return jsonify({
# 'status': 'OK',
# 'errorInfo': None,
# 'data': {
# 'city': city,
# 'temp': temperature,
# 'windspeed': windspeed,
# 'winddirect': winddirect
# }
# })
# 返回对LLM友好的字符串格式的响应
return f"{city}今天是晴天,温度{temperature}, 风速{windspeed}, 风向{winddirect}"
if __name__ == '__main__':
app.run(host='0.0.0.0',debug=False, port=4397)
1.2. 接口优化方法
在编写工具的http服务时我们有2个优化方向,即LLM调用友好和LLM理解友好,我在之前写的文章【LLMOps】如何借助AI实现智能客服有过介绍,下面我重新写一下:
LLM调用友好:多步骤整合
我们知道,调用哪些工具,以及根据工具的返回结果回答客户问题完全是依靠模型实现的。工具越多,工具调用的步骤越复杂,工具返回的结果越复杂,模型可能会出错。为了降低这个错误率,对模型的能力要求就会更高,同时模型的使用成本也会更高。为了避免这种情况,我们可以把多步骤的接口合并成一个,让AI模型直接调用。比如查询天气可能需要调用3个接口:鉴权、订阅、查询天气,如果直接让AI使用这三个工具,AI需要三个步骤才能获取到订单数据,对模型的要求就会升高,问题回答速度也会变慢。我们就可以把这三个接口合并成一个接口,对外提供服务。大多数情况,为了不影响原来的业务,我们可能无法改动这三个接口,所以我们可以专门做一个接口整合的服务,去中转这些复杂的接口,只提供给模型易用的接口。
LLM理解友好:自然语言式的返回结果
另外一个优化的方向是工具返回的结果,还是以天气查询接口为例,如果接口直接返回一个json结构,而且字段中都是英文缩写,AI可能根本无法理解这些字段的含义。一种方法是我们可以在提示词中预先告诉模型每个字段的含义,但是这样不够方便。最直接的方法是我们把接口返回的信息翻译成模型容易理解的文字,这样模型更容易理解这个结果。
2. 生成openapi json schema
2.1. 测试接口
在运行上述代码,搭建好天气查询服务后,我们首先需要测试一下这个接口,保证能够调通这个接口,可以利用ApiFox进行测试。
我首先把代码部署到我的服务器上,地址为https://weather.hanfangyuan.cn/weather,然后测试接口。
首先填写请求方法和地址,然后不要忘记填写认证的Authorization header
然后填写body,发送请求,确认接口正确返回数据
2.2. 生成openapi schema
- 接口测试无误后,我们按照下图方式导出接口curl命令
- 复制curl请求代码
- 利用gpt4把curl命令转为openapi schema
提示词如下
请把curl请求命令转成openapi 3.1.0 版本的json schema
<curl>
curl --location --request POST 'https://weather.hanfangyuan.cn/weather' \
--header 'Authorization: Bearer hanfangyuan' \
--header 'User-Agent: Apifox/1.0.0 (https://apifox.com)' \
--header 'Content-Type: application/json' \
--data-raw '{
"city": "上海"
}'
</curl>
json schema请参照下面的例子
<json-schema>
{
"openapi": "3.1.0",
"info": {
"title": "Get weather data",
"description": "Retrieves current weather data for a location.",
"version": "v1.0.0"
},
"servers": [
{
"url": "https://weather.example.com"
}
],
"paths": {
"/location": {
"get": {
"description": "Get temperature for a specific location",
"operationId": "GetCurrentWeather",
"parameters": [
{
"name": "location",
"in": "query",
"description": "The city and state to retrieve the weather for",
"required": true,
"schema": {
"type": "string"
}
}
],
"deprecated": false
}
}
},
"components": {
"schemas": {}
}
}
</json-schema>
生成的json结果如下
{
"openapi": "3.1.0",
"info": {
"title": "Weather Service API",
"description": "API for retrieving weather data for a specified city.",
"version": "1.0.0"
},
"servers": [
{
"url": "https://weather.hanfangyuan.cn"
}
],
"paths": {
"/weather": {
"post": {
"description": "Retrieve weather data for a specific city",
"operationId": "getWeatherData",
"requestBody": {
"description": "City for which to fetch weather",
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "Name of the city"
}
},
"required": ["city"]
}
}
}
},
"responses": {
"200": {
"description": "Successful response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"temperature": {
"type": "number",
"description": "Current temperature in Celsius"
},
"description": {
"type": "string",
"description": "Weather condition description"
}
}
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
]
}
}
},
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
这个open api schema包含了天气工具的作用、url地址、请求参数、参数的描述等信息,利用这些信息能够正确创建http请求,并且能够提供模型这个工具的作用,指导模型什么时候应该调用这个工具。
3. 在dify中创建自定义工具
3.1. 导入schema
- 进入dify工具页面
- 创建自定义工具
- 填写名称
- 填写生成的open api json schema
3.2. 设置工具认证信息
- 点击设置鉴权方法
- 鉴权类型 API Key
- 头部Bearer
- 键 Authorization
- 值 hanfangyuan
配置上面认证方法的依据是,我们在1.1 flask 的代码设置了鉴权,具体代码如下
def get_weather():
auth_header = request.headers.get('Authorization')
if auth_header != 'Bearer hanfangyuan':
return {"msg": "Invalid Authorization header"}, 403
3.3. 测试工具
- 点击测试
- 填写参数值上海
- 点击测试
- 确认正常返回
测试正常后不要忘了点击右下角保存
4. 调用工具
4.1. Agent应用中调用工具
4.1.1. 创建agent应用
在工作室页面按照如下步骤创建agent类型应用
4.1.2. 添加工具
创建成功后按照如下步骤添加工具
4.1.3. 测试工具
工具添加完毕后,发送问题今天上海天气如何,可以看到成功调用工具,并返回结果。
4.2. 聊天助手工作流中调用工具
4.2.1. 创建工作流应用
- 工作室页面
- 创建空白应用
- 选择聊天助手
- 选择工作流编排
- 输入名称,工具调用-工作流
创建聊天工作流,在聊天工作流中调用工具