项目实训 | Vue3 FastAPI | NeurIPS 2025 A-MEM 复现与工程落地一、背景与动机在法律文书智能分析系统的开发过程中我们发现了一个核心痛点AI助手没有记忆。用户在第一轮对话里详细描述了案件事实——“我是原告张三2024年3月15日购买了8999元的笔记本电脑屏幕花屏联系客服三次被推诿”——但切换到新对话后AI 完全不记得这些信息用户需要反复重述。传统方案是把历史对话塞进 prompt 上下文但这有两个致命问题上下文窗口有限几十轮对话就爆 token 了信息密度低大量寒暄和重复内容浪费 token我们需要的是一种长程记忆机制自动从对话中提取关键知识持久化存储在需要时精准召回。二、技术选型A-MEMNeurIPS 2025经过调研我们选择了A-MEMAgentic Memory for LLM Agents这是 NeurIPS 2025 的一篇 Spotlight 论文提出了模仿人类 Atkinson-Shiffrin 记忆模型的三步记忆算法2.1 核心算法流程用户输入 │ ▼ ┌──────────────────────────────┐ │ Step 1: Note Construction │ LLM 抽取 keywords/context/tags │ 笔记构建 │ 构建结构化 MemoryNote 对象 └──────────────┬───────────────┘ │ ▼ ┌──────────────────────────────┐ │ Step 2: Link Generation │ ChromaDB embedding 检索 │ 关联生成 │ 召回 top-K 语义邻居建立关联边 └──────────────┬───────────────┘ │ ▼ ┌──────────────────────────────┐ │ Step 3: Memory Evolution │ LLM 判断 should_evolve │ 记忆演化 │ strengthen强化连接 │ │ update_neighbor更新邻居标签 │ │ evo_cnt threshold → consolidate └──────────────────────────────┘关键创新点记忆不是静态存储而是会演化。新记忆加入后LLM 会评估其与已有记忆的关系决定是否强化连接或更新邻居的元数据。这模拟了人脑的记忆巩固过程。2.2 技术栈组件选型说明LLMDeepSeek-Chat知识抽取 演化决策Embeddingall-MiniLM-L6-v2语义检索 (sentence-transformers)向量数据库ChromaDBA-MEM 原生支持持久化SQLite二次备份重启可恢复后端FastAPI异步 API前端Vue 3 ECharts记忆图谱可视化三、工程实现3.1 架构设计前端 (Vue3) 后端 (FastAPI) ┌─────────────┐ ┌──────────────────┐ │ AssistantView│ ──memory-chat──→ │ /api/assistant/ │ │ 聊天页面 │ │ memory-chat │ └─────────────┘ │ │ │ │ ▼ │ ┌─────────────┐ │ ┌──────────────┐ │ │ MMMemoryView │ ──graph────────→ │ │legal_memory.py│ │ │ 记忆图谱 │ │ │ A-MEM 集成层 │ │ └─────────────┘ │ └──────┬───────┘ │ │ │ │ │ ▼ │ │ ┌───────────┐ │ │ │ A-MEM 上游 │ │ │ │ (NeurIPS) │ │ │ └───────────┘ │ └──────────────────┘3.2 DeepSeek 适配Monkey-PatchA-MEM 上游代码写死了 OpenAI 的 API 格式尤其是response_formatjson_schema但 DeepSeek 不支持这个参数。解决方案是monkey-patchdefpatched_get_completion(self,prompt,response_format,temperature0.7):# 把 json_schema 内嵌进 prompt外层改用 json_objectifisinstance(fmt,dict)andfmt.get(type)json_schema:schemafmt[json_schema][schema]schema_hint\n\n仅返回合法JSON匹配schema:\njson.dumps(schema)fmt{type:json_object}# 调用 DeepSeek APIrself.client.chat.completions.create(modelself.model,messages[...],response_formatfmt,)踩坑记录DeepSeek 的json_object模式要求 system prompt 必须包含 “JSON” 关键词否则会报错。3.3 知识提取引擎核心改进这是我们对 A-MEM 的主要工程改进。原始 A-MEM 的add_note()直接存储输入文本。如果我们把用户的聊天消息原样存入记忆库就会充满 “三次客服都说啥了” 这样的废话。改进方案在对话完成后用 LLM 从用户问题 AI回复中提取结构化知识点每个知识点独立存入 A-MEM。_KNOWLEDGE_EXTRACT_PROMPT从下面的对话中提取有价值的结构化知识点。 规则 1. 只提取事实性知识不要存对话本身 2. 每条知识点必须独立可理解 3. 关注案件事实、法律依据、关键证据、时间线 返回JSON: {knowledge: [{content: ..., category: 事实|证据|法条|诉求}]}asyncdefextract_and_store_knowledge(user_msg,ai_resp):# 调用 DeepSeek 提取知识respawaithttpx.AsyncClient().post(f{base_url}/chat/completions,json{messages:[...],response_format:{type:json_object}},)itemsresp.json()[choices][0][message][content]# 每条知识独立存入 A-MEMforiteminitems[knowledge]:ms.add_note(contentitem[content])效果对比存原始消息知识提取后存入内容“三次客服都说啥了”“客服第一次说等检测第二次说人为损坏第三次不接电话”检索质量噪声多相关性低精准匹配信息密度高Token 开销存储冗余精炼节省 70%3.4 全局记忆设计最初我们按session_id隔离记忆每个对话框独立记忆但用户反馈这不符合使用习惯——“我换个对话框记忆就没了”。改为全局记忆所有对话共享同一个 ChromaDB collectionlegal_amem_globalSQLite 表amem_notes作为持久化备份。启动时从 SQLite 回放全部笔记到 ChromaDB。GLOBAL_SESSION__global__defget_legal_memory():# 全局单例跨会话共享msAgenticMemorySystem(collection_namelegal_amem_global)_replay_all_notes(ms)# 启动时从 SQLite 恢复returnms3.5 记忆图谱可视化使用 ECharts 的graph类型渲染记忆图谱节点每个 MemoryNote按类别着色事实/证据/法条/诉求边语义关联ChromaDB 检索建立 演化关联LLM 决策建立交互点击节点展开详情keywords、tags、evolution_history布局力导向布局repulsion280, gravity0.15节点 label 只展示分类名hover tooltip 显示摘要和标签避免信息过载。四、踩坑与解决4.1 ChromaDB 实例冲突问题项目原有的文档向量检索和 A-MEM 各自创建 ChromaDB 客户端导致An instance of Chroma already exists for ephemeral with different settings。解决将文档向量检索改为PersistentClientA-MEM 保持 ephemeral 模式两者不冲突。4.2 Pydantic BaseSettings 优先级问题.env文件里配了正确的 API key但后端一直报 “Invalid API key”。原因PydanticBaseSettings优先读取系统环境变量而非.env。Windows 系统上存在一个旧的OPENAI_API_KEY环境变量覆盖了.env的值。解决启动命令中显式设置环境变量确保优先级最高。4.3 PowerShell 中文编码问题PowerShell 执行含中文的python -c ...命令时字符被编码损坏导致 SyntaxError。解决将 Python 代码写入.py文件再执行设置PYTHONIOENCODINGutf-8。4.4 记忆注入方式问题最初将记忆上下文追加在用户消息末尾AI 经常忽略这部分内容。解决改为以独立的system消息注入明确告知 AI “这些是已知事实”messages.insert(1,{role:system,content:以下是与用户案件相关的长程记忆知识点视为已知信息\nmem_lines})五、项目结构backend/ ├── app/ │ ├── api/ │ │ ├── assistant.py # 聊天端点 (memory-chat 知识提取) │ │ └── mmem.py # 记忆管理 API (/notes, /search, /graph) │ └── services/ │ └── mmem/ │ ├── legal_memory.py # A-MEM 集成patch 知识引擎 │ └── migration.py # SQLite schema frontend/ ├── src/ │ ├── views/ │ │ ├── AssistantView.vue # 聊天 (含长程记忆模式) │ │ └── MMMemoryView.vue # 记忆图谱页面 │ └── api/ │ └── mmem.ts # 记忆 API 调用六、总结本次实训完成了 A-MEM 长程记忆系统从论文到工程的完整落地算法复现完整保留了 A-MEM 的三步流程Note Construction → Link Generation → Memory Evolution工程适配Monkey-patch 解决 DeepSeek 兼容、ChromaDB 冲突、全局记忆等问题创新改进知识提取引擎从对话中自动萃取结构化知识而非存储原始消息可视化ECharts 图谱直观展示记忆网络的节点和关联核心收获论文算法到工程落地之间有巨大的 gap——API 兼容、并发冲突、数据质量、用户体验——这些在论文里一笔带过的implementation details往往是实际开发中最耗时的部分。