ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

OpenClaw-SuperMemory本地部署:构建可编程AI记忆系统实战

OpenClaw-SuperMemory本地部署:构建可编程AI记忆系统实战 1. 为什么我要折腾一个可编程记忆系统做本地AI部署有一段时间了从最早的Ollama跑Llama系列到后来折腾DeepSeek、Qwen的本地量化版本模型换了一茬又一茬但有个问题始终没解决每次对话都是失忆的。今天跟它聊完一个项目的架构设计明天再问它它完全不记得我们讨论过什么。每次都要重新贴背景、重新解释上下文这种体验用久了真的会让人抓狂。后来我开始关注记忆系统这个方向。市面上做RAG的方案不少Dify、FastGPT这些我都试过但它们更多是面向知识库问答的场景跟我想要的“持续记忆、自动整理、可编程调用”还是不太一样。直到我接触到OpenClaw-SuperMemory这个项目它的定位很明确给AI Agent装一个可编程的长期记忆层支持本地部署数据完全自己掌控。这篇文章我会把整个部署过程、踩过的坑、参数调优的经验完整地分享出来。不管你是刚接触本地AI部署的新手还是已经在跑RAG的老手应该都能从中找到有用的东西。核心关键词就几个OpenClaw-SuperMemory、本地部署、可编程记忆系统、智能知识管理。我会围绕这几个点把从零到跑通的完整路径讲清楚。先说清楚这个系统能干什么。简单来说它给AI模型加了一层“记忆中间件”——你喂给它的信息会被结构化存储支持语义检索、标签过滤、时间衰减等机制而且提供了API接口让你可以用代码去操作记忆。比如你可以写个脚本每天自动把工作日志灌进去需要的时候让AI基于这些记忆来回答问题。这跟传统的向量数据库检索的方案相比多了一层“记忆管理”的逻辑不是简单的存和取而是有遗忘曲线、重要性评分、关联图谱这些机制在里面。适合谁来参考我觉得三类人最需要一是已经在本地跑大模型、想让模型有持续记忆能力的开发者二是做知识管理、想把碎片信息变成可检索知识库的效率工具爱好者三是对AI Agent开发感兴趣、想研究记忆机制怎么实现的技术人。前提是你得有一点Linux基础会用Docker能看懂Python代码不需要很深的AI背景。2. 系统架构与核心组件拆解2.1 整体架构长什么样OpenClaw-SuperMemory的架构设计我觉得挺清晰的它没有把东西都塞在一起而是分成了几个独立的层。最底层是存储层用的是PostgreSQL加上pgvector扩展来做向量存储同时用Redis做热数据的缓存。中间是记忆引擎层这是核心负责记忆的写入、检索、衰减、关联这些逻辑。最上面是接口层提供REST API和Python SDK两种调用方式。为什么选PostgreSQLpgvector而不是专门的向量数据库比如Milvus或者Qdrant我一开始也有这个疑问。后来看了项目的设计文档才明白他们需要的是关系型查询和向量检索的混合能力。记忆系统不只是做相似度搜索还要支持按时间范围过滤、按标签筛选、按重要性排序这些用SQL来表达比用专门的向量数据库要灵活得多。而且pgvector现在的性能已经足够支撑中小规模的记忆库了几万到几十万条记忆的检索延迟可以控制在几十毫秒级别。Redis的角色主要是缓存最近访问的记忆和会话状态。因为记忆检索有个特点最近用过的记忆大概率还会被用到。把热数据放在Redis里可以减少对PostgreSQL的查询压力。这个设计思路跟传统的缓存策略是一致的但用在记忆系统上有额外的意义——它模拟了人类记忆的“近期激活”效应。2.2 记忆的数据模型理解数据模型是用好这个系统的关键。每条记忆在数据库里大概长这样字段类型说明idUUID唯一标识contentTEXT记忆的原始文本内容embeddingVECTOR(768)语义向量维度取决于嵌入模型importanceFLOAT重要性评分0-1之间access_countINTEGER被检索次数last_accessedTIMESTAMP最后访问时间created_atTIMESTAMP创建时间tagsTEXT[]标签数组sourceTEXT来源标识decay_factorFLOAT衰减因子动态计算这个模型里我觉得最有意思的是importance和decay_factor这两个字段。重要性评分不是固定的它会根据访问频率、用户反馈、内容长度等因素动态调整。衰减因子则是根据最后访问时间计算出来的时间越久远、访问越少的记忆在检索时的权重就越低。这就模拟了人类记忆的遗忘曲线——不常用的记忆会逐渐模糊但不会完全消失关键时刻还是能被想起来。嵌入维度是768这是因为我用的嵌入模型是nomic-embed-text它的输出维度就是768。如果你换用其他嵌入模型比如BGE系列或者OpenAI的text-embedding-3维度可能不同需要在配置里对应修改。这里有个坑嵌入维度一旦确定就不能随便改因为数据库表的vector字段维度是固定的。要换嵌入模型就得重建表、重新生成所有记忆的向量。2.3 记忆的生命周期管理记忆从写入到被遗忘整个生命周期有几个阶段。写入的时候系统会做几件事生成嵌入向量、计算初始重要性、提取关键词作为标签、检查是否与已有记忆重复。重复检测用的是语义相似度如果新记忆跟已有记忆的余弦相似度超过阈值默认0.92就会触发合并逻辑而不是新建一条。检索的时候系统不是简单地做向量相似度搜索。它会综合考虑多个因素语义相似度占60%权重重要性评分占20%时间新鲜度占15%访问频率占5%。这些权重都是可以在配置文件里调的。我实测下来默认权重对大多数场景都够用但如果你做的是客服问答这种需要优先返回最新信息的场景可以把时间新鲜度的权重调高一些。遗忘机制是定期执行的。系统会有一个后台任务每天跑一次扫描所有记忆重新计算衰减因子。衰减因子低于某个阈值的记忆会被标记为“冷记忆”检索时默认不返回但不会删除。如果你想彻底清理需要手动调用清理接口。这个设计我觉得很合理——自动遗忘但不自动删除给用户留了后悔的余地。3. 本地部署实操全流程3.1 环境准备与依赖检查我用的是一台Dell T30服务器配置不算高Xeon E3-1225 v5、16GB内存、512GB SSD。这个配置跑OpenClaw-SuperMemory加上一个7B参数的本地模型是够用的。如果你要在同一台机器上跑更大的模型内存建议至少32GB。操作系统我用的是Ubuntu 22.04 LTS。不建议用CentOS 7因为它的glibc版本太老有些Python包编译会出问题。Ubuntu 20.04也可以但22.04的软件源更新一些省事。部署前需要确认几件事Docker和Docker Compose已经安装。我用的是Docker 24.0.7和Compose v2.23.0版本不用完全一致但Docker版本不要低于20.10。Python 3.10或以上。系统自带的Python3版本可能不够建议用pyenv或者conda装一个独立的。至少10GB的磁盘空间。PostgreSQL的数据、Redis的持久化文件、Docker镜像加起来差不多要这么多。内存至少8GB。如果同时跑本地模型建议16GB起步。检查命令很简单docker --version docker compose version python3 --version free -h df -h如果Docker还没装用官方脚本装就行curl -fsSL https://get.docker.com | sh sudo usermod -aG docker $USER装完记得重新登录一下让用户组权限生效。3.2 Docker Compose编排配置OpenClaw-SuperMemory官方提供了Docker Compose文件但我建议不要直接用默认的根据自己的环境改一改。下面是我调整过的版本version: 3.8 services: postgres: image: pgvector/pgvector:pg16 container_name: supermemory-postgres environment: POSTGRES_USER: supermemory POSTGRES_PASSWORD: your_strong_password_here POSTGRES_DB: supermemory volumes: - ./data/postgres:/var/lib/postgresql/data ports: - 5432:5432 healthcheck: test: [CMD-SHELL, pg_isready -U supermemory] interval: 10s timeout: 5s retries: 5 restart: unless-stopped redis: image: redis:7-alpine container_name: supermemory-redis command: redis-server --appendonly yes --maxmemory 512mb --maxmemory-policy allkeys-lru volumes: - ./data/redis:/data ports: - 6379:6379 restart: unless-stopped supermemory-api: image: openclaw/supermemory:latest container_name: supermemory-api depends_on: postgres: condition: service_healthy redis: condition: service_started environment: DATABASE_URL: postgresql://supermemory:your_strong_password_herepostgres:5432/supermemory REDIS_URL: redis://redis:6379/0 EMBEDDING_MODEL: nomic-embed-text EMBEDDING_DIM: 768 OLLAMA_BASE_URL: http://host.docker.internal:11434 API_KEY: your_api_key_here LOG_LEVEL: info volumes: - ./config:/app/config - ./logs:/app/logs ports: - 8080:8080 restart: unless-stopped这里有几个关键点要解释。pgvector/pgvector:pg16这个镜像已经预装了pgvector扩展省得自己编译。Redis的maxmemory-policy设成allkeys-lru意思是内存满了就淘汰最近最少使用的键这对缓存场景是最合适的策略。OLLAMA_BASE_URL指向host.docker.internal:11434这是因为Ollama跑在宿主机上容器内部要访问宿主机的服务需要用这个特殊域名。Linux环境下host.docker.internal默认可能不生效需要在docker-compose.yml里加一行extra_hosts: - host.docker.internal:host-gateway这个坑我踩过当时容器一直连不上Ollama排查了半天才发现是这个问题。3.3 嵌入模型的选型与配置嵌入模型的选择直接决定了记忆检索的质量。我对比过几个方案模型维度中文效果速度资源占用nomic-embed-text768中等快低BGE-M31024优秀中等中等text-embedding-3-small1536优秀快需联网m3e-base768良好快低我最终选了nomic-embed-text主要考虑是它在Ollama上跑很方便资源占用低而且768维在存储和检索效率上比较平衡。如果你对中文语义匹配要求很高建议用BGE-M3但维度变成1024需要改数据库表结构。在Ollama上拉取嵌入模型ollama pull nomic-embed-text验证一下能不能正常生成向量curl http://localhost:11434/api/embeddings -d { model: nomic-embed-text, prompt: 测试文本 }返回的JSON里会有一个embedding数组长度是768就对了。3.4 数据库初始化与迁移容器起来之后需要初始化数据库表结构。项目提供了迁移脚本但我建议手动跑一遍这样出问题好排查。先进到PostgreSQL容器里docker exec -it supermemory-postgres psql -U supermemory -d supermemory然后执行建表语句CREATE EXTENSION IF NOT EXISTS vector; CREATE TABLE IF NOT EXISTS memories ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), content TEXT NOT NULL, embedding VECTOR(768), importance FLOAT DEFAULT 0.5, access_count INTEGER DEFAULT 0, last_accessed TIMESTAMP DEFAULT NOW(), created_at TIMESTAMP DEFAULT NOW(), tags TEXT[] DEFAULT {}, source TEXT DEFAULT manual, decay_factor FLOAT DEFAULT 1.0, metadata JSONB DEFAULT {} ); CREATE INDEX idx_memories_embedding ON memories USING ivfflat (embedding vector_cosine_ops) WITH (lists 100); CREATE INDEX idx_memories_tags ON memories USING GIN(tags); CREATE INDEX idx_memories_created_at ON memories (created_at DESC); CREATE INDEX idx_memories_importance ON memories (importance DESC);ivfflat索引的lists参数需要根据数据量调整。经验公式是数据量小于100万时lists设为sqrt(行数)。我预估记忆条数在1万左右所以设了100。如果后面数据量大了可以重建索引调大这个值。3.5 启动与健康检查所有配置就绪后启动服务docker compose up -d然后检查各个容器的状态docker compose ps应该看到三个容器都是running状态。接着检查API是否正常curl http://localhost:8080/health返回{status:ok}就说明服务起来了。如果返回连接拒绝检查一下端口有没有被占用或者容器日志里有没有报错docker compose logs supermemory-api --tail 504. 可编程记忆管理的核心操作4.1 写入记忆的几种方式写入记忆是最基础的操作。系统提供了三种写入方式单条写入、批量写入、文件导入。单条写入用REST APIcurl -X POST http://localhost:8080/api/v1/memories \ -H Authorization: Bearer your_api_key_here \ -H Content-Type: application/json \ -d { content: 今天跟团队讨论了新项目的技术选型决定用FastAPI做后端前端用Vue3。, tags: [工作, 技术选型, 项目A], importance: 0.8, source: daily_log }这里importance我手动设了0.8因为技术选型这种决策信息比较重要。如果不设系统会根据内容长度、是否包含关键词等规则自动计算一个初始值。批量写入适合一次性导入大量记忆import requests memories [ {content: 记忆内容1, tags: [标签1], importance: 0.6}, {content: 记忆内容2, tags: [标签2], importance: 0.7}, # ... ] response requests.post( http://localhost:8080/api/v1/memories/batch, headers{Authorization: Bearer your_api_key_here}, json{memories: memories} ) print(response.json())批量写入的时候注意单次不要超过100条否则请求体太大会超时。我一般50条一批稳一点。文件导入支持Markdown和JSON两种格式。Markdown文件会按标题层级自动切分每个段落作为一条独立记忆。这个功能很适合把已有的笔记直接灌进去。4.2 检索记忆的查询语法检索是记忆系统最核心的能力。基础检索就是传一个查询文本系统返回最相关的N条记忆response requests.post( http://localhost:8080/api/v1/memories/search, headers{Authorization: Bearer your_api_key_here}, json{ query: 之前讨论的技术选型是什么, limit: 5, min_similarity: 0.7 } )但真正强大的是组合查询。你可以同时指定语义查询、标签过滤、时间范围、重要性阈值response requests.post( http://localhost:8080/api/v1/memories/search, headers{Authorization: Bearer your_api_key_here}, json{ query: 技术选型, tags: [项目A], created_after: 2024-01-01T00:00:00Z, min_importance: 0.5, limit: 10, sort_by: relevance # 可选 relevance, recency, importance } )这个组合查询的能力是pgvector方案的优势所在。如果用纯向量数据库做标签过滤和时间过滤会比较别扭要么在应用层做二次过滤要么用数据库自己的过滤语法灵活度差很多。4.3 记忆的更新与合并记忆不是一成不变的。当有新信息进来时系统会判断是新建一条记忆还是更新已有的。这个判断逻辑基于语义相似度# 伪代码展示合并逻辑 def should_merge(new_content, existing_memories, threshold0.92): new_embedding get_embedding(new_content) for mem in existing_memories: similarity cosine_similarity(new_embedding, mem.embedding) if similarity threshold: return mem.id return None如果判定为合并系统会把新内容追加到已有记忆的content字段同时更新last_accessed和importance。但这里有个问题追加内容会让记忆变得很长影响检索精度。我的做法是对于需要合并的场景不是简单追加而是让AI做一次摘要整合。比如def merge_memories(old_content, new_content): prompt f请将以下两段信息合并成一段简洁的记忆 旧信息{old_content} 新信息{new_content} 要求保留关键信息去除重复内容控制在200字以内。 # 调用本地模型生成合并后的内容 merged call_llm(prompt) return merged这样合并后的记忆更精炼检索效果更好。但这个操作会增加一次模型调用需要权衡。4.4 记忆衰减与清理策略衰减机制是自动运行的但你可以手动触发一次全量重算curl -X POST http://localhost:8080/api/v1/maintenance/recalculate-decay \ -H Authorization: Bearer your_api_key_here衰减因子的计算公式大概是这样的decay_factor exp(-lambda * days_since_last_access) * (1 log(access_count 1))lambda是衰减速率默认0.05。意思是如果一条记忆30天没被访问它的衰减因子会降到exp(-0.05*30) ≈ 0.22。但如果它被访问过很多次access_count的加成会抵消一部分衰减。清理冷记忆需要谨慎。我建议先查询一下哪些记忆会被清理curl http://localhost:8080/api/v1/memories/cold?threshold0.1limit100 \ -H Authorization: Bearer your_api_key_here确认没问题后再执行删除curl -X DELETE http://localhost:8080/api/v1/memories/cold?threshold0.1 \ -H Authorization: Bearer your_api_key_here注意删除操作不可逆建议先备份数据库。备份命令docker exec supermemory-postgres pg_dump -U supermemory supermemory backup.sql5. 与本地大模型集成的实战方案5.1 用Ollama做对话模型的对接记忆系统本身不生成回答它只负责存储和检索。要让它发挥作用需要跟对话模型对接。我用的是Ollama跑Qwen2.5-7B流程是这样的用户提问用问题去记忆系统检索相关记忆把检索到的记忆作为上下文拼进Prompt调用对话模型生成回答把本轮对话的关键信息写回记忆系统用Python写出来大概是这样import requests import json def chat_with_memory(user_input): # 1. 检索相关记忆 search_response requests.post( http://localhost:8080/api/v1/memories/search, headers{Authorization: Bearer your_api_key_here}, json{query: user_input, limit: 5, min_similarity: 0.6} ) memories search_response.json()[results] # 2. 拼接上下文 memory_context \n.join([f- {m[content]} for m in memories]) system_prompt f你是一个有记忆的AI助手。以下是你之前记住的相关信息 {memory_context} 请基于这些记忆和你的知识来回答用户问题。如果记忆中没有相关信息就正常回答。 # 3. 调用Ollama ollama_response requests.post( http://localhost:11434/api/chat, json{ model: qwen2.5:7b, messages: [ {role: system, content: system_prompt}, {role: user, content: user_input} ], stream: False } ) answer ollama_response.json()[message][content] # 4. 写回记忆 requests.post( http://localhost:8080/api/v1/memories, headers{Authorization: Bearer your_api_key_here}, json{ content: f用户问{user_input}\n回答{answer}, tags: [对话记录], importance: 0.4, source: chat } ) return answer这个流程跑通之后体验提升非常明显。模型能记住之前聊过的内容回答的时候会引用之前的讨论感觉就像在跟一个真正有记忆的助手对话。5.2 记忆注入的Prompt工程技巧把记忆拼进Prompt看起来简单但怎么拼效果最好是有讲究的。我试过几种方式方式一直接罗列。就是把检索到的记忆原样列出来。简单直接但记忆多了会占用大量Token而且模型可能抓不住重点。方式二按相关性排序截断。按相似度从高到低排列只取前3-5条。比方式一好一些但还是可能包含不相关的记忆。方式三让模型先筛选。把检索到的10条记忆给模型让它自己判断哪些跟当前问题相关然后只用相关的。这个方式效果最好但多了一次模型调用。方式四分层注入。把记忆分成“核心记忆”和“参考记忆”两层。核心记忆是重要性高、访问频繁的直接放进System Prompt参考记忆放在User Message里作为补充。这个方式我目前用得最多平衡了效果和成本。实际用下来我建议根据场景选简单问答用方式二就够了复杂任务用方式四对精度要求极高的场景用方式三。5.3 自动化记忆整理的脚本记忆库用久了会变得杂乱需要定期整理。我写了几个自动化脚本用cron定时跑。第一个是每日摘要生成。每天凌晨跑一次把当天的对话记录聚合成一条摘要记忆import requests from datetime import datetime, timedelta def daily_summary(): today datetime.now().strftime(%Y-%m-%d) yesterday (datetime.now() - timedelta(days1)).strftime(%Y-%m-%d) # 获取昨天的对话记忆 response requests.post( http://localhost:8080/api/v1/memories/search, headers{Authorization: Bearer your_api_key_here}, json{ tags: [对话记录], created_after: f{yesterday}T00:00:00Z, created_before: f{today}T00:00:00Z, limit: 100 } ) memories response.json()[results] if not memories: return # 调用模型生成摘要 content \n.join([m[content] for m in memories]) summary call_llm(f请将以下对话记录总结成一段200字以内的摘要\n{content}) # 写入摘要记忆 requests.post( http://localhost:8080/api/v1/memories, headers{Authorization: Bearer your_api_key_here}, json{ content: f[{yesterday}摘要] {summary}, tags: [每日摘要], importance: 0.7, source: auto_summary } )第二个是重复记忆清理。每周跑一次找出相似度极高的记忆对合并或删除def deduplicate(): # 获取所有记忆 all_memories get_all_memories() for i, mem_a in enumerate(all_memories): for mem_b in all_memories[i1:]: similarity cosine_similarity(mem_a[embedding], mem_b[embedding]) if similarity 0.95: # 保留importance更高的那条 if mem_a[importance] mem_b[importance]: delete_memory(mem_b[id]) else: delete_memory(mem_a[id])实操心得去重阈值不要设太低0.95以上才合并。我一开始设了0.9结果把很多相关但不重复的记忆也合并了丢失了细节信息。6. 踩坑记录与性能调优6.1 常见问题速查表问题现象可能原因解决方法API返回503PostgreSQL未就绪检查healthcheck等数据库完全启动检索结果不相关嵌入模型不匹配确认写入和检索用的是同一个嵌入模型写入超时单次批量太大减小batch size到50以下内存占用过高Redis缓存无上限设置maxmemory和淘汰策略检索速度慢向量索引未建或参数不当检查ivfflat索引调整lists参数容器间无法通信网络配置问题确认在同一个Docker network里中文检索效果差嵌入模型中文能力弱换用BGE-M3或m3e-base6.2 性能调优的几个关键参数PostgreSQL的shared_buffers。默认值通常太小建议设为系统内存的25%。16GB内存的机器可以设4GBALTER SYSTEM SET shared_buffers 4GB; ALTER SYSTEM SET effective_cache_size 12GB; ALTER SYSTEM SET work_mem 256MB;ivfflat索引的probes参数。这个参数控制检索时扫描多少个聚类。值越大越精确但越慢。默认是1我一般设成10SET ivfflat.probes 10;Redis的maxmemory。根据记忆总量来设。如果记忆库有10万条每条平均1KB加上向量数据大概500MBRedis缓存设512MB到1GB比较合适。嵌入生成的批处理。如果要导入大量数据不要一条一条生成嵌入攒一批一起生成。Ollama的embeddings接口支持批量输入一次传10-20条文本效率最高。6.3 我踩过的三个大坑第一个坑嵌入维度不匹配。一开始我用的是BGE-M3生成嵌入维度是1024但数据库表建的是768。写入的时候没报错但检索的时候一直返回空结果。排查了很久才发现是维度问题。教训是建表之前一定要确认嵌入模型的输出维度。第二个坑Docker网络隔离。Supermemory的API容器和Ollama不在同一个网络里导致API调不到Ollama。解决方案是把Ollama也放进同一个Docker network或者用host.docker.internal。我选了后者因为Ollama跑在宿主机上性能更好。第三个坑记忆写入没有去重。早期没有配置去重逻辑同样的内容写了好几次导致检索结果里全是重复的。后来加了语义去重相似度超过0.92的自动合并问题才解决。但去重阈值需要根据实际数据调太高了去不掉太低了会误合并。6.4 备份与恢复策略记忆数据是长期积累的资产丢了很麻烦。我现在的备份策略是每天凌晨2点自动备份PostgreSQLpg_dump导出SQL文件备份文件保留最近30天更早的自动删除每周做一次全量备份存到另一块硬盘上Redis的数据不做备份因为都是缓存丢了可以从PostgreSQL重建恢复的时候docker exec -i supermemory-postgres psql -U supermemory supermemory backup.sql注意恢复之前先停掉API服务否则可能会有写入冲突。恢复完成后重启API。7. 记忆系统的扩展玩法7.1 接入多种数据源记忆系统不只是存对话记录。我把日常的工作日志、读书笔记、甚至浏览器书签都灌进去了。具体做法是写不同的适配器脚本工作日志从Markdown文件读取按日期和标题切分读书笔记从微信读书导出按章节切分网页剪藏从浏览器书签导出HTML提取正文内容邮件摘要从邮件客户端导出提取关键信息每个数据源打不同的标签检索的时候可以按来源过滤。这样整个知识管理体系就串起来了。7.2 构建个人知识图谱记忆之间的关联可以通过标签和语义相似度来建立。我写了个脚本定期分析记忆之间的关联强度生成一个知识图谱def build_knowledge_graph(): memories get_all_memories() edges [] for i, mem_a in enumerate(memories): for mem_b in memories[i1:]: # 语义相似度 sem_sim cosine_similarity(mem_a[embedding], mem_b[embedding]) # 标签重叠度 tag_overlap len(set(mem_a[tags]) set(mem_b[tags])) / \ len(set(mem_a[tags]) | set(mem_b[tags])) # 综合关联强度 strength 0.7 * sem_sim 0.3 * tag_overlap if strength 0.6: edges.append({ source: mem_a[id], target: mem_b[id], strength: strength }) return edges这个图谱可以用NetworkX或者D3.js可视化出来能直观地看到哪些主题是核心节点哪些是边缘节点。我用它来发现知识盲区和关联线索效果不错。7.3 多Agent共享记忆如果你同时跑多个AI Agent可以让它们共享同一个记忆库。比如一个Agent负责写代码一个负责写文档一个负责做测试。它们各自产生的记忆都写到同一个库里检索的时候可以互相参考。但这里有个问题不同Agent的记忆可能会互相干扰。解决方案是用source字段区分检索的时候按source过滤。或者给每个Agent分配独立的命名空间底层还是同一个数据库但逻辑上隔离。# Agent A的记忆 {content: ..., source: agent_coder, tags: [代码]} # Agent B的记忆 {content: ..., source: agent_writer, tags: [文档]} # 检索时按source过滤 {query: ..., source: agent_coder}7.4 记忆的版本控制有些记忆是会演变的比如项目需求、个人偏好。我希望能追溯记忆的变化历史。实现方式是在写入新版本之前先把旧版本存到一张历史表里CREATE TABLE memory_history ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), memory_id UUID REFERENCES memories(id), content TEXT, importance FLOAT, tags TEXT[], version INTEGER, changed_at TIMESTAMP DEFAULT NOW() );每次更新记忆时先把当前版本插入历史表版本号加1然后再更新主表。这样就能看到一条记忆从创建到现在的所有变化。8. 实际使用中的一些体会这套系统我跑了大概三个月积累了两万多条记忆。最大的感受是记忆系统让AI从工具变成了助手。以前每次对话都是冷启动现在它能记住我的偏好、我的项目背景、我之前问过的问题。这种连续性带来的体验提升比换一个更大的模型要明显得多。有几个经验值得分享。第一记忆的质量比数量重要。一开始我什么都往里灌结果检索的时候噪音很大。后来我加了过滤规则只保留有长期价值的信息检索准确率明显提升。第二标签体系要提前规划。我一开始随便打标签后来发现标签太乱没法用。现在固定了几个维度项目、类型、重要性、时间。第三定期回顾和整理。我每周会花半小时看看这周新增的记忆手动调整一些重要性评分合并一些重复的删除一些没用的。这个习惯让记忆库保持在一个健康的状态。还有一个我觉得很有用的技巧给记忆加“触发词”。比如某条记忆是关于某个项目的技术决策我会在内容里显式地写上项目名和关键词。这样检索的时候即使语义相似度不是最高关键词匹配也能把它捞出来。相当于给记忆加了一个精确检索的通道。后续我打算试试把记忆系统跟本地的代码助手集成让它在写代码的时候能参考之前的项目经验。还打算研究一下记忆的自动摘要和分层压缩解决记忆库越来越大之后检索效率下降的问题。这些等跑通了再另开一篇来写。
返回列表