Function Calling 是一个允许大型语言模型(如 GPT)在生成文本的过程中调用外部函数或服务的功能。
Function Calling允许我们以 JSON 格式向 LLM 模型描述函数,并使用模型的固有推理能力来决定在生成响应之前是否调用该函数。模型本身不执行函数,而是生成包含_函数名称_和_执行函数所需的参数_的 JSON。
现在我们定义提示词像大语言模型问一下当前北京的天气?
因为 LLM 大语言模型缺乏实时数据,所以无法回答实时数据这种场景。这时候就需要用到 LLM 的 Function Calling 功能来帮助回答用户的问题
OpenAI 的 function calling的核心是我们将Prompts 提示词和可用函数列表一起发送给LLM。
OpenAI Chat Completions 接口
- {
- "tool_choice": "auto",
- "messages": [
- {
- "role": "system",
- "content": "You are a helpful assistant."
- },
- {
- "role": "user",
- "content": "我想知道现在北京的天气状况"
- }
- ],
- "tools": [
- {
- "type": "function",
- "function": {
- "name": "Get_Weather_For_City",
- "description": "获取指定城市的天气",
- "parameters": {
- "type": "object",
- "properties": {
- "cityName": {
- "type": "string",
- "description": "城市名"
- }
- }
- }
- }
- }
- ]
- }
-
-
这个参数决定了模型是否应该自动选择是否调用函数。值为 "auto" 表示模型将根据情况自动决定是否调用函数。 默认情况下,如果请求中不存在任何函数,则将其设置为“none”,则设置为“auto”。
在 tools 部分定义了一个函数,这个函数可以被 OpenAI 的模型调用。以下是 tools 部分参数的简单解释:
这个 tools 部分定义了一个名为 Get_Weather_For_City 的函数,它需要一个名为 cityName 的字符串参数,用于指定想要查询天气的城市。当模型需要调用这个函数时,它将使用这个参数来获取相应的天气信息。
- {
- "id": "chatcmpl-9TOuIqnuMirU3BUDluCrHMTlsjz97",
- "object": "chat.completion",
- "created": 1716794282,
- "model": "gpt-4",
- "choices": [
- {
- "index": 0,
- "message": {
- "role": "assistant",
- "content": null,
- "tool_calls": [
- {
- "id": "call_DQU6OKHWyv3HVLyWVjSRqvwZ",
- "type": "function",
- "function": {
- "name": "Get_Weather_For_City",
- "arguments": "{\n \"cityName\": \"北京\"\n}"
- }
- }
- ]
- },
- "logprobs": null,
- "finish_reason": "tool_calls"
- }
- ],
- "usage": {
- "prompt_tokens": 83,
- "completion_tokens": 20,
- "total_tokens": 103
- },
- "system_fingerprint": null
- }
-
-
最核心的方法是tool_calls回参里面返回了我们需要的方法名和一个 json 参数 比如"{\n \"cityName\": \"北京\"\n}"包含了我们的参数和值。
- {
- "max_tokens": 3000,
- "tool_choice": "auto",
- "messages": [
- {
- "role": "system",
- "content": "You are a helpful assistant."
- },
- {
- "role": "user",
- "content": "我想知道北京的天气状况"
- },
- {
- "role": "assistant",
- "function_call": {
- "name": "Get_Weather_For_City",
- "arguments": "{\n \"cityName\": \"北京\"\n}"
- }
- },
- {
- "role": "function",
- "name": "Get_Weather_For_City",
- "content": "27度,晴朗"
- }
- ],
- "tools": [
- {
- "type": "function",
- "function": {
- "name": "Get_Weather_For_City",
- "description": "获取指定城市的天气",
- "parameters": {
- "type": "object",
- "properties": {
- "cityName": {
- "type": "string",
- "description": "城市名"
- }
- }
- }
- }
- },
- {
-
-
需要把上下文信息和function calling的result回答的信息传给LLM
- {
- "role": "assistant",
- "function_call": {
- "name": "Get_Weather_For_City",
- "arguments": "{\n \"cityName\": \"北京\"\n}"
- }
- }
-
-
- {
- "role": "function",
- "name": "Get_Weather_For_City",
- "content": "27度,晴朗"
- }
-
-
LLM 输出
- {
- "id": "chatcmpl-9TRZBqCcRMBYIojuZimio6GOpsTi4",
- "object": "chat.completion",
- "created": 1716804505,
- "model": "gpt-4",
- "choices": [
- {
- "index": 0,
- "message": {
- "role": "assistant",
- "content": "北京的天气状况是27度,晴朗。"
- },
- "logprobs": null,
- "finish_reason": "stop"
- }
- ],
- "usage": {
- "prompt_tokens": 133,
- "completion_tokens": 19,
- "total_tokens": 152
- },
- "system_fingerprint": null
- }
-
-
到现在为止简单的function calling的简单调用已经完成了
具体的流程可以总结为
可以看到function calling跟大预言模型至少有两次交互的的过程。
再举个实际代码Demo,例子中:通过提前写好的获取天气的function,让大模型自动调用获取天气的function,并给出问题答案。其中用户问题是:“通过未来5天深圳南山区的天气怎么样”。具体操作方法如下:
1、向 LLM 描述这个函数,函数描述的必备要素:函数名、函数的功能描述、函数的请求参数说明、函数的响应参数说明。获取天气的function的描述如下:
- tools = [
- {
- "type": "function",
- "function": {
- "name": "get_n_day_weather_forecast",
- "description": "获取最近n天的天气预报",
- "parameters": {
- "type": "object",
- "properties": {
- "location": {
- "type": "string",
- "description": "城市或镇区 如:深圳市南山区",
- },
- "format": {
- "type": "string",
- "enum": ["celsius", "fahrenheit"],
- "description": "要使用的温度单位,摄氏度 or 华氏度",
- },
- "num_days": {
- "type": "integer",
- "description": "预测天数",
- }
- },
- "required": ["location", "format", "num_days"]
- },
- }
- }
- ]
-
2、向LLM实例化传入tools这个参数,大模型则会知道拥有哪些参数可供使用。并且会根据用户的输入,推理出应该调用哪些函数,并将自然语言转成函数的请求参数,返回给请求方。
- from openai import OpenAI
-
- def chat_completion_request(messages, tools=None, tool_choice=None, model="gpt-3.5-turbo"):
- try:
- response = client.chat.completions.create(
- model=model,
- messages=messages,
- tools=tools,
- tool_choice=tool_choice,
- )
- return response
- except Exception as e:
- print("Unable to generate ChatCompletion response")
- print(f"Exception: {e}")
- return e
-
-
- if __name__ == "__main__":
- messages = []
- messages.append({"role": "system", "content": "不要假设将哪些值输入到函数中。如果用户请求不明确,请要求澄清"})
- messages.append({"role": "user", "content": "未来5天深圳南山区的天气怎么样"})
- chat_response = chat_completion_request(
- messages, tools=tools
- )
-
- tool_calls = chat_response.choices[0].message.tool_calls
- print("===回复===")
- print(tool_calls)
-
得到的返回如下:
- [
- {
- "id": "call_7qGdyUEWp34ihubinIUCTXyH",
- "function": {
- "arguments": {
- "location": "深圳市南山区",
- "format": "celsius",
- "num_days": 5
- },
- "name": "get_n_day_weather_forecast"
- },
- "type": "function"
- }
- ]
-
3、调用函数,并将函数调用结果返回给大模型,生成最终回复
- # 执行函数
- for tool_call in tool_calls:
- function = tool_call.function.name
- arguments_list = json.loads(tool_call.function.arguments)
- function_to_call = globals().get(function)
- result = function_to_call(**arguments_list)
- print("===" + function + "===")
- print(result)
-
- # 把函数调用结果加入到对话历史中
- messages.append(
- {
- "tool_call_id": tool_call.id, # 用于标识函数调用的 ID
- "role": "user",
- "name": function,
- "content": "函数执行结果为:" + str(result)
- }
- )
- # 函数执行结果传给LLM,组织成自然语言回复用户
- chat_response = chat_completion_request(
- messages, tools=tools
- )
- print("===回复===")
- print(chat_response.choices[0].message.content)
-
得到的结果如下:
- ===get_n_day_weather_forecast===
- [{'date': '2023-04-01', 'location': '深圳市南山区', 'temperature': '20°C', 'description': '晴朗'}, {'date': '2023-04-02', 'location': '深圳市南山区', 'temperature': '21°C', 'description': '多云'}, {'date': '2023-04-03', 'location': '深圳市南山区', 'temperature': '22°C', 'description': '晴朗'}, {'date': '2023-04-04', 'location': '深圳市南山区', 'temperature': '23°C', 'description': '多云'}, {'date': '2023-04-05', 'location': '深圳市南山区', 'temperature': '24°C', 'description': '晴朗'}]
- ===回复===
- 未来5天深圳南山区的天气情况如下:
- - 4月1日:晴朗,温度20°C
- - 4月2日:多云,温度21°C
- - 4月3日:晴朗,温度22°C
- - 4月4日:多云,温度23°C
- - 4月5日:晴朗,温度24°C
-
- 请注意天气预报仅供参考,实际情况可能会有所变化。
-
根据文档中的描述,OpenAI的函数调用(function calling)过程可以简化为以下几个步骤,并且可以用一个流程图来表示:
下面是一个简化的流程图,描述了上述过程:
在这个流程图中:
这个流程图是基于文档内容的简化表示,实际的系统可能包含更多的细节和步骤。