ERP-Agent 记忆系统优化方案

一、当前架构与参考项目对比

1.1 当前实现(ERP-Agent)

核心文件:MemoryManager (backend/core/memory.py)

  • 短期记忆:滑动窗口机制(window_size=100轮 = 200条消息)

  • 持久化方式:JSON 文件存储(命名格式:{session_id}.json)

  • 元数据管理:{session_id}.meta.json(包含标题、owner、时间戳等信息)

  • 实体记忆:EntityMemory 模块(用于提取对话中的关键实体,如项目名、模块名等)

核心特点

  • ✅ 架构简单直接,易于理解和维护

  • ✅ 支持关键实体提取,辅助对话理解

  • ❌ 缺乏记忆压缩/摘要机制,无法保留早期对话信息

  • ❌ 长对话场景下,滑动窗口会丢失早期上下文

  • ❌ 无跨会话知识积累能力,会话间信息孤立

1.2 Nanobot 实现(参考项目)

核心文件:MemoryStore (nanobot/agent/memory.py)

  • 长期记忆:MEMORY.md(结构化事实存储,持续更新)

  • 历史日志:HISTORY.md(时间线式日志,支持grep搜索)

  • 自动压缩:当消息token消耗超过预算时,通过LLM自动总结归档

  • 容错机制:压缩失败3次后,直接归档原始消息

核心特点

  • ✅ 双层记忆架构(事实存储+时间线日志),分工明确

  • ✅ 自动压缩机制,确保不丢失重要信息

  • ✅ 历史日志可搜索,便于追溯对话过程

  • ✅ 支持跨会话知识积累,实现长期记忆

  • ❌ 实现复杂,需额外调用LLM,增加成本和复杂度

1.3 Claw-Code 实现(参考项目)

核心模块:Session Memory(Rust语言实现)

  • 消息历史:完整保留所有消息,按token预算进行裁剪

  • 项目上下文:整合Git状态、配置文件、指令文件等项目相关信息

  • 状态跟踪:实时统计message_count、turns、token使用量等指标

  • 配置加载:支持多层配置文件(项目级、用户级),适配不同场景

核心特点

  • ✅ 具备项目上下文感知能力,可关联Git、配置等外部信息

  • ✅ 完善的Token预算管理,精准控制上下文规模

  • ✅ 多层配置系统,适配不同使用场景

  • ❌ 缺乏记忆压缩机制,长对话仍可能出现信息冗余

二、优化方案(分阶段实施)

阶段1:增强当前记忆系统(低成本,高收益)

1.1 添加 Token 预算管理

当前问题:仅按消息数量(100轮)裁剪上下文,未考虑消息实际token消耗,可能出现短消息未达数量上限但token超标的情况,或长消息未达数量却已超出LLM上下文窗口。

优化方案:在MemoryManager类中新增max_tokens参数,实现按token预算裁剪上下文,代码调整如下:

python 复制代码
class MemoryManager:
    def __init__(
        self,
        persist_dir: str = "./rag_data/memory",
        window_size: int = 100,
        max_tokens: int = 8000,  # 新增:最大 token 预算
    ):
        self.max_tokens = max_tokens
    
    def _trim(self, session_id: str):
        # 新增逻辑:计算当前上下文token总量,超过max_tokens时裁剪
        # 优先保留最新消息,确保关键上下文不丢失
        pass

实施收益

  • 实现更精确的上下文控制,适配LLM的上下文窗口限制

  • 避免因长消息导致的token超标问题,提升对话稳定性

  • 区分长消息和短消息,合理利用token预算,减少不必要的裁剪

1.2 添加会话摘要(Session Summary)

当前问题:滑动窗口机制会直接丢弃早期对话内容,导致LLM无法获取对话前期的关键信息,影响对话连贯性和准确性。

优化方案:在MemoryManager中新增会话摘要生成方法,基于规则提取早期对话关键信息,存入元数据文件,代码如下:

python 复制代码
class MemoryManager:
    def get_session_summary(self, session_id: str) -> str:
        """生成会话摘要(关键信息提取)"""
        meta = self._read_meta(session_id)
        
        # 如果已有摘要,直接返回,避免重复生成
        if "summary" in meta:
            return meta["summary"]
        
        # 否则,从历史消息中提取关键信息(规则提取,无需LLM调用)
        # 提取规则:用户核心需求、关键操作、重要结果、实体信息等
        history = self.get_history(session_id)
        summary = self._extract_key_info(history)
        
        # 将摘要存入元数据,持久化保存
        meta["summary"] = summary
        self._write_meta(session_id, meta)
        return summary

使用场景:在系统提示词中注入会话摘要,帮助LLM理解对话背景,代码示例如下:

复制代码

# 在系统提示词中注入会话摘要 summary = memory.get_session_summary(session_id) if summary: system_prompt += f"\n\n## 会话背景\n{summary}\n"

实施收益

  • 保留早期对话的关键信息,避免因滑动窗口裁剪导致的信息丢失

  • 帮助LLM快速掌握对话背景,提升回复的准确性和连贯性

  • 采用规则提取方式,无需额外调用LLM,成本低、效率高

1.3 增强实体记忆(EntityMemory)

当前问题:实体记忆(EntityMemory)与主记忆(对话历史、摘要)独立存在,未实现联动,导致LLM无法同时获取实体信息和对话上下文,影响对话理解能力。

优化方案:新增统一的上下文生成接口,整合会话摘要、实体记忆和操作历史,为LLM提供完整的上下文信息,代码如下:

python 复制代码
class MemoryManager:
    def get_context_for_llm(self, session_id: str) -> str:
        """生成完整的上下文信息(摘要 + 实体 + 近期对话)"""
        parts = []
        
        # 1. 会话摘要(早期关键信息)
        summary = self.get_session_summary(session_id)
        if summary:
            parts.append(f"## 会话背景\n{summary}")
        
        # 2. 实体记忆(关键实体信息)
        entity_memory = self.get_entity_memory(session_id)
        if entity_memory:
            parts.append(f"## 关键实体\n{entity_memory}")
        
        # 3. 近期对话(滑动窗口内的最新消息)
        recent_history = self.get_recent_history(session_id)
        if recent_history:
            parts.append(f"## 近期对话\n{recent_history}")
        
        # 拼接所有部分,返回完整上下文
        return "\n\n".join(parts) if parts else ""

实施收益

  • 提供统一的上下文接口,简化LLM调用逻辑

  • 整合摘要、实体、近期对话,为LLM提供更完整的对话上下文

  • 强化实体信息的利用,提升LLM对业务场景(如ERP查询)的理解能力

阶段2:借鉴 Nanobot 的双层记忆(中等成本)

2.1 添加 MEMORY.md(长期事实)与 HISTORY.md(时间线日志)

设计方案:调整记忆存储目录结构,新增长期事实文件和时间线日志文件,实现短期记忆与长期记忆的分离存储,目录结构如下:

python 复制代码
rag_data/memory/{session_id}/
├── messages.json          # 当前实现(短期记忆,滑动窗口内消息)
├── messages.meta.json     # 元数据(含会话摘要、owner、时间戳等)
├── MEMORY.md             # 新增:长期事实(结构化存储关键信息)
└── HISTORY.md            # 新增:时间线日志(可搜索,记录完整对话轨迹)

MEMORY.md 示例

python 复制代码
# 会话记忆:ERP 查询助手

## 用户偏好
- 喜欢以表格形式展示查询结果
- 关注组织 ID 86 的相关数据

## 已知数据库信息
- 主要使用 APPS schema
- 常用表:HR_OPERATING_UNITS(组织表)
- 连接信息:APPS / app_3hincerp / HEHE_SIT / Normal

## 关键操作记录
- 已查询组织 ID 86 的基本信息,结果为:NAME=XX公司,ORGANIZATION_ID=86
- 已调用知识库检索,获取 ERP 组织管理相关文档3份

HISTORY.md 示例

复制代码

# 会话历史日志 [2026-04-14 17:10] 用户查询组织 ID 86 的信息 - 调用工具:search_knowledge_base - 检索到 3 个文档 - 调用工具:query_oracle_data - SQL: SELECT NAME, ORGANIZATION_ID FROM APPS.HR_OPERATING_UNITS WHERE ORGANIZATION_ID = 86 - 结果:1 行数据(NAME=XX公司,ORGANIZATION_ID=86) [2026-04-14 17:15] 用户要求以表格形式展示上述结果 - 响应:生成表格展示查询结果,用户确认无误 [2026-04-14 17:20] 用户询问该组织的关联数据表 - 调用工具:query_oracle_metadata - 检索到关联表:HR_EMPLOYEES、HR_DEPARTMENTS - 响应:返回关联表信息及简要说明

2.2 自动压缩机制(可选,暂缓实施)

触发条件:满足以下任一条件时,触发记忆压缩:

  • 消息数超过200条

  • 当前上下文token消耗超过10000

压缩流程

复制代码

async def consolidate_memory(self, session_id: str): """将旧消息压缩到 MEMORY.md,释放短期记忆空间""" history = self.get_history(session_id) # 1. 取出最早的 50 条消息(可配置),作为压缩对象 to_consolidate = history[:50] # 2. 调用 LLM 提取关键信息,更新到 MEMORY.md prompt = f""" 分析以下对话内容,提取关键信息并更新到结构化事实中,要求: 1. 保留用户核心需求、关键操作、重要结果 2. 补充新的实体信息、配置信息、用户偏好 3. 语言简洁,结构化呈现(分章节、分点) 4. 不保留冗余的对话交互细节 对话内容: {to_consolidate} """ # 调用LLM生成压缩后的关键信息 consolidated_info = await llm_client.generate(prompt) # 3. 将压缩信息追加到 MEMORY.md self._append_to_memory_md(session_id, consolidated_info) # 4. 删除已压缩的旧消息,释放短期记忆空间 self._delete_history(session_id, to_consolidate) # 5. 容错处理:若压缩失败3次,直接将原始消息归档到HISTORY.md pass

实施收益

  • 实现长对话支持,避免早期关键信息丢失

  • 支持跨会话知识积累,后续会话可复用历史关键信息

  • 时间线日志可搜索,便于管理员追溯对话过程、排查问题

阶段3:借鉴 Claw-Code 的项目上下文(高级,可选)

3.1 项目上下文感知

设计方案:新增ProjectContext类,整合项目相关的上下文信息(Git状态、配置文件、Oracle连接历史等),为LLM提供更全面的业务场景信息,代码如下:

复制代码

class ProjectContext: """项目上下文管理,整合项目相关的外部信息""" def __init__(self, workspace: Path): self.workspace = workspace # 项目工作目录 self.git_context = self._get_git_context() # Git状态信息 self.config_context = self._get_config_context() # 配置文件信息 self.db_context = self._get_db_context() # 数据库连接历史 def _get_git_context(self) -> str: """获取Git状态上下文(分支、提交记录、未提交修改等)""" # 调用git命令获取当前分支、最近提交信息等 pass def _get_config_context(self) -> str: """获取项目配置上下文(项目级、用户级配置)""" # 读取多层配置文件,提取关键配置信息(如ERP系统地址、端口等) pass def _get_db_context(self) -> str: """获取数据库连接上下文(历史连接信息、常用表等)""" # 从记忆系统中提取Oracle连接历史、常用表信息等 pass def get_context(self) -> str: """获取完整的项目上下文,用于注入系统提示词""" parts = [] if self.git_context: parts.append(f"## Git 项目状态\n{self.git_context}") if self.config_context: parts.append(f"## 项目配置信息\n{self.config_context}") if self.db_context: parts.append(f"## 数据库上下文\n{self.db_context}") return "\n\n".join(parts) if parts else ""

使用方式:在系统提示词中注入项目上下文,提升LLM对业务场景的感知能力:

复制代码

# 在系统提示词中注入项目上下文 project_ctx = ProjectContext(workspace).get_context() system_prompt += f"\n\n{project_ctx}\n"

实施收益

  • 实现更智能的上下文感知,LLM可获取项目相关的外部信息

  • 减少用户重复输入配置信息(如Oracle连接信息),提升交互效率

  • 适配ERP业务场景,帮助LLM更好地理解项目相关的查询和操作需求

三、推荐实施顺序(4周规划)

第1周:阶段1.1 + 1.2 + 1.3(立即可做,低成本高收益)

  • ✅ 完成Token预算管理功能开发与测试

  • ✅ 实现会话摘要生成(规则提取方式),并集成到元数据管理

  • ✅ 开发统一上下文接口,实现摘要、实体记忆与近期对话的联动

预期收益:快速解决当前核心问题,实现上下文的精准控制和早期信息保留,无需额外成本,提升对话稳定性和准确性。

第2-3周:阶段2.1(需要测试,中等成本)

  • ✅ 调整记忆存储目录结构,新增MEMORY.md和HISTORY.md文件

  • ✅ 实现手动压缩功能(管理员触发),将旧消息关键信息归档到MEMORY.md

  • ⏸️ 自动压缩功能暂缓实施(需额外LLM调用,成本高且需容错设计)

预期收益:实现长对话支持和跨会话知识积累,历史日志可搜索,便于问题追溯和知识复用。

第4周:阶段3.1(可选,高级优化)

  • ✅ 开发ProjectContext类,实现Git状态、项目配置的感知

  • ✅ 整合Oracle连接历史、常用表信息,完善数据库上下文

  • ✅ 将项目上下文注入系统提示词,优化LLM业务场景理解能力

预期收益:进一步提升ERP-Agent的智能化水平,减少重复配置,适配更复杂的业务场景。

四、核心建议

优先级1:Token 预算管理(必做)

当前按消息数量裁剪上下文的方式不够精确,易导致token超标或信息浪费,改为按token预算裁剪是解决长对话稳定性问题的核心,开发成本低、收益高,必须优先实施。

优先级2:会话摘要(推荐)

采用规则提取方式生成会话摘要,无需额外调用LLM,可有效保留早期对话关键信息,帮助LLM理解对话背景,提升回复准确性,是低成本高收益的优化点,推荐紧随Token预算管理实施。

优先级3:双层记忆(可选)

适合长期使用、需要跨会话知识积累的场景(如长期ERP查询助手),但需要额外的开发和测试成本,建议在阶段1验证效果后,根据实际业务需求决定是否实施。

不推荐:自动压缩(暂缓)

自动压缩需要额外调用LLM,增加成本和系统复杂度,且存在压缩失败的风险,需设计完善的容错机制。建议在业务场景确实需要长对话自动管理时,再考虑实施。

总结:建议优先实施阶段1的优化内容,快速解决当前核心问题、验证效果;后续根据业务需求,逐步推进阶段2和阶段3的优化,平衡开发成本与业务收益。

相关推荐
coderlin_2 小时前
Langgraph项目 一(mysql,es,qdrant,embedding模块)
mysql·elasticsearch·embedding
灵途科技2 小时前
灵途科技董事长李传文受聘华科大光电分会副会长,参与产业协同发展
大数据·科技
java1234_小锋2 小时前
Java高频面试题:Spring框架中的单例bean是线程安全的吗?
java·spring·面试
Tingjct2 小时前
C++ 多态
java·开发语言·c++
Devin~Y2 小时前
大厂Java面试实战:Spring Boot/WebFlux、Redis+Kafka、K8s可观测性与Spring AI RAG/Agent三轮连环问
java·spring boot·redis·kafka·kubernetes·resilience4j·spring webflux
花间相见2 小时前
【AI私人家庭医生day01】—— 项目介绍
大数据·linux·人工智能·python·flask·conda·ai编程
renhongxia12 小时前
人机智能体合作:承诺理论考虑
大数据·人工智能·深度学习·语言模型·自然语言处理·transformer
工頁光軍2 小时前
论文:面向长期存续的数字社会型智能体矩阵架构设计与演进研究
大数据·人工智能
倒流时光三十年2 小时前
Elasticsearch SearchRequest 构建备忘录
大数据·elasticsearch