Post

Understanding the Lifecycle of a Function Call

Understanding the Lifecycle of a Function Call

1. Function Calling 的生命周期

Function Calling 是 OpenAI API 中的重要机制,用于让模型在无法直接回答问题时调用外部函数来获取所需信息。其生命周期主要包含以下五个阶段:

1. 建立连接

在发起一次对话请求前,客户端需要:

  • 指定所使用的模型(如 gpt-4o-mini);
  • 提供用户输入的上下文信息(messages);
  • 注册可供调用的函数(通过 tools 参数);
  • 可选:设置是否支持并行函数调用(parallel_tool_calls)。

2. 模型决策

模型会基于自身的原生知识与上下文信息,判断该问题:

  • 是否可以直接生成回答;
  • 是否需要调用某个工具函数来获取额外信息。

这一阶段完全由模型判断,并返回是否调用函数及其参数。

3. 函数调用

若模型决定调用函数,将明确返回:

  • 所调用函数的名称;
  • 需要传递的参数(以 JSON 格式提供);
  • 可包含多个函数调用请求(如果启用并行调用)。

4. 执行函数

客户端收到模型的函数调用指令后,应:

  • 根据调用指令,从本地注册的函数中执行对应函数;
  • 使用模型提供的参数调用;
  • 将函数返回结果封装为 tool 类型消息,继续添加进对话上下文。

5. 回复用户

在函数执行完成后,再次调用模型,将用户原问题、模型中间调用信息、函数结果一并传入:

  • 模型会根据完整上下文,生成最终对用户的回复;
  • 最终回复可包含解释、格式化结果等内容。

2. 示例代码

以下为一个典型的 function calling 流程的 Python 实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
from openai import OpenAI
import json

client = OpenAI()
messages = []

while True:
    prompt = input('\n提出一个问题: ')
    if prompt.lower() == "退出":
        break  # 退出交互

    # 添加用户提问到消息历史
    messages.append({'role': 'user', 'content': prompt})

    # 模型判断是否调用函数
    completion = client.chat.completions.create(
        model="gpt-4o-mini", 
        messages=messages,
        tools=tools,
        parallel_tool_calls=False  # 可选:是否启用并行调用
    )

    response = completion.choices[0].message
    tool_calls = response.tool_calls

    if tool_calls:
        # 模型请求调用函数
        function_name = tool_calls[0].function.name
        function_args = json.loads(tool_calls[0].function.arguments)

        # 执行本地函数
        function_response = available_functions[function_name](**function_args)

        # 添加模型请求调用信息
        messages.append(response)

        # 添加函数执行结果,必须带 tool_call_id
        messages.append({
            "role": "tool",
            "name": function_name,
            "content": str(function_response),
            "tool_call_id": tool_calls[0].id,
        })

        # 再次请求模型生成最终回应
        second_response = client.chat.completions.create(
            model="gpt-4o-mini", 
            messages=messages,
        )

        final_response = second_response.choices[0].message.content
        messages.append({'role': 'assistant', 'content': final_response})
        print(final_response)
    else:
        # 模型无需调用函数,直接回复
        print(response.content)
        messages.append({'role': 'assistant', 'content': response.content})

3. 注意事项

1. tool_call_id 的必要性

1
2
3
4
5
6
messages.append({
    "role": "tool",
    "name": function_name,
    "content": str(function_response),
    "tool_call_id": tool_calls[0].id,
})

每一个函数执行结果的消息(role: tool必须对应一次 tool_calls 中的调用请求,并使用相同的 tool_call_id。这是模型识别函数调用链的重要依据。

2. parallel_tool_calls 控制项

当一次请求可能涉及多个函数调用时:

  • 若希望模型同时发起多个调用请求,需设置 parallel_tool_calls=True(默认值);
  • 若只希望模型每次只调用一个函数,应显式设置 parallel_tool_calls=False
This post is licensed under CC BY 4.0 by the author.

© cryanskl. Some rights reserved.

本页浏览 2476 次 | 总访问量 13481

Using the Chirpy theme for Jekyll.