全能助手
赋予联网功能,将用户问题进行分类,细分后对接对应 API 获取信息,经 GPT 整理后返回
该教程由社区提供,部分模块已经过期,需调整后才能使用。
众所周知 GPT 只是一个语言模型,功能上有很多局限,但只要综合利用高级编排各模块功能,就可以轻松突破原有 GPT 的局限,实现更多功能。
当然,所谓“全能助手”只是一个遥远的设想,高级编排的玩法有很大的可能性,本文只是扩展了诸如【天气查询】、【微博热搜查询】的功能,主要还是希望大家能通过案例来了解下高级编排的思路,然后可以分享更多有意思的玩法。
简要介绍一下“全能助手”的思路
思路说来也简单,以下分别用文字和图片两种方式介绍下
- 文字描述:
- 对于用户输入的问题,通过【问题分类】模块进行区分,分出【询问天气】、【微博热搜】、【其他问题】等
- 对于【询问天气】的情况,调用第三方 API 查询天气(后文会介绍),将查询到的 json 结果丢给【AI 对话】模块,让它根据用户问题来给出回答
- 对于【微博热搜】的情况,同理,也是调的第三方 API
- 对于【其他问题】的情况,直接走【AI 对话】模块就好了,跟普通的 GPT 聊天一样
- 流程图(方便理解):
详细步骤
以下对于相同的步骤不会赘述,对于第三方接口只介绍了【天气查询】,而【微博热榜】跟【天气查询】的步骤是一样的,只是接口和提示词不同,所以不再赘述。后文会发出完整的高级编排配置,可以导入自行查看~
第三方 API 获取
案例中第三方接口来源目前都是在 https://api.vvhan.com/ 里获得,里面有许多花里胡哨的接口可以用,当然你有其他的接口可以对接也可以,反正主要是返回的数据。
举个查询天气的例子:
- 找到查询天气的 API 接口
- 由于我想要的效果是用户可以随意问接下来一周内任意时间的天气(比如用户可以问“接下来一周的天气适合晾被子吗”),所以选择了上面接口的这个格式:https://api.vvhan.com/api/weather?city=徐州&type=week
返回 json:
{"success":true,"city":"徐州市","data":[{"date":"2023-09-21","week":"星期四","type":"多云","low":"14°C","high":"24°C","fengxiang":"东北风","fengli":"3级","night":{"type":"多云","fengxiang":"南风","fengli":"3级"}},{"date":"2023-09-22","week":"星期五","type":"阴","low":"19°C","high":"25°C","fengxiang":"东风","fengli":"3级","night":{"type":"阴","fengxiang":"东风","fengli":"3级"}},{"date":"2023-09-23","week":"星期六","type":"小雨","low":"20°C","high":"23°C","fengxiang":"东北风","fengli":"3级","night":{"type":"小雨","fengxiang":"东北风","fengli":"3级"}},{"date":"2023-09-24","week":"星期日","type":"中雨","low":"20°C","high":"23°C","fengxiang":"东风","fengli":"3级","night":{"type":"中雨","fengxiang":"东北风","fengli":"3级"}},{"date":"2023-09-25","week":"星期一","type":"小雨","low":"20°C","high":"24°C","fengxiang":"北风","fengli":"3级","night":{"type":"阴","fengxiang":"北风","fengli":"3级"}},{"date":"2023-09-26","week":"星期二","type":"阴","low":"21°C","high":"27°C","fengxiang":"北风","fengli":"3级","night":{"type":"阴","fengxiang":"北风","fengli":"3级"}},{"date":"2023-09-27","week":"星期三","type":"阴","low":"21°C","high":"25°C","fengxiang":"东北风","fengli":"3级","night":{"type":"阴","fengxiang":"北风","fengli":"3级"}}]}
- 由于 FastGPT 的 【http 模块】,对于返回的 json 是以对象形式接收,而我们期望得到的是上述 json 中的“data”字段,而“data”又是数组格式,无法直接丢给【AI 对话】模块(我丢过,非字符串格式报错了,不知道后面会不会更新),所以需要对其做一层中转,将“data”字段转成字符串格式。思路如此,中转方式多样,这里介绍我自己的做法:用 python 起一个服务,来负责对 API 的中转,代码如下(包含了天气接口和微博热搜接口):
from flask import Flask, request, Response
import requests
import json
app = Flask(__name__)
@app.route('/weather', methods=['GET','POST'])
def weather():
if request.method == 'POST':
city = request.form.get('city')
if not city:
data = request.get_json()
if data:
city = data.get('city')
else:
city = request.args.get('city')
api_url = "https://api.vvhan.com/api/weather"
# 为了方便,这里强行写死一周了,只有城市是外部传进来的
params = {"city": city, "type": "week"}
response = requests.get(api_url, params=params)
res = json.loads(response.text)
# 将data字段转成字符串格式
res['data'] = json.dumps(res['data'], ensure_ascii=False)
return Response(json.dumps(res, ensure_ascii=False), mimetype="application/json")
@app.route('/wbhot', methods=['GET','POST'])
def wbhot():
api_url = "https://api.vvhan.com/api/wbhot"
response = requests.get(api_url)
res = json.loads(response.text)
# 只返回前10条热搜(免得数据太多耗token)
res['data'] = res['data'][:10]
# 将data字段转成字符串格式
res['data'] = json.dumps(res['data'], ensure_ascii=False)
return Response(json.dumps(res, ensure_ascii=False), mimetype="application/json")
if __name__ == '__main__':
#部署在3017端口,可自行修改
app.run(host='0.0.0.0', port=3017)
- 接口测试返回数据:
{"success": true, "city": "广州市", "data": "[{\"date\": \"2023-09-21\", \"week\": \"星期四\", \"type\": \"雷阵雨\", \"low\": \"25°C\", \"high\": \"34°C\", \"fengxiang\": \"微风\", \"fengli\": \"3级\", \"night\": {\"type\": \"雷阵雨\", \"fengxiang\": \"微风\", \"fengli\": \"3级\"}}, {\"date\": \"2023-09-22\", \"week\": \"星期五\", \"type\": \"雷阵雨\", \"low\": \"25°C\", \"high\": \"32°C\", \"fengxiang\": \"微风\", \"fengli\": \"3级\", \"night\": {\"type\": \"多云\", \"fengxiang\": \"微风\", \"fengli\": \"3级\"}}, {\"date\": \"2023-09-23\", \"week\": \"星期六\", \"type\": \"多云\", \"low\": \"25°C\", \"high\": \"32°C\", \"fengxiang\": \"微风\", \"fengli\": \"3级\", \"night\": {\"type\": \"多云\", \"fengxiang\": \"微风\", \"fengli\": \"3级\"}}, {\"date\": \"2023-09-24\", \"week\": \"星期日\", \"type\": \"多云\", \"low\": \"25°C\", \"high\": \"34°C\", \"fengxiang\": \"微风\", \"fengli\": \"3级\", \"night\": {\"type\": \"多云\", \"fengxiang\": \"微风\", \"fengli\": \"3级\"}}, {\"date\": \"2023-09-25\", \"week\": \"星期一\", \"type\": \"多云\", \"low\": \"25°C\", \"high\": \"34°C\", \"fengxiang\": \"微风\", \"fengli\": \"3级\", \"night\": {\"type\": \"多云\", \"fengxiang\": \"微风\", \"fengli\": \"3级\"}}, {\"date\": \"2023-09-26\", \"week\": \"星期二\", \"type\": \"多云\", \"low\": \"25°C\", \"high\": \"34°C\", \"fengxiang\": \"微风\", \"fengli\": \"3级\", \"night\": {\"type\": \"多云\", \"fengxiang\": \"微风\", \"fengli\": \"3级\"}}, {\"date\": \"2023-09-27\", \"week\": \"星期三\", \"type\": \"中雨\", \"low\": \"26°C\", \"high\": \"33°C\", \"fengxiang\": \"微风\", \"fengli\": \"3级\", \"night\": {\"type\": \"中雨\", \"fengxiang\": \"微风\", \"fengli\": \"3级\"}}]"}
用户问题分类
第一步就是对用户问题进行分类,如图红框部分:
接口参数获取及处理
数据获取:
由于天气接口需要传入的是“城市”字段,所以需要我们从用户的问题中提取出“城市”字段,所以【文本内容提取】模块登场。
提取要求描述(自行调试另一个 prompt 也行):
你是一个天气查询助手。根据用户问题,提取出城市。注意不是简单的文本提取,而是上下文理解后的提取。如果用户问题中不包含城市则不提取
目标字段:城市
数据处理:
- 设计一个好用的功能往往需要把用户当成小白,所以用户的问题中很可能是没有我们需要的参数的,所以当“提取字段缺失”时,我们需要【指定回复】模块来提示用户输入城市
- 若提取成功,则将提取出来的“城市”发给 http 模块
如图:
AI 总结回复
上述步骤已经拿到了天气的 json 结果,但我们需要的是语义化的结果,所以就要把“json 结果”、“当前时间”(方便用户问今天还是明天天气时可以判断)、“上下文聊天记录”(方便用户的问题涉及上下文关联时能区分)这三个参数传给【AI 对话】模块,让它来总结回复。 限定词(我自己调试的,你有更好的也可以替换):
已知条件:1. 当前时间是{{cTime}};2. 这份json数据是要询问的地方的天气数据,比如用户问的是“北京”的天气,那这份json就是“北京”的天气数据。
现在请自行解析json后回复用户
如图:
模块编排
复制下面配置,点击「高级编排」右上角的导入按键,导入该配置。
PS1:接口的第三方域名已打码,需要自行替换
PS2:配置中的问题分类还包含着“联网搜索”,这个是另一个案例中整合进来的,这里不做介绍,有兴趣看另一篇“联网 GPT”案例。没兴趣也可以在问题分类中删掉这个分支
编排配置
[
{
"moduleId": "userChatInput",
"name": "用户问题(对话入口)",
"flowType": "questionInput",
"position": {
"x": 464.32198615344566,
"y": 1602.2698463081606
},
"inputs": [
{
"key": "userChatInput",
"type": "systemInput",
"label": "用户问题",
"connected": true
}
],
"outputs": [
{
"key": "userChatInput",
"label": "用户问题",
"type": "source",
"valueType": "string",
"targets": [
{
"moduleId": "toho1d",
"key": "userChatInput"
},
{
"moduleId": "rov9zf",
"key": "content"
},
{
"moduleId": "6q1n0a",
"key": "userChatInput"
},
{
"moduleId": "i0u1iy",
"key": "userChatInput"
},
{
"moduleId": "uo68aj",
"key": "userChatInput"
},
{
"moduleId": "3k4zw1",
"key": "content"
},
{
"moduleId": "01fwnb",
"key": "userChatInput"
}
]
}
]
},
{
"moduleId": "history",
"name": "聊天记录",
"flowType": "historyNode",
"position": {
"x": 452.5466249541586,
"y": 1276.3930310334215
},
"inputs": [
{
"key": "maxContext",
"type": "numberInput",
"label": "最长记录数",
"value": 6,
"min": 0,
"max": 50,
"connected": true
},
{
"key": "history",
"type": "hidden",
"label": "聊天记录",
"connected": true
}
],
"outputs": [
{
"key": "history",
"label": "聊天记录",
"valueType": "chatHistory",
"type": "source",
"targets": [
{
"moduleId": "toho1d",
"key": "history"
},
{
"moduleId": "6q1n0a",
"key": "history"
},
{
"moduleId": "rov9zf",
"key": "history"
},
{
"moduleId": "uo68aj",
"key": "history"
},
{
"moduleId": "3k4zw1",
"key": "history"
},
{
"moduleId": "01fwnb",
"key": "history"
}
]
}
]
},
{
"moduleId": "toho1d",
"name": "问题分类",
"flowType": "classifyQuestion",
"showStatus": true,
"position": {
"x": 942.1068912757241,
"y": 1044.6701989335747
},
"inputs": [
{
"key": "systemPrompt",
"type": "textarea",
"valueType": "string",
"value": "",
"label": "系统提示词",
"description": "你可以添加一些特定内容的介绍,从而更好的识别用户的问题类型。这个内容通常是给模型介绍一个它不知道的内容。",
"placeholder": "例如: \n1. Laf 是一个云函数开发平台……\n2. Sealos 是一个集群操作系统",
"connected": true
},
{
"key": "history",
"type": "target",
"label": "聊天记录",
"valueType": "chatHistory",
"connected": true
},
{
"key": "userChatInput",
"type": "target",
"label": "用户问题",
"required": true,
"valueType": "string",
"connected": true
},
{
"key": "agents",
"type": "custom",
"label": "",
"value": [
{
"value": "询问天气",
"key": "fasw"
},
{
"value": "其它问题",
"key": "wl9i"
},
{
"value": "微博热榜",
"key": "sf09"
},
{
"value": "联网搜索",
"key": "6p8b"
}
],
"connected": true
}
],
"outputs": [
{
"key": "fasw",
"label": "",
"type": "hidden",
"targets": [
{
"moduleId": "rov9zf",
"key": "switch"
}
]
},
{
"key": "fqsw",
"label": "",
"type": "hidden",
"targets": []
},
{
"key": "fesw",
"label": "",
"type": "hidden",
"targets": []
},
{
"key": "wl9i",
"label": "",
"type": "hidden",
"targets": [
{
"moduleId": "i0u1iy",
"key": "switch"
}
]
},
{
"key": "sf09",
"label": "",
"type": "hidden",
"targets": [
{
"moduleId": "3m320f",
"key": "switch"
}
]
},
{
"key": "6p8b",
"label": "",
"type": "hidden",
"targets": [
{
"moduleId": "3k4zw1",
"key": "switch"
}
]
}
]
},
{
"moduleId": "rov9zf",
"name": "文本内容提取",
"flowType": "contentExtract",
"showStatus": true,
"position": {
"x": 1632.5948304111266,
"y": 331.84468967718163
},
"inputs": [
{
"key": "switch",
"type": "target",
"label": "触发器",
"valueType": "any",
"connected": true
},
{
"key": "description",
"type": "textarea",
"valueType": "string",
"value": "你是一个天气查询助手。根据用户问题,提取出城市。注意不是简单的文本提取,而是上下文理解后的提取。如果用户问题中不包含城市则不提取",
"label": "提取要求描述",
"description": "写一段提取要求,告诉 AI 需要提取哪些内容",
"required": true,
"placeholder": "例如: \n1. 你是一个实验室预约助手。根据用户问题,提取出姓名、实验室号和预约时间",
"connected": true
},
{
"key": "history",
"type": "target",
"label": "聊天记录",
"valueType": "chatHistory",
"connected": true
},
{
"key": "content",
"type": "target",
"label": "需要提取的文本",
"required": true,
"valueType": "string",
"connected": true
},
{
"key": "extractKeys",
"type": "custom",
"label": "目标字段",
"description": "由 '描述' 和 'key' 组成一个目标字段,可提取多个目标字段",
"value": [
{
"desc": "城市",
"key": "city",
"required": true
}
],
"connected": true
}
],
"outputs": [
{
"key": "success",
"label": "字段完全提取",
"valueType": "boolean",
"type": "source",
"targets": [
{
"moduleId": "4gy7tw",
"key": "switch"
}
]
},
{
"key": "failed",
"label": "提取字段缺失",
"valueType": "boolean",
"type": "source",
"targets": [
{
"moduleId": "eu1xhx",
"key": "switch"
}
]
},
{
"key": "fields",
"label": "完整提取结果",
"description": "一个 JSON 字符串,例如:{\"name:\":\"YY\",\"Time\":\"2023/7/2 18:00\"}",
"valueType": "string",
"type": "source",
"targets": []
},
{
"key": "city",
"label": "提取结果-城市",
"description": "无法提取时不会返回",
"valueType": "string",
"type": "source",
"targets": [
{
"moduleId": "4gy7tw",
"key": "city"
}
]
}
]
},
{
"moduleId": "eu1xhx",
"name": "指定回复",
"flowType": "answerNode",
"position": {
"x": 2137.9125850753494,
"y": 326.06694967444105
},
"inputs": [
{
"key": "switch",
"type": "target",
"label": "触发器",
"valueType": "any",
"connected": true
},
{
"key": "text",
"type": "textarea",
"valueType": "string",
"value": "请告诉我你要查询的是哪个城市的天气",
"label": "回复的内容",
"description": "可以使用 \\n 来实现换行。也可以通过外部模块输入实现回复,外部模块输入时会覆盖当前填写的内容",
"connected": true
}
],
"outputs": [
{
"key": "finish",
"label": "回复结束",
"description": "回复完成后触发",
"valueType": "boolean",
"type": "source",
"targets": []
}
]
},
{
"moduleId": "4gy7tw",
"name": "HTTP模块",
"flowType": "httpRequest",
"showStatus": true,
"position": {
"x": 2156.411722495609,
"y": 661.4677041198821
},
"inputs": [
{
"key": "url",
"value": "http://api.xxx.cn/weather",
"type": "input",
"label": "请求地址",
"description": "请求目标地址",
"placeholder": "https://api.fastgpt.run/getInventory",
"required": true,
"connected": true
},
{
"key": "switch",
"type": "target",
"label": "触发器",
"valueType": "any",
"connected": true
},
{
"valueType": "string",
"type": "target",
"label": "城市",
"edit": true,
"required": false,
"connected": true,
"key": "city"
}
],
"outputs": [
{
"label": "结果",
"valueType": "string",
"type": "source",
"edit": true,
"targets": [
{
"moduleId": "6q1n0a",
"key": "systemPrompt"
}
],
"key": "data"
},
{
"key": "finish",
"label": "请求结束",
"valueType": "boolean",
"type": "source",
"targets": [
{
"moduleId": "6q1n0a",
"key": "switch"
}
]
}
]
},
{
"moduleId": "6q1n0a",
"name": "AI 对话",
"flowType": "chatNode",
"showStatus": true,
"position": {
"x": 2771.9325168087653,
"y": 262.8526145591803
},
"inputs": [
{
"key": "model",
"type": "custom",
"label": "对话模型",
"value": "gpt-3.5-turbo",
"list": [
{
"label": "GPT35-4k",
"value": "gpt-3.5-turbo"
},
{
"label": "GPT35-16k",
"value": "gpt-3.5-turbo-16k"
},
{
"label": "GPT4-8k",
"value": "gpt-4"
}
],
"connected": true
},
{
"key": "temperature",
"type": "slider",
"label": "温度",
"value": 0,
"min": 0,
"max": 10,
"step": 1,
"markList": [
{
"label": "严谨",
"value": 0
},
{
"label": "发散",
"value": 10
}
],
"connected": true
},
{
"key": "maxToken",
"type": "custom",
"label": "回复上限",
"value": 2000,
"min": 100,
"max": 4000,
"step": 50,
"markList": [
{
"label": "100",
"value": 100
},
{
"label": "4000",
"value": 4000
}
],
"connected": true
},
{
"key": "systemPrompt",
"type": "textarea",
"label": "系统提示词",
"max": 300,
"valueType": "string",
"description": "模型固定的引导词,通过调整该内容,可以引导模型聊天方向。该内容会被固定在上下文的开头。可使用变量,例如 {{language}}",
"placeholder": "模型固定的引导词,通过调整该内容,可以引导模型聊天方向。该内容会被固定在上下文的开头。可使用变量,例如 {{language}}",
"value": "",
"connected": true
},
{
"key": "quoteTemplate",
"type": "hidden",
"label": "引用内容模板",
"valueType": "string",
"value": "",
"connected": true
},
{
"key": "quotePrompt",
"type": "hidden",
"label": "引用内容提示词",
"valueType": "string",
"value": "",
"connected": true
},
{
"key": "switch",
"type": "target",
"label": "触发器",
"valueType": "any",
"connected": true
},
{
"key": "quoteQA",
"type": "custom",
"label": "引用内容",
"description": "对象数组格式,结构:\n [{q:'问题',a:'回答'}]",
"valueType": "datasetQuote",
"connected": false
},
{
"key": "history",
"type": "target",
"label": "聊天记录",
"valueType": "chatHistory",
"connected": true
},
{
"key": "userChatInput",
"type": "target",
"label": "用户问题",
"required": true,
"valueType": "string",
"connected": true
},
{
"key": "limitPrompt",
"type": "textarea",
"valueType": "string",
"label": "限定词",
"description": "限定模型对话范围,会被放置在本次提问前,拥有强引导和限定性。可使用变量,例如 {{language}}。引导例子:\n1. 知识库是关于 Laf 的介绍,参考知识库回答问题,与 \"Laf\" 无关内容,直接回复: \"我不知道\"。\n2. 你仅回答关于 \"xxx\" 的问题,其他问题回复: \"xxxx\"",
"placeholder": "限定模型对话范围,会被放置在本次提问前,拥有强引导和限定性。可使用变量,例如 {{language}}。引导例子:\n1. 知识库是关于 Laf 的介绍,参考知识库回答问题,与 \"Laf\" 无关内容,直接回复: \"我不知道\"。\n2. 你仅回答关于 \"xxx\" 的问题,其他问题回复: \"xxxx\"",
"value": "已知条件:1. 当前时间是{{cTime}};2. 这份json数据是要询问的地方的天气数据,比如用户问的是“北京”的天气,那这份json就是“北京”的天气数据。\n\n现在请自行解析json后回复用户",
"connected": true
}
],
"outputs": [
{
"key": "answerText",
"label": "AI回复",
"description": "将在 stream 回复完毕后触发",
"valueType": "string",
"type": "source",
"targets": []
},
{
"key": "finish",
"label": "回复结束",
"description": "AI 回复完成后触发",
"valueType": "boolean",
"type": "source",
"targets": []
}
]
},
{
"moduleId": "i0u1iy",
"name": "AI 对话",
"flowType": "chatNode",
"showStatus": true,
"position": {
"x": 1636.416225126142,
"y": 1243.2398251366028
},
"inputs": [
{
"key": "model",
"type": "custom",
"label": "对话模型",
"value": "gpt-3.5-turbo",
"list": [
{
"label": "GPT35-4k",
"value": "gpt-3.5-turbo"
},
{
"label": "GPT35-16k",
"value": "gpt-3.5-turbo-16k"
},
{
"label": "GPT4-8k",
"value": "gpt-4"
}
],
"connected": true
},
{
"key": "temperature",
"type": "slider",
"label": "温度",
"value": 0,
"min": 0,
"max": 10,
"step": 1,
"markList": [
{
"label": "严谨",
"value": 0
},
{
"label": "发散",
"value": 10
}
],
"connected": true
},
{
"key": "maxToken",
"type": "custom",
"label": "回复上限",
"value": 4000,
"min": 100,
"max": 4000,
"step": 50,
"markList": [
{
"label": "100",
"value": 100
},
{
"label": "4000",
"value": 4000
}
],
"connected": true
},
{
"key": "systemPrompt",
"type": "textarea",
"label": "系统提示词",
"max": 300,
"valueType": "string",
"description": "模型固定的引导词,通过调整该内容,可以引导模型聊天方向。该内容会被固定在上下文的开头。可使用变量,例如 {{language}}",
"placeholder": "模型固定的引导词,通过调整该内容,可以引导模型聊天方向。该内容会被固定在上下文的开头。可使用变量,例如 {{language}}",
"value": "",
"connected": true
},
{
"key": "quoteTemplate",
"type": "hidden",
"label": "引用内容模板",
"valueType": "string",
"value": "",
"connected": true
},
{
"key": "quotePrompt",
"type": "hidden",
"label": "引用内容提示词",
"valueType": "string",
"value": "",
"connected": true
},
{
"key": "switch",
"type": "target",
"label": "触发器",
"valueType": "any",
"connected": true
},
{
"key": "quoteQA",
"type": "custom",
"label": "引用内容",
"description": "对象数组格式,结构:\n [{q:'问题',a:'回答'}]",
"valueType": "datasetQuote",
"connected": false
},
{
"key": "history",
"type": "target",
"label": "聊天记录",
"valueType": "chatHistory",
"connected": true
},
{
"key": "userChatInput",
"type": "target",
"label": "用户问题",
"required": true,
"valueType": "string",
"connected": true
},
{
"key": "limitPrompt",
"type": "textarea",
"valueType": "string",
"label": "限定词",
"description": "限定模型对话范围,会被放置在本次提问前,拥有强引导和限定性。可使用变量,例如 {{language}}。引导例子:\n1. 知识库是关于 Laf 的介绍,参考知识库回答问题,与 \"Laf\" 无关内容,直接回复: \"我不知道\"。\n2. 你仅回答关于 \"xxx\" 的问题,其他问题回复: \"xxxx\"",
"placeholder": "限定模型对话范围,会被放置在本次提问前,拥有强引导和限定性。可使用变量,例如 {{language}}。引导例子:\n1. 知识库是关于 Laf 的介绍,参考知识库回答问题,与 \"Laf\" 无关内容,直接回复: \"我不知道\"。\n2. 你仅回答关于 \"xxx\" 的问题,其他问题回复: \"xxxx\"",
"value": "",
"connected": true
}
],
"outputs": [
{
"key": "answerText",
"label": "AI回复",
"description": "将在 stream 回复完毕后触发",
"valueType": "string",
"type": "source",
"targets": []
},
{
"key": "finish",
"label": "回复结束",
"description": "AI 回复完成后触发",
"valueType": "boolean",
"type": "source",
"targets": []
}
]
},
{
"moduleId": "3m320f",
"name": "HTTP模块",
"flowType": "httpRequest",
"showStatus": true,
"position": {
"x": 1640.5198770218628,
"y": 2420.3111570417573
},
"inputs": [
{
"key": "url",
"value": "http://api.xxx.cn/wbhot",
"type": "input",
"label": "请求地址",
"description": "请求目标地址",
"placeholder": "https://api.fastgpt.run/getInventory",
"required": true,
"connected": true
},
{
"key": "switch",
"type": "target",
"label": "触发器",
"valueType": "any",
"connected": true
}
],
"outputs": [
{
"label": "data",
"valueType": "string",
"type": "source",
"edit": true,
"targets": [
{
"moduleId": "uo68aj",
"key": "systemPrompt"
}
],
"key": "data"
},
{
"key": "finish",
"label": "请求结束",
"valueType": "boolean",
"type": "source",
"targets": [
{
"moduleId": "uo68aj",
"key": "switch"
}
]
}
]
},
{
"moduleId": "uo68aj",
"name": "AI 对话",
"flowType": "chatNode",
"showStatus": true,
"position": {
"x": 2248.9999960823247,
"y": 2411.459363346701
},
"inputs": [
{
"key": "model",
"type": "custom",
"label": "对话模型",
"value": "gpt-3.5-turbo-16k",
"list": [
{
"label": "GPT35-4k",
"value": "gpt-3.5-turbo"
},
{
"label": "GPT35-16k",
"value": "gpt-3.5-turbo-16k"
},
{
"label": "GPT4-8k",
"value": "gpt-4"
}
],
"connected": true
},
{
"key": "temperature",
"type": "slider",
"label": "温度",
"value": 0,
"min": 0,
"max": 10,
"step": 1,
"markList": [
{
"label": "严谨",
"value": 0
},
{
"label": "发散",
"value": 10
}
],
"connected": true
},
{
"key": "maxToken",
"type": "custom",
"label": "回复上限",
"value": 16000,
"min": 100,
"max": 4000,
"step": 50,
"markList": [
{
"label": "100",
"value": 100
},
{
"label": "4000",
"value": 4000
}
],
"connected": true
},
{
"key": "systemPrompt",
"type": "textarea",
"label": "系统提示词",
"max": 300,
"valueType": "string",
"description": "模型固定的引导词,通过调整该内容,可以引导模型聊天方向。该内容会被固定在上下文的开头。可使用变量,例如 {{language}}",
"placeholder": "模型固定的引导词,通过调整该内容,可以引导模型聊天方向。该内容会被固定在上下文的开头。可使用变量,例如 {{language}}",
"value": "",
"connected": true
},
{
"key": "quoteTemplate",
"type": "hidden",
"label": "引用内容模板",
"valueType": "string",
"value": "",
"connected": true
},
{
"key": "quotePrompt",
"type": "hidden",
"label": "引用内容提示词",
"valueType": "string",
"value": "",
"connected": true
},
{
"key": "switch",
"type": "target",
"label": "触发器",
"valueType": "any",
"connected": true
},
{
"key": "quoteQA",
"type": "custom",
"label": "引用内容",
"description": "对象数组格式,结构:\n [{q:'问题',a:'回答'}]",
"valueType": "datasetQuote",
"connected": false
},
{
"key": "history",
"type": "target",
"label": "聊天记录",
"valueType": "chatHistory",
"connected": true
},
{
"key": "userChatInput",
"type": "target",
"label": "用户问题",
"required": true,
"valueType": "string",
"connected": true
},
{
"key": "limitPrompt",
"type": "textarea",
"valueType": "string",
"label": "限定词",
"description": "限定模型对话范围,会被放置在本次提问前,拥有强引导和限定性。可使用变量,例如 {{language}}。引导例子:\n1. 知识库是关于 Laf 的介绍,参考知识库回答问题,与 \"Laf\" 无关内容,直接回复: \"我不知道\"。\n2. 你仅回答关于 \"xxx\" 的问题,其他问题回复: \"xxxx\"",
"placeholder": "限定模型对话范围,会被放置在本次提问前,拥有强引导和限定性。可使用变量,例如 {{language}}。引导例子:\n1. 知识库是关于 Laf 的介绍,参考知识库回答问题,与 \"Laf\" 无关内容,直接回复: \"我不知道\"。\n2. 你仅回答关于 \"xxx\" 的问题,其他问题回复: \"xxxx\"",
"value": "以上json数据是当前的微博热榜数据,回答的时候用markdown格式,只需回复热搜标题的前10即可",
"connected": true
}
],
"outputs": [
{
"key": "answerText",
"label": "AI回复",
"description": "将在 stream 回复完毕后触发",
"valueType": "string",
"type": "source",
"targets": []
},
{
"key": "finish",
"label": "回复结束",
"description": "AI 回复完成后触发",
"valueType": "boolean",
"type": "source",
"targets": []
}
]
},
{
"moduleId": "qoccls",
"name": "聊天记录",
"flowType": "historyNode",
"position": {
"x": 448.94080110453046,
"y": 990.48670949044
},
"inputs": [
{
"key": "maxContext",
"type": "numberInput",
"label": "最长记录数",
"value": 50,
"min": 0,
"max": 50,
"connected": true
},
{
"key": "history",
"type": "hidden",
"label": "聊天记录",
"connected": true
}
],
"outputs": [
{
"key": "history",
"label": "聊天记录",
"valueType": "chatHistory",
"type": "source",
"targets": [
{
"moduleId": "i0u1iy",
"key": "history"
}
]
}
]
},
{
"moduleId": "3k4zw1",
"name": "文本内容提取",
"flowType": "contentExtract",
"showStatus": true,
"position": {
"x": 1608.4732867173993,
"y": 3651.5738821560017
},
"inputs": [
{
"key": "switch",
"type": "target",
"label": "触发器",
"valueType": "any",
"connected": true
},
{
"key": "description",
"type": "textarea",
"valueType": "string",
"value": "你是谷歌搜索机器人,可以生成搜索词。你需要自行判断是否需要生成搜索词,如果不需要则返回空字符串。",
"label": "提取要求描述",
"description": "写一段提取要求,告诉 AI 需要提取哪些内容",
"required": true,
"placeholder": "例如: \n1. 你是一个实验室预约助手。根据用户问题,提取出姓名、实验室号和预约时间",
"connected": true
},
{
"key": "history",
"type": "target",
"label": "聊天记录",
"valueType": "chatHistory",
"connected": true
},
{
"key": "content",
"type": "target",
"label": "需要提取的文本",
"required": true,
"valueType": "string",
"connected": true
},
{
"key": "extractKeys",
"type": "custom",
"label": "目标字段",
"description": "由 '描述' 和 'key' 组成一个目标字段,可提取多个目标字段",
"value": [
{
"desc": "搜索词",
"key": "searchKey",
"required": true
}
],
"connected": true
}
],
"outputs": [
{
"key": "success",
"label": "字段完全提取",
"valueType": "boolean",
"type": "source",
"targets": []
},
{
"key": "failed",
"label": "提取字段缺失",
"valueType": "boolean",
"type": "source",
"targets": []
},
{
"key": "fields",
"label": "完整提取结果",
"description": "一个 JSON 字符串,例如:{\"name:\":\"YY\",\"Time\":\"2023/7/2 18:00\"}",
"valueType": "string",
"type": "source",
"targets": []
},
{
"key": "searchKey",
"label": "提取结果-搜索词",
"description": "无法提取时不会返回",
"valueType": "string",
"type": "source",
"targets": [
{
"moduleId": "3ojl65",
"key": "searchKey"
}
]
}
]
},
{
"moduleId": "3ojl65",
"name": "HTTP模块",
"flowType": "httpRequest",
"showStatus": true,
"position": {
"x": 2250.5435150325084,
"y": 3647.785854643283
},
"inputs": [
{
"key": "url",
"value": "http://api.xxx.cn/google",
"type": "input",
"label": "请求地址",
"description": "请求目标地址",
"placeholder": "https://api.fastgpt.run/getInventory",
"required": true,
"connected": true
},
{
"key": "switch",
"type": "target",
"label": "触发器",
"valueType": "any",
"connected": false
},
{
"valueType": "string",
"type": "target",
"label": "搜索词",
"edit": true,
"key": "searchKey",
"required": true,
"connected": true
}
],
"outputs": [
{
"label": "搜索词",
"valueType": "string",
"type": "source",
"edit": true,
"targets": [],
"key": "searchKey"
},
{
"label": "搜索结果",
"valueType": "string",
"type": "source",
"edit": true,
"targets": [
{
"moduleId": "01fwnb",
"key": "systemPrompt"
}
],
"key": "prompt"
},
{
"key": "finish",
"label": "请求结束",
"valueType": "boolean",
"type": "source",
"targets": [
{
"moduleId": "01fwnb",
"key": "switch"
}
]
}
]
},
{
"moduleId": "01fwnb",
"name": "AI 对话",
"flowType": "chatNode",
"showStatus": true,
"position": {
"x": 2913.2501313416833,
"y": 3642.3449136226823
},
"inputs": [
{
"key": "model",
"type": "custom",
"label": "对话模型",
"value": "gpt-3.5-turbo-16k",
"list": [
{
"label": "GPT35-4k",
"value": "gpt-3.5-turbo"
},
{
"label": "GPT35-16k",
"value": "gpt-3.5-turbo-16k"
},
{
"label": "GPT4-8k",
"value": "gpt-4"
}
],
"connected": true
},
{
"key": "temperature",
"type": "slider",
"label": "温度",
"value": 0,
"min": 0,
"max": 10,
"step": 1,
"markList": [
{
"label": "严谨",
"value": 0
},
{
"label": "发散",
"value": 10
}
],
"connected": true
},
{
"key": "maxToken",
"type": "custom",
"label": "回复上限",
"value": 16000,
"min": 100,
"max": 4000,
"step": 50,
"markList": [
{
"label": "100",
"value": 100
},
{
"label": "4000",
"value": 4000
}
],
"connected": true
},
{
"key": "systemPrompt",
"type": "textarea",
"label": "系统提示词",
"max": 300,
"valueType": "string",
"description": "模型固定的引导词,通过调整该内容,可以引导模型聊天方向。该内容会被固定在上下文的开头。可使用变量,例如 {{language}}",
"placeholder": "模型固定的引导词,通过调整该内容,可以引导模型聊天方向。该内容会被固定在上下文的开头。可使用变量,例如 {{language}}",
"value": "",
"connected": true
},
{
"key": "quoteTemplate",
"type": "hidden",
"label": "引用内容模板",
"valueType": "string",
"value": "",
"connected": true
},
{
"key": "quotePrompt",
"type": "hidden",
"label": "引用内容提示词",
"valueType": "string",
"value": "",
"connected": true
},
{
"key": "switch",
"type": "target",
"label": "触发器",
"valueType": "any",
"connected": true
},
{
"key": "quoteQA",
"type": "custom",
"label": "引用内容",
"description": "对象数组格式,结构:\n [{q:'问题',a:'回答'}]",
"valueType": "datasetQuote",
"connected": false
},
{
"key": "history",
"type": "target",
"label": "聊天记录",
"valueType": "chatHistory",
"connected": true
},
{
"key": "userChatInput",
"type": "target",
"label": "用户问题",
"required": true,
"valueType": "string",
"connected": true
},
{
"key": "limitPrompt",
"type": "textarea",
"valueType": "string",
"label": "限定词",
"description": "限定模型对话范围,会被放置在本次提问前,拥有强引导和限定性。可使用变量,例如 {{language}}。引导例子:\n1. 知识库是关于 Laf 的介绍,参考知识库回答问题,与 \"Laf\" 无关内容,直接回复: \"我不知道\"。\n2. 你仅回答关于 \"xxx\" 的问题,其他问题回复: \"xxxx\"",
"placeholder": "限定模型对话范围,会被放置在本次提问前,拥有强引导和限定性。可使用变量,例如 {{language}}。引导例子:\n1. 知识库是关于 Laf 的介绍,参考知识库回答问题,与 \"Laf\" 无关内容,直接回复: \"我不知道\"。\n2. 你仅回答关于 \"xxx\" 的问题,其他问题回复: \"xxxx\"",
"value": "",
"connected": true
}
],
"outputs": [
{
"key": "answerText",
"label": "AI回复",
"description": "将在 stream 回复完毕后触发",
"valueType": "string",
"type": "source",
"targets": []
},
{
"key": "finish",
"label": "回复结束",
"description": "AI 回复完成后触发",
"valueType": "boolean",
"type": "source",
"targets": []
}
]
},
{
"moduleId": "kq35bj",
"name": "用户引导",
"flowType": "userGuide",
"position": {
"x": 359.84546622310677,
"y": 686.3487640909323
},
"inputs": [
{
"key": "welcomeText",
"type": "input",
"label": "开场白",
"value": "你好,我是你的全能助手,目前我拥有【查询天气】、【查看微博热搜】、【智能聊天】功能。来跟我对话吧~",
"connected": true
}
],
"outputs": []
}
]
效果图
后记
- 案例中的提示词不一定完美,如果有出现抽风的情况,可以自行调整提示词。
- 查询天气的 ai 对话,为了省 token 我用的是 GPT3.5,按理说 GPT4 理解力会高点,可以自行试试。
- 本案例中采用了“限定词”的方式引导 【AI 对话】模块,但最新版好像不支持限定词了(当然导入配置是没问题的),大家可以自行研究下新版的用法~