微信扫码
添加专属顾问
我要投稿
Spring AI让Java开发者轻松实现结构化输出,直接获取对象响应,提升开发效率。 核心内容: 1. Spring AI结构化输出的原理与实现方式 2. 实战演示如何响应entity、List、Map对象 3. 完整代码示例与配置指南
Java作为面向对象语言,如果Spring AI调用模型可以直接响应对象,对于依赖可靠输入值的下游应用程序非常重要,Spring AI提供了可以直接响应entity的配置。
本节我们将实现Spring AI 结构化输出entity、List、Map对象。
搭建SpringBoot项目、添加SpringAI依赖、配置Open AI参数,请大家直接看Spring AI入门这篇。
因为众所周知的原因,我们不能直接访问国外网站。如果有需要Open AI 代理地址,请关注公众号,点击菜单apikey 免费获取!
开始调用之前,我们先创建ChatController类,然后注入ChatClient,Spring AI框架已将ChatModel注入到ChatClient中,所以这里我们不需要对模型进行任何配置。
@RestController
public class ChatController {
private final ChatClient chatClient;
public ChatController(ChatClient.Builder chatClientBuilder) {
this.chatClient = chatClientBuilder.build();
}
}
由于本节我们将响应entity对象,这里在ChatController中创建一个对象,该对象仅有两个属性:String actor
演员名称List<String> movies
出演的电影列表
// record是Java 14引入的一个新特性,用于创建不可变的数据载体类。
// 它简化了创建简单数据类的过程,自动提供了equals、hashCode、toString等方法的实现。
record ActorFilms(String actor, List<String> movies) {}
这里我们创建一个get方法,接收一个userInput参数。
@RestController
public class ChatController {
...
@GetMapping("/entity")
ActorFilms entity(String userInput) {
return this.chatClient.prompt()
.user(userInput)
.call()
.entity(ActorFilms.class);
}
}
这里SpringAI进行了更高等级的封装,无法从代码直观感受到结构化输出的原理。下面使用更底层的原子API来实现同样的响应。
@RestController
publicclassChatController {
...
@GetMapping("/originEntity")
ActorFilms originEntity(String userInput) {
// 创建bean输出转换器
BeanOutputConverter<ActorFilms> beanOutputConverter =
newBeanOutputConverter<>(ActorFilms.class);
// 获取bean对象格式指令
Stringformat= beanOutputConverter.getFormat();
// 将指令、用户输入传入chatClient,然后调用模型,获取模型输出
Stringoutput=this.chatClient.prompt(format)
.user(userInput)
.call()
.content();
// 将模型输出转换成bean对象
ActorFilmsactorsFilms= beanOutputConverter.convert(output);
return actorsFilms;
}
}
这里我们在浏览器发送get请求http://localhost:8080/entity?userInput=列出成龙出演的电影
或http://localhost:8080/originEntity?userInput=列出成龙出演的电影
Spring AI还提供了重载的entity方法,签名是`entity(ParameterizedTypeReference type)``,允许指定诸如泛型列表等类型。
@RestController
public class ChatController {
...
@GetMapping("/entityList")
List<ActorFilms> entityList(String userInput) {
List<ActorFilms> actorFilms = chatClient.prompt()
.user(userInput)
.call()
.entity(new ParameterizedTypeReference<List<ActorFilms>>() {});
return actorFilms;
}
}
这里我们在浏览器发送一个get请求http://localhost:8080/entityList?userInput=列出周星驰、周润发、成龙出演的电影
这里就不再展示原子API的写法了,就是将new BeanOutputConverter<>(ActorFilms.class);
改为new BeanOutputConverter<>(new ParameterizedTypeReference<List<ActorFilms>>() {});
不再赘述
既然提供了 List 的响应,那么Map也必然不可少。
@RestController
publicclassChatController {
...
// 响应Map<String, Object>对象
@GetMapping("/mapEntity")
Map<String, Object> mapEntity() {
Map<String, Object> result = this.chatClient.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(newParameterizedTypeReference<Map<String, Object>>() {
});
return result;
}
}
浏览器发送get请求:http://localhost:8080/mapEntity
如果使用原子API,则需要将转换器改为new MapOutputConverter();
,表明我们要求输出的是一个Map类型。
上面的接口都是同步响应,这是由于结构化输出的原理决定的,全部数据响应完,数据结构才完整,才能进行最后一步文本转结构化。
目前SpringAI流式响应,只能使用更底层的原子 API,使用方式如下:
@RestController
publicclassChatController {
...
@GetMapping("/entityListStream")
List<ActorFilms> entityListStream(String userInput) {
varconverter=newBeanOutputConverter<>(newParameterizedTypeReference<List<ActorFilms>>() {});
Flux<String> flux = this.chatClient.prompt(converter.getFormat())
.user(userInput)
.stream()
.content();
Stringcontent= flux.collectList().block().stream().collect(Collectors.joining());
List<ActorFilms> actorFilms = converter.convert(content);
return actorFilms;
}
}
这里我们在浏览器发送一个get请求http://localhost:8080/entityListStream?userInput=列出周星驰、周润发、成龙出演的电影
结构化输出是大模型开发不能避免的环节,Spring AI的封装帮助程序员节省大量时间,致使大模型为下游程序、函数提供可靠输入,当然理解其原理我们才能更灵活掌握结构化输出用法。
53AI,企业落地大模型首选服务商
产品:场景落地咨询+大模型应用平台+行业解决方案
承诺:免费场景POC验证,效果验证后签署服务协议。零风险落地应用大模型,已交付160+中大型企业
2025-06-16
简单说,AI搜索是普通人变强的超级外挂
2025-06-16
零基础解码Transformer与大模型核心原理
2025-06-16
采购DeepSeek API成本对比与本地部署
2025-06-16
ClackyAI:用云端 Agent 开启 Coding 下一站
2025-06-16
OpenAI o3-pro发布,也许当前的RAG过时了...
2025-06-16
基于Dify构建客服智能体全流程实战,揭秘提升RAG效果关键
2025-06-16
大模型+智能体赋能:打造新一代智能告警处置体系
2025-06-16
Function Calling(函数调用):解锁大语言模型的潜力
2025-05-29
2025-03-20
2025-03-21
2025-04-11
2025-03-20
2025-03-19
2025-03-20
2025-03-19
2025-03-19
2025-03-19