拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Agent记忆系统实战:基于MCP与Docker的LLM长期记忆架构

Agent记忆系统实战:基于MCP与Docker的LLM长期记忆架构

1. 从“hindsight”说起:为什么记忆是 Agent 落地的最后一公里

第一次看到 “hindsight” 这个词,是在给一个客服 Agent 做复盘的时候。用户投诉说,同一个问题上周已经反馈过,这周换了个客服 Agent 接待,结果对方像完全没听过一样,从头再问一遍。技术团队排查了半天,发现不是模型不行,也不是提示词写得烂,而是这个 Agent 压根没有“记忆”——它每次对话都是白纸一张,上一秒聊完,下一秒就忘。

这就是 hindsight 这个词戳中我的地方。它的字面意思是“后见之明”,也就是事后回头看才明白的那件事。放到 Agent 语境里,它其实指向一个非常具体的能力:Agent 能不能记住过去发生过什么,并且在需要的时候把这段记忆调出来用。没有这个能力,Agent 永远只能做“一次性问答”,做不了真正的长期助手。

围绕 hindsight 这个核心,最近一年冒出来一堆相关概念:agent memory、LLM、MCP、Docker。这几个词不是随便凑在一起的,它们其实构成了一个完整的落地链条。LLM 是大脑,负责理解和生成;agent memory 是海马体,负责存储和检索;MCP 是神经接口,负责让大脑和外部工具、数据源对话;Docker 是培养皿,负责把这一整套东西稳定地跑起来。少了任何一环,Agent 都只能停留在 demo 阶段。

我写这篇东西,不是要讲什么高深理论,而是想把过去大半年在 Agent 记忆系统上踩过的坑、试过的方案、最后跑通的架构,原原本本讲一遍。适合谁看?如果你正在做 Agent 产品,或者打算给自己的 LLM 应用加上“记住用户”的能力,又或者你只是好奇 MCP 和 Docker 到底怎么配合起来用,那这篇应该能帮你省下不少试错时间。我会从设计思路讲到具体实现,从参数选择讲到故障排查,尽量做到你照着抄就能跑起来。

2. Agent Memory 的整体设计思路:为什么不能只靠上下文窗口

2.1 上下文窗口不是记忆,它只是草稿纸

很多人第一次做 Agent 记忆,第一反应是“我把历史对话全塞进 prompt 不就行了”。我一开始也这么干过,结果很快就撞墙了。上下文窗口再大,它也是有限的,而且成本随长度线性上涨。更关键的是,上下文窗口里的内容是“平铺”的,模型要在几千上万 token 里自己找相关信息,效果非常不稳定。你问它“我上次说的那个地址”,它可能翻到三段无关的闲聊,就是找不到那句关键信息。

所以上下文窗口的本质是工作记忆(working memory),相当于你桌面上摊开的草稿纸,写满了当前任务相关的东西。而真正的**长期记忆(long-term memory)**必须外置,存到数据库或者文件系统里,需要的时候再按需检索回来。这个区分非常重要,它决定了你整个架构是“堆 prompt”还是“建系统”。

我后来总结了一个简单的判断标准:如果一段信息在下一轮对话里大概率用不到,但它未来某天可能有用,那它就不该留在上下文里,而应该写进外部记忆。比如用户的偏好、历史订单、上次投诉的原因,这些都属于长期记忆。而当前这轮对话的具体问题、刚查到的数据,属于工作记忆,留在上下文里就行。

2.2 记忆的三个核心动作:写入、检索、遗忘

一个能用的 Agent 记忆系统,必须处理好三个动作。第一个是写入,也就是什么时候把什么信息存下来。这里最容易犯的错是“什么都存”,结果记忆库变成垃圾场,检索的时候全是噪音。我的做法是让 LLM 自己判断:在每轮对话结束时,让它输出一个结构化结果,标明这轮有没有值得长期记住的信息,有的话是什么类型、什么内容。

第二个是检索,也就是在需要的时候把相关记忆找回来。这里的关键是“相关”,不是“全部”。我试过最简单的做法是把所有记忆按时间倒序塞回去,效果很差,因为最近的未必是最相关的。后来改成基于向量相似度的检索,效果好很多,但也带来了新问题:向量检索对“精确匹配”不敏感,比如用户问“我的订单号 12345”,向量检索可能返回一堆语义相近但订单号不对的记忆。所以我现在用的是混合检索:向量相似度加关键词匹配,两路结果合并排序。

第三个是遗忘,这个最容易被忽略,但恰恰是让记忆系统长期可用的关键。记忆不是越多越好,过期的、矛盾的、低价值的信息必须清理掉。我见过一个 Agent 因为记住了用户三个月前随口说的一句“我最近在减肥”,结果三个月后还在推荐低卡食谱,用户早就忘了这回事,体验非常割裂。遗忘策略可以是基于时间的(超过 N 天降权),也可以是基于冲突的(新记忆覆盖旧记忆),还可以是基于价值的(LLM 打分低的直接丢弃)。

2.3 为什么选 MCP 作为记忆的接入层

记忆系统建好了,接下来要解决的是“怎么让 Agent 用上它”。早期我是在代码里硬编码调用,Agent 要查记忆就调一个内部函数。这样做能用,但扩展性极差,每加一种记忆类型就要改一次代码,而且不同 Agent 之间没法复用。

MCP(Model Context Protocol)的出现解决了这个问题。它本质上是一套标准协议,把“能力”封装成一个个 server,Agent 通过统一的接口去调用。记忆系统可以做成一个 MCP server,对外暴露几个工具:write_memory、search_memory、forget_memory。Agent 不需要知道记忆存在哪、用什么数据库、检索算法是什么,它只需要知道“我有一个叫 memory 的工具可以用”。

这样做的好处非常明显。第一,解耦,记忆系统的实现可以随便换,Agent 侧完全无感。第二,复用,同一个记忆 server 可以同时给多个 Agent 用,甚至给不同的应用用。第三,可观测,所有记忆操作都走 MCP 协议,日志和监控天然统一。我现在的做法是,凡是 Agent 需要的外部能力,一律做成 MCP server,记忆只是其中一个。

2.4 Docker 在整套架构里的角色

最后说 Docker。很多人觉得 Docker 只是部署工具,跟 Agent 记忆没关系。但我的实际体验是,Docker 是让这套架构从“能跑”变成“稳定跑”的关键。原因有三个。

第一,记忆系统依赖的组件很多:向量数据库、关系数据库、缓存、MCP server 本身。这些组件版本兼容性很敏感,直接在宿主机上装,很容易出现“我本地能跑,服务器上跑不起来”的情况。用 Docker 把每个组件容器化,环境就固定了,换机器也能一键拉起。

第二,Agent 的调试经常需要“重置状态”。比如我想测试记忆写入逻辑,就得把记忆库清空重来。如果记忆库跑在 Docker 里,我直接删容器重建就行,几秒钟的事。如果装在宿主机上,清理起来很麻烦,还容易误删其他数据。

第三,MCP server 本身也适合容器化。一个记忆 MCP server 跑在容器里,通过标准端口对外提供服务,Agent 侧只需要配置一个地址就能连上。这样本地开发、测试环境、生产环境可以用同一套镜像,行为一致,减少“环境差异”导致的 bug。

3. 核心细节解析:记忆系统的数据结构与检索策略

3.1 记忆的存储结构:不只是文本加向量

很多人做记忆,就是存一条文本加一个向量,简单粗暴。我一开始也这样,后来发现不够用。一条记忆至少需要这几个字段:内容(content)、类型(type)、时间戳(timestamp)、来源(source)、重要性(importance)、向量(embedding)。类型用来区分是事实、偏好、事件还是任务;来源用来追溯这条记忆是从哪轮对话来的;重要性用来做检索排序和遗忘决策。

我现在的表结构大概是这样:id、content、type、source、importance、created_at、last_accessed_at、access_count、embedding。其中last_accessed_at和access_count很关键,它们让记忆有了“热度”概念。经常被检索到的记忆权重更高,长期没人访问的记忆逐渐降权,这比单纯按时间遗忘更符合真实使用场景。

还有一个细节是记忆的粒度。太粗了检索不准,太细了检索太碎。我的经验是,一条记忆最好对应一个“原子事实”,比如“用户偏好顺丰快递”是一条,“用户上次投诉原因是配送慢”是另一条。不要把一整段对话直接存成一条记忆,那样检索出来是一大坨,模型还得自己从中提取,效率低。

3.2 向量检索的坑:相似不等于相关

向量检索是记忆系统的核心,但它有几个坑必须提前知道。第一个坑是相似度阈值。余弦相似度 0.8 以上算相关,这个经验值在通用场景下还行,但在垂直领域经常失灵。比如医疗领域,“高血压”和“低血压”向量距离很近,但语义完全相反。所以阈值不能一刀切,得根据你的领域数据调。

第二个坑是嵌入模型的选型。不同嵌入模型对同一段文本的向量表示差异很大。我试过用通用模型和领域模型做对比,在客服场景下,领域微调过的模型检索准确率能高出 20% 以上。选型的时候不要只看榜单,一定要拿自己的真实数据测。测试方法很简单:准备 50 条查询和对应的正确记忆,看不同模型的前 5 命中率。

第三个坑是多语言混合。如果你的用户中英文混着说,嵌入模型必须支持多语言,否则中文查询检索不到英文记忆。我踩过这个坑,后来换成多语言模型才解决。另外,记忆写入的时候最好统一语言,或者至少记录语言标签,检索时按语言过滤。

3.3 混合检索的实现:向量加关键词加规则

纯向量检索不够,纯关键词检索也不够,所以我现在用的是混合检索。具体做法是:查询进来后,同时走三路。第一路是向量检索,取 top 20;第二路是关键词检索(用倒排索引或者数据库的 LIKE),取 top 20;第三路是规则检索,比如“如果查询里包含订单号,直接精确匹配订单号字段”。三路结果合并后,用一个加权的分数排序,向量分占 0.5,关键词分占 0.3,规则命中占 0.2,最后取 top 5 返回给 Agent。

这个权重不是拍脑袋定的,是我拿真实查询日志调出来的。调参方法也简单:准备一批查询,人工标注哪些记忆是真正相关的,然后网格搜索权重组合,看哪个组合的 NDCG 最高。我实测下来,向量权重在 0.4 到 0.6 之间效果最好,太低会漏掉语义相关但字面不同的记忆,太高会引入语义相近但实际无关的噪音。

还有一个技巧是查询改写。用户的问题往往很口语,直接拿去检索效果一般。我会先用 LLM 把查询改写成更适合检索的形式,比如把“我上次那个快递咋样了”改写成“用户历史订单 配送状态 查询”。这一步能明显提升召回率,代价是多一次 LLM 调用,延迟增加几百毫秒。如果对延迟敏感,可以只在复杂查询上做改写。

3.4 记忆写入的时机与去重

写入时机很关键。我的做法是在每轮对话结束后触发一次写入判断,而不是每句话都写。判断逻辑是让 LLM 看这轮对话,输出一个 JSON,包含should_write、memory_type、memory_content、importance。should_write为 false 就跳过,为 true 才写入。

去重是另一个必须处理的点。用户可能反复说同一件事,比如“我喜欢喝美式”,如果每次都写一条,记忆库很快就冗余了。我的去重策略是:写入前先做一次检索,如果找到相似度超过 0.9 的已有记忆,就不新增,而是更新那条记忆的last_accessed_at和access_count。如果相似度在 0.7 到 0.9 之间,就让 LLM 判断是“补充”还是“冲突”,补充就合并内容,冲突就用新的覆盖旧的。

这里有个经验:去重阈值不要设太高。我一开始设 0.95,结果很多语义相同但表述不同的记忆没被识别出来,库里一堆重复。后来降到 0.85,效果好很多。但也不能太低,低于 0.8 会误合并不同记忆。0.85 左右是我实测比较稳的值。

4. 实操过程:从零搭一套带记忆的 Agent

4.1 环境准备:Docker 安装与常见故障

先说环境。我假设你用的是 Windows 或者 Linux,Mac 也类似。第一步是装 Docker Desktop。Windows 上装的时候最容易遇到两个问题。一个是WSL2 没装,Docker Desktop 启动会报错,提示需要 WSL2 后端。解决办法是管理员权限打开 PowerShell,跑wsl --install,然后重启。另一个是虚拟化没开,报错信息里会有 “virtualization support not detected” 之类的字样。这个得进 BIOS 开 VT-x 或者 AMD-V,不同主板位置不一样,一般在 CPU 配置里。

装好之后验证一下,命令行跑docker --version和docker compose version,都能输出版本号就 OK。如果docker ps报错说连不上 daemon,多半是 Docker Desktop 没启动,或者当前用户不在 docker 用户组里。Linux 上把用户加进 docker 组就行:sudo usermod -aG docker $USER,然后重新登录。

提示:Windows 上如果 Docker Desktop 一直卡在启动界面,先检查 Hyper-V 和 WSL2 是否都启用。两个都开有时候会冲突,我的经验是只用 WSL2 后端,把 Hyper-V 关掉,稳定性更好。

4.2 用 Docker Compose 拉起记忆系统依赖

记忆系统需要几个组件:PostgreSQL(存结构化记忆)、pgvector(向量检索扩展)、Redis(缓存热点记忆)、以及 MCP server 本身。我用 Docker Compose 把它们编排在一起,一个docker-compose.yml搞定。

version: "3.8" services: postgres: image: pgvector/pgvector:pg16 environment: POSTGRES_USER: agent POSTGRES_PASSWORD: agent_pass POSTGRES_DB: memory ports: - "5432:5432" volumes: - pgdata:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U agent"] interval: 5s retries: 5 redis: image: redis:7-alpine ports: - "6379:6379" command: redis-server --appendonly yes memory-mcp: build: ./memory-mcp ports: - "8080:8080" environment: DATABASE_URL: postgresql://agent:agent_pass@postgres:5432/memory REDIS_URL: redis://redis:6379 depends_on: postgres: condition: service_healthy redis: condition: service_started volumes: pgdata:

这里有几个细节值得说。pgvector/pgvector:pg16这个镜像已经内置了 vector 扩展,不用自己编译。healthcheck很重要,它保证 postgres 真正 ready 之后 memory-mcp 才启动,否则会连不上数据库。depends_on配合condition用,比单纯写depends_on靠谱得多。

启动命令就一句:docker compose up -d。第一次会拉镜像,可能要几分钟。起来之后docker compose ps看状态,都是 running 就对了。如果 memory-mcp 一直重启,看日志docker compose logs memory-mcp,多半是数据库连接串写错了,或者 postgres 还没 ready。

4.3 记忆 MCP Server 的核心实现

MCP server 我用 Python 写,因为生态最成熟。核心是暴露三个工具:write_memory、search_memory、forget_memory。下面是最关键的search_memory实现逻辑。

async def search_memory(query: str, top_k: int = 5, memory_type: str = None): # 1. 查询改写 rewritten = await rewrite_query(query) # 2. 生成查询向量 query_embedding = embed(rewritten) # 3. 向量检索 vector_results = await db.fetch(""" SELECT id, content, type, importance, 1 - (embedding <=> $1) AS similarity FROM memories WHERE ($2::text IS NULL OR type = $2) ORDER BY embedding <=> $1 LIMIT 20 """, query_embedding, memory_type) # 4. 关键词检索 keyword_results = await db.fetch(""" SELECT id, content, type, importance, ts_rank(to_tsvector('simple', content), plainto_tsquery('simple', $1)) AS rank FROM memories WHERE content ILIKE '%' || $1 || '%' OR ($2::text IS NULL OR type = $2) ORDER BY rank DESC LIMIT 20 """, rewritten, memory_type) # 5. 合并排序 merged = merge_and_rank(vector_results, keyword_results) # 6. 更新访问记录 for mem in merged[:top_k]: await db.execute(""" UPDATE memories SET last_accessed_at = NOW(), access_count = access_count + 1 WHERE id = $1 """, mem["id"]) return merged[:top_k]

这段代码里有几个关键点。<=>是 pgvector 的余弦距离操作符,1 - 距离就是相似度。ts_rank是 PostgreSQL 全文检索的排序函数,用simple配置是因为中文分词需要额外扩展,先用 simple 做基础匹配。合并排序的时候,我给向量分乘 0.5,关键词分乘 0.3,再加一个基于importance和access_count的加权分乘 0.2。

rewrite_query那一步是可选的,如果延迟敏感可以去掉。我的实测是,加上改写后检索准确率提升大概 15%,但延迟增加 300 到 500 毫秒。如果你的场景对延迟要求高,可以只在查询长度超过一定阈值时才改写。

4.4 接入 Agent:MCP 客户端配置

MCP server 跑起来之后,Agent 侧要配置连接。不同框架配置方式不一样,但核心都是填一个 server 地址。以常见的配置为例,大概长这样:

{ "mcpServers": { "memory": { "url": "http://localhost:8080/sse", "transport": "sse" } } }

这里transport用sse是因为 MCP 支持多种传输方式,SSE 是最通用的一种。如果你的 Agent 框架支持 stdio 传输,也可以把 server 做成命令行工具,通过 stdio 通信,省去网络开销。我两种都用过,SSE 的好处是 server 可以独立部署,多个 Agent 共享;stdio 的好处是简单,不用管端口和网络。

配置好之后,Agent 启动时会自动发现 memory server 提供的工具。你可以在 Agent 的 prompt 里告诉它:“你有 write_memory、search_memory、forget_memory 三个工具,当用户提到需要长期记住的信息时,调用 write_memory;当需要回忆历史信息时,调用 search_memory。” 这样 Agent 就会在合适的时机自动调用。

注意:不要让 Agent 每轮都调 search_memory,那样会拖慢响应。我的做法是在 prompt 里加判断条件,比如“只有当用户的问题涉及历史信息、个人偏好、之前发生过的事情时,才调用 search_memory”。这样能过滤掉大部分不必要的检索。

5. 常见问题与排查技巧实录

5.1 记忆检索不准的排查思路

检索不准是最常见的问题,表现是 Agent 明明有相关记忆,但就是没检索出来,或者检索出来一堆无关的。排查我一般按这个顺序走。

先看查询本身。把用户原始查询和改写后的查询都打出来,看看改写有没有跑偏。我遇到过改写把“帮我查下上次那个事”改成“查询历史事件”,结果检索出一堆无关记忆。这种情况要么调改写 prompt,要么干脆关掉改写。

再看向量质量。拿几条典型查询,手动算一下它们和正确记忆的相似度。如果相似度低于 0.7,说明嵌入模型不适合你的领域,考虑换模型或者做微调。如果相似度正常但没检索出来,检查是不是被memory_type过滤掉了,或者top_k设太小。

最后看排序逻辑。把三路检索的原始结果都打出来,看看正确记忆在哪一路、排第几。如果正确记忆在向量路排第 15,但合并后掉出 top 5,说明权重需要调。我一般会把向量权重调高一点,或者给importance高的记忆额外加权。

5.2 记忆写入过多或过少的平衡

写入过多会让记忆库膨胀,检索噪音大;写入过少会让 Agent 记不住东西。这个平衡点得靠调。我的经验是,先宽松后收紧。初期把should_write的判断标准放宽,让 LLM 多写一些,然后观察一周,看哪些记忆从来没被检索过,哪些被检索了但用户反馈不好。根据这些数据反过来收紧写入标准。

具体调法:在写入 prompt 里加几个反例,告诉 LLM“以下情况不要写入:寒暄、重复信息、临时状态、用户明确说不用记的”。同时给importance打分加约束,比如“只有 importance 大于 0.6 的才写入”。这样能过滤掉大部分低价值记忆。

还有一个技巧是定期清理。我写了一个定时任务,每周跑一次,把access_count为 0 且创建超过 30 天的记忆标记为待删除,让 LLM 最后判断一次是否真的没用。这样能保持记忆库的精简。

5.3 Docker 网络与连接问题速查

Docker 相关的坑主要集中在网络上。下面这张表是我遇到过的典型问题和解决办法。

问题现象可能原因解决办法
容器间连不上不在同一网络用 docker compose 默认网络,或手动创建 network
宿主机连不上容器端口没映射检查 ports 配置,确认端口没被占用
容器连不上外网DNS 配置问题在 compose 里指定 dns: 8.8.8.8
数据库连接超时健康检查没配加 healthcheck,用 depends_on condition
数据丢失没挂 volume关键数据目录必须挂 volume

还有一个常见问题是端口冲突。比如你宿主机上已经装了 PostgreSQL 占了 5432,容器再映射 5432 就会失败。解决办法是把宿主机端口改成 5433,容器内还是 5432,连接的时候用 5433。这个在 compose 里写"5433:5432"就行。

5.4 性能优化:让检索快起来

记忆检索的延迟主要花在三个地方:查询改写、向量生成、数据库检索。查询改写和向量生成都是模型调用,延迟大头在这。优化手段有几个。

第一,缓存。高频查询的向量可以缓存到 Redis,下次同样查询直接取。我实测缓存命中率能到 40% 左右,平均延迟降了三分之一。

第二,批量。如果一轮对话需要检索多次,合并成一次批量检索,减少模型调用次数。

第三,降级。延迟敏感的场景,可以跳过查询改写,直接用原始查询做向量检索。准确率降一点,但延迟能降一半。

第四,索引。pgvector 的向量索引一定要建,不然数据量大了检索会慢得离谱。建索引的语句是CREATE INDEX ON memories USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);。lists的值根据数据量调,一般数据量的平方根左右比较合适。

6. 记忆系统的扩展方向与个人体会

6.1 从单一记忆到分层记忆

现在这套系统是单层记忆,所有记忆平铺在一起。但真实场景里,记忆其实是有层次的。比如用户的长期偏好是一层,最近几轮对话的上下文是一层,当前任务的临时状态又是一层。分层之后,检索可以按层过滤,效率更高,也更符合认知科学里的记忆模型。

我最近在试的做法是加一个layer字段,分long_term、session、task三层。long_term存偏好和事实,session存本次会话的上下文,task存当前任务的中间状态。检索的时候根据查询类型决定查哪层,或者多层合并。这个还在调,但初步效果不错,尤其是 session 层能明显减少长期记忆的噪音干扰。

6.2 记忆的主动遗忘与冲突消解

遗忘这件事,我越来越觉得它是记忆系统的核心竞争力。一个不会遗忘的系统,最终一定会被自己的记忆淹没。我现在用的遗忘策略是组合式的:时间衰减加访问频率加重要性。具体公式大概是score = importance * 0.5 + log(access_count + 1) * 0.3 - days_since_access * 0.01,score 低于阈值的进入待删除队列。

冲突消解是另一个难点。用户改主意了,比如之前说喜欢咖啡,后来说改喝茶了。系统得能识别这是冲突,用新的覆盖旧的。我的做法是在写入时做冲突检测,如果新记忆和旧记忆相似度高但内容矛盾,就让 LLM 判断哪个更新,然后标记旧记忆为superseded,检索时默认过滤掉。

6.3 我踩过的几个印象深刻的坑

第一个坑是记忆污染。有一次测试的时候,我往记忆库里灌了一批假数据,忘了清理,结果上线后 Agent 一直推荐一些莫名其妙的东西。排查了半天才发现是测试数据混进去了。教训是:测试环境和生产环境的记忆库必须物理隔离,用不同的数据库实例,绝对不能共用。

第二个坑是向量维度不匹配。我中途换过一次嵌入模型,从 768 维换到 1024 维,但忘了重建索引,结果检索一直报错。换嵌入模型一定要重建所有向量和索引,这个操作最好写成一个迁移脚本,别手动搞。

第三个坑是并发写入冲突。多个 Agent 同时写记忆,偶尔会出现重复写入。后来加了数据库层面的唯一约束,配合写入前的去重检查,才解决。如果你的系统是多 Agent 共享记忆,并发控制一定要提前考虑。

6.4 后续可以怎么扩展

这套架构跑通之后,扩展方向其实很多。一个方向是多模态记忆,把图片、语音也纳入记忆体系,用对应的嵌入模型生成向量,存到同一个库里。另一个方向是记忆共享,让多个 Agent 之间共享部分记忆,比如一个团队里的多个助手共享用户偏好。还有一个方向是记忆可视化,做一个界面让用户能看到 Agent 记住了什么,并且能手动编辑和删除,这对建立用户信任很有帮助。

我个人最看好的方向是记忆的主动整理。现在的记忆写入是被动的,用户说什么就记什么。未来可以让 Agent 定期回顾记忆库,主动发现关联、合并冗余、提炼更高层的抽象。比如从“用户喜欢美式”“用户早上喝咖啡”“用户不喜欢加糖”提炼出“用户是黑咖啡爱好者”。这种主动整理能让记忆系统从“存储”进化到“理解”,价值会大很多。

最后分享一个小技巧:调试记忆系统的时候,一定要把每次检索的原始结果和最终返回结果都打日志。我一开始只看最终结果,排查问题很费劲。后来把三路检索的中间结果都记下来,一眼就能看出是哪一路出了问题。这个日志习惯帮我省了大量时间,强烈建议你也加上。

返回列表