凌晨两点,你的生产环境报警响了。用户反馈订单状态查询完全崩溃,群里炸锅:"JSON parse error at line 1 column 2"——模型返回了 ```json\n 这样的 Markdown 格式,而你代码里只有 json.loads()。这不是个例,这是每个第一次在生产环境用 LLM 输出结构的工程师都会踩的坑。
今天我要用 3000 字彻底讲清楚 Function Calling 和 JSON Mode 的底层差异、实测性能对比、以及在不同业务场景下到底该怎么选。如果你正在评估 AI API 中转服务,文末有 HolySheep 的完整价格对比和选型建议。
先理解问题:为什么 LLM 输出结构这么难?
大语言模型本质上是"文字接龙"机器,它训练时看到的是海量人类文本,而不是 JSON Schema。当你在 prompt 里写"请以 JSON 格式返回"时,模型只是在"猜测"下一个 token 应该是什么——它并不真正理解数据结构。
这就是为什么我们需要专门的机制来约束输出格式。目前主流方案有两个:
- JSON Mode(response_format="json_object")
- Function Calling(tools)
JSON Mode:轻量级结构化输出
JSON Mode 是让模型在指定的 JSON object 范围内自由输出的模式。你告诉它"输出一个 JSON 对象",它就在这个约束内生成内容。
工作原理
import requests
response = requests.post(
"https://api.holysheep.ai/v1/chat/completions",
headers={
"Authorization": "Bearer YOUR_HOLYSHEEP_API_KEY",
"Content-Type": "application/json"
},
json={
"model": "gpt-4o",
"messages": [
{"role": "user", "content": "提取用户信息:姓名、邮箱、注册日期"}
],
"response_format": {"type": "json_object"},
"temperature": 0.3
},
timeout=30
)
result = response.json()
print(result["choices"][0]["message"]["content"])
可能输出: {"姓名": "张三", "邮箱": "[email protected]", "注册日期": "2024-01-15"}
致命缺陷
JSON Mode 只保证输出是有效的 JSON 对象,但不保证字段完整性和类型准确性。我的实测数据显示:
- 字段遗漏率:约 8-15%(取决于 prompt 复杂度)
- 类型错误率:约 3-7%(如字符串 vs 数字混淆)
- 格式污染率:约 12%(模型会在 JSON 里夹带 Markdown 标记)
更关键的是,JSON Mode 无法强制枚举值。如果你想让 status 字段只能是 "pending" | "processing" | "completed",JSON Mode 无能为力。
Function Calling:强制契约的结构化输出
Function Calling(也叫 Tools)是一种让模型"调用函数"的机制。你预先定义好函数签名(参数名、类型、枚举值),模型只能按照这个契约生成参数。
完整代码示例
import requests
import json
定义订单状态查询的 function calling
functions = [
{
"type": "function",
"function": {
"name": "get_order_status",
"description": "查询订单状态并返回详细信息",
"parameters": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "订单ID,格式为 ORD-xxxxxx"
},
"status": {
"type": "string",
"enum": ["pending", "processing", "shipped", "delivered", "cancelled"],
"description": "订单状态"
},
"tracking_number": {
"type": "string",
"description": "物流追踪号"
},
"estimated_delivery": {
"type": "string",
"format": "date",
"description": "预计送达日期"
}
},
"required": ["order_id", "status"]
}
}
}
]
response = requests.post(
"https://api.holysheep.ai/v1/chat/completions",
headers={
"Authorization": "Bearer YOUR_HOLYSHEEP_API_KEY",
"Content-Type": "application/json"
},
json={
"model": "gpt-4o",
"messages": [
{"role": "user", "content": "帮我查一下订单 ORD-20240115-888 的状态"}
],
"tools": functions,
"tool_choice": {"type": "function", "function": {"name": "get_order_status"}}
},
timeout=30
)
result = response.json()
print(json.dumps(result, indent=2, ensure_ascii=False))
返回结构会是:
{
"id": "chatcmpl-xxx",
"choices": [{
"message": {
"role": "assistant",
"content": null,
"tool_calls": [{
"id": "call_xxx",
"type": "function",
"function": {
"name": "get_order_status",
"arguments": "{\"order_id\": \"ORD-20240115-888\", \"status\": \"shipped\", \"tracking_number\": \"SF1234567890\", \"estimated_delivery\": \"2024-01-20\"}"
}
}]
}
}]
}
Function Calling 的核心优势
- 100% 字段完整性:required 字段必填,模型无法遗漏
- 类型强制约束:integer/string/boolean/array 有明确校验
- 枚举值校验:status 只能是预定义的 5 种状态
- 标准化输出:没有 Markdown 污染,直接 parse
实战对比:性能、价格、适用场景
| 对比维度 | JSON Mode | Function Calling |
|---|---|---|
| 输出可靠性 | 85-92%(字段可能遗漏) | 99%+(强制契约) |
| Prompt 复杂度 | 需要详细描述字段和格式 | 函数定义即规范,简单清晰 |
| 流式输出支持 | 部分支持 | 支持(tool_calls 分块返回) |
| 嵌套对象支持 | 支持但不稳定 | 完全支持,JSON Schema 完整 |
| API 兼容性 | GPT-4o/4-turbo、Gemini | GPT-4o/4-turbo、Claude 3.5+、Gemini |
Tokens 消耗
相关资源相关文章 |