当前位置: 首页 > news >正文

005-Spring AI Alibaba Structured Output 功能完整案例

本案例将引导您一步步构建一个 Spring Boot 应用,演示如何利用 Spring AI Alibaba 的 Structured Output 功能,实现将大模型输出转换为结构化数据(如 Java Bean、JSON、Map 和 List)。

1. 案例目标

我们将创建一个包含多个结构化输出功能的 Web 应用:

  1. Java Bean 输出 (/bean/*):将大模型输出转换为指定的 Java Bean 对象。
  2. JSON 格式输出 (/json/*):使用 DashScope 的 JSON 模式,确保输出为有效的 JSON 格式。
  3. Map 和 List 输出 (/map-list/*):将大模型输出转换为 Map 或 List 集合。

2. 技术栈与核心依赖

  • Spring Boot 3.x
  • Spring AI Alibaba (用于对接阿里云 DashScope 通义大模型)
  • Maven (项目构建工具)

在 pom.xml 中,你需要引入以下核心依赖:

<dependencies><!-- Spring AI Alibaba 核心启动器,集成 DashScope --><dependency><groupId>com.alibaba.cloud.ai</groupId><artifactId>spring-ai-alibaba-starter-dashscope</artifactId></dependency><!-- Spring Web 用于构建 RESTful API --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>
</dependencies>

3. 项目配置

在 src/main/resources/application.yml 文件中,配置你的 DashScope API Key 和响应格式。

server:port: 10007spring:application:name: spring-ai-alibaba-structured-exampleai:dashscope:api-key: ${AI_DASHSCOPE_API_KEY}chat:response-format: json

重要提示:请将 AI_DASHSCOPE_API_KEY 环境变量设置为你从阿里云获取的有效 API Key。配置中的 response-format: json 表示默认使用 JSON 格式响应。

4. 定义实体类

首先,我们定义一个用于接收结构化输出的实体类 BeanEntity

package com.alibaba.cloud.ai.example.outparser.entity;import com.fasterxml.jackson.annotation.JsonPropertyOrder;@JsonPropertyOrder({"title", "date", "author", "content"}) // 指定属性的顺序
public class BeanEntity {private String title;private String author;private String date;private String content;public BeanEntity() {}// Getter 和 Setter 方法public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}public String getAuthor() {return author;}public void setAuthor(String author) {this.author = author;}public String getDate() {return date;}public void setDate(String date) {this.date = date;}public String getContent() {return content;}public void setContent(String content) {this.content = content;}@Overridepublic String toString() {return "StreamToBeanEntity{" +"title='" + title + '\'' +", author='" + author + '\'' +", date='" + date + '\'' +", content='" + content + '\'' +'}';}
}

5. 编写控制器代码

5.1 BeanController.java - Java Bean 输出

实现将大模型输出转换为 Java Bean 对象的功能。

package com.alibaba.cloud.ai.example.outparser.controller;import com.alibaba.cloud.ai.example.outparser.entity.BeanEntity;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.prompt.PromptTemplate;
import org.springframework.ai.converter.BeanOutputConverter;
import org.springframework.ai.template.st.StTemplateRenderer;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;import java.util.Map;
import java.util.Objects;@RestController
@RequestMapping("/bean")
public class BeanController {private static final Logger log = LoggerFactory.getLogger(BeanController.class);private final ChatClient chatClient;private final ChatModel chatModel;private final BeanOutputConverter<BeanEntity> converter;private final String format;public BeanController(ChatClient.Builder builder, ChatModel chatModel) {this.chatModel = chatModel;this.converter = new BeanOutputConverter<>(new ParameterizedTypeReference<BeanEntity>() {});this.format = converter.getFormat();log.info("format: {}", format);this.chatClient = builder.build();}@GetMapping("/chat")public String simpleChat(@RequestParam(value = "query", defaultValue = "以影子为作者,写一篇200字左右的有关人工智能诗篇") String query) {String result = chatClient.prompt(query).call().content();log.info("result: {}", result);assert result != null;try {BeanEntity convert = converter.convert(result);log.info("反序列成功,convert: {}", convert);} catch (Exception e) {log.error("反序列化失败");}return result;}@GetMapping("/chat-format")public BeanEntity simpleChatFormat(@RequestParam(value = "query", defaultValue = "以影子为作者,写一篇200字左右的有关人工智能诗篇") String query) {return chatClient.prompt(query).call().entity(BeanEntity.class);}@GetMapping("/chat-model-format")public String chatModel(@RequestParam(value = "query", defaultValue = "以影子为作者,写一篇200字左右的有关人工智能诗篇") String query) {String template = query + "{format}";PromptTemplate promptTemplate = PromptTemplate.builder().template(template).variables(Map.of("format", format)).renderer(StTemplateRenderer.builder().build()).build();Prompt prompt = promptTemplate.create();String result = chatModel.call(prompt).getResult().getOutput().getText();log.info("result: {}", result);assert result != null;try {BeanEntity convert = converter.convert(result);log.info("反序列成功,convert: {}", convert);} catch (Exception e) {log.error("反序列化失败");}return result;}/*** @return {@link BeanEntity}*/@GetMapping("/play")public BeanEntity simpleChat(HttpServletResponse response) {Flux<String> flux = this.chatClient.prompt().user(u -> u.text("""requirement: 请用大概 120 字,作者为 牧生 ,为计算机的发展历史写一首现代诗;format: 以纯文本输出 json,请不要包含任何多余的文字——包括 markdown 格式;outputExample: {"title": {title},"author": {author},"date": {date},"content": {content}};""")).stream().content();String result = String.join("\n", Objects.requireNonNull(flux.collectList().block())).replaceAll("\\n", "").replaceAll("\\s+", " ").replaceAll("\"\\s*:", "\":").replaceAll(":\\s*\"", ":\"");log.info("LLMs 响应的 json 数据为:{}", result);return converter.convert(result);}
}

5.2 JsonController.java - JSON 格式输出

实现使用 DashScope 的 JSON 模式,确保输出为有效的 JSON 格式。

package com.alibaba.cloud.ai.example.outparser.controller;import com.alibaba.cloud.ai.dashscope.api.DashScopeResponseFormat;
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatOptions;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/json")
public class JsonController {private final ChatClient chatClient;private final DashScopeResponseFormat responseFormat;public JsonController(ChatClient.Builder builder) {// AI模型内置支持JSON模式DashScopeResponseFormat responseFormat = new DashScopeResponseFormat();responseFormat.setType(DashScopeResponseFormat.Type.JSON_OBJECT);this.responseFormat = responseFormat;this.chatClient = builder.build();}@GetMapping("/chat")public String simpleChat(@RequestParam(value = "query", defaultValue = "请以JSON格式介绍你自己") String query) {return chatClient.prompt(query).call().content();}@GetMapping("/chat-format")public String simpleChatFormat(@RequestParam(value = "query", defaultValue = "请以JSON格式介绍你自己") String query) {return chatClient.prompt(query).options(DashScopeChatOptions.builder().withTopP(0.7).withResponseFormat(responseFormat).build()).call().content();}
}

5.3 MapListController.java - Map 和 List 输出

实现将大模型输出转换为 Map 或 List 集合的功能。

package com.alibaba.cloud.ai.example.outparser.controller;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.ChatClientAttributes;
import org.springframework.ai.converter.ListOutputConverter;
import org.springframework.ai.converter.MapOutputConverter;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import java.util.List;
import java.util.Map;@RestController
@RequestMapping("/map-list")
public class MapListController {private static final Logger log = LoggerFactory.getLogger(BeanController.class);private final ChatClient chatClient;private final MapOutputConverter mapConverter;private final ListOutputConverter listConverter;public MapListController(ChatClient.Builder builder) {// map转换器this.mapConverter = new MapOutputConverter();// list转换器this.listConverter = new ListOutputConverter(new DefaultConversionService());this.chatClient = builder.build();}@GetMapping("/chatMap")public Map<String, Object> chatMap(@RequestParam(value = "query", defaultValue = "请为我描述下影子的特性") String query) {return chatClient.prompt(query).advisors(a -> a.param(ChatClientAttributes.OUTPUT_FORMAT.getKey(), mapConverter.getFormat())).call().entity(mapConverter);}@GetMapping("/chatList")public List<String> chatList(@RequestParam(value = "query", defaultValue = "请为我描述下影子的特性") String query) {return chatClient.prompt(query).advisors(a -> a.param(ChatClientAttributes.OUTPUT_FORMAT.getKey(), listConverter.getFormat())).call().entity(listConverter);}
}

6. 运行与测试

  1. 启动应用:运行你的 Spring Boot 主程序。
  2. 使用浏览器或 API 工具(如 Postman, curl)进行测试

测试 1:Java Bean 输出

访问以下 URL,测试基本对话功能:

GET http://localhost:10007/bean/chat

访问以下 URL,测试格式化输出为 Java Bean:

GET http://localhost:10007/bean/chat-format

访问以下 URL,测试使用 ChatModel 格式化输出:

GET http://localhost:10007/bean/chat-model-format

访问以下 URL,测试流式输出并转换为 Bean:

GET http://localhost:10007/bean/play

测试 2:JSON 格式输出

访问以下 URL,测试基本 JSON 输出:

GET http://localhost:10007/json/chat

访问以下 URL,测试使用 DashScope 的 JSON 模式:

GET http://localhost:10007/json/chat-format

测试 3:Map 和 List 输出

访问以下 URL,测试输出为 Map:

GET http://localhost:10007/map-list/chatMap

访问以下 URL,测试输出为 List:

GET http://localhost:10007/map-list/chatList

7. 实现思路与扩展建议

实现思路

本案例的核心思想是"结构化输出转换"。我们将大模型的非结构化文本输出转换为结构化数据对象,这使得:

  • 数据一致性高:通过预定义的结构,确保输出数据的一致性和可预测性。
  • 易于集成:结构化数据可以轻松集成到现有的业务系统中。
  • 类型安全:使用强类型的 Java 对象,减少运行时错误。

扩展建议

  • 自定义输出转换器:可以根据业务需求,实现自定义的输出转换器,支持更复杂的数据结构。
  • 输出验证:添加输出验证机制,确保转换后的数据符合业务规则。
  • 多格式支持:扩展支持更多输出格式,如 XML、YAML 等。
  • 错误处理:增强错误处理机制,当输出无法正确转换时提供有意义的错误信息。
  • 性能优化:对于大规模数据转换,可以考虑使用缓存或批量处理来提高性能。
http://www.dtcms.com/a/533371.html

相关文章:

  • 私密性最好的浏览器营销网站优化推广
  • 电商网页精品欣赏网站企业管理培训课程机构
  • 中国住房建设网官方网站博客主题 wordpress
  • TVM | TupleNode / TupleGetItemNode
  • 什么做网站统计好杭州百度网站建设
  • 一流的网站建设与优化wordpress更改上传
  • now9999网站提示建设中网站制作怎么做下拉菜单
  • 深度学习周报(10.20~10.26)
  • 通用抓取算法AnyGrasp(Graspnet)——本地部署并测试自定义输入数据
  • 1.2.2 大数据方法论与实践指南-数据助力业务场景
  • php做的直播网站烟台网站制作这
  • 1.模拟算法
  • 昆明优化网站wordpress用户注册插件
  • 若依框架学习Day02:功能改造与问题攻坚实战
  • 如何建设销售型企业网站锦州哪家做网站
  • 二叉树的最大深度-力扣
  • 悟空建站seo服务电商网站 网站服务内容
  • 域名打不开原来的网站官网域名改版方案
  • importlib.import_module(module).__dict__[class_name]
  • 宁波企业网站制作河南优化网站
  • 媒体网站 建设网络强国网站推广软件app
  • 三维视觉:原理与实践(课程笔记-相机模型与标定)
  • C++进阶:(一)深入理解继承机制
  • 南通网站建设服务公司公司签约网站
  • 网站后台开发做什么网站主体负责人能查询到吗
  • chp04【组队学习】Post-training-of-LLMs
  • 摄像机数据对象存储S3测试 之RustFS
  • web识别开发,在线%老版本图像识别和分类%系统开发,基于html,css,jquery,python,flask,cnn,opencv,无数据库
  • Vue项目配置cdn
  • 网站开发与设计岗位职责网线制作工具有哪些