Java程序员学从0学AI(五)
一、前言
在上一篇文章中我们学习了SpringAI为我们提供的提示词模板,一个好的提示词可以让大模型更加清晰的回答我们的问题,今天我们继续学习,学习SpringAI的格式化输出。
二、Structured Output Converter
1、什么是Structured Output Converter
Structured Output Converter直接翻译过来是 “结构化输出转化器”,顾名思义就是用来辅助大模型结构化输出的。
StructuredOutputConverter是SpringAI为我们提供的一个接口它允许我们从大模型中获取结构化的输出,例如将大模型的返回映射成一个Map、一个Java对象或者是一个List。
2、流程图
从图中我们可以看出StructuredOutputConverter作用于大模型调用前后,StructuredOutputConvertert会把我们原始的输入+结构化提示词一起发送给大模型,当大模型返回后,又会通过Convert方法将其转化为我们所期望的类型。
Tips:
1、StructuredOutputConverte会尽最大努力将大模型的输出转化成我们期望的类型,但是大模型不保证会返回我们所需要的结构化请求。大模型或许没有理解提示词,或者根本就不能产生结构化的输出。考虑实现一种验证机制,以确保模型输出符合预期。
2、StructuredOutputConverte不作用于FunctionCalling,因为FunctionCalling本身就提供了结构化输出的能力。
3、默认提供的Convert
SpringAI为我们默认提供了几个实现分别是:
`AbstractConversionServiceOutputConverter,AbstractMessageOutputConverte, BeanOutputConverter,ListOutputConverter
三、示例代码
案例1:Bean Output Converter
需求:我们使用BeanOutputConvert来格式化大模型的输出;我们希望大模型给我们输出某个演员演的五部电影
1、首先我们定义一个Record:Jdk16新特性
public record ActorsFilms(String actor, List<String> movies) {}
2、编写接口
@GetMapping("/chat")public ActorsFilms chat(String actor) {return client.prompt().user(u -> u.text("生成指定{actor}演的5部电影").param("actor", actor)).call().entity(ActorsFilms.class);}
3、查看结果
{“actor”:“周星驰”,“movies”:[“大话西游”,“喜剧之王”,“少林足球”,“功夫”,“唐伯虎点秋香”]}
可以看到结果已经是JSON格式的了。这里可能会有同学质疑,我们好像并没有使用到BeanOutputConvert,确实在代码里没有直接使用,这个是entity这个方法内部嗲用了,我们查看entity的方法源码,在源码中我们可以看到这里底层使用了BeanOutputConvert
案例2:Property Ordering in Generated Schema
指的是在自动生成的数据模型(如 JSON Schema、XML Schema、API 文档等)中,对属性(字段)进行排序的功能。还是刚才那个例子,
1、我们对record稍加修改
@JsonPropertyOrder({"actor", "movies"})
public record ActorsFilms(String actor, List<String> movies) {}
2、编写接口
@GetMapping("/chat2")
public List<ActorsFilms> chat2(String actor1,String actor2) {return client.prompt().user(u -> u.text("生成{actor1}和{actor2}演的5部电影").param("actor1", actor1).param("actor2", actor2)).call().entity(new ParameterizedTypeReference<List<ActorsFilms>>() {});
}
3、测试
请求url:http://localhost:8080/chat2?actor1=%E5%91%A8%E6%98%9F%E9%A9%B0&actor2=%E6%88%90%E9%BE%99
结果:[{“actor”:“周星驰”,“movies”:[“少林足球”,“功夫”,“喜剧之王”,“唐伯虎点秋香”,“大话西游”]},{“actor”:“成龙”,“movies”:[“警察故事”,“醉拳”,“龙之怒吼”,“尖峰时刻”,“新警察故事”]}]
案例3:Map Output Converter
从名字就可以看出,该Convert的作用是将大模型的输出转换成Map类型,这里不再赘述,直接引用官网的例子。代码
Map<String, Object> result = ChatClient.create(chatModel).prompt().user(u -> u.text("Provide me a List of {subject}").param("subject", "an array of numbers from 1 to 9 under they key name 'numbers'")).call().entity(new ParameterizedTypeReference<Map<String, Object>>() {});
案例4:List Output Converter
这个也很好理解,转化为List,同样不在赘述
List<String> flavors = ChatClient.create(chatModel).prompt().user(u -> u.text("List five {subject}").param("subject", "ice cream flavors")).call().entity(new ListOutputConverter(new DefaultConversionService()));
四、总结
综上,本文围绕 SpringAI 的格式化输出能力展开,核心介绍了StructuredOutputConverter
这一关键接口。它作为连接大模型与结构化输出的桥梁,在调用大模型前后发挥着重要作用:先将原始输入与结构化提示词结合发送给模型,再通过convert
方法将模型返回的原始输出转换为预期类型。
文中还介绍了 SpringAI 默认提供的多种实现类,如BeanOutputConverter
、MapOutputConverter
、ListOutputConverter
等,并通过具体案例展示了它们的用法。例如,BeanOutputConverter
可将输出格式化为指定的 Java 对象(如利用 JDK 16 的 Record 特性定义的数据类),Property Ordering in Generated Schema
功能还能对生成的数据模型属性进行排序,让输出更符合需求。
需要注意的是,StructuredOutputConverter
无法保证大模型一定返回符合预期的结构化结果,可能需要额外的验证机制,且它不适用于本身已支持结构化输出的FunctionCalling
。
通过本文的学习,我们了解到 SpringAI 的格式化输出能力能有效简化大模型输出处理流程,帮助开发者更便捷地获取结构化数据,为 Java 程序员在 AI 开发中处理模型输出提供了实用的工具和思路。