LLM的Function Calling(Tools)基本用法
在Ollama支持函数调用、QWen2.5也开开源了出了一大堆参数尺寸的模型之后这么久才来写这一篇介绍Tools的基本用法,就是因为在这期间也用过好几家大语言模型平台,虽然文档中表明兼容OpenAI API接口,但是在使用一些需要使用Tools功能的工具中时,还是出现了一大堆不兼容的问题,或多或少都有一点输出内容的差异导致解析失败。
所以在当今以OpenAI API有先发优势成为为LLM API标准的今天还是重新学习一下Tools接口的使用方法。
介绍
Function calling现在是构建LLM应用的一个重要的组件,尤其是他通过上下文生成的输出内容格式化为固定的格式,而不是自然语言。因此可以使用此功能来使用LLM来处理内容,并可以轻松的处理输出的内容。
当然输出内容的准确度也是要看所使用的大语言模型的能力如何,像OpenAI在24年8月又加入了一个新的参数strict: true
,这个参数在结构化输出时会提高输出内容与目标结构的准确度(Ollama目前还不支持这个参数)。
开始使用
调用过程
整个Tools使用的流程应该是如下所示:
准备好上下文->准备可以调用的函数结构->发送给LLM进行处理->接受输出内容->处理内容并调用目标函数
因此虽然OpenAI给他命名叫Function Calling,但是实际上LLM起的还是一个结构化输出的作用,最后的函数调用还是由应用程序层来处理。
Function
{
"name": "get_delivery_date",
"description": "Get the delivery date for a customer's order. Call this whenever you need to know the delivery date, for example when a customer asks 'Where is my package'",
"parameters": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "The customer's order ID."
}
},
"required": ["order_id"],
"additionalProperties": false
}
}
这是一个官方的Tools结构实例,当你想让LLM调用Tool时,你必须带上每个Tool的具体结构描述。
整个Tool内部的结构是
- name:函数名
- description:对函数功能的具体描述,也可以给出调用函数的具体情形示例
- parameters:参数体
- type:参数类型
- properties:参数
- order_id:具体的参数名
- type:参数类型
- description:参数的描述
- order_id:具体的参数名
- required:必须参数
- additionalProperties:是否允许对象包含未在 JSON 模式中定义的额外键/值。目前都设置为false 其中有一个参数additionalProperties在Function calling中并未进行解释,但是在结构化输出中解释了它的功能,目前OpenAI的模型还不支持自动提取有用的键值,所以都需要设置这个参数且设置为false。
支持的类型
以下类型支持结构化输出:
- String 字符串
- Number 数字
- Boolean 布尔类型的
- Integer 整数
- Object 对象
- Array 数组
- Enum 枚举
- anyOf 任意一项
- ### Calling
现在开始调用函数,将自己的Tools加入请求结构中,在Http数据内容下,他看起来应该是这样的:
curl https://api.openai.com/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-d '{
"model": "gpt-4o",
"messages": [
{
"role": "user",
"content": "What'\''s the weather like in Boston today?"
}
],
"tools": [
{
"type": "function",
"function": {
"name": "get_current_weather",
"description": "Get the current weather in a given location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g. San Francisco, CA"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"]
}
},
"required": ["location"]
}
}
}
],
"tool_choice": "auto"
}'
这是一个带着天气调用功能的请求,在这里也多出了一个新的参数:tool_choice。可以有以下几个参数:
- none:不调用参数,仅进行内容生成
- required:必须在tools中选择一个或多个参数进行调用
- auto:自动判断
同时还有参数parallel_tool_calls,并行函数调用,这个参数是可以返回多个参数结果,例如当前的user message中询问了多个地点的天气,那么启用这个参数之后就会返回多个Calling的结构。但是当你想遵守严格模式的输出时,就应该禁用这个参数。默认为true。
Return
接下来就开始处理返回结果。
{
"id": "chatcmpl-abc123",
"object": "chat.completion",
"created": 1699896916,
"model": "gpt-4o-mini",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": null,
"tool_calls": [
{
"id": "call_abc123",
"type": "function",
"function": {
"name": "get_current_weather",
"arguments": "{\n\"location\": \"Boston, MA\"\n}"
}
}
]
},
"logprobs": null,
"finish_reason": "tool_calls"
}
],
"usage": {
"prompt_tokens": 82,
"completion_tokens": 17,
"total_tokens": 99,
"completion_tokens_details": {
"reasoning_tokens": 0
}
}
}
返回的内容会添加到message中的tool_calls参数中,参数为数据,意味可能的多个调用结果,这时候应用程序解析内容,并根据内容调用函数就完成了一次Function Calling。