当前位置: 首页 > web >正文

【Spring AI】Spring AI 1.0.0-M7、M8更新至1.0.0版本兼容的所需修改要点

引言        

        Spring AI更新的速度非常快,在一个月之前我还在用着最新的M7版本,中间经过M8、1.0.0RC1,现在马上就到了1.0.0正式版。正式版当然也新增了许多东西。

        核心功能包括支持20个AI模型的ChatClient接口、适配20个向量数据库的检索模块、支持滑动窗口和向量搜索的对话记忆功能、基于@Tool注解的工具调用机制,以及模型评估、可观测性和Model Context Protocol(MCP)支持。此外,新增RAG流水线、ETL框架、工作流驱动和自主代理功能。

        更新的契机还是在引入百度的MCP Server的时候,百度的sse包含一个路径参数,而Spring AI默认在url后面拼接一个/sse,导致服务怎么都启动不起来,看源码才发现它是直接将终端节点endpoint硬编码了,也没有提供API去修改endpoint,我就意识到要更新版本了,而1.0.0版本是支持这个特性的最新版,更新之后当然有许多东西不兼容了,代码直接报错了。

        别的不多说了,因为大多数人都在用M7和M8版本的Spring AI,本篇文章我就介绍一下M7、M8版本向1.0.0版本做兼容时主要需要修改的点

模型记忆存储

        在旧版本中,模型记忆的存储的方式很有限,基本都是用的InMemoryChatMemory,这样写的:

 ChatMemory chatMemory = new InMemoryChatMemory();ChatMemory chatMemoey = ChatClient.builder(chatClient).defaultAdvisors(new MessageChatMemoryAdvisor(chatMemory)).build

而在1.0.0版本中,相应的写法应该这么写:

ChatMemory chatMemory = MessageWindowChatMemory.builder().maxMessages(50).build();ChatClient chatClient = ChatClient.builder(chatModel).defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build()).build();

我看了一下官方文档,改动的意思主要就是:原来的ChatMemory支持InMemoryChatMemory,由内存自动管理;现在的是ChatMemory的实现变味了MessageWindowChatMemory,需要由构造器构造,它的下面新增了一批内存管理类,比如总工程类ChatMemoryRepository,其中可以传参InMemoryChatMemoryRepository、JdbcChatMemoryRepository、Neo4jChatMemoryRepository、CassandraChatMemoryRepository。其中InMemoryChatMemoryRepository就相当于原来的InMemoryChatmemory,同样也是默认的实现。

例如现在你可以这么写:

ChatMemory chatMemory = MessageWindowChatMemory.builder().chatMemoryRepository(new InMemoryChatMemoryRepository()).maxMessages(50).build();

还有一个改动点是:原来的内存管理没有上限,想存多少存多少,现在则是可以在构造内存管理的时候定义最大消息数.maxMessage(),类似于滑动窗口,超出限制就把最早的消息从记忆中删除。

不写的话默认就是存储20条。

会话存储

        在旧版本中,我们是通过引入advisors配置会话id以在内存中分别管理不同会话的消息,其是以键值对的形式存储,其中key是通过一个静态变量配置

import static org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY;chatClient.prompt().system().advisors(a -> a.param(CHAT_MEMORY_CONVERSATION_ID_KEY, request.getChatId())).content();  

而现在的key变化了,直接通过Chatmemory中的属性作为键


chatClient.prompt().system().advisors(a -> a.param(ChatMemory.CONVERSATION_ID, request.getChatId())).content();  

工具调用

        以往在配置工具时,通过.tools()配置工具回调

chatClient.prompt().system().tools(new AsyncMcpToolCallbackProvider(mcpASyncClients)).content();  

现在则变成了.toolCallbacks()

chatClient.prompt().system().toolCallbacks(new AsyncMcpToolCallbackProvider(mcpASyncClients)).content();  

MCP配置

        在1.0.0版本之前,在配置MCP客户端时,要连接一个MCP服务端,双方都会默认的在url的最后加一个/sse,并且不能轻易更改,还是硬拼接。

        比如客户端这么写:http://localhost:8080/api

        服务端的url就应该这么写:http://localhost:8080/api

        而在请求时则其实是这都是这样:http://localhost:8080/api/sse

这种情况还好,但是现在MCP Server越来越多,服务提供商可能就需要用户在连接时提供凭证,比如密钥什么的,url可能就需要请求参数,这时候直接把/sse拼接到最后就直接导致地址解析失败

以前的写法:

spring.ai.mcp.client.sse.connections.server1.url=http://localhost:8080# 相当于 http://localhost:8080/sse

现在可以额外配置:

spring.ai.mcp.client.sse.connections.server1.url=http://localhost:8080
spring.ai.mcp.client.sse.connections.server1.sse-endpoint=/sse# 相当于 http://localhost:8080/sse#spring.ai.mcp.client.sse.connections.server2.url=https://mcp.map.baidu.com
#spring.ai.mcp.client.sse.connections.server2.sse-endpoint=/sse?ak=123456789# 相当于 https://mcp.map.baidu.com/sse?ak=123456789

当然不写的话默认还是自动添加/sse

目前最常用的兼容性改动差不多是这些,后续再遇到我会在进行整理。

更详细的技术点请查看官方文档:引言 :: Spring AI Reference(中文版)

http://www.xdnf.cn/news/9336.html

相关文章:

  • 【ARM】如何通过ARMDS的Map文件查看堆栈调用情况
  • 【MAP容器姓名成绩输入查询修改删除】2022-2-4
  • 5 WPF中的Page页面的使用
  • 2.3 TypeScript 非空断言操作符(后缀 !)详解
  • C++中回调函数详解
  • javaEE1
  • 【JavaEE】-- 文件操作和IO
  • FART 自动化脱壳框架一些 bug 修复记录
  • Python学习(1) ----- Python的文件读取和写入
  • 芝麻糊SSVIP2.0.5.7 | 自动收取能量 小游戏任务
  • CSS 中的transform详解
  • OptiStruct结构分析与工程应用:NVH外声场分析
  • AStar低代码平台-脚本调用C#方法
  • 【MySQL】2-MySQL索引P2-执行计划
  • 2025蓝桥杯WP
  • C++学习-入门到精通【9】面向对象编程:继承
  • 青少年编程与数学 02-020 C#程序设计基础 06课题、运算符和表达式
  • 内容中台的AI驱动是什么?
  • Linux--CentOs 8配置及基础命令
  • atomic.Value与sync.map有什么区?
  • 建筑兔零基础Arduino自学记录100|简易折纸机器人-17
  • C语言中清空缓存区到底写到哪里比较好
  • 2025-05-27 Python深度学习7——损失函数和反向传播
  • 电子电路:充电宝的工作原理
  • ActiveMQ
  • UPS的工作原理和UPS系统中旁路的作用
  • Python
  • sockfd = lwip_socket,newfd = lwip_accept 有什么区别
  • Milvus索引操作和最佳实践避坑指南
  • 2025-05-27 Python深度学习6——神经网络模型