今天我们将继续探讨如何在Spring AI中接入大语言模型,以OpenAI为例,详细分析其接入过程。我们将逐步探讨OpenAI是如何与Spring AI系统对接的,具体包括如何配置接口、如何封装接口参数以及如何定义相关的接口。在讲解过程中,我们仍然会以整体架构为主线,逐步深入,详细了解类内部的实现细节和定义。这种渐进式的分析方式有助于更清晰地理解每个模块的功能和它们是如何协同工作的。

整体结构

在这里,我简单地绘制了一张示意图,旨在帮助你更直观、快速地理解整个系统是如何运作的。通过这张图,你可以清晰地看到各个组件之间的关系,以及数据如何在各个模块中流动和交互。如图所示:

接下来,我们将查看它的整体目录文件内容,具体内容如图所示:

刚才提到的所有目录结构实际上并没有包含具体的业务实现,所有的实现都集中在外层的定义部分。举个例子,我们要了解的核心业务是聊天功能,而这一功能的具体实现则是在 OpenAIChatModel 类中。因此,关于聊天实现的细节我们会稍后深入探讨。

至于其他的细节问题,我们稍后也会一一解析。如果对前面提到的 AOT 协议不太熟悉,可以参考我之前的文章,我已专门对该协议做了详细的讲解。这里不做主要说明了。

聊天对接

我们目前主要关注的是聊天接口是如何接入的,至于其他功能,如音频或图像处理,我们可以在后续的讨论中再进行详细探讨。不过,为了更好地理解整个系统,我们需要找到一个合适的切入点,从而逐步通过查看各个类的引用关系,深入了解整个架构的运作方式。

在我们以往构建 Agent 的过程中,第一步通常是注入一个 chatClient 类,这个类实际上就是我们最初使用的核心起点。因此,接下来我们就从 chatClient 这个类开始,深入分析其实现细节和作用。

ChatClient

这个部分是由 Spring AI 封装好的,目的是为了能够在进行底层大模型切换时,确保代码能够做到无感知地平滑过渡,依然能够正常调用。为了快速了解 Spring AI 如何实现这个链路的传递,我们可以简要地浏览一下非常简单的用法:

@GetMapping("/ai-Entity")
ActorFilms generationByEntity() {
ActorFilms actorFilms = chatClient.prompt()
.user("Generate the filmography for a random actor.")
.call()
.entity(ActorFilms.class);//只接收string的话,正常写成content()即可
return actorFilms;
}

这里的写法实际上说明,无论底层所采用的具体大模型是什么类型,若希望能够顺利将其集成到系统中,必须首先进行与ChatClient的适配。如果没有经过这一层适配,系统将无法正确地处理和调用底层模型。因此,接下来我们将直接分析其如何将请求切换至OpenAiChatModel,并实现通过API进行通信的过程。具体实现方式可以参考下方示意图:

关于AdvisedResponse,我们之前已经详细讲解过其定义和作用,因此在此不再赘述。需要强调的是,所有集成到系统中的ChatModel都必须实现一个名为call的方法,stream一样。如图所示:

OpenAiChatModel

虽然这个类包含了众多方法,但从实际应用的角度来看,我们主要关注的实际上只有两个核心方法。第一个是用于生成文本回复的方法,第二个则是支持流式回复的处理方法。其他方法大多数都是私有的辅助性方法,主要作用是为了将主方法的实现进行拆分和优化,从而避免将主方法代码写得过于复杂和臃肿。如图所示:

这几个方法内的代码也基本是固定的写法,具体业务逻辑,我们下一章节再讲。

OpenAiChatOptions

这个类的设计十分直观,理解起来并没有太多复杂的内容。其核心功能主要集中在一些常见的大模型参数配置上,比如选择具体的模型类型、调整生成结果的temperature等。这些配置项是大多数大模型在实际应用中都需要进行设置的参数,对于那些有过大模型使用经验的人来说,应该会非常熟悉这些概念。如图所示:

由于OpenAI提供的功能极为丰富,其系统中涉及到的参数种类也相应很多。

总结

通过今天的分析,我们对如何在Spring AI框架中接入OpenAI的大语言模型有了更清晰的了解。从配置接口到封装参数,再到定义相关接口,我们逐步剖析了整个接入过程。通过对ChatClientOpenAiChatModelOpenAiChatOptions等核心类的简单解析,我们不仅看到了大语言模型如何与Spring AI系统高效协同工作,也对其背后的设计理念有了更深刻的认识。值得一提的是,我们采取的渐进式分析方法,让每个模块的功能和其相互关系更加明了,帮助我们更好地把握整体架构。


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

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

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

深入解析 Spring AI 系列:剖析OpenAI接口接入组件的更多相关文章

  1. Spring Boot系列(三):Spring Boot整合Mybatis源码解析

    一.Mybatis回顾 1.MyBatis介绍 Mybatis是一个半ORM框架,它使用简单的 XML 或注解用于配置和原始映射,将接口和Java的POJOs(普通的Java 对象)映射成数据库中的记 ...

  2. Spring Cloud系列(三):Eureka源码解析之服务端

    一.自动装配 1.根据自动装配原理(详见:Spring Boot系列(二):Spring Boot自动装配原理解析),找到spring-cloud-starter-netflix-eureka-ser ...

  3. Spring Cloud系列(四):Eureka源码解析之客户端

    一.自动装配 1.根据自动装配原理(详见:Spring Boot系列(二):Spring Boot自动装配原理解析),找到spring-cloud-netflix-eureka-client.jar的 ...

  4. Spring Boot 系列教程11-html页面解析-jsoup

    需求 需要对一个页面进行数据抓取,并导出doc文档 html解析器 jsoup 可直接解析某个URL地址.HTML文本内容.它提供了一套非常省力的API,可通过DOM,CSS以及类似于JQuery的操 ...

  5. spring源码系列(二):IOC接口设计分析

    这里主要对springIOC接口体系进行简单的概述和分析,具体每个接口详细分析在下面目录: 参考内容: <Spring技术内幕:深入解析 Spring架构与设计原理> 和 <Spri ...

  6. Spring Boot系列(四):Spring Boot源码解析

    一.自动装配原理 之前博文已经讲过,@SpringBootApplication继承了@EnableAutoConfiguration,该注解导入了AutoConfigurationImport Se ...

  7. Spring入门系列:浅析知识点

    前言 讲解Spring之前,我们首先梳理下Spring有哪些知识点可以进行入手源码分析,比如: Spring IOC依赖注入 Spring AOP切面编程 Spring Bean的声明周期底层原理 S ...

  8. Spring mvc系列一之 Spring mvc简单配置

    Spring mvc系列一之 Spring mvc简单配置-引用 Spring MVC做为SpringFrameWork的后续产品,Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块 ...

  9. Spring 源码剖析IOC容器(一)概览

    目录 一.容器概述 二.核心类源码解读 三.模拟容器获取Bean ======================= 一.容器概述 spring IOC控制反转,又称为DI依赖注入:大体是先初始化bean ...

  10. Spring基础系列-AOP源码分析

    原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/9560803.html 一.概述 Spring的两大特性:IOC和AOP. AOP是面向切 ...

随机推荐

  1. 狂神说-Docker基础-学习笔记-05 Docker镜像原理

    狂神说-Docker基础-学习笔记-05 Docker镜像原理 视频地址:https://www.bilibili.com/video/BV1og4y1q7M4?p=19 镜像是什么 镜像是一种轻量级 ...

  2. Angular 19 "要" 来了⚡

    前言 Angular 19 预计会在 11 月中旬发布,目前 (2024-10-27) 最新版本是 v19.0.0-next.11. 这次 v19 的改动可不小哦,新增了很多功能,甚至连 effect ...

  3. Context的典型使用场景

    获取应用文件路径 基类Context提供了获取应用文件路径的能力,ApplicationContext.AbilityStageContext.UIAbilityContext和ExtensionCo ...

  4. unique:数组去重,返回一个新数组

    function unique(arr){ if(!isArrayLink(arr)){ //不是类数组对象 return arr } let result = [] let objarr = [] ...

  5. 哪些网站可以申请免费的纯IP地址https证书

    申请免费纯IP地址HTTPS证书,您可以按照以下步骤进行: 一.选择证书颁发机构(CA) 目前,虽然一些大型云服务提供商(如阿里云.华为云.腾讯云等)已经取消了免费一年期SSL证书的供应,但仍有一些C ...

  6. Python中函数或者类对象带()与不带()的区别——闭包和函数返回时的常见现象

    Python中函数或者类对象带()与不带()的区别-----闭包和函数返回时的常见现象 - 函数不带括号时,调用的是这个函数本身 ,是整个函数体,是一个函数对象,不需等该函数执行完成,返回一个已定义函 ...

  7. .NET9 - 新功能体验(一)

    被微软形容为"迄今为止最高效.最现代.最安全.最智能.性能最高的.NET版本"--.NET 9已经发布有一周了,今天想和大家一起体验一下新功能. 此次.NET 9在性能.安全性和功 ...

  8. 发布一个TCP 吞吐性能测试小工具

    当写完一个TCP服务的时候,是不是很想马上测试一下这个服务的性能,它到底能应付怎样的请求处理,其性能又是怎样呢.相信以下这个小工具能帮到你的小忙,它是基于Beetle实现的一个小工具只需要设置一下参数 ...

  9. BitLocker驱动器加锁和解锁

    应用场景: 单位配备给你使用的电脑(Win10系统),偶尔也会有其他人使用.你可以设置某一个磁盘为你的私密数据存储空间,只有你输入密码后才能进入磁盘.即使系统重装.硬盘被拆下来挂载到其他机器上,没有密 ...

  10. ZCMU-1153

    思路 一个感觉是规律问题的数学问题 因为输入的是n所以要的出有关n的关系或者关系 有关排序,所以可以从位次入手,设双胞胎前一个位置在ai,后一个在bi. Sum(bi-ai)=(2+3+4+5+6+. ...