首页 / 结构化输出与函数调用
结构化输出与函数调用
苏姆卡皮 · OpenAI 兼容 AI API 网关 · Base URL https://sub.sumcapi.top/v1
让模型稳定返回可解析结果,靠的不是"请求它输出 JSON",而是响应模式、字段约束、示例与校验四件套。这一页给出在苏姆卡皮上的具体做法。
结构化输出与函数调用
三种落地方式,按可控性排序
| 方式 | 关键参数 | 可控性 | 适用场景 |
|---|---|---|---|
| JSON 模式 | response_format 指定 json_object | 高:保证是合法 JSON | 抽取、分类、打标 |
| 函数 / 工具调用 | tools 与 tool_choice | 高:按 schema 生成参数 | Agent、外部动作、查询编排 |
| 提示词约束 | 示例 + 字段清单 + 禁止多余文本 | 中:需自行解析与重试 | 前两者不可用时的兜底 |
JSON 模式示例
curl -N https://sub.sumcapi.top/v1/chat/completions \
-H "Authorization: Bearer $SUMCAPI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-5-mini",
"temperature": 0,
"response_format": {"type": "json_object"},
"messages": [
{"role": "system", "content": "只输出 JSON,字段:brand(字符串), price(数字), risks(字符串数组)"},
{"role": "user", "content": "从下面这段商品描述里抽取字段:……"}
]
}'
配合 temperature: 0 与逐字段说明,可显著降低同输入不同输出的抖动。
函数调用(工具编排)
{
"tools": [{
"type": "function",
"function": {
"name": "search_orders",
"description": "按用户与时间范围查询订单,用于回答历史相关问题",
"parameters": {
"type": "object",
"properties": {
"user_id": {"type": "string"},
"days": {"type": "integer", "description": "回溯天数,默认 30,最大 365"}
},
"required": ["user_id"]
}
}
}],
"tool_choice": "auto"
}
工程约定:
- 工具描述写"什么时候用",比写"这是什么"更能减少误调用;
- 枚举与单位写进 description,不要让模型猜口径;
- 执行前本地校验:参数不合法就把错误信息回传给模型自纠,不要静默修正;
- 限制最大步数:Agent 循环要设步数上限与总预算,防止互相调用停不下来;
- 保持幂等:外部动作携带请求 ID,重试不会重复下单。
解析失败的三级兜底
- 一级:用括号匹配截取 JSON 主体,处理偶发的前后缀说明文字;
- 二级:把具体报错回灌给模型要求重写一次,通常一次即可收敛;
- 三级:切换更听话的模型,或降级为模板化输出;
- 全程记录失败率与脱敏后的原始片段,它是提示词迭代的唯一依据。
成本注意
结构化输出的输出 token 常被忽略:字段冗余、数组元素重复都会推高成本。只要求必要字段、用数组替代重复对象、给出长度上限,通常能省下三成以上,见 长上下文与缓存。
下一步
常见问题
开了 JSON 模式还会输出非法 JSON 吗?
仍可能。超长输出被 max_tokens 截断、模型在字符串里塞未转义引号,都会导致解析失败。生产侧务必保留一层修复与重试兜底。
response_format 和函数调用该选哪个?
只要一个结构化对象,用 JSON 模式最直接;需要「模型决定调用哪个工具、传什么参数」的多步编排,用函数调用更合适,参数校验交给你的代码。
解析失败可以让模型自己重试吗?
可以,把上一次的输出和具体错误一起回传,明确要求「仅输出修正后的 JSON,不要解释」,通常一轮就能收敛。重试上限设 2 次,之后回落到人工或默认值。
Schema 写得越复杂越准吗?
相反。字段少、枚举明确、层级浅的 schema 遵循度最高。把可选字段拆成多次调用,比一次要求十几个嵌套字段更可靠。
苏姆卡皮