深入解析 Spring AI 系列:解析返回参数处理

news/2025/1/22 7:22:51/文章来源:https://www.cnblogs.com/guoxiaoyu/p/18670755

关于普通聊天对接,目前已经完成了大部分讲解,剩下的就是最后一步,今天我们将重点讨论在返回参数时需要注意的几个关键点。为了更好地说明这些注意事项,我们仍然以OpenAI接口为例,逐步讲解相关的代码实现,帮助大家更清楚地理解这一部分的细节。

接下来,我们就直接看一下这一部分代码,分析其中的注意事项。

image

其实,对于这部分代码来说,核心逻辑的重点在于将大模型返回的内容封装到 response 中,从而完成对接工作。然而,值得注意的是,为什么代码中还要额外获取并处理一些看似并未直接使用的值,例如 metadatarateLimitusage 等?实际上,这并非多余的操作。这些信息虽然在当前版本的代码中并没有立即被使用,但它们的存在是为了为后续可能的需求变化做准备。

如果我们仅仅是为了简单地将获取到的返回内容输出给用户,其实是可以省去这些额外步骤的,也不需要做如此复杂的处理。如图所示:

image

这是Minimax算法的处理方式,相较于OpenAI的处理方式,这里采用的方法显得更加简洁和直观。因此,这部分代码的实现较为简单,理解后可以快速跳过,不必深入细节。在实际应用中,只需要在有用的地方将相应的信息提取并填充到response对象中即可。

如果某些信息在当前上下文中并未使用到,那么就不需要进行封装或处理,避免不必要的复杂度。

ChatGenerationMetadata

buildGeneration的核心逻辑其实就是在寻找需要的工具调用和结束信息,核心代码如下所示,看一下:

private Generation buildGeneration(Choice choice, Map<String, Object> metadata, ChatCompletionRequest request) {List<AssistantMessage.ToolCall> toolCalls = choice.message().toolCalls() == null ? List.of(): choice.message().toolCalls().stream().map(toolCall -> new AssistantMessage.ToolCall(toolCall.id(), "function",toolCall.function().name(), toolCall.function().arguments())).toList();String finishReason = (choice.finishReason() != null ? choice.finishReason().name() : "");var generationMetadataBuilder = ChatGenerationMetadata.builder().finishReason(finishReason);List<Media> media = new ArrayList<>();String textContent = choice.message().content();var audioOutput = choice.message().audioOutput();if (audioOutput != null) {String mimeType = String.format("audio/%s", request.audioParameters().format().name().toLowerCase());byte[] audioData = Base64.getDecoder().decode(audioOutput.data());Resource resource = new ByteArrayResource(audioData);Media.builder().mimeType(MimeTypeUtils.parseMimeType(mimeType)).data(resource).id(audioOutput.id()).build();media.add(Media.builder().mimeType(MimeTypeUtils.parseMimeType(mimeType)).data(resource).id(audioOutput.id()).build());if (!StringUtils.hasText(textContent)) {textContent = audioOutput.transcript();}generationMetadataBuilder.metadata("audioId", audioOutput.id());generationMetadataBuilder.metadata("audioExpiresAt", audioOutput.expiresAt());}var assistantMessage = new AssistantMessage(textContent, metadata, toolCalls, media);return new Generation(assistantMessage, generationMetadataBuilder.build());
}

无论在何种情况下省略逻辑,toolCallsfinishReason这两个要素是必须要被识别和处理的。除非某个大型模型不支持toolCalls功能,否则我们在实现时不应忽略它们。实际上,绝大多数主流的大型模型都具备这部分功能,因为如果一个模型缺失了toolCalls功能,这意味着它无法支持Agent的开发和运行,进而就失去了介入Spring AI生态系统的基本目的。总之,确保对这两个关键要素的识别,对于实现模型的有效性和功能完整性至关重要。

关于media是因为OpenAI接口是会返回此信息字段,看下接口文档:

image

除此之外ChatGenerationMetadata目前除了finishReason我找到了使用目的,其他的还未找到用处,ChatGenerationMetadata功能基本如下:

  1. 可以用来测试
  2. 可以用来观测
  3. 目前还没咋用上,先留个心

ChatResponseMetadata

作用也是一样的,仍然是为了观测使用,只不过他封装的信息和上面有一些区别而已。如图所示:

image

Usage

本质上,这只是一个用于统计token使用情况的信息,功能上并没有特别复杂的内容,理解起来并不难。如果你之前不太了解这部分的细节,可以查看它的核心代码,这将帮助你迅速掌握其工作原理。

需要注意的是,绝大多数大型模型接口都提供了类似的字段,因为在实际应用中,了解token的消耗情况非常重要,毕竟资源的投入(如费用)最终需要与使用效果相对应,这也是模型开发者和使用者关心的重点之一。如图所示:

image

总结

在这一部分的讲解中,我们详细探讨了返回参数处理的关键要点,特别是如何封装与使用相关的字段。尽管某些信息(如metadatarateLimit等)在当前实现中未直接用到,但它们的引入是为了更好地支持未来的扩展和需求变化。

通过对比不同处理方式,我们也看到不同模型接口在设计上的差异。在实际开发过程中,理解这些细节对于保证接口的扩展性和系统的稳定性至关重要。


我是努力的小雨,一个正经的 Java 东北服务端开发,整天琢磨着 AI 技术这块儿的奥秘。特爱跟人交流技术,喜欢把自己的心得和大家分享。还当上了腾讯云创作之星,阿里云专家博主,华为云云享专家,掘金优秀作者。各种征文、开源比赛的牌子也拿了。

💡 想把我在技术路上走过的弯路和经验全都分享出来,给你们的学习和成长带来点启发,帮一把。

🌟 欢迎关注努力的小雨,咱一块儿进步!🌟

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

演练 dotnet 使用 GeneratedComInterface 源代码生成方式调用 COM 接口

本文将提供使用源代码生成方式的 COM 调用。本文例子基于 dotnet 9 框架官方文档:ComWrappers source generation - .NET Microsoft Learn Using the ComWrappers API - .NET Microsoft Learn本文将演练在 WPF 应用里面手动写 COM 调用的方式,调用打开文件对话框。访问 COM 的…

演练 dotnet 使用 函数指针 调用 COM 接口

本文将和大家演练如何在 dotnet 里面使用 函数指针 调用 COM 接口,整个过程没有 COM 封装的存在,其性能非常高,调用非常直接和底层,无中间商赚差价官方文档: 函数指针 - C# feature specifications Microsoft Learn ComWrappers source generation - .NET Microsoft Learn…

读量子霸权11基因剪辑

读量子霸权11基因剪辑1. 癌症 1.1. 癌症是美国人口死亡病因中排名第二的“杀手”​,仅次于心血管疾病1.1.1. 虽然手术、化学治疗和放射治疗等医学手段在对抗癌症方面取得了越来越多的进展,但因癌症而死亡的人数仍然居高不下1.2. 人类与癌症之间的战争尚存在一个根本问题没有得…

Wi-Fi 8:开创连接的未来

Wi-Fi 8:开创连接的未来 下一代 Wi-Fi 8。主要见解包括:多 AP 协调 进一步优化频谱效率 扩展范围 能效改进然而,Wi-Fi 8 优先考虑无线通信的一个方面,这个方面变得越来越重要:可靠性。 Wi-Fi 8 的 8021.1 亿则专注于“超高可靠性”。 本白皮书讨论了 Wi-Fi 8 的新功能、蜂…

请说说什么是分区响应图?

分区响应图在前端开发中是一种特殊的技术实现,它允许开发者将一张图片划分为多个区域,并为每个区域指定不同的超链接或响应行为。当用户点击图片的不同区域时,会根据该区域的设置触发相应的操作,比如跳转到不同的网页或执行特定的JavaScript函数。 以下是关于分区响应图的详…

用于非均匀二次谐波产生的光子集成电路

用于非均匀二次谐波产生的光子集成电路 摘要:GaAs基激光器与倍频波导的异质集成为在所谓的绿隙中实现可扩展相干源提供了一条清晰的途径,但到目前为止,倍频系统一直依赖于单独制造的激光器来提供足够的功率用于二次谐波产生。在这项工作中,提出了一种光子集成电路(PIC),…

迈向基于离子的大规模集成电路:离子电子元件的电路级设计、仿真和集成

迈向基于离子的大规模集成电路:离子电子元件的电路级设计、仿真和集成 离子电子学将离子作为电荷载体与类电子操作相结合,实现了独特的信息处理、化学调节和增强的生物可整合性。标准仿真工具在有效模拟集成离子电子元件的行为方面遇到了困难,这突显了对专门设计和仿真方法的…

推荐书籍《AI芯片开发核心技术详解》、《智能汽车传感器:原理设计应用》、《TVM编译器原理与实践》、《LLVM编译器原理与实践》,谢谢

4本书推荐《AI芯片开发核心技术详解》、《智能汽车传感器:原理设计应用》、《TVM编译器原理与实践》、《LLVM编译器原理与实践》由清华大学出版社资深编辑赵佳霓老师策划编辑的新书《AI芯片开发核心技术详解》已经出版,京东、淘宝天猫、当当等网上,相应陆陆续续可以购买。该…

JavaScript的其他常用库

setTimeout与setInterval、requestAnimationFrame、Map与Set、localStorage、JSON、日期、WebSocket、window、canvas等常用库ε=ε=ε=(~ ̄▽ ̄)~setTimeout与setIntervalsetTimeout(func, delay) :delay毫秒后,执行函数func()。 例如: let main = function() {let $div =…

内外网安全文件交换系统:守护企业数据安全的坚固防线

介绍内外网安全文件交换系统的使用在当今数字化时代,企业内外网数据交换的需求日益增长,但数据安全问题也愈发突出。如何在保障数据高效传输的同时,确保其安全性?内外网安全文件交换系统给出了完美答案。 一、产品定位与功能亮点 内外网安全文件交换系统是一款专为企业内外…

git 证书验证问题 SSL certificate problem

提示这个 fatal: unable to access https://github.com/example/repo.git/: SSL certificate problem: unable to get local issuer certificate 一般配置证书即可 第一步 导出网站证书第二步 添加导出的证书 具体命令为 git config --global http.sslCAInfo /path/to/root_cer…

Solidity中数据的布局

1.Storage中 1.1-基本原则(基本的值类型) 在这里面的变量都是独立的,互相不影响,所以非常"安全"; 均存储在slot中,slot有2^256个,每个长度256位; 从0开始连续往后存储(除动态数组和映射),当有连续几个都小于256位时,会尝试将它们放在同一个slot中; 同时也…