核心要点

  • 结构化输出指把模型返回的自由文本,可靠地转成 Java Bean/POJO、Map、List 等强类型对象,便于接进业务代码。

  • Spring AI 提供 StructuredOutputConverter 体系:BeanOutputConverter(转任意 Java Bean)、MapOutputConverter(转 Map)、ListOutputConverter(转 List)。

  • ChatClient 高层 API 用 .entity(Class) 一步完成「调用 + 解析」,底层自动选用对应 Converter。

  • 原理:把目标 JSON Schema / 格式说明注入 prompt 引导模型按格式输出,再对返回文本做解析,配合校验与重试容错。

标准回答

问题背景:LLM 返回的是文本,业务要的是对象模型默认输出一段自然语言文本,但 Java 业务往往需要一个强类型对象(比如一个 Order、一个 List<String>)才能继续处理。Spring AI 的结构化输出(Structured Output) 就是解决这个「文本 → 对象」的转换问题。核心抽象:StructuredOutputConverterSpring AI 把转换逻辑统一封装为 StructuredOutputConverter,它同时承担两件事:

-getFormat()生成「格式说明」注入到 prompt 里,告诉模型该按什么 JSON Schema 或结构来回答。
-
convert() 拿到模型返回的字符串后,把它解析成目标类型。

常用实现有三个:

-BeanOutputConverter:最常用,根据你的 Java Bean/POJO 的字段自动推导 JSON Schema,再把返回的 JSON 反序列化成该 Bean。
-
MapOutputConverter: 把返回解析成 Map<String, Object>,适合字段不固定的场景。
-ListOutputConverter把返回解析成 List<String>,适合枚举、清单类任务。 最简写法:ChatClient.entity()实际开发里一般不直接手写 Converter,而是用 ChatClient 的流式 API 一步到位,例如 chatClient.prompt().user("...").call().entity(ActorFilms.class)。传入一个 Class,Spring AI 内部就会用 BeanOutputConverter 注入格式说明并解析返回,直接给你一个填好的对象;也支持 entity(new ParameterizedTypeReference<List<X>>(){}) 处理泛型集合。 容错很关键
模型并不保证 100% 输出合法 JSON,所以工程上要配合:对解析失败做捕获与重试、对字段做校验(如 Bean Validation)、必要时结合支持原生 JSON Mode / 函数调用的模型来提高稳定性。这样才能把 LLM 安全地接进强类型 Java 业务链路。

常见误区

⚠️ 常见踩坑

误以为 .entity() 能保证模型一定返回合法结构——它只是注入格式说明并尝试解析,模型仍可能跑偏或返回多余文字,解析会抛异常。生产环境必须加重试、校验与降级,不能假设一次成功;另外别把超大复杂嵌套对象硬塞给小模型,Schema 越复杂出错率越高。

追问

追问 1BeanOutputConverter 是怎么让模型知道该返回什么格式的?

它会根据目标 Java Bean 的字段,用反射/Jackson 推导出对应的 JSON Schema,然后通过 getFormat() 把这段 Schema 和「请只返回符合该 Schema 的 JSON、不要包含额外说明」之类的指令拼进 prompt。模型据此输出 JSON,convert() 再用 ObjectMapper 把 JSON 反序列化成 Bean。本质是「用提示词约束格式 + 反序列化解析」,而不是模型原生强约束。

追问 2结构化输出和模型原生的 JSON Mode / 函数调用有什么关系?

层次不同但可叠加。StructuredOutputConverter 是 Spring AI 在应用层做的「提示注入 + 解析」,对所有模型通用、不依赖底层能力;而 JSON Mode、函数/工具调用是部分模型在 API 层提供的原生结构化保证。最佳实践是:底层用支持 JSON Mode 的模型提升合法率,上层仍用 Spring AI 的 Converter/entity() 拿到强类型对象,两者互补,可靠性更高。

追问 3如果模型返回的 JSON 总是少字段或类型不对,怎么排查和增强稳定性?

先看注入的格式说明是否清晰、Schema 是否过于复杂;可以拆小对象、减少嵌套、给字段加描述。运行期加 Bean Validation 校验,失败时携带「上次错误」让模型重试(self-correction)。还可换更强或支持原生结构化输出的模型、降低 temperature,并在 prompt 里强调「只输出 JSON、不要 markdown 代码块」。最后保留兜底解析和默认值,避免单次失败拖垮整个链路。

🔗 相似问题

同一考点的不同问法,面试官可能换着问,一起刷更稳

没找到想看的面试题?把你想看的告诉我们 →

延伸学习

按主题分类的相关资源,便于系统复习