← 返回博客

Function Calling 是什么?AI Agent 接 API 的关键能力与接入实战

Function Calling 是 AI Agent 接入外部工具和 API 的关键能力。本文用开发者能落地的方式讲清原理、接入步骤、常见错误,以及如何用 APIBox 快速验证。

如果你在做 AI Agent、工作流自动化或企业内部助手,Function Calling 基本就是“能不能真正接 API 干活”的分水岭。一句话理解:它让模型不只是“会说”,而是能按结构化参数去调用天气、搜索、数据库、工单、支付、CRM 等外部工具。对开发者来说,重点不是概念,而是 什么时候该用、参数怎么设计、怎么避免调用翻车。本文会用 APIBox 的 OpenAI 兼容接法,把这件事讲到能落地。

一、Function Calling 解决的到底是什么问题

很多人第一次做 Agent,都会先用 Prompt 硬写:

  • 让模型“根据用户问题决定是否查天气”
  • 让模型“尽量按 JSON 输出”
  • 让模型“如果需要查库存就返回商品 ID”

这套方法能跑,但一进生产环境就容易出问题:

  • 输出格式不稳定
  • 参数字段名经常漂
  • 同一个问题不同轮次行为不一致
  • 一旦接真实 API,就会出现字段缺失、类型错误、误调用

Function Calling 的作用,就是把“调用工具”这件事,从自然语言提示词,改成更稳定的结构化协作流程。

它最适合的 4 类场景

场景典型动作是否建议用 Function Calling
查外部实时信息天气、汇率、物流、库存强烈建议
执行业务动作创建工单、发消息、下订单强烈建议
调内部系统CRM、数据库、权限系统强烈建议
纯内容生成写文案、总结文章、改写文本不一定需要

结论很简单:只要模型需要“拿数据”或“做动作”,就优先考虑 Function Calling。

二、它的工作原理到底是什么

Function Calling 不是模型真的去执行函数,而是:

  1. 你把可用工具的描述和参数 schema 发给模型
  2. 模型判断当前问题要不要调用工具
  3. 如果要调用,它返回结构化的工具名和参数
  4. 你的程序收到后,自己去执行真实 API
  5. 再把工具结果回传给模型,让模型生成最终回答

也就是说:

  • 模型负责决策和参数生成
  • 你的应用负责真正执行

一个最常见的调用流程

用户:北京今天下雨吗?

模型:需要调用 get_weather(city="北京")

你的后端:请求天气 API

工具返回:{"city":"北京","condition":"多云","temp":19}

模型:今天北京多云,19℃,降雨概率较低

三、开发者最容易踩的 5 个坑

1. 工具定义写得太宽泛

坏例子:

  • get_info
  • query_system
  • do_action

这种名字对模型来说太模糊,它很难知道什么时候该调、该传什么。

更好的写法:

  • get_weather_by_city
  • search_order_by_id
  • create_support_ticket

函数名越具体,模型越容易稳定。

2. 参数 schema 不够严格

如果你只是写一个大概描述,而没有明确:

  • 字段名
  • 字段类型
  • 必填项
  • 枚举值
  • 参数含义

模型就会自由发挥,最后最痛苦的是后端。

3. 让一个工具做太多事

比如一个 manage_order 同时支持:

  • 查询订单
  • 取消订单
  • 修改地址
  • 申请退款

这会让模型决策空间过大。更稳的办法通常是拆成多个职责清晰的工具

4. 工具返回值不规范

如果你的工具返回一大段自然语言,模型二次处理时反而容易丢信息。

更好的方式:

  • 结构化 JSON
  • 字段含义清晰
  • 错误码统一

5. 没有失败兜底

真实环境里,工具调用经常失败:

  • 上游 429
  • 参数非法
  • 权限不足
  • 接口超时

如果你没设计失败分支,用户体验会很差。

四、什么时候应该用,什么时候不该用

建议用的情况

  • 你需要查询实时数据
  • 你需要让模型调内部业务系统
  • 你要做多步骤 Agent
  • 你需要稳定的结构化参数输出
  • 你要让工作流节点可观测、可审计

不建议一上来就用的情况

  • 只是简单写文案
  • 只是摘要、翻译、润色
  • 还在做最早期 DEMO,目标只是先验证一句话能不能生成

一句话判断:

如果结果要进入代码逻辑或业务动作,就尽量不用“纯 Prompt 猜格式”,而用 Function Calling。

五、一个能直接跑的最小示例

下面用 OpenAI 兼容 SDK 演示。你可以直接把 base_url 指向 APIBox,快速测试支持工具调用的模型。

from openai import OpenAI
import json

client = OpenAI(
    api_key="YOUR_APIBOX_KEY",
    base_url="https://api.apibox.cc/v1"
)

tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather_by_city",
            "description": "根据城市名称获取实时天气",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {
                        "type": "string",
                        "description": "中文城市名,例如北京、上海、深圳"
                    }
                },
                "required": ["city"]
            }
        }
    }
]

response = client.chat.completions.create(
    model="gpt-5",
    messages=[
        {"role": "user", "content": "帮我查一下北京今天天气"}
    ],
    tools=tools,
    tool_choice="auto"
)

msg = response.choices[0].message
print(msg)

如果模型触发了工具调用,下一步怎么做

你需要取出工具名和参数,自己执行真实函数:

tool_call = msg.tool_calls[0]
function_name = tool_call.function.name
arguments = json.loads(tool_call.function.arguments)

if function_name == "get_weather_by_city":
    result = {
        "city": arguments["city"],
        "condition": "多云",
        "temp": 19
    }

然后把工具结果再发回模型,让它生成最终回答:

second_response = client.chat.completions.create(
    model="gpt-5",
    messages=[
        {"role": "user", "content": "帮我查一下北京今天天气"},
        msg,
        {
            "role": "tool",
            "tool_call_id": tool_call.id,
            "content": json.dumps(result, ensure_ascii=False)
        }
    ]
)

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

六、参数设计怎么做才稳

这是最关键的实战部分。

推荐的参数设计规则

规则错误写法更好的写法
函数名具体do_taskcreate_support_ticket
字段名语义清晰quser_question
类型明确模糊描述string / integer / boolean
必填项收紧全部可选明确 required
枚举尽量固定任意字符串order_status: pending/shipped/cancelled

一个比较稳的工单工具示例

{
  "type": "function",
  "function": {
    "name": "create_support_ticket",
    "description": "为用户创建售后工单",
    "parameters": {
      "type": "object",
      "properties": {
        "order_id": {
          "type": "string",
          "description": "订单号"
        },
        "issue_type": {
          "type": "string",
          "enum": ["refund", "delivery", "invoice", "other"],
          "description": "问题类型"
        },
        "user_message": {
          "type": "string",
          "description": "用户原始问题"
        }
      },
      "required": ["order_id", "issue_type", "user_message"]
    }
  }
}

这个定义有几个好处:

  • 模型不容易乱传字段
  • 后端更容易校验
  • 日志更清晰
  • 出错更容易排查

七、如何把它接到 AI Agent 或工作流里

如果你在做 Agent,常见的接法一般分三层:

方案 1:单模型 + 多工具

适合:

  • 客服助手
  • 查询助手
  • 企业知识 + 内部 API 混合场景

特点:接入简单,但工具多了之后治理成本会上升。

方案 2:分类模型 + 工具执行模型

流程示意:

用户问题

轻量模型做意图分类

决定是否调用工具

主模型负责参数生成与回答

适合:

  • 请求量大
  • 对成本敏感
  • 任务分层明显

方案 3:工作流平台接入

如果你在用:

  • Dify
  • n8n
  • Flowise
  • 自研工作流引擎

通常都可以通过 OpenAI 兼容接口快速接入 APIBox,然后把支持 Function Calling 的模型挂进去做验证。

八、成本和性能上怎么权衡

Function Calling 比纯文本问答更贵一点,主要贵在:

  • 多轮请求
  • 工具调用中间状态
  • 参数生成 + 结果总结

成本主要受 4 个因素影响

因素影响
工具描述长度tools schema 越长,输入 token 越高
调用轮数一次问答变两次甚至三次请求
模型选择高级模型单价更高
工具结果长度返回内容越长,二次总结越贵

实际建议

  • 轻任务:先用低成本模型试工具决策
  • 重任务:把关键步骤交给更强模型
  • 长工具描述:要压缩,不要写成文档
  • 工具结果:只返回必要字段,不要整页 JSON 原样塞回去

如果你本来就在做多模型接入,APIBox 这种统一入口的价值会更明显:

  • 方便切模型验证效果
  • 不用换 SDK
  • 不用为每家供应商单独接一套

九、最推荐的落地检查清单

一篇文章讲原理不够,真正上线前至少过这份表:

上线前检查

  • 每个工具的名称是否具体可理解
  • 参数字段是否有类型和必填约束
  • 是否设计了失败分支和超时处理
  • 是否记录了 tool_call 日志
  • 是否限制了模型可用工具范围
  • 是否避免把整个数据库查询结果原样返回给模型
  • 是否区分了测试模型和生产模型

不建议的做法

  • 一个工具干所有事
  • schema 写得像自然语言说明文
  • 返回值全靠模型自己猜
  • 出错就无限重试
  • 只在单次 DEMO 场景测过,没有测异常场景

十、总结

Function Calling 的真正价值,不是“多一个炫技功能”,而是让 AI Agent 从“会聊天”变成“能接系统、能做动作、能稳定协作”。

如果你现在正准备做:

  • AI Agent
  • 工作流自动化
  • 企业内部助手
  • 需要查实时数据或执行 API 的 LLM 应用

那你最该优先做好 3 件事:

  1. 工具定义要具体
  2. 参数 schema 要严格
  3. 调用失败要有兜底

如果只是想先低成本验证,直接用 OpenAI 兼容 SDK + APIBox 的 base_url 切换,通常是最快的起步方式。先把工具链路跑通,再谈复杂 Agent 架构,会更稳。

立即体验,注册后加客服并发送账号 ID,可限时领取 ¥10 体验额度

免费注册 →