当前位置:首页 > 学习资源 > 讲师博文 > 大模型Function Calling是什么?模型究竟是怎么“调用工具”的?

大模型Function Calling是什么?模型究竟是怎么“调用工具”的? 时间:2026-10-23      来源:华清远见

学习大模型的 Function Calling(函数调用)既简单又有趣。通过 Function Calling,可以让一个”只会输出文字”的模型去查天气、搜网页、查数据库、发邮件——完成那些靠语言模型本身根本做不到的事情。所以,想要构建真正能用的 AI 应用,学习 Function Calling 是很有必要的。

正如您所知道的,大模型本质上是一个文本生成器:它只能读取文本、输出文本。它不知道今天是几号,不能联网,也不会执行任何代码。请看下面的对比实例,同样是问天气,有没有 Function Calling 的区别:

实例:没有提供工具时

用户提问:

杭州今天多少度?要带伞吗?

模型的输出:

抱歉,我无法获取实时天气数据。建议您通过天气类应用或网站查询最新信息。

实例:提供了工具时

模型的输出(不再说”抱歉”,而是一段 JSON):

{

  "role": "assistant",

  "content": null,

  "tool_calls": [

    {

      "id": "call_abc123",

      "type": "function",

      "function": {

        "name": "get_current_weather",

        "arguments": "{\"location\": \"杭州\", \"unit\": \"celsius\"}"

      }

    }

  ]

}

通过上面的对比,我们了解了 Function Calling 能带来什么。接下来让我们看看它到底是什么。

什么是 Function Calling?

Function Calling(函数调用),也叫 Tool Use(工具调用),是一种让大模型在对话过程中“请求执行外部函数”的机制。请注意”请求”两个字:模型只负责提出请求,真正执行函数的,永远是您编写的程序。

就像其他 API 参数一样,您必须在使用工具之前,先把工具声明随请求发送给模型。工具声明的一般形式为:

{

  "type": "function",

  "function": {

    "name": "函数名",

    "description": "这个工具是干什么的、什么时候该用",

    "parameters": { "": "JSON Schema 参数定义" }

  }

}

在这里,type 是工具类型,目前主流 API 中固定为 "function";name 是函数名,必须是一个合法的标识符;description 是写给模型看的”使用说明书”,模型完全靠它来决定要不要用这个工具;parameters 是一个 JSON Schema,用来约束参数的名称、类型与必填项。以下是有效的工具声明:

get_current_weather    /* 查询某个城市的实时天气 */

web_search             /* 联网搜索最新资料 */

run_sql_query          /* 在数据库上执行只读查询 */

send_email             /* 给指定收件人发送邮件 */

所有工具对模型来说都是一样的,都只是一段 JSON 文本。不同工具之间唯一的不同,是 description 与参数 Schema 不同——模型从不关心、也永远看不到函数内部是怎么实现的。

模型究竟是怎么”调用工具”的?

这是最容易被误解的地方,先把结论说清楚:

模型从不执行任何代码。 所谓”调用工具”,是模型输出了一段结构化的 JSON 文本,表示”我想调用某个函数、参数是什么”;随后由您的程序解析并执行,再把结果交还给模型。

整个协作过程如下:

分步来看:

第 1 步:登记工具。 您在请求中附带 tools 数组。注意:发出去的只有”说明书”(名称、描述、参数结构),不包含任何实现代码。

第 2 步:模型决策。 模型读用户的问题,逐个对照工具的 description,判断”这个问题我自己能答,还是需要某个工具”。这本质上是它的老本行——根据上下文预测下一段文本,只不过您用 tools 参数告诉了它:“现在允许你输出一种特殊格式”。

第 3 步:模型输出”调用请求”。 它不直接回答用户,而是返回一条 finish_reason 为 "tool_calls" 的消息,内容是函数名 + JSON 参数。

第 4 步:您的程序执行。 解析 arguments、做参数校验、调用真正的函数——天气 API、数据库、搜索引擎,全部运行在您自己的环境中。

第 5 步:结果回填。 把函数返回值包装成 role 为 "tool" 的消息,带上 tool_call_id,追加到对话历史,再次请求模型。

第 6 步:模型生成最终回答。 模型看到工具结果之后,才用自然语言回答用户。

请看下面的实例,这是第一次请求返回的原始内容:

{

  "id": "chatcmpl-xxx",

  "choices": [

    {

      "finish_reason": "tool_calls",

      "message": {

        "role": "assistant",

        "content": null,

        "tool_calls": [

          {

            "id": "call_abc123",

            "type": "function",

            "function": {

              "name": "get_current_weather",

              "arguments": "{\"location\": \"杭州\", \"unit\": \"celsius\"}"

            }

          }

        ]

      }

    }

  ]

}

请注意两个细节:

finish_reason 是 "tool_calls" 而不是 "stop"。API 客户端靠它判断:“模型想调工具了,轮到您执行。”

arguments 是一个字符串,不是 JSON 对象。它是被 JSON 编码过的参数,需要您自己反序列化。

完整实例

下面用 Python(OpenAI SDK 风格)完整演示一次 Function Calling:

from openai import OpenAI

import json

 

client = OpenAI()   # 需要事先配置 API Key

 

# 第 1 步:登记工具(只有说明书,没有代码)

tools = [{

    "type": "function",

    "function": {

        "name": "get_current_weather",

        "description": "查询指定城市的当前天气,当用户询问天气时使用",

        "parameters": {

            "type": "object",

            "properties": {

                "location": {

                    "type": "string",

                    "description": "城市名,如:杭州"

                },

                "unit": {

                    "type": "string",

                    "enum": ["celsius", "fahrenheit"],

                    "description": "温度单位,默认 celsius"

                }

            },

            "required": ["location"]

        }

    }

}]

 

# 真正干活的函数:在您自己的环境里执行

def get_current_weather(location: str, unit: str = "celsius") -> str:

    # 演示用假数据;实际项目中这里调用真实天气 API

    data = {"location": location, "temp": 31, "condition": "晴", "unit": unit}

    return json.dumps(data, ensure_ascii=False)

 

messages = [

    {"role": "user", "content": "杭州今天多少度?要带伞吗?"}

]

 

# 第 2 步:第一次请求 —— 模型只返回"想调用什么"

resp = client.chat.completions.create(

    model="gpt-4o",

    messages=messages,

    tools=tools,

)

assistant_msg = resp.choices[0].message

messages.append(assistant_msg)          # 别忘了把这条也记入历史

 

# 第 3 步:模型提出调用请求?那就由您来执行

if assistant_msg.tool_calls:

    for tc in assistant_msg.tool_calls:

        args = json.loads(tc.function.arguments)   # 注意:参数是字符串

        result = get_current_weather(**args)       # 真正执行!

        messages.append({                          # 第 4 步:结果回填

            "role": "tool",

            "tool_call_id": tc.id,                 # 与请求一一对应

            "content": result,

        })

 

    # 第 5 步:带着结果再次请求

    final = client.chat.completions.create(

        model="gpt-4o",

        messages=messages,

        tools=tools,

    )

    print(final.choices[0].message.content)

当上面的代码被执行时,它会产生下列结果:

杭州现在 31°C,天气晴,不需要带伞。

 

模型没有调用工具,怎么办?

在变量声明的时候,如果没有确切的地址可以赋值,为指针赋一个 NULL 值是一个良好的编程习惯——类似地,您必须同时处理”模型不想调工具”的情况。当模型认为仅凭自身知识就能回答时(比如用户问”1+1 等于几”),它会直接返回普通文本,此时 finish_reason 为 "stop",tool_calls 为空。

如需检查模型是否想调用工具,您可以使用 if 语句,如下所示:

if msg.tool_calls:      # 模型想调用工具 → 解析、执行、回填

if not msg.tool_calls:  # 模型直接回答 → msg.content 就是最终答案

您还可以用 tool_choice 参数主动控制模型的”动手欲望”:

并行调用与工具循环

并行调用:如果一个问题需要多个互不依赖的工具,模型会在一轮里同时返回多个 tool_calls。例如用户问”北京和上海今天哪个更热?“:

"tool_calls": [

  {

    "id": "call_001",

    "function": {

      "name": "get_current_weather",

      "arguments": "{\"location\": \"北京\"}"

    }

  },

  {

    "id": "call_002",

    "function": {

      "name": "get_current_weather",

      "arguments": "{\"location\": \"上海\"}"

    }

  }

]

您的程序应依次(或并发)执行这两个函数,回填两条 role 为 "tool" 的消息,tool_call_id 分别对应 call_001、call_002。

工具循环(Agent Loop):复杂任务往往需要连续调用多次工具,标准写法是一个循环:

while True:

    resp = client.chat.completions.create(

        model="gpt-4o", messages=messages, tools=tools)

    msg = resp.choices[0].message

    messages.append(msg)

 

    if not msg.tool_calls:            # 模型不再要求调用工具

        print(msg.content)            # 这就是最终回答

        break

 

    for tc in msg.tool_calls:         # 执行每一个调用并回填结果

        result = execute(tc)

        messages.append({

            "role": "tool",

            "tool_call_id": tc.id,

            "content": result,

        })

模型可以在这个循环里”调用 → 看结果 → 再调用 → 再看结果”,直到它认为信息足够为止——这正是所谓 AI Agent(智能体)的核心骨架。

 

Function Calling 详解

在使用 Function Calling 时,有很多相关的概念,这些概念都很简单,但都很重要。下面列出了必须清楚的一些重要概念:

各平台的术语对照(机制完全相同,只是字段名不同):

无论哪一家,本质都是同一个三段式:模型输出结构化请求 → 程序执行 → 结果回填。

注意事项与常见误区

1.模型永远不执行代码。 Function Calling 输出的只是 JSON 文本,执行权 100% 在您的程序手里。任何”模型自己调了 API”的说法,省略的都是中间那段您写的代码。

2.arguments 是字符串,不是对象。 需要自行 json.loads;解析失败或参数不合法时应当报错处理,而不是硬着头皮执行。

3.参数可能有”幻觉”。 模型可能编造不存在的城市、漏掉必填项、写错枚举值。执行前务必校验参数;必要时把错误信息回填给模型,让它重试。

4.description 决定调用准确率。 模型是靠读说明书选工具的。“查询指定城市当前天气,当用户询问天气时使用”远好于”调用这个函数”。工具越多,各工具的描述越要写得互不重叠。

5.注意安全边界。 工具在您的环境中执行,等于给了模型一只”手”。数据库、Shell、支付、删除类工具必须做权限最小化、参数白名单,敏感操作加人工确认。

6.注意 token 成本。 tools 清单会随每一次请求一起发送并计入上下文,工具定义越多、越长,费用越高。

7.结果要对号入座。 回填结果时 tool_call_id 必须与调用一一对应,并行调用时尤其容易出错。

上一篇:C语言开发最容易混淆的知识点 ——数组和指针到底有什么区别?

下一篇:Linux进程和线程到底有什么区别:从地址空间到资源共享的底层解析

戳我查看嵌入式每月就业风云榜

点我了解华清远见高校学霸学习秘籍

猜你关心企业是如何评价华清学员的

干货分享
相关新闻
前台专线:010-82525158 企业培训洽谈专线:010-82525379 院校合作洽谈专线:010-82525379 Copyright © 2004-2026 北京华清远见科技发展有限公司 版权所有 ,京ICP备16055225号-5,京公海网安备11010802025203号

回到顶部