本文深入探讨了如何将大模型的非结构化输出转化为工程可靠的契约,核心围绕结构化输出 (数据契约)和Function Calling(工具调用意图)两大主题展开。
1. 为什么"请返回JSON"不可靠?
- 本质问题 :自然语言指令无法替代工程契约,模型输出具有概率性,容易出现:
- 格式漂移:输出包含额外解释文本,导致JSON解析失败。
- 字段缺失:模型可能省略非必填或把握不大的字段。
- 类型错误 :如字符串
"false"代替布尔值false。 - 边界条件崩溃:输入模糊、矛盾时,模型可能放弃指定格式。
- 核心结论:Prompt表达意图,但不能替代Schema、校验器和重试机制。
2. 将JSON从格式变为契约
关键概念分层:
- JSON Mode :约束输出为合法JSON(管语法),不保证字段和业务语义。
- JSON Schema :一种结构描述规范(管契约),定义字段、类型、枚举、必填等。
- Structured Outputs :模型API的结构化生成能力 ,将Schema传入生成链路,使输出尽量或严格贴合结构(管生成约束)。
对比总结:
- JSON Mode管语法;JSON Schema管契约;Structured Outputs将契约前移到生成阶段。
- 无论模型侧约束多强,服务端校验都不能省。
3. Function Calling:模型生成的是调用意图
- 误解澄清 :模型不直接执行 函数。它只根据用户问题和工具描述,生成结构化的工具调用意图(工具名+参数)。
- 完整链路 :
- 服务端注册工具定义(名称、描述、参数Schema)。
- 模型根据用户请求选择工具并生成参数。
- 业务侧校验参数(类型、权限、业务规则)。
- 业务侧执行真实工具(查数据库、调API)。
- 工具结果回填模型。
- 模型基于事实生成最终回答。
- 价值:完成"自然语言意图 → 结构化参数"的可靠映射。
下面是 Function Calling 的完整调用链路:
#mermaid-svg-RrenAgQuliug7Ypg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-RrenAgQuliug7Ypg .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-RrenAgQuliug7Ypg .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-RrenAgQuliug7Ypg .error-icon{fill:#552222;}#mermaid-svg-RrenAgQuliug7Ypg .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-RrenAgQuliug7Ypg .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-RrenAgQuliug7Ypg .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-RrenAgQuliug7Ypg .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-RrenAgQuliug7Ypg .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-RrenAgQuliug7Ypg .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-RrenAgQuliug7Ypg .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-RrenAgQuliug7Ypg .marker{fill:#333333;stroke:#333333;}#mermaid-svg-RrenAgQuliug7Ypg .marker.cross{stroke:#333333;}#mermaid-svg-RrenAgQuliug7Ypg svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-RrenAgQuliug7Ypg p{margin:0;}#mermaid-svg-RrenAgQuliug7Ypg .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-RrenAgQuliug7Ypg .cluster-label text{fill:#333;}#mermaid-svg-RrenAgQuliug7Ypg .cluster-label span{color:#333;}#mermaid-svg-RrenAgQuliug7Ypg .cluster-label span p{background-color:transparent;}#mermaid-svg-RrenAgQuliug7Ypg .label text,#mermaid-svg-RrenAgQuliug7Ypg span{fill:#333;color:#333;}#mermaid-svg-RrenAgQuliug7Ypg .node rect,#mermaid-svg-RrenAgQuliug7Ypg .node circle,#mermaid-svg-RrenAgQuliug7Ypg .node ellipse,#mermaid-svg-RrenAgQuliug7Ypg .node polygon,#mermaid-svg-RrenAgQuliug7Ypg .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-RrenAgQuliug7Ypg .rough-node .label text,#mermaid-svg-RrenAgQuliug7Ypg .node .label text,#mermaid-svg-RrenAgQuliug7Ypg .image-shape .label,#mermaid-svg-RrenAgQuliug7Ypg .icon-shape .label{text-anchor:middle;}#mermaid-svg-RrenAgQuliug7Ypg .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-RrenAgQuliug7Ypg .rough-node .label,#mermaid-svg-RrenAgQuliug7Ypg .node .label,#mermaid-svg-RrenAgQuliug7Ypg .image-shape .label,#mermaid-svg-RrenAgQuliug7Ypg .icon-shape .label{text-align:center;}#mermaid-svg-RrenAgQuliug7Ypg .node.clickable{cursor:pointer;}#mermaid-svg-RrenAgQuliug7Ypg .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-RrenAgQuliug7Ypg .arrowheadPath{fill:#333333;}#mermaid-svg-RrenAgQuliug7Ypg .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-RrenAgQuliug7Ypg .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-RrenAgQuliug7Ypg .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-RrenAgQuliug7Ypg .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-RrenAgQuliug7Ypg .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-RrenAgQuliug7Ypg .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-RrenAgQuliug7Ypg .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-RrenAgQuliug7Ypg .cluster text{fill:#333;}#mermaid-svg-RrenAgQuliug7Ypg .cluster span{color:#333;}#mermaid-svg-RrenAgQuliug7Ypg div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-RrenAgQuliug7Ypg .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-RrenAgQuliug7Ypg rect.text{fill:none;stroke-width:0;}#mermaid-svg-RrenAgQuliug7Ypg .icon-shape,#mermaid-svg-RrenAgQuliug7Ypg .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-RrenAgQuliug7Ypg .icon-shape p,#mermaid-svg-RrenAgQuliug7Ypg .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-RrenAgQuliug7Ypg .icon-shape .label rect,#mermaid-svg-RrenAgQuliug7Ypg .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-RrenAgQuliug7Ypg .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-RrenAgQuliug7Ypg .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-RrenAgQuliug7Ypg :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 校验通过
校验失败
用户自然语言请求
模型解析意图
选择工具并生成参数
业务侧校验参数
类型/权限/业务规则
业务侧执行真实工具
查数据库/调API
返回错误给模型
有限重试1-2次
工具结果回填模型
模型基于事实生成最终回答
4. Function Calling、MCP、HTTP API、Agent Skill分层
| 能力 | 本质定位 | 解决问题 |
|---|---|---|
| Function Calling | 模型到工具的调用意图生成机制 | 自然语言转工具名和参数 |
| MCP | 工具和上下文接入协议 | 标准化工具发现、描述、调用 |
| 普通HTTP API | 业务服务接口 | 确定性业务读写 |
| Agent Skill | 可复用任务说明书 | 复杂任务的流程编排和SOP |
关系:Function Calling是"神经信号",MCP是"接口标准",HTTP API是"业务能力",Skill是"执行说明书"。
下面是四层能力的层次关系图:
#mermaid-svg-KooewLq4N2LhPenv{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-KooewLq4N2LhPenv .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-KooewLq4N2LhPenv .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-KooewLq4N2LhPenv .error-icon{fill:#552222;}#mermaid-svg-KooewLq4N2LhPenv .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-KooewLq4N2LhPenv .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-KooewLq4N2LhPenv .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-KooewLq4N2LhPenv .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-KooewLq4N2LhPenv .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-KooewLq4N2LhPenv .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-KooewLq4N2LhPenv .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-KooewLq4N2LhPenv .marker{fill:#333333;stroke:#333333;}#mermaid-svg-KooewLq4N2LhPenv .marker.cross{stroke:#333333;}#mermaid-svg-KooewLq4N2LhPenv svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-KooewLq4N2LhPenv p{margin:0;}#mermaid-svg-KooewLq4N2LhPenv .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-KooewLq4N2LhPenv .cluster-label text{fill:#333;}#mermaid-svg-KooewLq4N2LhPenv .cluster-label span{color:#333;}#mermaid-svg-KooewLq4N2LhPenv .cluster-label span p{background-color:transparent;}#mermaid-svg-KooewLq4N2LhPenv .label text,#mermaid-svg-KooewLq4N2LhPenv span{fill:#333;color:#333;}#mermaid-svg-KooewLq4N2LhPenv .node rect,#mermaid-svg-KooewLq4N2LhPenv .node circle,#mermaid-svg-KooewLq4N2LhPenv .node ellipse,#mermaid-svg-KooewLq4N2LhPenv .node polygon,#mermaid-svg-KooewLq4N2LhPenv .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-KooewLq4N2LhPenv .rough-node .label text,#mermaid-svg-KooewLq4N2LhPenv .node .label text,#mermaid-svg-KooewLq4N2LhPenv .image-shape .label,#mermaid-svg-KooewLq4N2LhPenv .icon-shape .label{text-anchor:middle;}#mermaid-svg-KooewLq4N2LhPenv .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-KooewLq4N2LhPenv .rough-node .label,#mermaid-svg-KooewLq4N2LhPenv .node .label,#mermaid-svg-KooewLq4N2LhPenv .image-shape .label,#mermaid-svg-KooewLq4N2LhPenv .icon-shape .label{text-align:center;}#mermaid-svg-KooewLq4N2LhPenv .node.clickable{cursor:pointer;}#mermaid-svg-KooewLq4N2LhPenv .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-KooewLq4N2LhPenv .arrowheadPath{fill:#333333;}#mermaid-svg-KooewLq4N2LhPenv .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-KooewLq4N2LhPenv .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-KooewLq4N2LhPenv .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-KooewLq4N2LhPenv .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-KooewLq4N2LhPenv .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-KooewLq4N2LhPenv .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-KooewLq4N2LhPenv .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-KooewLq4N2LhPenv .cluster text{fill:#333;}#mermaid-svg-KooewLq4N2LhPenv .cluster span{color:#333;}#mermaid-svg-KooewLq4N2LhPenv div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-KooewLq4N2LhPenv .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-KooewLq4N2LhPenv rect.text{fill:none;stroke-width:0;}#mermaid-svg-KooewLq4N2LhPenv .icon-shape,#mermaid-svg-KooewLq4N2LhPenv .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-KooewLq4N2LhPenv .icon-shape p,#mermaid-svg-KooewLq4N2LhPenv .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-KooewLq4N2LhPenv .icon-shape .label rect,#mermaid-svg-KooewLq4N2LhPenv .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-KooewLq4N2LhPenv .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-KooewLq4N2LhPenv .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-KooewLq4N2LhPenv :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 能力分层
生成调用意图
标准化接入
编排流程
Function Calling
调用意图生成机制
MCP
工具接入协议
HTTP API
业务服务接口
Agent Skill
任务执行说明书
5. 结构化输出工程化落地要点
- Schema设计 :
- 字段原子化(一个字段只表达一件事)。
- 优先使用
enum约束分类、状态,避免自由文本。 - 字段描述写明"何时用、何时不用",边界清晰。
- 包含
schemaVersion字段支持版本兼容。
- 校验与重试 :
- 服务端必须做结构校验 、业务校验 (如订单归属)和权限校验。
- 校验失败时,将具体错误反馈给模型进行有限重试(1-2次),让模型修正结构。
- 降级策略 :失败时进入人工队列、使用规则兜底或返回明确错误,禁止模型编造事实。
- 安全治理 :
- 高风险操作(退款、删数据)需二次确认。
- 写操作必须设计幂等 (如使用
idempotencyKey)。 - 记录全链路审计日志(用户输入、模型参数、校验结果、真实执行结果)。
下面是结构化输出的工程化落地流程:
#mermaid-svg-RvnNIlxvpZTcRWHe{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-RvnNIlxvpZTcRWHe .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-RvnNIlxvpZTcRWHe .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-RvnNIlxvpZTcRWHe .error-icon{fill:#552222;}#mermaid-svg-RvnNIlxvpZTcRWHe .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-RvnNIlxvpZTcRWHe .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-RvnNIlxvpZTcRWHe .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-RvnNIlxvpZTcRWHe .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-RvnNIlxvpZTcRWHe .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-RvnNIlxvpZTcRWHe .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-RvnNIlxvpZTcRWHe .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-RvnNIlxvpZTcRWHe .marker{fill:#333333;stroke:#333333;}#mermaid-svg-RvnNIlxvpZTcRWHe .marker.cross{stroke:#333333;}#mermaid-svg-RvnNIlxvpZTcRWHe svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-RvnNIlxvpZTcRWHe p{margin:0;}#mermaid-svg-RvnNIlxvpZTcRWHe .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-RvnNIlxvpZTcRWHe .cluster-label text{fill:#333;}#mermaid-svg-RvnNIlxvpZTcRWHe .cluster-label span{color:#333;}#mermaid-svg-RvnNIlxvpZTcRWHe .cluster-label span p{background-color:transparent;}#mermaid-svg-RvnNIlxvpZTcRWHe .label text,#mermaid-svg-RvnNIlxvpZTcRWHe span{fill:#333;color:#333;}#mermaid-svg-RvnNIlxvpZTcRWHe .node rect,#mermaid-svg-RvnNIlxvpZTcRWHe .node circle,#mermaid-svg-RvnNIlxvpZTcRWHe .node ellipse,#mermaid-svg-RvnNIlxvpZTcRWHe .node polygon,#mermaid-svg-RvnNIlxvpZTcRWHe .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-RvnNIlxvpZTcRWHe .rough-node .label text,#mermaid-svg-RvnNIlxvpZTcRWHe .node .label text,#mermaid-svg-RvnNIlxvpZTcRWHe .image-shape .label,#mermaid-svg-RvnNIlxvpZTcRWHe .icon-shape .label{text-anchor:middle;}#mermaid-svg-RvnNIlxvpZTcRWHe .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-RvnNIlxvpZTcRWHe .rough-node .label,#mermaid-svg-RvnNIlxvpZTcRWHe .node .label,#mermaid-svg-RvnNIlxvpZTcRWHe .image-shape .label,#mermaid-svg-RvnNIlxvpZTcRWHe .icon-shape .label{text-align:center;}#mermaid-svg-RvnNIlxvpZTcRWHe .node.clickable{cursor:pointer;}#mermaid-svg-RvnNIlxvpZTcRWHe .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-RvnNIlxvpZTcRWHe .arrowheadPath{fill:#333333;}#mermaid-svg-RvnNIlxvpZTcRWHe .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-RvnNIlxvpZTcRWHe .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-RvnNIlxvpZTcRWHe .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-RvnNIlxvpZTcRWHe .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-RvnNIlxvpZTcRWHe .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-RvnNIlxvpZTcRWHe .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-RvnNIlxvpZTcRWHe .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-RvnNIlxvpZTcRWHe .cluster text{fill:#333;}#mermaid-svg-RvnNIlxvpZTcRWHe .cluster span{color:#333;}#mermaid-svg-RvnNIlxvpZTcRWHe div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-RvnNIlxvpZTcRWHe .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-RvnNIlxvpZTcRWHe rect.text{fill:none;stroke-width:0;}#mermaid-svg-RvnNIlxvpZTcRWHe .icon-shape,#mermaid-svg-RvnNIlxvpZTcRWHe .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-RvnNIlxvpZTcRWHe .icon-shape p,#mermaid-svg-RvnNIlxvpZTcRWHe .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-RvnNIlxvpZTcRWHe .icon-shape .label rect,#mermaid-svg-RvnNIlxvpZTcRWHe .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-RvnNIlxvpZTcRWHe .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-RvnNIlxvpZTcRWHe .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-RvnNIlxvpZTcRWHe :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 通过
失败
通过
失败
通过
失败
Schema设计
字段原子化/enum约束/版本兼容
模型生成结构化输出
服务端结构校验
业务校验
归属/状态
反馈错误给模型
有限重试1-2次
权限校验
身份/角色
降级策略
人工队列/规则兜底
执行真实业务
审计日志记录
全链路追踪
6. 工具调用安全与Java后端示例
- 安全三层校验:结构校验 → 业务校验(归属、状态)→ 权限校验(身份、角色)。
- Java示例要点 :
- 使用JSON Schema Validator进行结构校验。
- 按工具名分发,未知工具直接拒绝。
- 权限校验通过后才调用业务服务(如
OrderService)。 - 工具返回结构化结果,供模型生成最终回答。
下面是工具调用的安全三层校验流程:
#mermaid-svg-0wpkcI9IPeFZ07kT{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-0wpkcI9IPeFZ07kT .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-0wpkcI9IPeFZ07kT .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-0wpkcI9IPeFZ07kT .error-icon{fill:#552222;}#mermaid-svg-0wpkcI9IPeFZ07kT .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-0wpkcI9IPeFZ07kT .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-0wpkcI9IPeFZ07kT .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-0wpkcI9IPeFZ07kT .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-0wpkcI9IPeFZ07kT .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-0wpkcI9IPeFZ07kT .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-0wpkcI9IPeFZ07kT .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-0wpkcI9IPeFZ07kT .marker{fill:#333333;stroke:#333333;}#mermaid-svg-0wpkcI9IPeFZ07kT .marker.cross{stroke:#333333;}#mermaid-svg-0wpkcI9IPeFZ07kT svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-0wpkcI9IPeFZ07kT p{margin:0;}#mermaid-svg-0wpkcI9IPeFZ07kT .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-0wpkcI9IPeFZ07kT .cluster-label text{fill:#333;}#mermaid-svg-0wpkcI9IPeFZ07kT .cluster-label span{color:#333;}#mermaid-svg-0wpkcI9IPeFZ07kT .cluster-label span p{background-color:transparent;}#mermaid-svg-0wpkcI9IPeFZ07kT .label text,#mermaid-svg-0wpkcI9IPeFZ07kT span{fill:#333;color:#333;}#mermaid-svg-0wpkcI9IPeFZ07kT .node rect,#mermaid-svg-0wpkcI9IPeFZ07kT .node circle,#mermaid-svg-0wpkcI9IPeFZ07kT .node ellipse,#mermaid-svg-0wpkcI9IPeFZ07kT .node polygon,#mermaid-svg-0wpkcI9IPeFZ07kT .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-0wpkcI9IPeFZ07kT .rough-node .label text,#mermaid-svg-0wpkcI9IPeFZ07kT .node .label text,#mermaid-svg-0wpkcI9IPeFZ07kT .image-shape .label,#mermaid-svg-0wpkcI9IPeFZ07kT .icon-shape .label{text-anchor:middle;}#mermaid-svg-0wpkcI9IPeFZ07kT .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-0wpkcI9IPeFZ07kT .rough-node .label,#mermaid-svg-0wpkcI9IPeFZ07kT .node .label,#mermaid-svg-0wpkcI9IPeFZ07kT .image-shape .label,#mermaid-svg-0wpkcI9IPeFZ07kT .icon-shape .label{text-align:center;}#mermaid-svg-0wpkcI9IPeFZ07kT .node.clickable{cursor:pointer;}#mermaid-svg-0wpkcI9IPeFZ07kT .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-0wpkcI9IPeFZ07kT .arrowheadPath{fill:#333333;}#mermaid-svg-0wpkcI9IPeFZ07kT .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-0wpkcI9IPeFZ07kT .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-0wpkcI9IPeFZ07kT .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-0wpkcI9IPeFZ07kT .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-0wpkcI9IPeFZ07kT .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-0wpkcI9IPeFZ07kT .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-0wpkcI9IPeFZ07kT .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-0wpkcI9IPeFZ07kT .cluster text{fill:#333;}#mermaid-svg-0wpkcI9IPeFZ07kT .cluster span{color:#333;}#mermaid-svg-0wpkcI9IPeFZ07kT div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-0wpkcI9IPeFZ07kT .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-0wpkcI9IPeFZ07kT rect.text{fill:none;stroke-width:0;}#mermaid-svg-0wpkcI9IPeFZ07kT .icon-shape,#mermaid-svg-0wpkcI9IPeFZ07kT .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-0wpkcI9IPeFZ07kT .icon-shape p,#mermaid-svg-0wpkcI9IPeFZ07kT .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-0wpkcI9IPeFZ07kT .icon-shape .label rect,#mermaid-svg-0wpkcI9IPeFZ07kT .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-0wpkcI9IPeFZ07kT .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-0wpkcI9IPeFZ07kT .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-0wpkcI9IPeFZ07kT :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 通过
失败
通过
失败
通过
失败
工具调用请求
第一层:结构校验
JSON Schema Validator
第二层:业务校验
归属/状态检查
拒绝请求
第三层:权限校验
身份/角色验证
调用业务服务
OrderService等
返回结构化结果
供模型生成回答
7. 常见误区与面试核心问题
- 误区 :
- Temperature=0不能完全保证稳定,不能替代Schema。
- 用了Structured Outputs仍需服务端校验。
- Schema非越复杂越好,工具非越多越好。
- Function Calling不能绕过业务权限。
- 面试要点 :
- 结构化输出是将模型输出收敛为程序可消费的数据契约。
- Function Calling的链路重点是意图生成与业务执行分离。
- MCP解决工具接入标准化,与Function Calling是不同层次。
总结
- 结构化输出 的本质是把自然语言承诺升级为可校验、可版本化、可降级的工程契约。
- Function Calling 的核心是意图与执行解耦,模型负责生成调用意图,业务侧负责安全的、确定的执行。
- 生产落地的底线是:服务端校验、权限控制、幂等设计和审计日志一个都不能少。