Spring AI 结构化输出详解
一、Spring AI 结构化输出的定义与核心概念
Spring AI 提供了一种强大的功能,允许开发者将大型语言模型(LLM)的输出从字符串转换为结构化格式,如 JSON、XML 或 Java 对象。这种结构化输出能力对于依赖可靠解析输出值的下游应用程序至关重要。
通过 Spring AI 的结构化输出转换器,开发者可以快速将 AI 模型的结果转换为可以传递给其他应用程序函数和方法的数据类型。转换器在 LLM 调用之前将期望的输出格式附加到 prompt 中,为模型提供生成所需输出结构的明确指导。在 LLM 调用之后,转换器获取模型的输出文本并将其转换为结构化类型的实例。

二、结构化输出的技术原理
结构化输出的技术原理可以分为以下几个关键步骤:
-
附加格式说明
在 LLM 调用之前,转换器会将期望的输出格式(output format instruction)附加到 prompt 中。这些指令充当蓝图,塑造模型的响应以符合指定的格式。例如:Your response should be in JSON format. The data structure for the JSON should match this Java class: java.util.HashMap Do not include any explanations, only provide a RFC8259 compliant JSON response following this format without deviation. -
模型生成响应
LLM 根据 prompt 中的格式说明生成符合要求的输出。 -
解析与转换
转换器获取模型的输出文本,并将其解析为结构化类型的实例。此过程涉及将原始文本输出映射到相应的结构化数据表示,如 JSON、XML 或特定于域的数据结构。
三、Spring AI 提供的转换器实现
Spring AI 提供了多种转换器实现,以满足不同的结构化输出需求:
-
BeanOutputConverter
- 使用指定的 Java 类(例如 Bean)或
ParameterizedTypeReference配置。 - 指示 AI 模型生成符合 JSON 模式的响应,随后利用
ObjectMapper将 JSON 输出反序列化为目标类的 Java 对象实例。
- 使用指定的 Java 类(例如 Bean)或
-
MapOutputConverter
- 指导 AI 模型生成符合 RFC8259 的 JSON 响应。
- 包含一个转换器实现,利用提供的
MessageConverter将 JSON 负载转换为java.util.Map<String, Object>实例。
-
ListOutputConverter
- 指导 AI 模型生成逗号分隔的格式化输出。
- 最终转换器将模型文本输出转换为
java.util.List。
四、结构化输出的应用场景
结构化输出技术广泛应用于以下场景:
-
智能助手
将模型输出转换为结构化数据,用于驱动智能助手的应用逻辑。 -
数据分析
将模型生成的分析结果转换为结构化格式,便于后续的数据处理和可视化。 -
内容生成
将模型生成的内容转换为特定的结构化格式,用于内容管理系统或自动化生成报告。
五、结构化输出的实现方式
以下是一些使用 Spring AI 结构化输出的代码示例:
1. 使用 BeanOutputConverter
import com.alibaba.cloud.ai.client.ChatClient;
import com.alibaba.cloud.ai.client.model.ChatModel;
import com.alibaba.cloud.ai.client.output.BeanOutputConverter;public class StructuredOutputExample {public static void main(String[] args) {ChatModel chatModel = ChatModel.create("your-model-id");// 定义目标类record ActorsFilms(String actor, List<String> movies) {}// 创建 BeanOutputConverterBeanOutputConverter<ActorsFilms> beanOutputConverter = new BeanOutputConverter<>(ActorsFilms.class);// 获取格式说明String format = beanOutputConverter.getFormat();// 构建 promptString actor = "Tom Hanks";String template = """Generate the filmography of 5 movies for {actor}.{format}""";// 调用模型Generation generation = chatModel.call(new PromptTemplate(template, Map.of("actor", actor, "format", format)).create()).getResult();// 转换为目标类ActorsFilms actorsFilms = beanOutputConverter.convert(generation.getOutput().getContent());System.out.println("Actor: " + actorsFilms.actor());System.out.println("Movies: " + actorsFilms.movies());}
}
2. 使用 MapOutputConverter
import com.alibaba.cloud.ai.client.ChatClient;
import com.alibaba.cloud.ai.client.model.ChatModel;
import com.alibaba.cloud.ai.client.output.MapOutputConverter;import java.util.Map;public class MapOutputExample {public static void main(String[] args) {ChatModel chatModel = ChatModel.create("your-model-id");// 创建 MapOutputConverterMapOutputConverter mapOutputConverter = new MapOutputConverter();// 构建 promptString subject = "an array of numbers from 1 to 9 under their key name 'numbers'";String prompt = "Provide me a List of " + subject;// 调用模型Generation generation = chatModel.call(new Prompt(prompt)).getResult();// 转换为 MapMap<String, Object> result = mapOutputConverter.convert(generation.getOutput().getContent());System.out.println("Result: " + result);}
}
3. 使用 ListOutputConverter
import com.alibaba.cloud.ai.client.ChatClient;
import com.alibaba.cloud.ai.client.model.ChatModel;
import com.alibaba.cloud.ai.client.output.ListOutputConverter;import java.util.List;public class ListOutputExample {public static void main(String[] args) {ChatModel chatModel = ChatModel.create("your-model-id");// 创建 ListOutputConverterListOutputConverter listOutputConverter = new ListOutputConverter(new DefaultConversionService());// 构建 promptString subject = "ice cream flavors";String prompt = "List five " + subject;// 调用模型Generation generation = chatModel.call(new Prompt(prompt)).getResult();// 转换为 ListList<String> flavors = listOutputConverter.convert(generation.getOutput().getContent());System.out.println("Flavors: " + flavors);}
}
4. 使用 ChatClient 进行结构化输出
import com.alibaba.cloud.ai.client.ChatClient;
import com.alibaba.cloud.ai.client.model.ChatModel;public class ChatClientExample {public static void main(String[] args) {ChatModel chatModel = ChatModel.create("your-model-id");// 定义目标类record ActorsFilms(String actor, List<String> movies) {}// 使用 ChatClient 转换为 ActorsFilms 对象ActorsFilms actorsFilms = ChatClient.create(chatModel).prompt().user(u -> u.text("Generate the filmography of 5 movies for {actor}.").param("actor", "Tom Hanks")).call().entity(ActorsFilms.class);System.out.println("Actor: " + actorsFilms.actor());System.out.println("Movies: " + actorsFilms.movies());}
}
六、结构化输出的未来发展方向
-
多模态输出
结合文本、图像、音频等多种模态数据,提升输出的多样性和准确性。 -
实时转换
提高转换器的实时性,支持更快速的输出解析和转换。 -
领域特定转换
针对特定领域(如医疗、法律)提供定制化的结构化输出转换器。 -
自动化优化
通过机器学习技术自动优化转换器的性能和准确性。
七、总结
Spring AI 的结构化输出功能为开发者提供了一种强大的工具,可以将 LLM 的输出转换为结构化格式,从而满足下游应用程序的需求。通过使用 Spring AI 提供的转换器实现,开发者可以轻松地将模型输出转换为 JSON、XML 或 Java 对象,提高开发效率和应用可靠性。随着技术的不断发展,结构化输出将在更多领域发挥重要作用,为开发者提供更多智能化的解决方案。
相关文章:
Spring AI 结构化输出详解
一、Spring AI 结构化输出的定义与核心概念 Spring AI 提供了一种强大的功能,允许开发者将大型语言模型(LLM)的输出从字符串转换为结构化格式,如 JSON、XML 或 Java 对象。这种结构化输出能力对于依赖可靠解析输出值的下游应用程…...
spring security oauth2.0的四种模式
OAuth 2.0 定义了 4 种授权模式(Grant Type),用于不同场景下的令牌获取。以下是每种模式的详细说明、适用场景和对比: 一、授权码模式(Authorization Code Grant) 适用场景 • Web 应用(有后端…...
从零开始的C++编程 2(类和对象下)
目录 1.构造函数初始化列表 2.类型转换 3.static成员 4.友元 5.内部类 6.匿名对象 1.构造函数初始化列表 ①之前我们实现构造函数时,初始化成员变量主要使⽤函数体内赋值,构造函数初始化还有⼀种⽅式,就是初始化列表,初始化…...
Vue 项目中 package.json 文件的深度解析
Vue 项目中 package.json 文件的深度解析 在 Vue 项目中,package.json 文件是项目配置的核心,它管理着项目的依赖关系、脚本命令、版本信息等重要内容。正确理解和配置 package.json 文件,对于项目的开发、构建、测试和部署都至关重要。本文…...
将三维非平面点集拆分为平面面片的MATLAB实现
将三维非平面点集拆分为平面面片的MATLAB实现 要将三维空间中不在同一平面上的点集拆分为多个平面面片,可以采用以下几种方法: 1. 三角剖分法 (Delaunay Triangulation) 最简单的方法是将点集进行三角剖分,因为三个点总是共面的࿱…...
AI结合VBA提升EXCEL办公效率尝试
文章目录 前言一、开始VBA编程二、主要代码三、添加到所有EXCEL四、运行效果五、AI扩展 前言 EXCEL右击菜单添加一个选项,点击执行自己逻辑的功能。 然后让DeepSeek帮我把我的想法生成VBA代码 一、开始VBA编程 我的excel主菜单没有’开发工具‘ 选项,…...
基于单片机的电梯智能识别电动车阻车系统设计与实现
标题:基于单片机的电梯智能识别电动车阻车系统设计与实现 内容:1.摘要 随着电动车在日常生活中的普及,将电动车带入电梯带来的安全隐患日益凸显,如引发火灾等。本研究的目的是设计并实现一种基于单片机的电梯智能识别电动车阻车系统。方法上,…...
Python快速入门指南:从零开始掌握Python编程
文章目录 前言一、Python环境搭建🥏1.1 安装Python1.2 验证安装1.3 选择开发工具 二、Python基础语法📖2.1 第一个Python程序2.2 变量与数据类型2.3 基本运算 三、Python流程控制🌈3.1 条件语句3.2 循环结构 四、Python数据结构🎋…...
Java——数据类型与变量
文章目录 字面常量Java数据类型变量定义变量的方式整形变量长整型变量短整型变量字节型变量浮点型变量双精度浮点型单精度浮点型 字符型变量布尔型变量 类型转换自动类型转换(隐式)强制类型转换(显式) 类型提升byte与byte的运算 字…...
9. C++STL详解vector的使用以及模拟实现
文章目录 一、vector的使用介绍1.1 vector的定义1.2 vector iterator 的使用1.3 vector 增删查改二、vector 迭代器失效问题会引起其底层空间改变的操作,都有可能是迭代器失效,比如:resize、reserve、insert、assign、push_back等。指定位置元…...
C/C++调用Python程序代码实现混合编程笔记教程
0、引言 Python在基础开发、数据科学、人工智能、Web框架开发等领域具有广泛的支持工具和开发教程,极大的缩短了产品原型开发周期、降低了开发难度。 有许多的功能,通过C/C实现,非常的复杂并且不方便,但是Python可能就是几行代码…...
LeetCode hot 100—子集
题目 给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 示例 示例 1: 输入:nums [1,2,3] 输出:[[],[1],[2…...
Linux网络编程——数据链路层详解,以太网、MAC地址、MTU、ARP、DNS、NAT、代理服务器......
目录 一、前言 二、以太网 二、以太网帧格式 三、 MAC地址 四、MTU 1、数据链路层的数据分片 2、MTU对UDP协议的影响 3、MTU对TCP协议的影响 五、ARP协议 1、什么是ARP 2、ARP的作用 3、ARP协议的工作流程 4、ARP缓存表 5、ARP请求报文 6、中间人 六、DNS&…...
MySQL 5.7.30 Linux 二进制安装包详解及安装指南
MySQL 5.7.30 Linux 安装包详解 mysql-5.7.30-linux-glibc2.12-x86_64.tar 是 MySQL 服务器 5.7.30 版本的 Linux 二进制发行包。 mysql-5.7.30-linux-glibc2.12-x86_64.tar 安装包下载 链接:https://pan.quark.cn/s/2943cd209ca5 包信息 版本: MySQL 5.7.30 平…...
基于springboot+vue的秦皇岛旅游景点管理系统
开发语言:Java框架:springbootJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包:Maven3.3.9 系统展示 用户登录 旅游路…...
Linux网络编程——TCP通信的四次挥手
一、前言 上篇文章讲到了TCP通信建立连接的“三次握手”的一些细节,本文再对TCP通信断开连接的“四次挥手”的过程做一些分析了解。 二、TCP断开连接的“四次挥手” 我们知道TCP在建立连接的时需要“三次握手”,三次握手完后就可以进行通信了。而在通…...
634SJBH苏州旅游网站
1 绪论 1.1 课题的提出、研究现状及研究意义 旅游业具有“无烟产业”和“永远的朝阳产业”的美称,它已经和石油业、汽车业并列为世界三大产业;根据WTTC的统计,它每年产出4.7万亿美金的收入,直接或间接地为2亿700万人提供了就业机…...
计算机视觉算法实现——SAM实例分割:原理、实现与应用全景
✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连✨ 1. 实例分割领域概述 实例分割(Instance Segmentation)是计算机视觉领域最具挑战性的任务之一,…...
基于SpringBoot的宠物健康咨询系统(源码+数据库+万字文档)
502基于SpringBoot的宠物健康咨询系统,系统包含三种角色:管理员、用户,顾问主要功能如下。 【用户功能】 1. 首页:查看系统主要信息和最新动态。 2. 公告:浏览系统发布的公告信息。 3. 顾问:浏览可提供咨询…...
vue2 el-element中el-select选中值,数据已经改变但选择框中不显示值,需要其他输入框输入值才显示这个选择框才会显示刚才选中的值
项目场景: <el-table-column label"税率" prop"TaxRate" width"180" align"center" show-overflow-tooltip><template slot-scope"{row, $index}"><el-form-item :prop"InquiryItemList. …...
pgsql:关联查询union(并集)、except(差集)、intersect(交集)
pgsql:关联查询union(并集)、except(差集)、intersect(交集)_pgsql except-CSDN博客...
CCF CSP 第35次(2024.09)(2_字符串变换_C++)(哈希表+getline)
CCF CSP 第35次(2024.09)(2_字符串变换_C) 解题思路:思路一(哈希表getline): 代码实现代码实现(思路一(哈希表getline)): …...
PostgreSQL 的 COPY 命令
PostgreSQL 的 COPY 命令 PostgreSQL 的 COPY 命令是高效数据导入导出的核心工具,性能远超常规 INSERT 语句。以下是 COPY 命令的深度解析: 一 COPY 命令基础 1.1 基本语法对比 命令类型语法示例执行位置文件访问权限服务器端COPYCOPY table FROM /p…...
Docker--利用dockerfile搭建mysql主从集群和redis集群
Docker镜像制作的命令 链接 Docker 镜像制作的注意事项 链接 搭建mysql主从集群 mysql主从同步的原理 MySQL主从同步(Replication)是一种实现数据冗余和高可用性的技术,通过将主数据库(Master)的变更操作同步到一个…...
Context的全面解析:在不同技术应用中的通用作用与差异
Context的全面解析:在不同技术应用中的通用作用与差异 引言: 在软件开发中,“Context”这个概念被广泛使用。它不仅限于某个特定的技术或编程语言,实际上,Context 作为一种抽象的设计模式,贯穿在许多开发领…...
蓝桥杯嵌入式考前模块总结
一.RTC 使用RTC直接再cubeMX中配置启动时钟和日历 如第六届省赛 想要让RTC的秒每隔一秒递增1需要在时钟树界面观察RTC的主频 由于RTC时钟主频为32KHZ将异步预分频计数器的值设为31,将同步预分频计数器的值设为999这样就可以将RTC的时钟信号分频为1HZ达到1秒自增的…...
关于举办“2025年第五届全国大学生技术创新创业大赛“的通知
赛事含金量 大赛获奖即可有机会为你的大学里的“创新创业”加分!这是每个大学要求必须修满的学分! 中国“互联网+”大学生创新创业大赛磨刀赛!“挑战杯”中国大学生创业计划大赛必参赛! 国赛获奖,“互联…...
spark安装过程问题
1. Spark-local模式 - 适用于单节点环境,无需启动Hadoop集群。 - 实验步骤包括解压文件、启动Local环境、运行命令行工具、提交测试应用等。 - 通过bin/spark-shell启动本地环境,通过sc.textFile等命令测试功能。 - 提交应用时使用--master loca…...
Ingress蓝绿发布
Ingress蓝绿发布 Ingress常用注解说明yaml资源清单绿色版本yml资源清单蓝色版本yaml资源清单 主Ingress金丝雀Ingress基于客户端请求头的流量切分结果验证 基于客户端来源IP的流量切分结果验证 基于服务权重的流量切分结果验证 基于IP来源区域来切分IP---方案未验证基于User-Ag…...
基于AOP+Log4Net+AutoFac日志框架
1.项目概述 这是一个基于 C# 的 WPF 项目 WpfApp12log4net,它综合运用了依赖注入、日志记录和接口实现等多种技术,同时使用了 Autofac、Castle.Core 和 log4net 等第三方库。 2.配置log4net 新建一个Log4Net.config,配置需要记录的日志信息…...
