Spring AI 1.0.0 M1版本新特性!

Spring AI 1.0.0 M1版本新特性介绍

  • 前言
  • 一、在1.0.0 M1版本中,主要有以下新特性:
    • 1.ChatModel
    • 2.ChatClient
    • 3.多模态的支持
    • 4.模型评估
    • RequestResponseAdvisor接口
      • MessageChatMemoryAdvisor
      • PromptChatMemoryAdvisor
      • QuestionAnswerAdvisor
        • 动态过滤表达式
      • VectorStoreChatMemoryAdvisor
  • 总结


前言

Spring AI 1.0.0-M1这个版本相对前一个版本增加了很多新特性,比如多模态的支持、模型结果评估机制、Fluent API等等,但其中我觉得最有意思的是引入了Spring AOP中的Advisor机制。

众所周知,Advisor是Spring AOP中的概念,一个Advisor表示一个切面,由Advice和PointCut组成,Advice表示切面逻辑,也就是增强逻辑,PointCut表示切点,也就是切哪些方法。

一、在1.0.0 M1版本中,主要有以下新特性:

1.ChatModel

以前的ChatClient变为了ChatModel,ChatModel表示某个模型,具体看配置使用了哪个模型,比如实现类OpenAiChatModel表示OpenAi旗下的大模型,比如gpt-4o

2.ChatClient

但ChatClient并没有废弃,而是变成了封装在ChatModel之上的客户端,相当于ChatClient底层使用的是ChatModel,ChatClient支持fluent API,ChatModel则不支持,比如:

@GetMapping("/clientChat")
public String clientChat() {
    return this.chatClient.prompt()
    .user("你是谁")
    .call()
    .content();
}

不过,我们需要自己定义ChatClient的Bean:

@Bean
public ChatClient chatClient(ChatClient.Builder builder) {
    return builder
    .build();
}

3.多模态的支持

通过Spring AI可以让大模型来理解图片内容

@GetMapping("/multimodalChat")
public String multimodalChat() {
    ClassPathResource imageData = new ClassPathResource("/test.jpg");

    var userMessage = new UserMessage("图片里有什么?",
        List.of(new Media(MimeTypeUtils.IMAGE_PNG, imageData)));

    return chatModel.call(userMessage);
}

4.模型评估

对于模型生成的结果,让可以让模型针对问题和答案评估是否相关:

@GetMapping("/evaluation")
public EvaluationResponse evaluation() {
    String userText = "apikey是什么";

    ChatResponse response = ChatClient.builder(chatModel)
    .build().prompt()
    .advisors(new QuestionAnswerAdvisor(vectorStore, SearchRequest.defaults()))
    .user(userText)
    .call()
    .chatResponse();

    // 评估器
    var relevancyEvaluator = new RelevancyEvaluator(ChatClient.builder(chatModel));

    // 评估请求
    EvaluationRequest evaluationRequest = new EvaluationRequest(userText,
        (List<Content>) response.getMetadata().get(QuestionAnswerAdvisor.RETRIEVED_DOCUMENTS), response);

    // 评估结果
    EvaluationResponse evaluationResponse = relevancyEvaluator.evaluate(evaluationRequest);

    return evaluationResponse;
}

评估结果为:

{
    "pass": true,
    "score": 1.0,
    "feedback": "",
    "metadata": {}
}

RequestResponseAdvisor接口

在这里插入图片描述
很明显,这个接口表示对请求和响应进行增强,传入一个请求或响应,返回增强后的请求或响应,有点类似于Spring MVC中的拦截器,联系到Spring AI的核心功能就是 请求大模型接口
以及 处理大模型响应结果 ,所以RequestResponseAdvisor接口的作用就是增强对于大模型的请求和响应,但具体增强逻辑是什么由具体的实现类来定义。

在这里插入图片描述

MessageChatMemoryAdvisor

广义的意思:
是一种Advisor,也是用来增强问答请求和响应的,而其中另外一个概念就是ChatMemory,默认实现为InMemoryChatMemory,它可以用来按conversationId进行历史对话记录的存储。

因此MessageChatMemoryAdvisor的作用就是将原始请求和向量添加到ChatMemory中。

源码讲解:
第一个实现类:MessageChatMemoryAdvisor ,类名中的 ChatMemory 也是Spring AI中的一个机制,也是1.0.0版本新增的一个特性,来源于LangChain4j,作用是用来保存与大模型的,聊天上下文,或者说聊天记录,或者说会话记录,或者说问答记录,都是一个意思,ChatMemory
是一个接口,默认实现类为InMemoryChatMemory ,表示聊天记录都存储在内存中(InMemory),当然你可以自定义一个实现类把聊天记录存在数据库中,InMemoryChatMemory,的实现其实很简单:

在这里插入图片描述
理解为就是一个Map,key为会话ID,value为会话对应的历史消息列表,注意这里的消息既包含了我们发送给大模型的UserMessage(比如“你是谁?”),也包含了大模型返回给我们的AssistantMessage(比如“我是gpt-4o…”),都是Message。

回到 MessageChatMemoryAdvisor ,它增强的是某一次请求和对应的响应,它的第一个作用就是把当前请求所发送的UserMessage添加到ChatMemory中,重点是第二个作用,由于大模型本身是无状态的,也就是大模型本身并不会保存我们和大模型之间的聊天记录,所以,我们如果想让大模型知道我们之前聊了什么,我们就需要在请求大模型时将历史聊天记录跟着当前请求一起发送给大模型,这样大模型才能知道前面聊了什么,而具体实现方式就是发送一个List给大模型,这个List中既包含了历史消息,也包含了最新消息,这样大模型就能知道前面聊天的内容了。

所以,当Spring AI接收到一个请求时,这个请求一开始只会携带一条UserMessage,比如“请换一个风格”,之后 MessageChatMemoryAdvisor 会将该请求对应的UserMessage添加到ChatMemory中,也就是Map中当前会话ID对应的List中,然后生成一个新的请求,将List设置到新请求中,因此这个新的请求中就不止一条UserMessage了,而是一个List,然后Spring AI会将这个新的请求发送给大模型,此时大模型也就知道了历史聊天记录,就能知道“请换一个风格”到底是什么意思了。

在这里插入图片描述
当大模型处理完请求后,会向Spring AI返回一个响应,在Spring AI中就是一条AssistantMessage,那么MessageChatMemoryAdvisor 需要对响应做什么增强逻辑呢?很简单,只需要将AssistantMessage添加到ChatMemory即可。

在这里插入图片描述

PromptChatMemoryAdvisor

也是用来记录历史对话记录的,和MessageChatMemoryAdvisor的不同点在于,MessageChatMemoryAdvisor是把每个历史请求和响应封装为Message增强到请求中,而PromptChatMemoryAdvisor是把所有请求和响应也会存到ChatMemory中,但是会把所有内容合并一条Message增强到请求中。

PromptChatMemoryAdvisor ,其实它的作用和MessageChatMemoryAdvisor类似,也会利用ChatMemory来保存聊天记录,它和MessageChatMemoryAdvisor的区别在于,最终发送给大模型的请求中不是一个List了,而是会额外设置了一个系统提示词SystemMessage
,内容为:

Use the conversation memory from the MEMORY section to provide accurate answers
----------------------------
MEMORY:
{memory}
----------------------------

{memory}相当于一个变量,发送给大模型之前会进行占位符的填充,那填充的是啥呢?没错啦,就是历史聊天记录,源码中会把List用

System.lineSeparator()

进行连接,相当于把历史聊天记录转为一个字符串,然后放到系统提示词中随着请求一起发送给大模型,这样大模型也能知道之前聊天的内容,从而准确的理解当前问题,和MessageChatMemoryAdvisor一样,PromptChatMemoryAdvisor也会将大模型的响应AssistantMessage保存到ChatMemory中。

看到这,是否Get到了Advisor在Spring AI中的作用了呢,看到源码时还是觉得挺惊艳的,Spring还是那么的优雅,切面机制永远这么强大。

不过需要注意的是,以上MessageChatMemoryAdvisor和PromptChatMemoryAdvisor虽然都叫做Advisor,但是它们都不是通过动态代理来实现的,而是这么实现的:
在这里插入图片描述
针对原始的请求和响应,依次利用RequestResponseAdvisor进行增强,有没有感觉和BeanPostProcessor的实现机制很像呢。

QuestionAnswerAdvisor

广义: Advisor是Spring AOP中的概率,这里也应用在了Spring
AI中,QuestionAnswerAdvisor的作用是对问题请求进行增强,增强逻辑为:

  1. 根据原始问题进行相似度搜索,得到匹配知识点
  2. 拼接RAG提示词模板

后续Spring
AI会根据增强后的请求进行提示词模版的变量填充,得到请求最终的提示词,并将请求发送给大模型,得到大模型的返回结果,QuestionAnswerAdvisor也会对返回结果进行增强,会把匹配的知识点放入ChatResponse的metadata中。

向量数据库存储的是 AI 模型不知道的数据,当用户问题被发送到 AI 模型时,QuestionAnswerAdvisor 会在向量数据库中查询与用户问题相关的文档。

来自向量数据库的响应被附加到用户消息 Prompt 中,为 AI 模型生成响应提供上下文。

假设您已将数据加载到中 VectorStore,则可以通过向 ChatClient 提供 QuestionAnswerAdvisor 实例来执行检索增强生成 (RAG ) 。

    ChatResponse response = ChatClient.builder(chatModel)
            .build().prompt()
            .advisors(new QuestionAnswerAdvisor(vectorStore, SearchRequest.defaults()))
            .user(userText)
            .call()
            .chatResponse();

在此示例中,SearchRequest.defaults() 将对 Vector 向量数据库中的所有文档执行相似性搜索。为了限制要搜索的文档类型,SearchRequest 采用了可移植到任意向量数据库中的类似 SQL 筛选表达式。

动态过滤表达式

SearchRequest 使用 FILTER_EXPRESSION Advisor 上下文参数在运行时更新过滤表达式:

    ChatClient chatClient = ChatClient.builder(chatModel)
        .defaultAdvisors(new QuestionAnswerAdvisor(vectorStore, SearchRequest.defaults()))
        .build();

    // Update filter expression at runtime
    String content = chatClient.prompt()
        .user("Please answer my question qjc")
        .advisors(a -> a.param(QuestionAnswerAdvisor.FILTER_EXPRESSION, "type == 'Spring'"))
        .call()
        .content();

该 FILTER_EXPRESSION 参数允许您根据提供的表达式动态过滤搜索结果。

VectorStoreChatMemoryAdvisor

这个就更加强大了,它既会进行RAG,也会把存储历史对话,只不过会把对话记录封装为Document存到向量数据库中。

VectorStoreChatMemoryAdvisor :构造函数VectorStoreChatMemoryAdvisor(VectorStore vectorStore, String defaultConversationId, int chatHistoryWindowSize)允许您指定要从中检索聊天历史记录的 VectorStore、唯一的对话 ID、要检索的聊天历史记录的大小(以令牌大小为单位)。

这个没有具体分析一下,我先提供一个案例:回头展开细说这个模块,因为我看到官方M2 M3也出来了,慢慢研究

 @Service
public class SupportAssistant {

        private final ChatClient chatClient;

        public SupportAssistant(ChatClient.Builder builder, VectorStore vectorStore, ChatMemory chatMemory) {

        this.chatClient = builder
                .defaultSystem("""
                    xxxxx
                        """)
                .defaultAdvisors(
                        new PromptChatMemoryAdvisor(chatMemory),
                        // new MessageChatMemoryAdvisor(chatMemory), // CHAT MEMORY
                        new QuestionAnswerAdvisor(vectorStore, SearchRequest.defaults()),
                        new LoggingAdvisor()) // RAG
                .build();
    }

    public Flux<String> chat(String chatId, String userMessageContent) {

        return this.chatClient.prompt()
                .user(userMessageContent)
                .advisors(a -> a
                        .param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId)
                        .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 100))
                .stream().content();
        }
    }

总结

这是个里程碑版本,后续M2 M3都已经出来了,目前文档看不到。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

爬虫逆向-js进阶(续写,搭建网站)

1.搭建简单网站1 from flask import Flask,render_template import requests import json app Flask(name)# **location**的温度是**temp**度&#xff0c;天气状况&#xff1a;**desc**app.route(/) # 绑定处理函数 def index_url():location 101010100data get_weather(lo…

黑马JavaWeb-day02

什么是JavaScript&#xff1f; JavaScript&#xff1a;简称Js,是一门跨平台、面向对象的脚本语言。是用来控制网页行为的&#xff0c;它能使网页可交互 JavaScript和Java是完全不同的语言&#xff0c;无论是概念还是设计。但是基础语法类似。 JavaScript JavaScript引入方式…

第三方软件测试中心有什么特点?江苏软件测试中心推荐

随着软件市场的激烈竞争&#xff0c;软件企业越来越多&#xff0c;为了更好的服务用户以及专心于产品开发工作&#xff0c;将软件测试外包给第三方软件测试中心已经成为了行业发展趋势。第三方软件测试中心顾名思义就是区别于软件开发方和需求方的第三方存在&#xff0c;是专门…

使用 MongoDB 构建 AI:利用实时客户数据优化产品生命周期

在《使用 MongoDB 构建 AI》系列博文中&#xff0c;我们看到越来越多的企业正在利用 AI 技术优化产品研发和用户支持流程。例如&#xff0c;我们介绍了以下案例&#xff1a; Ventecon 的 AI 助手帮助产品经理生成和优化新产品规范 Cognigy 的对话式 AI 帮助企业使用任意语言&a…

《MYSQL实战45讲 》 优化器如何选择索引?

SHOW VARIABLES LIKE long_query_time; set long_query_time0 优化器如何选择索引&#xff1f; 1.扫描的行数 估计出各个索引大致的要扫描的行数&#xff0c;行数越少&#xff0c;效率越高。 索引的基数也叫区分度&#xff0c;就是这个索引所在的字段上不同的值又多少个。优…

10.21 多进程间通信-信号、消息队列

作业&#xff1a;使用消息队列实现两个进程间通信 编程代码&#xff1a;使用父子进程实现通信 msgsnd.c #include <myhead.h> //定义自定义函数用于接收僵尸进程 void handler(int signo){if(signoSIGCHLD){while(waitpid(-1,NULL,WNOHANG)>0);} } //定义存储消息队…

[云] Deploying Your First Serverless Application

• Goal: • Hands-on lab to get started with Serverless • Agenda: • Deploying Your First Serverless Application • Assignment Introduction Create and test function in AWS Lambda • Lets create an addition function using AWS Lambda. • To create the addi…

pipeline开发笔记

pipeline开发笔记 jenkins常用插件Build Authorization Token Root配置GitLab的webhooks(钩子)配置构建触发器--示例 piblish over sshBlue OceanWorkspace Cleanup PluginGit插件PipelineLocalization: Chinese (Simplified) --中文显示Build Environment Plugin 显示构建过程…

vscode离线状态ssh连接不断输入密码登不上:配置commit_id

如题&#xff0c;vscode在一个离线服务器上&#xff0c;通过remote-ssh登录远程服务器&#xff0c;不断弹出密码框&#xff0c;总是进不去&#xff0c;后来了解到主要是不同vscode版本需要下载对应抑制commit-id的vscode-server-linux-x64.tar.gz包。 1&#xff09;vscode, 点…

Jupyter Notebook汉化(中文版)

原版jupyter notebook是英文的&#xff0c;想要将其改为中文 在jupyter notebook所在环境输入以下命令 pip install jupyterlab-language-pack-zh-CN打开jupyter notebook&#xff0c;在设置语言中将其设置为中文

提升小学语文教学效果的思维导图方法

众所周知&#xff0c;教学不仅仅是站在讲台上传授知识&#xff0c;它还包括了备课、评估学生学习成果以及不断调整教学方法等多个环节。在面对教学中的各种挑战时&#xff0c;思维导图可以成为解决这些问题的有力工具。思维导图是一种利用图形来组织和表达发散性思维的工具&…

【DBA Part01】国产Linux上安装Oracle进行数据迁移

内容如下&#xff1a; 1.1.生产环境RHEL/OEL Linux8Oracle11gR2安装配置 1.2.国产麒麟操作系统Oracle11gR2安装配置 1.3.国产麒麟操作系统Oracle11gR2 RAC集群安装配置 1.4.Oracle11gR2迁移到国产麒麟操作系统&#xff08;单机/RAC&#xff09; 本阶段课程项目需求说明&am…

Spring配置/管理bean-IOC(控制反转) 非常详细!基于XML及其注解!案例分析! 建议复习收藏!

目录 1.Spring配置/管理bean介绍 2.基于XML配置bean 2.1基于id来获取bean对象 2.2基于类型获取bean对象 2.3通过指定构造器配置bean对象 2.4通过p名称空间配置bean 2.5通过ref配置bean(实现依赖注入) 2.6注入内部Bean对象&#xff0c;依赖注入另一种方式 2.7 注入集合…

PCL 基于距离阈值去除错误对应关系

目录 一、概述 1.1原理 1.2实现步骤 1.3应用场景 二、代码实现 2.1关键函数 2.1.1 获取初始对应点对 2.1.2 基于距离的对应关系筛选函数 2.1.3 可视化函数 2.2完整代码 三、实现效果 PCL点云算法汇总及实战案例汇总的目录地址链接&#xff1a; PCL点云算法与项目实…

批量处理文件权限:解决‘/usr/bin/chmod: Argument list too long’的有效方法

批量处理文件权限&#xff1a;解决‘/usr/bin/chmod: Argument list too long’的有效方法 错误原因解决方案1. 分批处理2. 使用xargs3. 增加ARG_MAX限制4. 使用脚本 结论 在Linux系统中&#xff0c;有时你可能会遇到这样的错误消息&#xff1a;“/usr/bin/chmod: Argument lis…

大数据之hive(分布式SQL计算工具)加安装部署

1.分布式SQL计算: 对数据进行统计分析&#xff0c; SQL是目前最为方便的编程工具. 2.hive:主要功能: 将 SQL语句翻译成MapReduce程序运行,提供用户分布式SQL计算能力 3.构建分布式SQL计算:(hive核心组件) 需要有: 一:元数据管理功能, 即&#xff1a;数据位置,数据结构,等对数…

SpringBoot篇(二、制作SpringBoot程序)

目录 一、代码位置 二、四种方式 1. IDEA联网版 2. 官网 3. 阿里云 4. 手动 五、在IDEA中隐藏指定文件/文件夹 六、复制工程-快速操作 七、更改引导类别名 一、代码位置 二、四种方式 1. IDEA联网版 2. 官网 官网制作&#xff1a;Spring Boot 3. 阿里云 阿里云版制…

HTTP和RPC通信协议

在软件开发中&#xff0c;通信协议扮演着关键的角色&#xff0c;它们定义了不同系统或组件之间进行通信的规则和方式。HTTP&#xff08;Hypertext Transfer Protocol&#xff09;和RPC&#xff08;Remote Procedure Call Protocol&#xff09;是两种常见的通信协议。然而RPC 和…

开源模型应用落地-Qwen2.5-7B-Instruct与vllm实现推理加速的正确姿势-Gradio

一、前言 目前&#xff0c;Qwen模型已经升级到了2.5版本。无论是语言模型还是多模态模型&#xff0c;它们都是在大规模的多语言和多模态数据上进行预训练的&#xff0c;并通过高质量的数据进行后期微调&#xff0c;以更好地符合人类的需求。 Gradio作为一个强大的工具&#xff…

Windows--使用node.js的免安装版本

原文网址&#xff1a;Windows--使用node.js的免安装版本_IT利刃出鞘的博客-CSDN博客 简介 本文介绍Windows下如何使用node.js的免安装版本。 下载 1.访问官网 https://nodejs.org/en 记住这个版本号&#xff0c;这个是长期支持的版本。 2.找到压缩包 点击其他下载&#…