作为一名AI应用开发者,你是否遇到过这样的困扰:大语言模型(LLM)的回答虽然内容准确,但格式千变万化,难以被程序直接使用?今天,我们就来聊聊Spring AI中的结构化输出转换器,看看如何让AI输出“规规矩矩”的数据,像Java对象、Map、List一样可靠。
一、为什么需要结构化输出?
大语言模型天然擅长生成自然语言,但在企业级应用中,我们往往需要将AI的回答与业务流程对接。例如:
- 从对话中提取“恋爱报告”,包含标题和建议列表
- 获取一份格式固定的电影清单
- 解析用户意图,生成结构化的操作指令
如果AI每次返回的格式都不同,下游程序将难以稳定解析。这时,结构化输出转换器就派上了用场。
二、Spring AI结构化输出转换器原理
Spring AI通过两个核心接口实现结构化输出:
1. FormatProvider接口:调用前“格式化指令”
在向AI发送请求之前,转换器会在提示词后追加格式说明,告诉模型“请按这个结构返回”。例如,我们希望AI返回一个恋爱报告对象:
{
"title": "张三的恋爱报告",
"suggestions": ["多沟通", "增加约会频率"]
}
转换器会生成类似这样的格式指令:
返回格式必须是 JSON,匹配以下结构:
{
"title": "string",
"suggestions": ["string1", "string2"]
}
请只返回 JSON,不要有任何其他内容。
2. Converter<String, T>接口:调用后“反序列化”
AI返回的文本(通常是JSON)会被Converter转换成我们指定的Java类型(如LoveReport、List<String>等)。
这两个步骤结合起来,就实现了“从自然语言到结构化数据”的完整闭环。
三、实战:恋爱报告的结构化输出
我们来看一个具体例子。假设我们有一个恋爱咨询应用,用户倾诉后,我们希望AI生成一份结构化的恋爱报告。
1. 定义报告类
record LoveReport(String title, List<String> suggestions) {}
这是一个简单的Java Record,包含标题和建议列表。
2. 使用entity()方法获取结构化对象
public LoveReport doChatWithReport(String message, String chatId) {
LoveReport report = chatClient.prompt()
.system(SYSTEM_PROMPT + "每次对话后都要生成恋爱结果,标题为{用户名}的恋爱报告,内容为建议列表")
.user(message)
.advisors(spec -> spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId)
.param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10))
.call()
.entity(LoveReport.class); // 关键:转换为LoveReport对象
return report;
}
重点解析:
.entity(LoveReport.class):Spring AI会自动在请求中加入格式指令,并将返回的JSON转换为LoveReport实例。- 系统提示词中我们明确要求“生成恋爱结果”,帮助模型理解输出目标。
3. 更复杂的结构:使用ParameterizedTypeReference
如果我们要返回一个List<LoveReport>,可以这样写:
List<LoveReport> reports = chatClient.prompt()
.user("为小明和小红分别生成恋爱报告")
.call()
.entity(new ParameterizedTypeReference<List<LoveReport>>() {});
这适用于嵌套泛型等复杂场景。
四、其他内置转换器示例
Spring AI还提供了多种开箱即用的转换器:
1. 输出为Map
Map<String, Object> result = chatClient.prompt()
.user("给我一个1到9的数字列表,key为numbers")
.call()
.entity(new ParameterizedTypeReference<Map<String, Object>>() {});
2. 输出为List<String>
List<String> flavors = chatClient.prompt()
.user("列出5种冰淇淋口味")
.call()
.entity(new ListOutputConverter(new DefaultConversionService()));
五、最佳实践建议
- 明确格式指令:在系统提示或用户提示中清晰描述期望的输出结构,尤其是字段含义。
- 添加验证与异常处理:AI输出可能不完全符合预期,建议对转换后的对象做非空校验或格式校验。
- 选择合适的模型:不同模型对指令遵循能力不同,优先选择支持结构化输出(如JSON模式)的模型。
- 复杂结构用
ParameterizedTypeReference:当返回类型涉及泛型时,这是更安全的选择。
六、总结
Spring AI的结构化输出转换器,本质上是通过前置格式约束与后置类型转换,让AI的输出从“自由文本”变为“可控数据”。它不仅简化了开发者的解析工作,也为AI应用与业务系统的深度集成铺平了道路。
在你的下一个AI项目中,不妨试试这套机制,让AI不仅“会说话”,更能“说结构话”。