使用文心大模型Function Call
需求背景
设想一个使用手机语音点外卖的场景,我们需要开发一个APP,这个APP可以与用户进行语音对话,能够理解用户的意图,为用户推荐外卖商品,当用户对某款商品满意时,为用户自动下单。
语音转文字(ASR)有成熟方案,不是本文关注的目标,这里不再赘述,如果对这个技术感兴趣,在百度智能云官网上能找到对应的产品。
为了实现上述需求,需要调用两个API接口:
-
delivery_inquiry, 用于查询给定位置的外卖商品,该接口还接受预期价格,返回在给定位置附近并且价格接近的商品。
-
delivery_order, 用于外卖下单,如果用户对某款外卖商品满意,则调用该接口下单。
需求分析与尝试
这个需求需要准确理解用户表达的意图, 并根据用户的意图调用对应的API。这里需要借助于大模型的语义理解能力,对用户不同表达方式的意图进行判断和分类。
在使用Function Call之前,使用Prompt方式做了尝试:
### 背景
有两个API接口:
1. 下单API:支持传入商家名称、商品名称。
2. 搜索API:支持传入地点与距离进行搜索,API会返回外卖商家和商品列表。
### 要求
根据输入的文本,需要决定是否调用API,调用哪个API并生成对应的查询结构体。
回答的时候给出: 1.下一步动作(action) 2.是否调用和调用哪个API 3.回复语句 4.查询结构体。
### 示例
问题:我在新街口,想吃20元左右的黄焖鸡。
答案:{ action: 'call', api: 2, params: ['新街口’, 20, '黄焖鸡']}
问题: 好的,我想吃杨铭宇黄焖鸡
答案:{action: 'call', api: 1, params:['', '', '杨铭宇黄焖鸡']
### 问题
问题:
简单场景下, Prompt方式也能解决问题, 底层都是大模型的语义理解及推理能力, 这一点与Function Call一样。
但是Function Call 更加规范, 它通过规范传入的Function描述及输入输出参数, 让大模型能更准确理解用户意图并与函数调用相匹配。
文心Function Call介绍
文心EB大模型在Body里提供了functions参数,该参数是一个数组,包含了应用需要调用的所有函数描述:
|
名称
|
类型
|
必填
|
描述
|
|
functions
|
List(function)
|
否
|
一个可触发函数的描述列表
|
其中每一个function的定义如下:
|
名称
|
类型
|
必填
|
描述
|
|
name
|
string
|
是
|
函数名
|
|
description
|
string
|
是
|
函数描述
|
|
parameters
|
object
|
是
|
函数请求参数,说明:
(1)JSON Schema 格式,参考JSON Schema描述 (2)如果函数没有请求参数,parameters值格式如下: {"type": "object","properties": {}} |
|
responses
|
object
|
否
|
函数响应参数,JSON Schema 格式,参考JSON Schema描述
|
|
examples
|
List(example)
|
否
|
function调用的一些历史示例
|
需要注意的是, 输入与输出参数需要遵循JSON Schema 格式, 使用该格式更加准确描述函数。
Function Call的使用
直接上代码:
import qianfan
import re
def eb_call(prompt, round):
print(prompt)
print('-' * 20,' EB Output ', '-'*20,"\n")
response = chat_comp.do(
model="ERNIE-Bot",
messages=[{
"role": "user",
"content": prompt
}],
temperature=0.000000001,
functions=[
{
"name": "delivery_inquiry",
"description": "查询商品",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "地址信息,包括街道、门牌号、城市、省份等信息"
},
"expect_price": {
"type": "int",
"description": "期望的价格"
}
},
"required": ["location"]
},
"responses": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "商品id"
},
"price": {
"type": "int",
"description": "商品价格"
},
"food": {
"type": "string",
"description": "商品名称"
},
},
},
},
{
"name": "delivery_order",
"description": "外卖下单",
"parameters": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "商品id"
},
"food": {
"type": "string",
"description": "商品名称"
},
},
"required": ["id"]
},
"responses": {
"type": "object",
"properties": {
"result": {
"type": "string",
"description": "是否下单成功"
},
}
},
}
]
)
print(response)
chat_comp = qianfan.ChatCompletion(ak="YOUR AK", sk="YOUR SK")
with open('prompt.txt', 'r') as f:
prompt = f.read()
prompt_list = re.split(r"###", prompt)
for pp in prompt_list:
eb_call(pp, round)
print('=' * 60,"\n")
Prompt.txt的内容如下:
东升街道附近20元的午餐有哪些推荐?
###
黄焖鸡不错,就买这个19号的黄焖鸡了
###
看下输出结果:
东升街道附近20元的午餐有哪些推荐?
-------------------- EB Output --------------------
{
'code': 200,
'headers': {
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Allow-Origin': '*',
'Appid': '33940484',
'Connection': 'keep-alive',
'Content-Encoding': 'gzip',
'Content-Type': 'application/json; charset=utf-8',
'Date': 'Sun, 08 Oct 2023 09:02:45 GMT',
'Server': 'Apache',
'Set-Cookie': 'BAIDUID=F340661B05C69925448A0CB5072D8F16:FG=1; Path=/; Domain=baidu.com; Max-Age=31536000, BAIDUID_BFESS=F340661B05C69925448A0CB5072D8F16:FG=1; Path=/; Domain=baidu.com; Max-Age=31536000; Secure; SameSite=None',
'Statement': 'AI-generated',
'Vary': 'Accept-Encoding',
'X-Aipe-Self-Def': 'eb_total_tokens:56-id:as-7639tqwfh3',
'X-Baidu-Request-Id': '2183e25d3803703893278a0f96cde8ed1000306',
'X-Openapi-Server-Timestamp': '1696755763',
'Content-Length': '310'
},
'id': 'as-7639tqwfh3',
'object': 'chat.completion',
'created': 1696755765,
'result': '',
'is_truncated': False,
'need_clear_history': False,
'function_call': {
'name': 'delivery_inquiry',
'thoughts': '我需要调用delivery_inquiry来解决这个问题。',
'arguments': '{"location":"东升街道","expect_price":20}'
},
'usage': {
'prompt_tokens': 16,
'completion_tokens': 40,
'total_tokens': 56
}
}
============================================================
黄焖鸡不错,就买这个19号的黄焖鸡了
-------------------- EB Output --------------------
{
'code': 200,
'headers': {
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Allow-Origin': '*',
'Appid': '33940484',
'Connection': 'keep-alive',
'Content-Encoding': 'gzip',
'Content-Type': 'application/json; charset=utf-8',
'Date': 'Sun, 08 Oct 2023 09:02:48 GMT',
'Server': 'Apache',
'Set-Cookie': 'BAIDUID=3C1D038FE73F1DE224224BEA9566547C:FG=1; Path=/; Domain=baidu.com; Max-Age=31536000, BAIDUID_BFESS=3C1D038FE73F1DE224224BEA9566547C:FG=1; Path=/; Domain=baidu.com; Max-Age=31536000; Secure; SameSite=None',
'Statement': 'AI-generated',
'Vary': 'Accept-Encoding',
'X-Aipe-Self-Def': 'eb_total_tokens:60-id:as-2nx17nnk24',
'X-Baidu-Request-Id': 'f61bf2addb96e7cc122cef404461f1001000088',
'X-Openapi-Server-Timestamp': '1696755765',
'Content-Length': '325'
},
'id': 'as-2nx17nnk24',
'object': 'chat.completion',
'created': 1696755768,
'result': '',
'is_truncated': False,
'need_clear_history': False,
'function_call': {
'name': 'delivery_order',
'thoughts': '用户已经提供了所有必要的信息,我可以直接下单。',
'arguments': '{"id":"19","food":"黄焖鸡"}'
},
'usage': {
'prompt_tokens': 16,
'completion_tokens': 44,
'total_tokens': 60
}
}
============================================================
注意大模型输出的“function_call”部分, 大模型准确理解了用户意图,给出调用的函数名称和参数,还给出里推理过程中的思路。
下一步
通过上面的示例,能看到大模型准确理解了用户的意图,并调用了对应的函数,返回结果还包含了从用户语义中提取出来的函数参数。下一步使用参数调用对应函数就可以了。
到这里大模型能帮到我们的就这些了, 最终还是需要应用将大模型的能力连接起来,从而打造更懂用户的应用。
posted on 2025-04-09 20:24 ExplorerMan 阅读(108) 评论(0) 收藏 举报
浙公网安备 33010602011771号