
之前在做基于大模型的开源 Agent 项目时一直有一个很头疼的问题AI Agent 每次对话结束就好像“失忆”了一样第二次再问它同样的问题它完全不记得你上次说过什么、做过什么、纠正过它什么。尤其是像 Hermes 这类追求轻量、灵活的智能体框架默认情况下只具备上下文窗口内的短期记忆一旦会话结束所有的“经验”都会归零。后来我参考了 RAG检索增强生成、向量数据库、长期记忆分层设计等思路给 Hermes 做了一套“记忆外挂”效果非常明显同一个 Agent 在经过几轮纠偏之后能记住用户的偏好、项目背景、常用术语甚至能基于历史对话做出更合理的推断。这篇文章就把这套方案完整拆解出来。内容涵盖记忆系统的概念设计、环境准备、核心代码实现、Hermes 集成方式、部署建议和常见问题排查。适合正在做 AI Agent 应用开发、想给聊天机器人或智能体增加持久化记忆能力的开发者。1. Hermes 是什么为什么需要记忆外挂1.1 Hermes 快速认知Hermes 在 AI 开源社区里是一个相对活跃的名字。它既指代基于 LLaMA 等底座模型微调出的 Hermes 系列模型也指一些以 Hermes 命名的轻量级 Agent 智能体项目。无论是哪一种形态它的核心定位都比较一致让大模型能够更自主地完成多步任务而不仅仅是被动地一问一答。与传统的 Prompt 调用不同Agent 类项目通常具备工具调用Function Call / Tool Use、任务规划Planning、环境交互Environment Interaction等能力。Hermes 这类项目把这些能力封装成了相对简洁的框架开发者可以在上面快速搭建自己的 AI 助手、自动化脚本、知识库问答机器人等。1.2 没有记忆的 Agent 有多难用刚接触 Agent 开发的人可能觉得大模型本身已经记住了海量知识为什么还要额外做记忆系统这里要区分两组概念参数记忆模型在训练阶段学到的知识存储在神经网络权重里知识截止到训练数据时间点。上下文记忆模型在推理阶段看到的对话历史存在于窗口上下文中用完即弃。普通聊天场景下上下文记忆基本够用。但 Agent 场景不同它需要理解一个持续多轮的目标比如“帮我监控服务器状态异常时通知我”“根据我的写作风格生成周报”“记住我常用的数据库连接配置”。如果没有长期记忆Agent 每次都是从零开始理解任务会出现下面这些尴尬情况用户已经明确说过“数据库地址是 127.0.0.1:3306不要用生产库”下一轮 Agent 又忘了。用户纠正了 Agent 的称呼习惯比如“以后都叫我老板”Agent 几轮后又恢复成直呼其名。Agent 根据历史经验本可以避免某些错误但因为没有记忆同一个坑反复踩。这些问题本质上不是因为模型不够聪明而是因为缺少一条从“短期会话上下文”到“长期可检索记忆”的通道。1.3 记忆外挂的解决思路所谓“记忆外挂”就是给 Agent 增加一个会话之外的持久化存储与检索层。核心思路并不复杂对话过程中系统自动提取有价值的信息用户偏好、任务结论、关键术语、纠偏指令经过向量化或其他结构化处理后存入存储介质下次对话开始时再根据当前输入召回相关的历史片段作为额外的上下文注入给模型。这个思路其实和 RAG 很相似区别在于RAG 通常检索的是静态知识库文档而记忆系统检索的是动态更新的、与用户和任务强相关的历史经验。2. 整体架构与记忆分层设计2.1 三层记忆模型在给 Hermes 设计记忆系统时可以参考认知科学中的记忆分层思路把记忆划分为三层记忆层级对应实现生命周期典型内容工作记忆当前会话上下文窗口单次会话最近几轮对话、工具调用中间结果情景记忆向量数据库中的历史会话摘要数天到数月某次任务的执行过程、用户纠偏记录语义记忆结构化偏好与事实表长期用户称呼、常用配置、业务术语、偏好设置工作记忆不需要额外开发大模型上下文天然支持。我们需要重点建设的是后两层。2.2 系统模块划分整个记忆外挂可以拆成四个核心模块记忆提取Memory Extractor从每轮对话和 Agent 执行日志中提取值得记住的信息。记忆存储Memory Store把提取到的信息写入持久化存储包括向量索引和结构化 KV 存储。记忆检索Memory Retriever在新对话开始时根据用户输入召回相关记忆。记忆注入Memory Injector把召回到的记忆片段整理成 Prompt 上下文交给 Hermes。这四个模块拧在一起就形成了 Agent 的“长期记忆闭环”。3. 环境准备与版本说明3.1 基础环境本文涉及的代码以 Python 为主建议准备以下环境操作系统Windows 10/11、macOS、Linux 均可Python3.9 及以上版本包管理工具pip 或 conda数据库SQLite内置零配置用于存储结构化记忆可选安装 Redis 用于缓存高频记忆需要说明的是Hermes 本身可能存在不同版本和分支不同版本的 API 设计会有差异。本文的重点是提供一套与框架无关的记忆层实现思路你在集成到自己使用的 Hermes 版本时只需要把记忆服务的输入输出接入对应的事件回调或工具调用处即可。3.2 安装依赖创建一个新的项目目录并准备虚拟环境mkdir hermes-memory cd hermes-memory python -m venv venv source venv/bin/activate # Windows 使用 venv\Scripts\activate需要安装的核心依赖如下pip install fastapi uvicorn numpy openai其中 FastAPI 用于提供记忆服务 HTTP 接口方便 Hermes 以工具调用的方式访问numpy 用于实现轻量级向量相似度计算openai 是 OpenAI 兼容接口的 Python SDK用来对接 Embedding 模型和对话模型。3.3 关于 Embedding 模型的选择记忆检索的核心是“语义相似度计算”。最简单可靠的方式是调用大模型厂商提供的 Embedding API。如果你使用的是 DeepSeek、OpenAI 或国内主流大模型平台大部分都提供了 Embedding 接口用法类似from openai import OpenAI client OpenAI( api_keyyour-api-key, base_urlhttps://your-embedding-endpoint ) resp client.embeddings.create( modelyour-embedding-model, input需要向量化的文本 ) vector resp.data[0].embedding如果你不方便调用外部 Embedding API也可以先使用 TF-IDF 或 BM25 这类传统文本检索算法做降级方案。文章后面会给出这种替代实现。4. 核心代码从零实现一个轻量记忆服务4.1 项目结构先规划目录结构hermes-memory/ ├── app.py # FastAPI 入口 ├── memory/ │ ├── __init__.py │ ├── extractor.py # 记忆提取器 │ ├── store.py # 记忆存储层 │ ├── retriever.py # 记忆检索器 │ └── injector.py # 记忆注入与 Prompt 组装 ├── data/ # SQLite 数据文件目录 │ └── memory.db └── requirements.txt4.2 记忆存储层首先实现最底层的存储层。考虑到大多数个人项目和中小型团队的部署成本这里先用 SQLite 作为持久化方案一张表存记忆文本和元信息一张表存向量。编辑memory/store.pyimport sqlite3 import json import numpy as np from datetime import datetime import os DB_PATH os.path.join(os.path.dirname(__file__), .., data, memory.db) class MemoryStore: def __init__(self, db_path: str DB_PATH): os.makedirs(os.path.dirname(db_path), exist_okTrue) self.conn sqlite3.connect(db_path, check_same_threadFalse) self._create_tables() def _create_tables(self): cursor self.conn.cursor() cursor.execute( CREATE TABLE IF NOT EXISTS memories ( id INTEGER PRIMARY KEY AUTOINCREMENT, content TEXT NOT NULL, memory_type TEXT DEFAULT episodic, user_id TEXT DEFAULT default, created_at TEXT NOT NULL ) ) cursor.execute( CREATE TABLE IF NOT EXISTS memory_vectors ( memory_id INTEGER PRIMARY KEY, vector BLOB NOT NULL, FOREIGN KEY (memory_id) REFERENCES memories(id) ) ) self.conn.commit() def add_memory(self, content: str, memory_type: str episodic, user_id: str default, vector: list None): 写入一条记忆可选附带向量 now datetime.now().isoformat() cursor self.conn.cursor() cursor.execute( INSERT INTO memories (content, memory_type, user_id, created_at) VALUES (?, ?, ?, ?), (content, memory_type, user_id, now) ) memory_id cursor.lastrowid if vector is not None: vector_blob np.asarray(vector, dtypenp.float32).tobytes() cursor.execute( INSERT INTO memory_vectors (memory_id, vector) VALUES (?, ?), (memory_id, vector_blob) ) self.conn.commit() return memory_id def get_all_memories(self, user_id: str default): 读取某用户全部记忆文本 cursor self.conn.cursor() cursor.execute( SELECT id, content, memory_type, created_at FROM memories WHERE user_id ? ORDER BY id DESC, (user_id,) ) rows cursor.fetchall() return [ {id: row[0], content: row[1], type: row[2], created_at: row[3]} for row in rows ] def get_all_vectors(self, user_id: str default): 读取该用户全部向量用于内存中相似度计算 cursor self.conn.cursor() cursor.execute( SELECT m.id, m.content, mv.vector FROM memories m JOIN memory_vectors mv ON m.id mv.memory_id WHERE m.user_id ? , (user_id,)) rows cursor.fetchall() result [] for row in rows: vector np.frombuffer(row[2], dtypenp.float32) result.append({id: row[0], content: row[1], vector: vector}) return result这段代码里要注意两个点check_same_threadFalse是为了让 FastAPI 的异步线程能够共享同一个 SQLite 连接简单场景够用生产环境建议改用连接池或用独立的数据库中间件。向量以 BLOB 格式存储读取时通过np.frombuffer还原为 numpy 数组。4.3 记忆提取器记忆提取器负责判断哪些信息值得保存。最理想的做法是让大模型来做这件事给它一段对话历史让它输出结构化摘要。编辑memory/extractor.pyimport json from openai import OpenAI class MemoryExtractor: def __init__(self, api_key: str, base_url: str, model: str gpt-4o-mini): self.client OpenAI(api_keyapi_key, base_urlbase_url) self.model model def extract(self, conversation: list) - list: 从对话历史中抽取值得长期记住的信息 messages [ { role: system, content: ( 你是一个长期记忆提取器。请从用户和助手的对话中提取出 值得长期记忆的事实性信息例如用户偏好、称呼、项目背景、 常用配置、纠偏指令、明确表态等。 输出 JSON 数组每个元素包含 content记忆内容和 memory_typesemantic 或 episodic。 不要输出记忆之外的任何文字。 ), }, { role: user, content: json.dumps(conversation, ensure_asciiFalse), }, ] resp self.client.chat.completions.create( modelself.model, messagesmessages, temperature0.2, ) raw resp.choices[0].message.content.strip() raw raw.replace(json, ).replace(, ).strip() try: return json.loads(raw) except json.JSONDecodeError: return []在实际项目中不一定要每一轮对话都调用一次提取模型。可以设置一个简单的策略每累积 35 轮对话或者检测到“用户纠正”“用户明确表态”等关键信号时再触发一次提取。如果你不想频繁调用大模型还可以用基于规则的关键词匹配做降级比如检测“记住”“以后”“不要”“我喜欢”等前缀。4.4 记忆检索器记忆检索器负责在对话开始前查询历史记忆。核心逻辑是将当前用户输入转化为向量然后与存储中的历史记忆向量进行余弦相似度计算返回 Top K 个最相关的结果。编辑memory/retriever.pyimport numpy as np from .store import MemoryStore class MemoryRetriever: def __init__(self, store: MemoryStore, api_key: str, base_url: str, embedding_model: str): self.store store self.api_key api_key self.base_url base_url self.embedding_model embedding_model def _embed(self, text: str) - list: from openai import OpenAI client OpenAI(api_keyself.api_key, base_urlself.base_url) resp client.embeddings.create( modelself.embedding_model, inputtext ) return resp.data[0].embedding def cosine_similarity(self, vec_a: np.ndarray, vec_b: np.ndarray) - float: dot np.dot(vec_a, vec_b) norm_a np.linalg.norm(vec_a) norm_b np.linalg.norm(vec_b) if norm_a 0 or norm_b 0: return 0.0 return float(dot / (norm_a * norm_b)) def retrieve(self, query: str, top_k: int 5, user_id: str default) - list: query_vector np.asarray(self._embed(query), dtypenp.float32) candidates self.store.get_all_vectors(user_iduser_id) scored [] for item in candidates: sim self.cosine_similarity(query_vector, item[vector]) scored.append({content: item[content], score: sim}) scored.sort(keylambda x: x[score], reverseTrue) return scored[:top_k]这里有几点需要说明每次检索都调用 Embedding API 会有一定延迟。实际项目中建议把用户输入向量缓存到 Redis或者本地做一个简单 LRU 缓存。如果记忆条目非常多超过数万条遍历计算相似度的性能会明显下降。这时候需要升级为专门的向量数据库比如 Chroma、Milvus 或 Qdrant但整体设计思路不变。如果不想依赖外部 Embedding 接口可以用 TF-IDF 特征向量替代后面小节给出代码。4.5 记忆注入器检索到相关记忆之后需要把它整合到 Hermes 的 Prompt 里。这里要注意格式不能让记忆上下文干扰主对话。编辑memory/injector.pyclass MemoryInjector: staticmethod def build_memory_block(memories: list) - str: 把检索到的记忆拼装成统一的系统提示片段 if not memories: return lines [以下是该用户的历史记忆请在回答时参考] for idx, item in enumerate(memories, start1): score round(item.get(score, 0), 4) lines.append(f{idx}. {item[content]} (相关度: {score})) return \n.join(lines)在集成时你只需要把这段记忆文本插入到 Hermes 系统 Prompt 的最前面或最后面。建议放在最前面让模型优先读到历史记忆作为回答的背景信息。4.6 FastAPI 服务入口最后把上述模块封装成 HTTP 接口便于 Hermes 以工具调用或插件方式接入。编辑app.pyfrom fastapi import FastAPI from pydantic import BaseModel from memory.store import MemoryStore from memory.retriever import MemoryRetriever from memory.extractor import MemoryExtractor from memory.injector import MemoryInjector app FastAPI(titleHermes Memory Service) store MemoryStore() retriever MemoryRetriever( storestore, api_keyyour-api-key, base_urlhttps://your-embedding-endpoint, embedding_modelyour-embedding-model ) extractor MemoryExtractor( api_keyyour-api-key, base_urlhttps://your-chat-endpoint, modelyour-chat-model ) class SaveRequest(BaseModel): conversation: list user_id: str default class QueryRequest(BaseModel): query: str top_k: int 5 user_id: str default app.post(/memory/save) def save_memory(req: SaveRequest): 保存对话记忆提取 向量化 存储 memories extractor.extract(req.conversation) saved_count 0 for mem in memories: vector retriever._embed(mem[content]) store.add_memory( contentmem[content], memory_typemem.get(memory_type, episodic), user_idreq.user_id, vectorvector ) saved_count 1 return {status: ok, saved: saved_count} app.post(/memory/recall) def recall_memory(req: QueryRequest): 召回相关记忆并返回注入文本 memories retriever.retrieve(req.query, top_kreq.top_k, user_idreq.user_id) block MemoryInjector.build_memory_block(memories) return {memory_block: block, memories: memories}启动服务uvicorn app:app --host 0.0.0.0 --port 8010启动后可以用 curl 做一次简单验证curl -X POST http://localhost:8010/memory/recall \ -H Content-Type: application/json \ -d {query: 服务器部署在哪个环境, user_id: test}返回结果中会带有一段记忆注入文本。5. 将记忆服务集成到 Hermes5.1 集成方式一工具调用Function Calling大部分 Hermes 类 Agent 框架都支持工具调用。你可以把记忆服务封装成两个工具让 Agent 在需要的时候主动调用save_memory(conversation)在对话结束或 Agent 完成任务时调用保存本轮有价值的记忆。recall_memory(query)在对话开始时或 Agent 觉得信息不足时调用补充历史背景。工具定义的大致写法如下以 JSON Schema 格式为例{ type: function, function: { name: recall_memory, description: 根据用户当前问题从长期记忆中检索相关历史信息, parameters: { type: object, properties: { query: { type: string, description: 用户当前输入或要查询的关键信息 } }, required: [query] } } }当 Hermes 收到用户提问后如果识别到当前问题可能依赖历史背景就会自动调用recall_memory把返回的memory_block作为额外上下文完成回答。5.2 集成方式二请求钩子Hook / 中间件如果你的 Hermes 版本不支持工具调用或者你希望“无感”注入记忆可以在请求处理链路中增加一个钩子。伪代码示例如下def before_agent_run(user_input, user_id): # 构造检索请求 memories call_memory_service(recall, { query: user_input, user_id: user_id }) # 拼接到系统 Prompt extra_context memories[memory_block] system_prompt build_system_prompt(extra_context) return system_prompt这种方式的侵入性更小只需要修改 Agent 启动时的 Prompt 组装逻辑。5.3 与对话循环的完整联动下面描述一个完整的记忆联动流程用户向 Hermes 发送消息。Hermes 启动前通过recall_memory检索与该用户相关的历史记忆。检索结果注入系统 Prompt。Hermes 正常执行任务得到回复。回复发送给用户后后台异步调用save_memory把“用户消息 Agent回复 用户反馈”打包提取记忆并存储。把第 5 步做成异步很重要否则每次对话都会增加一次或多次大模型调用延迟影响用户体验。6. 不依赖外部 Embedding 的降级方案如果你暂时没有可用的 Embedding API或者不想让私密对话内容经过外部接口可以使用传统的 TF-IDF 特征向量配合余弦相似度做记忆检索。这种方式对短文本的语义理解能力弱一些但在“关键词强相关”的场景下效果依然可用。import math from collections import Counter import jieba class TfidfRetriever: def __init__(self): self.doc_freq Counter() self.doc_count 0 self.doc_vectors [] def tokenize(self, text: str) - list: return [w for w in jieba.cut(text) if w.strip()] def fit(self, docs: list): self.doc_count len(docs) for doc in docs: words set(self.tokenize(doc)) for w in words: self.doc_freq[w] 1 def tfidf_vector(self, text: str) - dict: tf Counter(self.tokenize(text)) total sum(tf.values()) vec {} for word, count in tf.items(): df self.doc_freq.get(word, 0) idf math.log((self.doc_count 1) / (df 1)) 1 vec[word] (count / total) * idf return vec def cosine(self, vec_a: dict, vec_b: dict) - float: common set(vec_a.keys()) set(vec_b.keys()) dot sum(vec_a[w] * vec_b[w] for w in common) norm_a math.sqrt(sum(v * v for v in vec_a.values())) norm_b math.sqrt(sum(v * v for v in vec_b.values())) if norm_a 0 or norm_b 0: return 0.0 return dot / (norm_a * norm_b)注意使用中文分词时需要安装 jiebapip install jieba这个降级方案的检索精度不如向量模型但在个人项目或调试阶段足够用。7. 部署与运行验证7.1 本地运行验证在本地启动记忆服务后你可以写一个简单的 Python 脚本验证“保存后能否召回”。import requests # 模拟保存记忆 save_resp requests.post(http://localhost:8010/memory/save, json{ conversation: [ {role: user, content: 以后所有的数据库密码都存在 Vault 里不要写在配置文件中}, {role: assistant, content: 好的已经记住。后续数据库密码统一从 Vault 获取。} ], user_id: user01 }) print(save:, save_resp.json()) # 模拟召回记忆 recall_resp requests.post(http://localhost:8010/memory/recall, json{ query: 密码管理用什么方案, top_k: 3, user_id: user01 }) print(recall:, recall_resp.json())如果保存和召回都正常说明记忆链路已经打通。7.2 Docker 部署参考如果后续要把记忆服务部署到服务器可以考虑用 Docker Compose 统一管理记忆服务和数据库。下面是一个最小化的 Dockerfile 示例FROM python:3.10-slim WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple COPY . . EXPOSE 8010 CMD [uvicorn, app:app, --host, 0.0.0.0, --port, 8010]配合一个简单的docker-compose.ymlversion: 3.8 services: memory-service: build: . container_name: hermes-memory ports: - 8010:8010 volumes: - ./data:/app/data environment: - OPENAI_API_KEY${OPENAI_API_KEY} - EMBEDDING_BASE_URL${EMBEDDING_BASE_URL} - EMBEDDING_MODEL${EMBEDDING_MODEL} restart: unless-stopped使用.env文件管理密钥和模型地址避免把密钥写死在代码里。7.3 Windows 环境部署说明如果你用的是 Windows 系统需要注意下面几点虚拟环境激活命令为venv\Scripts\activate不是source venv/bin/activate。如果使用 Docker Desktop确保 WSL2 后端已开启。路径含中文时SQLite 连接可能遇到编码问题建议db_path使用绝对路径或统一使用英文目录。uvicorn 在 Windows 下建议不要开多 worker避免 SQLite 并发写锁问题。8. 常见问题与排查思路8.1 问题现象表问题现象常见原因解决思路保存记忆时接口超时提取模型响应过慢或触发了外部 API 限流将保存改为异步任务增加超时重试控制提取触发频率召回的回忆内容完全不相关Embedding 模型效果不佳或向量维度不一致检查 embedding 模型是否前后一致尝试切换更强的 Embedding 模型SQLite 报 database is locked多个线程同时写入使用check_same_threadFalse减少并发写入生产换 PostgreSQL 或 MySQL调用 /memory/save 没有保存任何记录大模型提取结果不是标准 JSON增加 JSON 解析容错考虑增加少量 prompt 示例记忆越来越多检索越来越慢全表遍历向量相似度引入向量数据库增加记忆条数上限和过期淘汰策略注入记忆后模型回答受影响记忆块格式不清晰或内容与当前问题无关增加相关度阈值把记忆放在独立 system 消息中8.2 记忆检索不准确的排查顺序如果你觉得 Agent 记忆效果不好建议按下面顺序排查先看原始记忆内容是否正确。很多问题出在“记忆提取”阶段保存了太多无意义内容。再看向量相似度分数。如果最高分都低于 0.3说明检索不到与当前问题语义相近的记忆。检查 Prompt 注入位置和格式。模型对记忆块的敏感度很高如果与系统指令混在一起可能被忽略。最后验证 Embedding 模型是否适合你的语言和场景。8.3 明确边界记忆不是万能药记忆外挂能显著提升 Agent 的个性化能力但它不是万能的。下面几种情况不适合硬套记忆系统对实时性要求极高的数据如股价、库存应该走实时 API而不是记忆。用户明确不想被记录的隐私内容不应该入库。过期的临时性信息比如“今晚 8 点开会”不需要放到长期记忆里否则会造成干扰。记忆系统应该具备“遗忘”机制。最简单的方式是要么在提取阶段就过滤掉时效性信息要么在存储时给记忆加上过期时间定期清理。9. 最佳实践与工程建议9.1 记忆内容宁缺毋滥保存记忆时会调用大模型提取消耗 token也会增加系统复杂度。建议遵循“宁缺毋滥”的原则只保存用户明确表达的偏好和事实。只保存可复用的配置和流程。不要保存临时性、一次性信息。可以在每次提取后让模型给记忆打分低于阈值就不保存。9.2 多用户隔离如果你的 Hermes 要给多个用户使用必须在存储和检索时都加上user_id维度避免用户 A 的记忆被用户 B 的对话检索到。这个看似基础的要求在实际开发中经常被遗漏。9.3 敏感信息过滤对话中可能包含密码、Token、密钥等敏感信息。记忆服务接入生产环境前一定要做敏感信息过滤。一个简单的做法是配置敏感词表在记忆保存前做一次正则匹配和替换。SENSITIVE_PATTERNS [ r(?i)(password|passwd|pwd)\s*[:]\s*\S, r(?i)(api[_-]?key|secret|token)\s*[:]\s*\S, ] def filter_sensitive(content: str) - str: import re for pattern in SENSITIVE_PATTERNS: content re.sub(pattern, [FILTERED], content) return content9.4 记忆注入的 Token 预算上下文窗口是有限资源。如果记忆条目很多全部注入会导致 Prompt 过长反而降低回答质量。建议单次注入记忆条数控制在 510 条。每条记忆在保存时尽量精简不要存冗长的原文。给记忆块设置整体 Token 上限比如不超过上下文窗口的 20%。9.5 异步与缓存策略记忆保存是典型的写操作不应该阻塞对话主流程。推荐使用消息队列或简单的后台线程池处理保存请求。对于高频用户可以使用 Redis 缓存最近召回的记忆减少 Embedding API 调用次数。9.6 日志与可观测性记忆系统作为 Agent 的外部依赖也需要有日志。建议记录以下信息每次保存和召回的耗时。召回结果的相关度分数。注入到 Prompt 中的记忆块内容便于复盘为什么模型给出了某个回答。外部 API 的调用量和失败率。只有把这些数据记录下来你才能持续优化记忆策略。10. 进阶方向参考如果把基础版记忆系统跑通之后你还可以继续往下面几个方向优化记忆压缩定期把一批旧的 episodic 记忆合并成更高层级的 semantic 记忆形成“记忆的遗忘与巩固”机制。记忆冲突消解当新记忆和旧记忆矛盾时决定谁覆盖谁或同时保留并由模型判断。分层记忆存储冷热分离高频记忆放 Redis低频记忆放向量数据库归档记忆放对象存储。结合知识图谱记忆中的实体关系用知识图谱表示支持多跳推理。这些方向并不复杂但每一步都能让 Agent 的长期记忆能力更接近真实人体的记忆机制。如果你在跟着实践的过程中遇到具体报错或排查不掉的问题可以把报错信息、依赖版本和调用链贴出来再分析。也欢迎在评论区交流你在给 Hermes 做记忆增强时的做法和踩过的坑互相借鉴一下。