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

Spring Ai 1.0.1中存在的问题:使用MessageChatMemoryAdvisor导致System未被正确的放在首位

使用MessageChatMemoryAdvisor导致System未被正确的放在首位

如下是使用Spring Ai实现多轮对话的官方例子(文档地址:https://docs.spring.io/spring-ai/reference/api/chat-memory.html):

 @AutowiredChatMemoryRepository chatMemoryRepository;  //注入对话记忆@GetMapping("/chatMemory")@Operation(summary = "带记忆的同步调用")String chatMemory(String userInput) {// 1. 构建对话记忆存储配置// 使用MessageWindowChatMemory实现窗口记忆策略ChatMemory chatMemory = MessageWindowChatMemory.builder().chatMemoryRepository(chatMemoryRepository) // 底层记忆存储仓库(测试使用内存实现).maxMessages(20)    // 设置历史消息最大保留轮次(滑动窗口大小).build();// 2. 生成唯一会话ID(实际项目中由)String conversationId = "123456789"; // 示例固定值,生产环境需动态生成// 3. 构建对话请求并配置各组件return this.chatClient.prompt()// 3.1 设置对话角色.system(system)  // 系统角色设定(AI人设/指令)// 3.2 设置基础参数.advisors(a -> a.param(ChatMemory.CONVERSATION_ID, conversationId) // 绑定当前对话ID到请求上下文)// 3.3 添加增强功能(Advisors).advisors(new SimpleLoggerAdvisor(),  // 启用请求日志记录(用于调试)MessageChatMemoryAdvisor.builder(chatMemory).build(),   // 启用记忆管理功能)// 3.4 设置当前用户输入.user(userInput)// 3.5 执行调用.call() // 发送同步请求到对话服务// 3.6 处理响应.content(); // 提取响应中的文本内容}

如上示例是根据官方文档写的,实际测下来是有问题的,例如:有的模型在二轮对话的时候返回顺序问题报错,有的模型在二轮对话的时候丢失人设。(这个和模型的兼容性有关系)

经过排查可以发现二轮对话的Message中内容顺序会有问题(System人设被放到了倒数第二句):

[{"role": "user","content": "您好"},{"role": "assistant","content": "\n\n您好!很高兴为您提供服务。请问有什么可以帮助您的吗?"},{"role": "system","content": "你是智能助理小明"},{"role": "user","content": "你叫什么名字啊"}
]

已上述的格式请求大模型会出现各种问题,因为正常规定的顺序就是S- U- A-U。
在GitHub中有大佬给出临时解决办法,创建一个SystemFirstSortingAdvisor来确保System人设始终保持第一位:(GitHub原问题地址:https://github.com/spring-projects/spring-ai/issues/4170)

/*** 保证SYSTEM在最前面的增强*/
public class SystemFirstSortingAdvisor implements BaseAdvisor {@Overridepublic ChatClientRequest before(ChatClientRequest chatClientRequest, AdvisorChain advisorChain) {List<Message> processedMessages = chatClientRequest.prompt().getInstructions();processedMessages.sort(Comparator.comparing(m -> m.getMessageType() == MessageType.SYSTEM ? 0 : 1));return chatClientRequest.mutate().prompt(chatClientRequest.prompt().mutate().messages(processedMessages).build()).build();}@Overridepublic ChatClientResponse after(ChatClientResponse chatClientResponse, AdvisorChain advisorChain) {return chatClientResponse; // no-op}@Overridepublic int getOrder() {return 0; // larger than MessageChatMemoryAdvisor so it runs afterwards}
}

最后正确调用(在advisors中加入SystemFirstSortingAdvisor):

 @AutowiredChatMemoryRepository chatMemoryRepository;  //注入对话记忆@GetMapping("/chatMemory")@Operation(summary = "带记忆的同步调用")String chatMemory(String userInput) {// 1. 构建对话记忆存储配置// 使用MessageWindowChatMemory实现窗口记忆策略ChatMemory chatMemory = MessageWindowChatMemory.builder().chatMemoryRepository(chatMemoryRepository) // 底层记忆存储仓库(测试使用内存实现).maxMessages(20)    // 设置历史消息最大保留轮次(滑动窗口大小).build();// 2. 生成唯一会话ID(实际项目中由)String conversationId = "123456789"; // 示例固定值,生产环境需动态生成// 3. 构建对话请求并配置各组件return this.chatClient.prompt()// 3.1 设置对话角色.system(system)  // 系统角色设定(AI人设/指令)// 3.2 设置基础参数.advisors(a -> a.param(ChatMemory.CONVERSATION_ID, conversationId) // 绑定当前对话ID到请求上下文)// 3.3 添加增强功能(Advisors).advisors(new SimpleLoggerAdvisor(),  // 启用请求日志记录(用于调试)MessageChatMemoryAdvisor.builder(chatMemory).build(),   // 启用记忆管理功能new SystemFirstSortingAdvisor() // 确保系统消息优先排序)// 3.4 设置当前用户输入.user(userInput)// 3.5 执行调用.call() // 发送同步请求到对话服务// 3.6 处理响应.content(); // 提取响应中的文本内容}

综上所述,下个版本可能会优化掉这个BUG,目前就先使用SystemFirstSortingAdvisor来保证正常调用。

http://www.dtcms.com/a/343771.html

相关文章:

  • 拆解本地组策略编辑器 (gpedit.msc) 的界面和功能
  • 相似度、距离
  • 【C++】--函数参数传递:传值与传引用的深度解析
  • C++ csignal库详细使用介绍
  • CXR-LT 2024:一场关于基于胸部X线的长尾、多标签和零样本疾病分类的MICCAI挑战赛|文献速递-深度学习人工智能医疗图像
  • 25年8月通信基础知识补充1:中断概率与遍历容量、Sionna通信系统开源库、各种时延区分
  • 针对pycharm缩进空格报错--解决方法
  • Linux下的网络编程
  • 实用R语言机器学习指南:从数据预处理到模型实战(附配套学习资源)
  • 如何低门槛自制Zigbee 3.0温湿度计?涂鸦上新开发包,开箱即用、完全开源
  • 【软考架构】第6章 数据库基本概念
  • go语言中的select的用法和使用场景
  • Elasticsearch核心概念
  • SQL185 试卷完成数同比2020年的增长率及排名变化
  • C# 简单工厂模式:构建灵活与可扩展的面向对象程序
  • 【实时Linux实战系列】实时气象数据分析系统
  • 【LeetCode题解】LeetCode 287. 寻找重复数
  • SQL184 近三个月未完成试卷数为0的用户完成情况
  • XP系统安装Android Studio 3.5.3并建立Java或Native C++工程,然后在安卓手机上运行
  • 【渲染流水线】[逐片元阶段]-[混合Blend]以UnityURP为例
  • 螺旋槽曲面方程的数学建模与偏导数求解
  • Unreal Engine UProjectileMovementComponent
  • 如何生成网关路由表
  • clickhouse实战(二)
  • 关于爬虫的基本步骤说明【爬虫七步骤】
  • AI适老服务暖人心:AI适老机顶盒破数字鸿沟、毫米波雷达护独居安全,银发生活新保障
  • 大模型压缩三剑客:量化、剪枝与知识蒸馏全解析
  • Logstash——安全与权限管理
  • Swift 项目结构详解:构建可维护的大型应用
  • 【Feed-forward optimization】 in Visual Geometry Grounded and 3DGS