Skip to content

什么是结构化输出?Spring AI 是怎么实现结构化输出的? ​

  • 标签:后端、编程导航

🏛 业务架构师 ​

结构化输出 = 把模型的自然语言回答约束成预定义的数据格式(JSON、Java 对象),让 AI 输出从"给人看的文本"变成"给程序用的数据"。

Spring AI 的实现路径:调用时传入目标类(或 JSON Schema),框架在 prompt 中注入格式指令,模型按 schema 生成,框架再反序列化成对象;支持带 Bean Validation 校验,解析失败可自动重试。

业务架构视角,这是 AI 应用的分水岭——没有它,模型输出只能展示给用户;有了它,模型成为业务流程中的一个环节:

  • 行程规划助手:模型输出 TripPlan { days: List<DayPlan{ morning, afternoon, evening }> }——前端直接渲染时间轴卡片,而不是让用户读一大段文字;
  • 数据分析:结论输出 { metric, trend, anomalies[] },直接进仪表盘与告警链路;
  • 多级编排:第一个模型的输出作为第二个模型的输入参数——AI 流水线的前提是中间产物可被程序消费。

工程纪律(结构化输出的坑):

  1. schema 要窄:字段越少越稳,枚举值用明确列表约束——给模型的自由度与格式的可靠性成反比;
  2. 必须有解析失败的兜底:重试 + 降级(换 prompt 再试 / 转人工),格式漂移是概率事件,按概率工程化处理;
  3. 校验前置于信任:模型输出过 validation 才能进业务——永远不信任模型输出的业务合法性(金额、日期范围这些业务规则要代码校验)。

一句话:结构化输出是把 AI 的不确定性装进类型系统的手段——是 AI 从 demo 到生产的关键一步。

🏗 系统架构师 ​

结构化输出 = 让模型按预定义的 Schema 返回可程序解析的数据(JSON/枚举/对象),而不是自由文本。它是 Agent 工程化的关键:下游代码(路由、检索、UI)需要确定性的数据结构。

Spring AI 实现原理(三步):

  1. 提示词注入约束:BeanOutputConverter 根据目标 POJO 生成 JSON Schema 描述(字段名、类型、格式),自动拼进 Prompt,要求模型"仅输出符合该格式的 JSON";
  2. 模型侧配合:现代模型的 JSON mode / structured output 能力(采样参数约束合法 JSON 语法)提升遵循度;
  3. 解析与转换:拿到响应后做 JSON 解析 → 反序列化为目标对象(entity(Class) 或 entity(ParameterizedTypeReference) 泛型集合)。

使用形态:

java
record SearchQuery(String query, String reason) {}
List<SearchQuery> queries = chatClient.prompt()
    .user(question)
    .call()
    .entity(new ParameterizedTypeReference<List<SearchQuery>>() {});

工程要点(实战坑):

  • 解析失败要重试(带上错误信息让模型自纠)+ 兜底策略(降级默认值/便宜模型重试);
  • Schema 越简单遵循度越高:嵌套深、字段多的复杂对象拆多次调用;
  • 用 record/枚举明确类型,禁止 Map 无 Schema;
  • 枚举/布尔这类强约束场景可靠性高,自由字符串数组要校验。

我的用法:多查询扩展(List<String>)、Agent 路由决策(枚举)、工具选择——凡是"模型输出要进程序分支"的地方一律结构化。

💻 全栈开发专家 ​

结构化输出 = 让模型按预定义的 JSON Schema 返回数据,直接反序列化成 Java 对象,而不是解析自然语言文本。用于后续业务逻辑消费模型结果的场景(分类、抽取、生成配置)。

Spring AI 的实现机制(两层):

1. API 层:.entity(Class) 一行搞定:

java
public record RiskReport(String level, List<String> reasons, double score) {}

RiskReport report = chatClient.prompt()
    .user("分析以下用户的消费行为并输出风险评估: " + data)
    .call()
    .entity(RiskReport.class);   // 返回值就是 Java 对象

2. 底层原理:BeanOutputConverter 做三件事——

  • 从 Java 类型(record/POJO)反射生成 JSON Schema;
  • 把 schema 和格式指令拼进 prompt("必须输出符合此 JSON 结构的内容");
  • 拿到模型文本后剥离 markdown 代码围栏(```json 包裹),Jackson 反序列化成对象。

工程必答的两个坑:

  1. 模型可能不守格式:弱模型会加解释文字或字段类型飘。解法:失败自动捕获 → 把格式错误回喂模型纠错重试一次;prompt 里强调"只输出 JSON";选用支持 JSON mode/function calling 强约束的模型;
  2. 嵌套复杂结构:字段太多模型容易漏,拆成多次简单结构化调用再组装,比一次要一个大对象成功率高得多。

我的经验:结构化输出选模型比调 prompt 更关键,DeepSeek/GPT-4o 级别基本一次过,小模型要加重试。