Function-Calling设计
核对日期:2026-05-09。
1. 定义与边界
函数调用(Function Calling)是模型生成结构化函数调用意图的能力,通常包括函数名和 JSON 参数。它解决的是“让模型把自然语言意图转成可执行接口参数”的问题。
Function Calling 不等于工具执行。模型只负责输出调用意图,运行时仍需要:
- 校验参数。
- 决定是否允许执行。
- 调用真实函数或远程服务。
- 处理错误和重试。
- 把结果作为 observation 回传模型。
OpenAI 官方文档把 function calling 放在 tools 机制下;Anthropic Messages API 以 tool_use / tool_result 内容块表达工具调用。不同平台格式不同,但工程抽象可以统一为 ToolCall{name, arguments, id}。
2. 为什么重要
没有结构化函数调用时,工程系统常通过正则、文本解析或提示约束让模型输出 JSON。这会带来高脆弱性:
- 参数字段拼写不稳定。
- 枚举值漂移。
- 多工具调用难以关联结果。
- 错误恢复依赖自然语言解析。
Function Calling 的价值是把“模型语言输出”收敛成“可验证的接口契约”。
3. 核心机制
3.1 四段式流程
3.2 统一调用结构
{
"id": "call_01",
"name": "calendar.create_event",
"arguments": {
"title": "项目复盘",
"start_time": "2026-05-10T10:00:00+08:00",
"duration_minutes": 60,
"attendees": ["alice@example.com"]
}
}
3.3 严格模式与结构化输出
生产系统应优先启用平台支持的严格 schema 能力,例如 OpenAI 的 Structured Outputs / strict schema、Anthropic 的严格工具使用能力。严格模式能降低参数漂移,但不能替代服务端校验,因为:
- 模型可能选择了不该选的工具。
- 合法 JSON 不代表业务含义合法。
- 用户上下文可能不允许执行该动作。
- 工具返回仍可能包含恶意内容。
4. 架构模式
4.1 Direct Function Call
模型调用业务服务中的函数。
适用于内部自动化、低风险读操作。实现简单,但工具注册、权限和日志容易耦合在业务代码里。
4.2 Adapter Function Call
模型只看到稳定的工具 schema,后端 adapter 再调用多个内部 API。
Model Tool Schema -> Adapter -> Internal API A/B/C
适用于旧系统、微服务聚合、字段需要转换的场景。
4.3 Workflow Function Call
函数不是单个 API,而是触发一个可观测工作流,例如审批流、异步任务、批处理。
适用于长耗时、高风险、需要回滚或人工审批的任务。
5. 工程实现
5.1 函数 schema 示例
{
"type": "function",
"name": "ticket.create",
"description": "创建一条内部工单。只在用户明确要求创建、提交、登记问题时使用。",
"parameters": {
"type": "object",
"additionalProperties": false,
"required": ["title", "priority", "description"],
"properties": {
"title": {
"type": "string",
"minLength": 5,
"maxLength": 80
},
"priority": {
"type": "string",
"enum": ["low", "medium", "high", "urgent"]
},
"description": {
"type": "string",
"maxLength": 2000
},
"assignee": {
"type": "string",
"description": "内部用户名;未知时不要猜测。"
}
}
}
}
5.2 运行时校验
const tool = registry.get(call.name);
if (!tool) throw new ToolError("unknown_tool");
const parsed = tool.inputSchema.safeParse(call.arguments);
if (!parsed.success) {
return {
status: "error",
code: "invalid_arguments",
details: parsed.error.issues
};
}
await policy.assertAllowed(user, tool, parsed.data);
return await tool.handler(parsed.data);
6. 生产实践
- 函数名采用领域前缀,例如
calendar.create_event、crm.search_customer。 - 描述只写触发条件和边界,不写长篇推理策略。
- 参数字段使用业务稳定名,不暴露内部数据库字段。
- 对时间、金额、地区、ID 使用明确格式。
- 对 destructive action 使用
dry_run或 preview 工具,再由确认工具执行。 - 每次 schema 变更要有版本记录和评测回归。
7. 常见反模式
| 反模式 | 问题 |
|---|---|
函数名过泛,例如 process、handle | 模型难以选择,审计不可读 |
参数用单个 query 字符串承载所有内容 | 失去结构化校验价值 |
| schema 和真实 API 直接绑定 | 内部 API 变更会破坏模型契约 |
| 让模型生成权限字段 | 权限应由系统计算,不能由模型自报 |
| 把执行结果当最终答案 | 仍需模型或模板解释结果、处理失败 |
8. 评测方法
Function Calling 评测不应只看最终回答。建议至少分四层:
| 层级 | 测什么 |
|---|---|
| 选择 | 该调用时调用,不该调用时不调用 |
| 参数 | 字段完整、格式正确、枚举合法 |
| 业务 | 参数符合用户真实意图和权限 |
| 恢复 | 缺字段、歧义、失败时能澄清或降级 |
测试集示例:
{
"input": "明天上午十点给张三约一个项目会",
"tools": ["calendar.create_event", "email.send"],
"expected_tool": "calendar.create_event",
"expected_arguments": {
"start_time": "2026-05-10T10:00:00+08:00",
"attendees_contains": ["张三"]
},
"requires_clarification": true
}
9. 安全与治理
- 函数 schema 中不要放密钥、内部 URL、数据库表名等敏感实现细节。
- 不允许模型选择自身权限范围;权限由运行时根据用户身份和资源策略计算。
- 对写操作使用 preview/confirm 两阶段。
- 对参数做注入防护,例如 SQL、shell、路径、模板注入。
- 对工具结果做脱敏,避免把敏感字段再次喂给模型。
10. 设计决策表
| 决策 | 推荐做法 | 不推荐做法 |
|---|---|---|
| 函数粒度 | 一个函数对应一个清晰业务动作 | 一个 execute 承载所有动作 |
| 写操作 | preview/confirm 两阶段 | 模型直接调用最终写接口 |
| 参数校验 | JSON Schema + 业务校验 | 只相信模型输出合法 |
| 缺失信息 | 澄清或调用读工具补齐 | 让模型猜 ID、时间、金额 |
| 返回结果 | 结构化 observation | 把原始 API 响应全量塞回 |
| 兼容多厂商 | 内部统一 ToolCall 抽象 | 业务层依赖厂商私有字段 |
11. Function Calling Eval Gate
建议评测集至少覆盖:
- 正确调用:用户明确要求执行某动作。
- 不调用:用户只是询问概念,不应调用工具。
- 相似工具:多个函数描述相近时是否选对。
- 参数歧义:缺时间、缺 ID、缺金额时是否澄清。
- 安全拒绝:用户诱导越权或注入参数时是否阻断。
12. 权威资料
- OpenAI Function Calling guide: https://platform.openai.com/docs/guides/function-calling
- OpenAI Structured Outputs guide: https://platform.openai.com/docs/guides/structured-outputs
- Anthropic Tool Use docs: https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/implement-tool-use
- Anthropic Strict tool use: https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/strict-tool-use