Browse Source
chore(deps): 升级 Spring Boot 3.5.8 / Spring AI 1.1.2 / Spring AI Alibaba 1.1.2.2
chore(deps): 升级 Spring Boot 3.5.8 / Spring AI 1.1.2 / Spring AI Alibaba 1.1.2.2
升级到官方兼容矩阵组合(SAA 1.1.2.2 的官方基线即 Boot 3.5.8 + SAI 1.1.2)。 编译适配 - SAA 1.1.2.2 将内部类 DashscopeChatOptionsBuilder 更名为 DashScopeChatOptionsBuilder - Spring AI 1.1.x 起 AssistantMessage/ToolResponseMessage 带 metadata 的构造器改为 protected,MessageConverter 改用标准 builder 依赖增删 - MCP SDK 继续排除传递依赖并锁定 0.18.3:1.1.2 传递的是 0.17.0,其 JsonMapper 包名 为 json.jackson(无 jackson2),与本项目使用的 json.jackson2 不兼容,不锁版本会编译失败; 已核对 spring-ai-mcp 1.1.2 仅引用 McpSyncClient/McpAsyncClient/McpClient/ McpTransportContext/McpSchema/Assert,这些类 0.18.3 均存在,覆盖安全 - 删除 spring-security-oauth2-client:原为 Spring AI 1.0.x ToolCallingAutoConfiguration 的 ClassNotFound workaround,1.1.2 已无该耦合(已核对字节码常量池零 oauth2 引用) - 删除显式 victools jsonschema-generator:改由 spring-ai-model 传递引入(4.38.0), 顺带消除原先 4.38.0/4.37.0 混用 - 删除 kryo:唯一使用者 FileBasedChatMemory 为死代码,本提交一并删除 - 新增 jtokkit 1.1.0(OverlapTokenTextSplitter 直接使用) - 升 Knife4j 4.5.0、MyBatis-Plus 3.5.14、hutool 5.8.41、jjwt 0.12.7; Lombok 版本交由 Boot 父 POM 托管(1.18.42) 刻意不采纳的升级建议 - 不导入 spring-ai-alibaba-bom:该 BOM 的 dependencyManagement 并不包含 spring-ai-alibaba-starter-dashscope,导入后仍需显式写版本号,无收益 - 保留 spring-ai-openai / spring-ai-pgvector-store 的非 starter 坐标:项目手动构建 ChatModel/EmbeddingModel/VectorStore,换 starter 会额外引入 model-openai、chat-client、 chat-memory 三个自动配置,可能生成与手写工厂、DatabaseChatMemory 冲突的 BeanSpring-AI-1.1.2
5 changed files with 53 additions and 119 deletions
-
65pom.xml
-
5src/main/java/com/wok/supportbot/SupportBotApplication.java
-
85src/main/java/com/wok/supportbot/chatmemory/FileBasedChatMemory.java
-
4src/main/java/com/wok/supportbot/config/ChatModelFactory.java
-
13src/main/java/com/wok/supportbot/converter/MessageConverter.java
@ -1,85 +0,0 @@ |
|||||
package com.wok.supportbot.chatmemory; |
|
||||
|
|
||||
import com.esotericsoftware.kryo.Kryo; |
|
||||
import com.esotericsoftware.kryo.io.Input; |
|
||||
import com.esotericsoftware.kryo.io.Output; |
|
||||
import org.objenesis.strategy.StdInstantiatorStrategy; |
|
||||
import org.springframework.ai.chat.memory.ChatMemory; |
|
||||
import org.springframework.ai.chat.messages.Message; |
|
||||
|
|
||||
import java.io.File; |
|
||||
import java.io.FileInputStream; |
|
||||
import java.io.FileOutputStream; |
|
||||
import java.io.IOException; |
|
||||
import java.util.ArrayList; |
|
||||
import java.util.List; |
|
||||
|
|
||||
/** |
|
||||
* 基于文件持久化的对话记忆 |
|
||||
*/ |
|
||||
public class FileBasedChatMemory implements ChatMemory { |
|
||||
|
|
||||
private final String BASE_DIR; |
|
||||
private static final Kryo kryo = new Kryo(); |
|
||||
|
|
||||
static { |
|
||||
kryo.setRegistrationRequired(false); |
|
||||
// 设置实例化策略 |
|
||||
kryo.setInstantiatorStrategy(new StdInstantiatorStrategy()); |
|
||||
} |
|
||||
|
|
||||
// 构造对象时,指定文件保存目录 |
|
||||
public FileBasedChatMemory(String dir) { |
|
||||
this.BASE_DIR = dir; |
|
||||
File baseDir = new File(dir); |
|
||||
if (!baseDir.exists()) { |
|
||||
baseDir.mkdirs(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void add(String conversationId, List<Message> messages) { |
|
||||
List<Message> conversationMessages = getOrCreateConversation(conversationId); |
|
||||
conversationMessages.addAll(messages); |
|
||||
saveConversation(conversationId, conversationMessages); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public List<Message> get(String conversationId) { |
|
||||
return getOrCreateConversation(conversationId); |
|
||||
} |
|
||||
|
|
||||
@Override |
|
||||
public void clear(String conversationId) { |
|
||||
File file = getConversationFile(conversationId); |
|
||||
if (file.exists()) { |
|
||||
file.delete(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private List<Message> getOrCreateConversation(String conversationId) { |
|
||||
File file = getConversationFile(conversationId); |
|
||||
List<Message> messages = new ArrayList<>(); |
|
||||
if (file.exists()) { |
|
||||
try (Input input = new Input(new FileInputStream(file))) { |
|
||||
messages = kryo.readObject(input, ArrayList.class); |
|
||||
} catch (IOException e) { |
|
||||
e.printStackTrace(); |
|
||||
} |
|
||||
} |
|
||||
return messages; |
|
||||
} |
|
||||
|
|
||||
private void saveConversation(String conversationId, List<Message> messages) { |
|
||||
File file = getConversationFile(conversationId); |
|
||||
try (Output output = new Output(new FileOutputStream(file))) { |
|
||||
kryo.writeObject(output, messages); |
|
||||
} catch (IOException e) { |
|
||||
e.printStackTrace(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private File getConversationFile(String conversationId) { |
|
||||
return new File(BASE_DIR, conversationId + ".kryo"); |
|
||||
} |
|
||||
} |
|
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue