平时做技术实践时,很多问题不是概念不会,而是细节没串起来。拿“OpenAI Function Calling特性示例”来说,它看着像小点,放到项目里常会牵出环境、配置、兼容性和维护成本。下面按实际采用顺序,把思路、关键写法和容易踩坑的地方讲清楚,便于大家直接对照操作。
Function Calling采用
OpenAI 在gpt-3.5-turbo-0613 和 gpt-4-0613两个模型的chat completion api中增加了一个叫 Function Calling 的新功能,本篇文章对其功能进行探究,并分析其作用。
理解这一步时,我认为这是一种比Plugin更优雅的方式,给开发者提供了更多的自由度,一方面识别出何时需调用函数来对输出格式化,一方面设定具体的格式化数据有助于接入后续业务逻辑。达到尽可能保证(注意这里,是根据你的函数描述最大可能保证,不能100%)LLM输出可控的基础上,来增强自己业务的目的。
show me code
从实现思路看,下面以记账应用为例,告诉AI:“今天喝奶茶花了6元”,正常思路来说,交互流程应该是这样的:
- 用户输入prompt
- AI进行语义分析
- 得到结构化的数据(每个子项是什么,花费是多少)
- 拿到数据进行下一步操作
实际处理时,借助Function Calling,微调后的模型能够检测何时应该调用函数同时采用符合函数签名的 JSON 进行响应,下面看代码例子
import openai
import json
from enum import Enum
class BaseTool(Enum):
Bookkeeping = "record_price"
RecordingTask = "record_task"
def record_price(category, price):
print(category, price)
# 记账应用 API
print("记账成功!")
def funtion_call_conversation():
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo-0613",
messages=[
{"role": "user", "content": "今天喝奶茶花了6元"},
],
temperature=0,
functions=[
{
"name": BaseTool.Bookkeeping.value,
"description": "bookkeeping assistant",
"parameters": {
"type": "object",
"properties": {
"category": {
"type": "string",
"description": "类目",
},
"price": {"type": "string", "description": "金额"},
},
"required": ["category", "price"],
},
}
],
function_call="auto",
)
message = response["choices"][0]["message"]
if(message.get("function_call")):
function_name = message["function_call"]["name"]
if function_name == BaseTool.Bookkeeping.value:
arguments = json.loads(message["function_call"]["arguments"])
record_price(arguments.get('category'), arguments.get('price'))
接口调用说明
- 理解这一步时,name字段表示要调用的函数名,description表示函数描述,paramters是一个符合JSON Schema格式的对象,用来描述这个函数的入参信息(让 LLM 读得懂的工具函数说明)
从实现思路看,record_price是用来给Function Calling调用的函数,这个函数接收两个必填的参数,category类目(string类型),price金额(string类型)
functions=[
{
"name": BaseTool.Bookkeeping.value,
"description": "bookkeeping assistant",
"parameters": {
"type": "object",
"properties": {
"category": {"type": "string","description": "类目"},
"price": {"type": "string", "description": "金额"},
},
"required": ["category", "price"],
},
}
],
LLM分析结果
结合项目来看,LLM 分析后命中了函数签名描述,就会得到给我们 function_call 这个字段以及函数签名中我们预定义的相关信息:
{
"role": "assistant",
"content": null,
"function_call": {
"name": "record_price",
"arguments": "{n "category": "u5976u8336",n "price": "6u5143"n}"
}
}- category得到给我们了类目是奶茶
- price识别出了金额是6元
在这个场景下,下面拿到参数,调用 record_price 进行记账的操作即可;如果没有命中函数签名描述,就不会得到function_call字段,也就不需进行任何操作:
if(message.get("function_call")):
function_name = message["function_call"]["name"]
if function_name == BaseTool.Bookkeeping.value:
arguments = json.loads(message["function_call"]["arguments"])
record_price(arguments.get('category'), arguments.get('price'))实际处理时,按照这种思路,能够扩展自己的外部工具,比如发邮件,记录待办清单,让LLM变成私人管家。
AI记账应用设想
LLM 加持的记账应用设想,不需打开记账软件写类目记金额:
- 直接对照Siri说“今天喝奶茶花了6元”
- 然后借助STT,转换为文本
- 借助上述程序提取类目和金额,调用记账API,记录成功
存在问题
- 函数描述是会被计入token的(果然魔法都是有成本的
- 潜在的风险:分析不准确,出现无法命中函数签名描述的情况
参考
- Function Calling 文档
- openai-cookbook
结合项目来看,以上就是OpenAI Function Calling特性作用详解的详细内容,更多关于OpenAI Function Calling的资料请关注脚本之家其它相关文章!
- OpenAI 函数调用示例及功能入门教程
- openai createChatCompletion函数采用实例
- OPENAI API 微调 GPT-3 的 Ada 模型
- 176万!GPT-4发布详解如何查看OpenAI的下载量
- OpenAI发布GPT-4兼容图像文本输入处理中文准确度大幅提升
- OpenAI的Whisper模型进行语音识别采用详解
- 人工智能深度学习OpenAI baselines的采用方法