Spring AI 结构化输出详解

news2025/4/13 6:07:52
一、Spring AI 结构化输出的定义与核心概念

Spring AI 提供了一种强大的功能,允许开发者将大型语言模型(LLM)的输出从字符串转换为结构化格式,如 JSON、XML 或 Java 对象。这种结构化输出能力对于依赖可靠解析输出值的下游应用程序至关重要。

通过 Spring AI 的结构化输出转换器,开发者可以快速将 AI 模型的结果转换为可以传递给其他应用程序函数和方法的数据类型。转换器在 LLM 调用之前将期望的输出格式附加到 prompt 中,为模型提供生成所需输出结构的明确指导。在 LLM 调用之后,转换器获取模型的输出文本并将其转换为结构化类型的实例。
在这里插入图片描述

二、结构化输出的技术原理

结构化输出的技术原理可以分为以下几个关键步骤:

  1. 附加格式说明
    在 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.
    
  2. 模型生成响应
    LLM 根据 prompt 中的格式说明生成符合要求的输出。

  3. 解析与转换
    转换器获取模型的输出文本,并将其解析为结构化类型的实例。此过程涉及将原始文本输出映射到相应的结构化数据表示,如 JSON、XML 或特定于域的数据结构。

三、Spring AI 提供的转换器实现

Spring AI 提供了多种转换器实现,以满足不同的结构化输出需求:

  1. BeanOutputConverter

    • 使用指定的 Java 类(例如 Bean)或 ParameterizedTypeReference 配置。
    • 指示 AI 模型生成符合 JSON 模式的响应,随后利用 ObjectMapper 将 JSON 输出反序列化为目标类的 Java 对象实例。
  2. MapOutputConverter

    • 指导 AI 模型生成符合 RFC8259 的 JSON 响应。
    • 包含一个转换器实现,利用提供的 MessageConverter 将 JSON 负载转换为 java.util.Map<String, Object> 实例。
  3. ListOutputConverter

    • 指导 AI 模型生成逗号分隔的格式化输出。
    • 最终转换器将模型文本输出转换为 java.util.List
四、结构化输出的应用场景

结构化输出技术广泛应用于以下场景:

  1. 智能助手
    将模型输出转换为结构化数据,用于驱动智能助手的应用逻辑。

  2. 数据分析
    将模型生成的分析结果转换为结构化格式,便于后续的数据处理和可视化。

  3. 内容生成
    将模型生成的内容转换为特定的结构化格式,用于内容管理系统或自动化生成报告。

五、结构化输出的实现方式

以下是一些使用 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) {}

        // 创建 BeanOutputConverter
        BeanOutputConverter<ActorsFilms> beanOutputConverter = new BeanOutputConverter<>(ActorsFilms.class);

        // 获取格式说明
        String format = beanOutputConverter.getFormat();

        // 构建 prompt
        String 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");

        // 创建 MapOutputConverter
        MapOutputConverter mapOutputConverter = new MapOutputConverter();

        // 构建 prompt
        String 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();

        // 转换为 Map
        Map<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");

        // 创建 ListOutputConverter
        ListOutputConverter listOutputConverter = new ListOutputConverter(new DefaultConversionService());

        // 构建 prompt
        String subject = "ice cream flavors";
        String prompt = "List five " + subject;

        // 调用模型
        Generation generation = chatModel.call(new Prompt(prompt)).getResult();

        // 转换为 List
        List<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());
    }
}
六、结构化输出的未来发展方向
  1. 多模态输出
    结合文本、图像、音频等多种模态数据,提升输出的多样性和准确性。

  2. 实时转换
    提高转换器的实时性,支持更快速的输出解析和转换。

  3. 领域特定转换
    针对特定领域(如医疗、法律)提供定制化的结构化输出转换器。

  4. 自动化优化
    通过机器学习技术自动优化转换器的性能和准确性。

七、总结

Spring AI 的结构化输出功能为开发者提供了一种强大的工具,可以将 LLM 的输出转换为结构化格式,从而满足下游应用程序的需求。通过使用 Spring AI 提供的转换器实现,开发者可以轻松地将模型输出转换为 JSON、XML 或 Java 对象,提高开发效率和应用可靠性。随着技术的不断发展,结构化输出将在更多领域发挥重要作用,为开发者提供更多智能化的解决方案。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2333601.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

从零开始的C++编程 2(类和对象下)

目录 1.构造函数初始化列表 2.类型转换 3.static成员 4.友元 5.内部类 6.匿名对象 1.构造函数初始化列表 ①之前我们实现构造函数时&#xff0c;初始化成员变量主要使⽤函数体内赋值&#xff0c;构造函数初始化还有⼀种⽅式&#xff0c;就是初始化列表&#xff0c;初始化…

AI结合VBA提升EXCEL办公效率尝试

文章目录 前言一、开始VBA编程二、主要代码三、添加到所有EXCEL四、运行效果五、AI扩展 前言 EXCEL右击菜单添加一个选项&#xff0c;点击执行自己逻辑的功能。 然后让DeepSeek帮我把我的想法生成VBA代码 一、开始VBA编程 我的excel主菜单没有’开发工具‘ 选项&#xff0c;…

Python快速入门指南:从零开始掌握Python编程

文章目录 前言一、Python环境搭建&#x1f94f;1.1 安装Python1.2 验证安装1.3 选择开发工具 二、Python基础语法&#x1f4d6;2.1 第一个Python程序2.2 变量与数据类型2.3 基本运算 三、Python流程控制&#x1f308;3.1 条件语句3.2 循环结构 四、Python数据结构&#x1f38b;…

Java——数据类型与变量

文章目录 字面常量Java数据类型变量定义变量的方式整形变量长整型变量短整型变量字节型变量浮点型变量双精度浮点型单精度浮点型 字符型变量布尔型变量 类型转换自动类型转换&#xff08;隐式&#xff09;强制类型转换&#xff08;显式&#xff09; 类型提升byte与byte的运算 字…

9. C++STL详解vector的使用以及模拟实现

文章目录 一、vector的使用介绍1.1 vector的定义1.2 vector iterator 的使用1.3 vector 增删查改二、vector 迭代器失效问题会引起其底层空间改变的操作&#xff0c;都有可能是迭代器失效&#xff0c;比如&#xff1a;resize、reserve、insert、assign、push_back等。指定位置元…

C/C++调用Python程序代码实现混合编程笔记教程

0、引言 Python‌在基础开发、数据科学、人工智能、Web框架开发等领域具有广泛的支持工具和开发教程&#xff0c;极大的缩短了产品原型开发周期、降低了开发难度。 有许多的功能&#xff0c;通过C/C实现&#xff0c;非常的复杂并且不方便&#xff0c;但是Python可能就是几行代码…

LeetCode hot 100—子集

题目 给你一个整数数组 nums &#xff0c;数组中的元素 互不相同 。返回该数组所有可能的子集&#xff08;幂集&#xff09;。 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 示例 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&#xff1a;[[],[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&…

基于springboot+vue的秦皇岛旅游景点管理系统

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;Maven3.3.9 系统展示 用户登录 旅游路…

Linux网络编程——TCP通信的四次挥手

一、前言 上篇文章讲到了TCP通信建立连接的“三次握手”的一些细节&#xff0c;本文再对TCP通信断开连接的“四次挥手”的过程做一些分析了解。 二、TCP断开连接的“四次挥手” 我们知道TCP在建立连接的时需要“三次握手”&#xff0c;三次握手完后就可以进行通信了。而在通…

计算机视觉算法实现——SAM实例分割:原理、实现与应用全景

✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连✨ ​​​ ​​​​​​​​​ ​​ 1. 实例分割领域概述 实例分割(Instance Segmentation)是计算机视觉领域最具挑战性的任务之一&#xff0c…

基于SpringBoot的宠物健康咨询系统(源码+数据库+万字文档)

502基于SpringBoot的宠物健康咨询系统&#xff0c;系统包含三种角色&#xff1a;管理员、用户&#xff0c;顾问主要功能如下。 【用户功能】 1. 首页&#xff1a;查看系统主要信息和最新动态。 2. 公告&#xff1a;浏览系统发布的公告信息。 3. 顾问&#xff1a;浏览可提供咨询…

vue2 el-element中el-select选中值,数据已经改变但选择框中不显示值,需要其他输入框输入值才显示这个选择框才会显示刚才选中的值

项目场景&#xff1a; <el-table-column label"税率" prop"TaxRate" width"180" align"center" show-overflow-tooltip><template slot-scope"{row, $index}"><el-form-item :prop"InquiryItemList. …

CCF CSP 第35次(2024.09)(2_字符串变换_C++)(哈希表+getline)

CCF CSP 第35次&#xff08;2024.09&#xff09;&#xff08;2_字符串变换_C&#xff09; 解题思路&#xff1a;思路一&#xff08;哈希表getline&#xff09;&#xff1a; 代码实现代码实现&#xff08;思路一&#xff08;哈希表getline&#xff09;&#xff09;&#xff1a; …

Docker--利用dockerfile搭建mysql主从集群和redis集群

Docker镜像制作的命令 链接 Docker 镜像制作的注意事项 链接 搭建mysql主从集群 mysql主从同步的原理 MySQL主从同步&#xff08;Replication&#xff09;是一种实现数据冗余和高可用性的技术&#xff0c;通过将主数据库&#xff08;Master&#xff09;的变更操作同步到一个…

蓝桥杯嵌入式考前模块总结

一.RTC 使用RTC直接再cubeMX中配置启动时钟和日历 如第六届省赛 想要让RTC的秒每隔一秒递增1需要在时钟树界面观察RTC的主频 由于RTC时钟主频为32KHZ将异步预分频计数器的值设为31&#xff0c;将同步预分频计数器的值设为999这样就可以将RTC的时钟信号分频为1HZ达到1秒自增的…

关于举办“2025年第五届全国大学生技术创新创业大赛“的通知

赛事含金量 大赛获奖即可有机会为你的大学里的“创新创业”加分&#xff01;这是每个大学要求必须修满的学分&#xff01; 中国“互联网&#xff0b;”大学生创新创业大赛磨刀赛&#xff01;“挑战杯”中国大学生创业计划大赛必参赛&#xff01; 国赛获奖&#xff0c;“互联…

Ingress蓝绿发布

Ingress蓝绿发布 Ingress常用注解说明yaml资源清单绿色版本yml资源清单蓝色版本yaml资源清单 主Ingress金丝雀Ingress基于客户端请求头的流量切分结果验证 基于客户端来源IP的流量切分结果验证 基于服务权重的流量切分结果验证 基于IP来源区域来切分IP---方案未验证基于User-Ag…

基于AOP+Log4Net+AutoFac日志框架

1.项目概述 这是一个基于 C# 的 WPF 项目 WpfApp12log4net&#xff0c;它综合运用了依赖注入、日志记录和接口实现等多种技术&#xff0c;同时使用了 Autofac、Castle.Core 和 log4net 等第三方库。 2.配置log4net 新建一个Log4Net.config&#xff0c;配置需要记录的日志信息…

python推箱子游戏

,--^----------,--------,-----,-------^--,-------- 作者 yty---------------------------^----------_,-------, _________________________XXXXXX XXXXXX XXXXXX ______(XXXXXXXXXXXX(________(------ 0 [[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], [1,0,0,0,0,0,0,0,0,0,0,0,…