文章目录
- [1. 前言](#1. 前言)
- [2. 结构化输出转换器](#2. 结构化输出转换器)
-
- [2.1 基本原理](#2.1 基本原理)
- [2.2 核心 API](#2.2 核心 API)
-
- [2.2.1 StructuredOutputConverter](#2.2.1 StructuredOutputConverter)
- [2.2.2 BeanOutputConverter](#2.2.2 BeanOutputConverter)
- [2.2.3 AbstractMessageOutputConverter](#2.2.3 AbstractMessageOutputConverter)
-
- [2.2.3.1 MapOutputConverter](#2.2.3.1 MapOutputConverter)
- [2.2.4 AbstractConversionServiceOutputConverter](#2.2.4 AbstractConversionServiceOutputConverter)
-
- [2.2.4.1 ListOutputConverter](#2.2.4.1 ListOutputConverter)
- [2.3 ChatClient 入口](#2.3 ChatClient 入口)
-
- [2.3.1 entity()](#2.3.1 entity())
- [2.3.2 responseEntity()](#2.3.2 responseEntity())
- [3. 模型原生结构化输出](#3. 模型原生结构化输出)
-
- [3.1 智谱 AI](#3.1 智谱 AI)
- [3.2 支持原生结构化输出的模型](#3.2 支持原生结构化输出的模型)
- [3.3 内置 JSON 模式](#3.3 内置 JSON 模式)
1. 前言
在之前的所有案例中,大模型返回的都是非结构化的文本,例如,用户提问 "介绍一下Spring AI" :
java
Spring AI 是一个由 Spring 团队开发的全新框架,旨在为 Java 生态系统提供强大的人工智能集成能力。以下是 Spring AI 的主要特点和介绍:
## 核心概念
**Spring AI** 是一个用于简化 AI 应用开发的 Spring 框架,它提供了统一的编程模型来与各种 AI 模型和平台进行交互。
## 主要特性
### 1. **统一的 AI 编程模型**
- 提供一致的 API 来调用不同的 AI 服务(如 OpenAI、Azure OpenAI、Anthropic Claude 等)
- 统一的接口设计,简化了 AI 集成的复杂性
在某些场景中,需要结构化的输出,比如在合同关键信息提取任务中,合同金额、日期、甲方、乙方等信息,期望大模型能返回结构化的内容信息,比如:
java
合同编号:HT-2026-001
甲方:北京XX科技有限公司
乙方:上海XX贸易有限公司
合同金额:1000000.50
签订日期:2026-03-15
关键条款:[保密条款:双方需对合同内容保密,保密期限为3年, 违约责任:任何一方违约需支付合同金额10%的违约金]
合同有效期:12个月
另外,还期望结构化的输出能转换为 POJO 对象,方便后续业务逻辑处理。
2. 结构化输出转换器
Spring AI 结构化输出转换器用于将 LLM 输出转换为结构化格式,方便开发者快速将 AI 模型的结果转换成可被其他应用函数和方法使用的数据类型,例如 JSON、XML 或 Java 类。
2.1 基本原理
工作流程 :

结构化输出转换器在 LLM 调用前后都扮演关键角色,确保得到期望的输出结构:
- 在调用
LLM之前:转换器会向提示词追加格式指令,为模型提供明确的生成指导。这些指令相当于蓝图,让模型的响应符合指定格式。 - 在调用
LLM之后:转换器接收模型输出的文本,并将其转换为结构化类型的实例。这个转换过程包括解析原始文本输出,并映射到对应的结构化数据表示,例如JSON、XML或领域特定数据结构。
注意事项:
-
结构化输出转换器尽最大努力将模型输出转为结构化输出。不保证
AI模型一定按要求返回结构化输出。模型可能无法理解提示词,或无法按要求生成结构。建议实现验证机制,确保模型输出符合预期。 -
结构化输出转换器不用于
LLM工具调用(Tool Calling/Function Calling),因为该功能默认就提供结构化输出。 -
随着越来越多
AI模型原生支持结构化输出,你可以通过AdvisorParams.ENABLE_NATIVE_STRUCTURED_OUTPUT使用原生结构化输出功能。
2.2 核心 API

2.2.1 StructuredOutputConverter
结构化输出的基础接口,允许你从基于文本的 AI 模型输出中获取结构化输出,例如将输出映射到 Java 类或值数组。继承了 Spring 的 Converter<String, T> 接口和 FormatProvider 接口。
接口定义如下:
java
public interface StructuredOutputConverter<T> extends Converter<String, T>, FormatProvider {
// Converter<String, T>: 将字符串转换为目标类型T
// FormatProvider: 提供格式说明(用于生成提示词)
String getFormat(); // 返回格式描述(如JSON Schema)
}
FormatProvider (格式提供者)向 AI 模型提供具体的格式规范,其输出可通过 Converter 转换为目标类型 T。
接口定义如下:
java
public interface FormatProvider {
String getFormat();
}
格式指令示例如下:
java
你的回复必须是 JSON 格式。
JSON 结构需匹配此类:java.util.HashMap
不要包含任何解释,仅返回符合 RFC8259 标准的 JSON,严格遵循格式。
格式指令通常使用 PromptTemplate 追加到用户输入末尾,如下所示:
java
// 1. 定义带{format}占位符的用户提示词模板
String userInputTemplate = """
... 用户输入 .... // 比如:"提取这份合同的甲方、乙方、金额信息"
{format} // 格式占位符,后续会替换成FormatProvider
""";
// 2. 组装完整提示词:用outputConverter.getFormat()填充{format}占位符
Prompt prompt = new Prompt(
PromptTemplate.builder()
.template(this.userInputTemplate) // 传入模板
.variables(Map.of(..., "format", this.outputConverter.getFormat())) // 填充占位符:format=AI的格式指南
.build().createMessage()
);
Converter (转换器)负责将生成的文本可以通过 Converter 转换成指定的目标类型 T。
接口定义如下:
java
@FunctionalInterface
public interface Converter<S, T> {
@Nullable
T convert(S source);
}
Spring AI 目前提供以下实现:

类结构说明:
AbstractConversionServiceOutputConverter<T>:提供预配置的GenericConversionService,用于将 LLM 输出转为目标格式。无默认的FormatProvider实现。AbstractMessageOutputConverter<T>:提供预配置的MessageConverter,用于将LLM输出转为目标格式。无默认的FormatProvider实现。BeanOutputConverter<T>:通过指定Java类或ParameterizedTypeReference配置。它使用FormatProvider指导模型输出符合JSON Schema (DRAFT_2020_12)的JSON,再通过ObjectMapper反序列化为Java对象。MapOutputConverter:继承AbstractMessageOutputConverter,指导模型输出RFC8259合规JSON,并转换为Map<String, Object>。ListOutputConverter:继承AbstractConversionServiceOutputConverter,用于逗号分隔列表格式输出,并转换为List。
2.2.2 BeanOutputConverter
将 AI 返回的文本自动解析为指定的 Java Bean/Record。
核心属性:
java
public class BeanOutputConverter<T> implements StructuredOutputConverter<T> {
/**
* 目标转换类型(可以是普通Class、泛型、Record)
*/
private final Type type;
/**
* Jackson 对象序列化/反序列化工具
*/
private final ObjectMapper objectMapper;
/**
* 根据目标类型自动生成的 JSON Schema(用于提示 AI 按格式输出)
*/
private String jsonSchema;
/**
* 模型返回文本清理器(处理 markdown、思考标签、空格等脏数据)
*/
private final ResponseTextCleaner textCleaner;
构造方法:
java
/**
* 通过 Class 构建转换器
*/
public BeanOutputConverter(Class<T> clazz) {
this(clazz, null, null);
}
/**
* 带自定义 ObjectMapper 的构造
*/
public BeanOutputConverter(Class<T> clazz, ObjectMapper objectMapper) {
this(clazz, objectMapper, null);
}
/**
* 完整构造:Class + ObjectMapper + 文本清理器
*/
public BeanOutputConverter(Class<T> clazz, ObjectMapper objectMapper, ResponseTextCleaner textCleaner) {
this(ParameterizedTypeReference.forType(clazz), objectMapper, textCleaner);
}
/**
* 通过 ParameterizedTypeReference 构建(支持泛型,如 List<Bean>)
*/
public BeanOutputConverter(ParameterizedTypeReference<T> typeRef) {
this(typeRef, null, null);
}
public BeanOutputConverter(ParameterizedTypeReference<T> typeRef, ObjectMapper objectMapper) {
this(typeRef, objectMapper, null);
}
public BeanOutputConverter(ParameterizedTypeReference<T> typeRef, ObjectMapper objectMapper, ResponseTextCleaner textCleaner) {
this(typeRef.getType(), objectMapper, textCleaner);
}
/**
* 最终私有构造:初始化所有组件并自动生成 JSON Schema
*/
private BeanOutputConverter(Type type, ObjectMapper objectMapper, ResponseTextCleaner textCleaner) {
Objects.requireNonNull(type, "Type cannot be null;");
this.type = type;
// 使用传入的 ObjectMapper 或创建默认
this.objectMapper = objectMapper != null ? objectMapper : getObjectMapper();
// 使用传入的清理器 或 创建默认
this.textCleaner = textCleaner != null ? textCleaner : createDefaultTextCleaner();
// 自动生成 JSON Schema
this.generateSchema();
}
核心方法:
- 自动生成
JSON Schema - 自动清洗模型返回文本
- 反序列化为目标对象
java
// ==================== 核心:创建默认文本清理器 ====================
/**
* 默认文本清理器组合:
* 1. 空格清理
* 2. <thinking> 思考标签清理
* 3. Markdown 代码块 ```json ```清理
* 4. 再次空格清理
* 确保 AI 返回的文本变成纯 JSON
*/
private static ResponseTextCleaner createDefaultTextCleaner() {
return CompositeResponseTextCleaner.builder()
.addCleaner(new WhitespaceCleaner())
.addCleaner(new ThinkingTagCleaner())
.addCleaner(new MarkdownCodeBlockCleaner())
.addCleaner(new WhitespaceCleaner())
.build();
}
// ==================== 核心:自动生成 JSON Schema ====================
/**
* 根据目标 Java 类型自动生成 JSON Schema(Draft 2020-12)
* 支持:
* - Jackson 注解(@JsonProperty、@JsonPropertyOrder、@JsonIgnore)
* - Kotlin 数据类
* - 所有字段默认必填
*/
private void generateSchema() {
// 集成 Jackson 注解模块
JacksonModule jacksonModule = new JacksonModule(
JacksonOption.RESPECT_JSONPROPERTY_REQUIRED,
JacksonOption.RESPECT_JSONPROPERTY_ORDER
);
// 构建 Schema 生成器配置:Draft2020_12 + 纯JSON格式
SchemaGeneratorConfigBuilder configBuilder = new SchemaGeneratorConfigBuilder(
SchemaVersion.DRAFT_2020_12,
OptionPreset.PLAIN_JSON)
.with(jacksonModule)
.with(Option.FORBIDDEN_ADDITIONAL_PROPERTIES_BY_DEFAULT); // 禁止额外属性
// 所有字段默认必填
configBuilder.forFields().withRequiredCheck(field -> true);
// 若项目存在 Kotlin,则自动加入 Kotlin 模块支持
if (KotlinDetector.isKotlinReflectPresent()) {
configBuilder.with(new KotlinModule());
}
// 生成 JSON Schema
SchemaGeneratorConfig config = configBuilder.build();
SchemaGenerator generator = new SchemaGenerator(config);
JsonNode jsonNode = generator.generateSchema(this.type);
// 格式化输出 JSON Schema
ObjectWriter objectWriter = this.objectMapper.writer(
new DefaultPrettyPrinter()
.withObjectIndenter(
new DefaultIndenter().withLinefeed(System.lineSeparator())
)
);
try {
this.jsonSchema = objectWriter.writeValueAsString(jsonNode);
} catch (JsonProcessingException e) {
logger.error("Could not pretty print json schema for type: {}", this.type);
throw new RuntimeException("Could not generate JSON Schema for " + this.type, e);
}
}
// ==================== 核心:将 AI 文本转为 Java Bean ====================
/**
* 转换入口:
* 1. 清理 AI 返回的脏文本(markdown、thinking、空格)
* 2. 使用 Jackson 反序列化为目标类型
*/
@Override
public T convert(@NonNull String text) {
try {
// 清理文本
text = this.textCleaner.clean(text);
// 反序列化 JSON → Java 对象
return this.objectMapper.readValue(text, this.objectMapper.constructType(this.type));
} catch (JsonProcessingException e) {
logger.error(LoggingMarkers.SENSITIVE_DATA_MARKER,
"Could not parse text to target type: \"{}\" into {}",
text, this.type);
throw new RuntimeException(e);
}
}
// ==================== 创建默认 ObjectMapper ====================
/**
* 创建默认 ObjectMapper:
* - 忽略未知属性(最关键,避免 AI 多返回字段导致解析失败)
* - 自动加载可用模块(如 Kotlin、Java8 时间)
*/
protected ObjectMapper getObjectMapper() {
return JsonMapper.builder()
.addModules(JacksonUtils.instantiateAvailableModules())
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.build();
}
// ==================== 生成给 AI 的格式提示指令 ====================
/**
* 生成给大模型的格式指令:
* 1. 输出 JSON
* 2. 不要解释
* 3. 严格遵循 RFC8259
* 4. 不要 markdown
* 5. 提供 JSON Schema
*/
@Override
public String getFormat() {
String template = """
Your response should be in JSON format.
Do not include any explanations, only provide a RFC8259 compliant JSON response following this format without deviation.
Do not include markdown code blocks in your response.
Remove the ```json markdown from the output.
Here is the JSON Schema instance your output must adhere to:
```%s```
""";
return String.format(template, this.jsonSchema);
}
// ==================== 工具方法 ====================
/**
* 获取生成的 JSON Schema 字符串
*/
public String getJsonSchema() {
return this.jsonSchema;
}
/**
* 将 JSON Schema 转为 Map(用于 Native Structured Output 原生模式)
*/
public Map<String, Object> getJsonSchemaMap() {
try {
return this.objectMapper.readValue(this.jsonSchema, Map.class);
} catch (JsonProcessingException e) {
logger.error("Could not parse JSON Schema to Map", e);
throw new IllegalStateException(e);
}
}
}
2.2.3 AbstractMessageOutputConverter
【基于消息转换器的结构化输出抽象转换器】,结构化输出转换器的另一种抽象实现,核心区别于 AbstractConversionServiceOutputConverter:
- 依赖
Spring Messaging模块的MessageConverter(消息转换器)而非ConversionService(类型转换服务) - 专注于「消息体格式」的结构化转换(如
JSON/XML格式的消息文本 ↔Java对象) - 更适配消息驱动的场景(如
Spring Cloud Stream、消息队列集成的AI应用)
核心属性:
java
/**
* 核心属性:Spring Messaging 消息转换器
* 作用:
* 1. 处理「消息文本(如JSON/XML)」与「Java对象」的双向转换
* 2. 支持多格式解析(区别于仅处理类型转换的 ConversionService)
* 3. 适配消息驱动场景(如从消息队列接收LLM输出的结构化消息)
* 修饰符说明:
* - 非final:允许子类在运行时替换/重置消息转换器(适配动态配置场景)
* - private:仅当前类访问,子类通过getter获取
*/
private MessageConverter messageConverter;
构造方法:
java
/**
* 构造器:注入消息转换器(依赖注入模式)
* 设计意图:
* - 强制子类初始化时指定消息转换器,避免空指针
* - 支持传入自定义配置的MessageConverter(如定制JSON解析规则的MappingJackson2MessageConverter)
*
* @param messageConverter 消息转换器实例(不能为空,实际源码中会通过Assert.notNull校验)
*/
public AbstractMessageOutputConverter(MessageConverter messageConverter) {
// 初始化消息转换器,交由父类统一管理
this.messageConverter = messageConverter;
}
核心抽象方法:
getFormat:生成LLM输出格式提示(如JSONSchema/XML格式说明)convert:将 LLM 返回的原始文本(如JSON/XML字符串)转换为目标类型T
java
/**
* Getter方法:给子类提供消息转换器的访问入口
* 典型使用场景:
* 子类实现convert()方法时,调用该方法获取转换器,完成「LLM输出文本 → 目标类型」的转换
*
* @return 初始化后的消息转换器实例
*/
public MessageConverter getMessageConverter() {
return this.messageConverter;
}
/**
* 【必须由子类实现】生成LLM输出格式提示(如JSON Schema/XML格式说明)
* 作用:告诉LLM需要返回的结构化格式(如"请返回符合以下JSON格式的文本:{...}")
* 注:该方法由StructuredOutputConverter接口定义,父类仅声明抽象,子类需按需实现
*/
@Override
public abstract String getFormat();
/**
* 【必须由子类实现】执行结构化转换核心逻辑
* 作用:将LLM返回的原始文本(如JSON/XML字符串)转换为目标类型T
* 注:该方法由StructuredOutputConverter接口定义,父类仅声明抽象,子类需结合MessageConverter实现
*
* @param source LLM返回的原始结构化文本(如JSON字符串、XML字符串)
* @return 转换后的目标类型实例(如ContractInfo、Book等)
*/
@Override
public abstract T convert(String source);
}
2.2.3.1 MapOutputConverter
【Map 输出转换器】将 AI 模型返回的 JSON 文本,自动清洗并转换为 Java Map<String, Object> 。
处理流程:
- 自动去除
Markdown代码块 - 使用
Spring MappingJackson2MessageConverter做JSON解析 - 自动生成格式提示词,要求模型返回标准
JSON
源码如下:
java
public class MapOutputConverter extends AbstractMessageOutputConverter<Map<String, Object>> {
/**
* 默认构造方法
* 直接使用 Spring 自带的 MappingJackson2MessageConverter 进行 JSON 转换
*/
public MapOutputConverter() {
super(new MappingJackson2MessageConverter());
}
/**
* 核心转换方法:将 AI 返回的文本 → Map<String, Object>
* @param text AI 返回的原始文本(可能带 Markdown)
* @return 解析后的 Map 对象
*/
@Override
public Map<String, Object> convert(@NonNull String text) {
// 1. 自动清理 AI 最常返回的 Markdown 代码块:```json ... ```
if (text.startsWith("```json") && text.endsWith("```")) {
// 去掉开头 ```json (7个字符) 和结尾 ```(3个字符)
text = text.substring(7, text.length() - 3);
}
// 2. 构建 Spring Message 对象,用于适配 MessageConverter
Message<?> message = MessageBuilder.withPayload(text.getBytes(StandardCharsets.UTF_8)).build();
// 3. 使用 JSON 消息转换器将文本转为 HashMap
return (Map) this.getMessageConverter().fromMessage(message, HashMap.class);
}
/**
* 生成给 AI 模型的格式指令(Prompt)
* 告诉模型:必须返回 JSON、不要解释、不要 Markdown
*/
@Override
public String getFormat() {
String rawFormat = """
Your response should be in JSON format.
The data structure for the JSON should match this Java class: %s
Do not include any explanations, only provide a RFC8259 compliant JSON response following this format without deviation.
Remove the ```json markdown surrounding the output including the trailing "```".
""";
// 格式化指令,填入 HashMap 类名
return String.format(rawFormat, HashMap.class.getName());
}
}
2.2.4 AbstractConversionServiceOutputConverter
【结构化输出转换器抽象基类】封装 Spring 内置的默认类型转换服务(DefaultConversionService),用于将 LLM 输出转为目标格式,没有提供默认的 FormatProvider 实现。
核心职责:
- 封装
Spring内置的默认类型转换服务(DefaultConversionService),避免子类重复实现基础类型转换逻辑 - 定义结构化输出转换器的通用骨架,遵循「模板方法模式」------ 通用逻辑封装在抽象父类,具体逻辑由子类实现
- 统一管理类型转换规则,保证所有子类的类型转换行为一致(如
String→LocalDate、String→BigDecimal等)
核心属性和构造器:
java
/**
* 【结构化输出转换器抽象基类】
* @param <T> 泛型:指定转换器最终要转换的目标类型(如 ContractInfo、Book 等业务对象)
* @author Mark Pollack
* @author Christian Tzolov
* @see StructuredOutputConverter 结构化输出转换器核心接口
* @see DefaultConversionService Spring 内置默认类型转换服务
* @see BeanOutputConverter 该抽象类的核心子类(JSON字符串转Java Bean)
*/
public abstract class AbstractConversionServiceOutputConverter<T> implements StructuredOutputConverter<T> {
/**
* 核心属性:Spring 内置的默认类型转换服务
* 作用:
* - 处理基础类型转换(String→int、String→double)
* - 处理复杂类型转换(String→LocalDate、String→BigDecimal、String→枚举)
* - 支持扩展自定义类型转换器(如 String→自定义业务枚举)
* 修饰符说明:
* - private:仅当前类可访问,子类通过 getter 方法获取
* - final:一旦初始化不可修改,保证线程安全(Spring AI 多线程场景下无并发问题)
*/
private final DefaultConversionService conversionService;
/**
* 构造器:注入类型转换服务(依赖注入模式)
* 设计思路:通过构造器注入而非硬编码,保证灵活性------子类可传入自定义配置的 ConversionService
*
* @param conversionService Spring 默认类型转换服务实例,不能为空(实际使用时会通过 Assert.notNull 校验)
*/
public AbstractConversionServiceOutputConverter(DefaultConversionService conversionService) {
// 初始化类型转换服务,交给父类统一管理
this.conversionService = conversionService;
}
}
也声明了 getFormat 和 convert 方法:
java
/**
* Getter 方法:给子类提供类型转换服务的访问入口
* 设计思路:子类(如 BeanOutputConverter)在实现具体转换逻辑时,需要调用该方法获取 ConversionService,
* 进而完成「中间数据(如 Map)→ 目标类型(如 ContractInfo)」的转换
*
* @return 初始化后的默认类型转换服务实例
*/
public DefaultConversionService getConversionService() {
return this.conversionService;
}
/**
* 【必须由子类实现】结构化输出转换器核心接口方法:生成格式提示(如 JSON Schema)
* 作用:告诉 LLM 需要返回的结构化格式(如 "你的输出必须符合以下JSON Schema:{...}")
* 注:该方法由 StructuredOutputConverter 接口定义,父类未实现,需子类按需实现
*
* @return 格式提示字符串(如 JSON Schema、字段说明等)
*/
@Override
public abstract String getFormat();
/**
* 【必须由子类实现】结构化输出转换器核心接口方法:执行转换逻辑
* 作用:将 LLM 返回的文本(如 JSON 字符串)转换为目标类型 T
* 注:该方法由 StructuredOutputConverter 接口定义,父类未实现,需子类按需实现
*
* @param source LLM 返回的原始文本(如 JSON 字符串、CSV 字符串等)
* @return 转换后的目标类型实例(如 ContractInfo、Book 等)
*/
@Override
public abstract T convert(String source);
2.2.4.1 ListOutputConverter
【List 输出转换器】将 AI 返回的【逗号分隔字符串】自动转换为 Java List<String> 。
核心特点:
- 不需要
JSON - 简单轻量,适合返回简单列表
- 基于
Spring ConversionService实现类型转换
源码如下:
java
public class ListOutputConverter extends AbstractConversionServiceOutputConverter<List<String>> {
/**
* 默认构造:使用 Spring 内置默认类型转换服务
*/
public ListOutputConverter() {
this(new DefaultConversionService());
}
/**
* 可传入自定义 ConversionService 的构造器
*/
public ListOutputConverter(DefaultConversionService defaultConversionService) {
super(defaultConversionService);
}
/**
* 生成给 AI 的格式指令:
* 要求返回【逗号分隔的简单列表】,不要多余文字、不要 JSON、不要解释
*/
@Override
public String getFormat() {
return "Respond with only a list of comma-separated values, without any leading or trailing text.\nExample format: foo, bar, baz\n";
}
/**
* 核心转换方法:
* 将 AI 返回的文本 → 自动转为 List<String>
*/
@Override
public List<String> convert(@NonNull String text) {
// 使用 Spring 类型转换服务,直接把字符串转成 List
return (List) this.getConversionService().convert(text, List.class);
}
}
2.3 ChatClient 入口
在使用时,Spring AI 提供了简单的入口:

2.3.1 entity()
把 AI 返回的文本动转换成你想要的 Java 对象。
三个重载方法:
entity(Class<T> type):传入普通Class类型(最常用)entity(ParameterizedTypeReference<T> type):传入 泛型类型(如List<ActorsFilms>)entity(StructuredOutputConverter<T> structuredOutputConverter):传入自定义转换器
2.3.2 responseEntity()
entity() 返回转换后的对象,responseEntity() 则可以将【原始响应体 + 转换后的 Java 对象】都返回。
三个重载方法:
responseEntity(Class<T> type):传入普通Class类型responseEntity(ParameterizedTypeReference<T> type):传入 泛型类型responseEntity(StructuredOutputConverter<T> structuredOutputConverter):传入自定义转换器
3. 模型原生结构化输出
大多数 AI 模型现已提供原生结构化输出支持,相比基于提示词的方式更可靠。
这种方式提供:
- 更高可靠性:模型保证输出符合
Schema - 更简洁的提示词:无需追加格式指令
- 更好性能:模型可内部优化结构化输出
Spring AI 也支持原生结构化输出功能,使用时,BeanOutputConverter 生成的 JSON Schema 会直接发送到模型的结构化输出 API,无需在提示词中加入格式指令。
3.1 智谱 AI
在 智谱 API 文档中,可以看到对话补全调用时,支持结构化输出参数 response_format:
text:表示普通文本输出模式,模型返回自然语言文本json_object:表示JSON输出模式,模型会返回有效的JSON格式数据,建议在提示词中明确说明需要JSON格式输出。

提示 :智谱 API 只支持配置响应格式,并不完全提供模型原生结构化输出,在 Spring AI 时,实际也是在提示词中直接添加的格式指令、输出 Schema 。
3.2 支持原生结构化输出的模型
除此之外,很多大模型还支持通过 format 请求参数,直接传递 JSON Schema ,而不是在提示词中加入格式指令。
例如 Ollama:

以下模型目前支持原生结构化输出:
OpenAI:GPT-4o及后续支持JSON Schema的模型Anthropic:Claude 3.5 Sonnet及后续模型Vertex AI Gemini:Gemini 1.5 Pro及后续模型Mistral AI:Mistral Small及后续支持JSON Schema的模型
注意:部分 AI 模型(如 OpenAI)原生不支持顶层对象数组。这种情况下,可以使用 Spring AI 默认的结构化输出转换(不使用原生结构化输出 advisor)。
3.3 内置 JSON 模式
部分 AI 模型提供专用配置选项来生成结构化(通常是 JSON)输出。
例如,OpenAiChatOptions 实现了 StructuredOutputChatOptions 接口:
java
public class OpenAiChatOptions implements ToolCallingChatOptions, StructuredOutputChatOptions {
可以通过 spring.ai.openai.chat.options.responseFormat 属性配置 Open AI 的结构化输出,确保模型生成的响应严格符合您提供的 JSON Schema :
yml
spring:
ai:
openai:
chat:
options:
response-format:
type: JSON_SCHEMA
name: MySchemaName
schema: {"type":"object","properties":{"steps":{"type":"array","items":{"type":"object","properties":{"explanation":{"type":"string"},"output":{"type":"string"}},"required":["explanation","output"],"additionalProperties":false}},"final_answer":{"type":"string"}},"required":["steps","final_answer"],"additionalProperties":false}
response-format 可以选择:
JSON_OBJECT:保证模型生成的是有效JSONJSON_SCHEMA:配合提供的schema,保证模型生成符合schema的响应
其他支持的模型:
Azure OpenAI:提供spring.ai.azure.openai.chat.options.responseFormat选项Ollama:提供spring.ai.ollama.chat.options.format选项Mistral AI:提供spring.ai.mistralai.chat.options.responseFormat选项