ARTICLE DETAIL

资讯详情

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

hindsight:为LLM Agent构建可检索的记忆系统实战

hindsight:为LLM Agent构建可检索的记忆系统实战 1. 从“hindsight”说起为什么我们需要给Agent装一个“后视镜”第一次看到“hindsight”这个词我脑子里蹦出来的不是技术概念而是生活里一个特别常见的场景开车的时候后视镜里能看到的东西往往比正前方更让人心里有底。变道、倒车、判断后车距离全靠它。后来做LLM Agent相关的东西做多了我越来越觉得一个能长期运行的Agent缺的就是这么一块“后视镜”。hindsight这个词本身的意思是“事后聪明”或者更准确地说是“事后的理解”。放在Agent Memory这个领域里它指向的是一个非常具体的问题当一个大语言模型驱动的Agent在跟用户交互、执行任务、调用工具的过程中它产生的那些历史信息到底该怎么存、怎么取、怎么用如果只是简单地把所有对话记录塞进上下文窗口那既昂贵又低效而且很快就会超出模型的上下文长度限制。如果完全不存那Agent就永远是一个“失忆症患者”每次对话都从零开始用户得反复交代背景体验极差。所以hindsight这个项目标题我理解它要解决的核心问题就是给LLM Agent构建一套可靠的、可检索的、有结构的记忆系统。它不是一个简单的聊天记录存储而是一套完整的记忆管理框架涉及到记忆的写入、索引、检索、更新和遗忘机制。结合热搜词里出现的agent memory、MCP、Docker、LLM这些关键词可以很清楚地看出这是一个面向LLM Agent开发者的基础设施类项目目标用户是那些正在构建自主Agent、需要让Agent具备长期记忆能力的工程师和研究者。这篇文章我会从项目整体设计思路开始拆然后深入到核心细节和实操要点接着给出一个完整的、可复现的实操流程最后把我自己踩过的坑和常见问题的排查方法整理出来。不管你是刚接触Agent Memory的新手还是已经在做相关项目的老手应该都能从中找到一些可以直接抄作业的东西。2. 内容整体设计与思路拆解2.1 为什么Agent Memory不能简单等同于“存聊天记录”很多人第一次做Agent Memory的时候直觉反应就是把每轮对话存到数据库里下次对话的时候根据关键词搜一下把相关的几条记录拼到prompt里不就完了我一开始也是这么想的但实际跑起来之后发现问题远比这个复杂。首先记忆的粒度问题。一轮对话可能包含多个信息点比如用户说“我下周要去北京出差帮我查一下那边的天气另外我上次说的那个项目文档你帮我找一下”。这一句话里至少有两个独立的信息一个是出差计划一个是文档检索需求。如果按整轮对话来存检索的时候要么全带出来要么全不带精度很差。所以hindsight这类项目通常会把记忆拆成更细的单元比如按“事实”、“事件”、“偏好”、“任务”来分类存储。其次记忆的时效性问题。有些记忆是永久有效的比如“用户的名字叫张三”有些记忆是有时效的比如“用户下周要去北京”还有些记忆是一次性的比如“用户刚才让我查了一下天气”。如果不区分时效性检索的时候就会把过期的信息也带出来干扰模型的判断。第三记忆的检索效率问题。当记忆库积累到几千条甚至几万条的时候单纯靠关键词匹配已经不够用了。这时候就需要引入向量检索、语义索引甚至图结构来组织记忆之间的关系。hindsight这个项目名字本身就暗示了“回头看”的能力也就是说它需要在需要的时候能够快速、准确地从历史记忆中找到最相关的那几条。所以整体设计上hindsight的思路应该是分层存储 多路检索 动态更新。分层存储解决粒度问题多路检索解决效率问题动态更新解决时效性问题。下面我分别展开说。2.2 分层存储把记忆当成一个数据库来设计我见过的比较成熟的Agent Memory方案通常会把记忆分成至少三层原始层Raw Layer存最原始的对话记录、工具调用日志、系统事件。这一层不做任何加工就是append-only的日志主要用于审计和回溯。提炼层Distilled Layer从原始层里提取出来的结构化信息比如实体、关系、事实、偏好。这一层是检索的主要来源。摘要层Summary Layer对一段时间内的记忆做概括比如“过去一周用户主要在处理项目A的文档工作”。这一层用于快速给Agent提供上下文概览。hindsight如果要对标a-memguard这类主动防御框架那它在分层上可能还会多一层安全层用来检测和过滤恶意注入的记忆防止Agent被污染。这个后面讲MCP集成的时候会再提到。分层的好处是不同层可以用不同的存储引擎。原始层用日志文件或者时序数据库提炼层用关系库或者向量库摘要层用缓存。检索的时候也是分层的先查摘要层拿概览再查提炼层拿细节最后如果需要再回原始层核对。这样既保证了速度又保证了精度。2.3 多路检索关键词、向量、图一个都不能少检索是Agent Memory最核心的能力。我实测下来单一检索方式很难满足所有场景关键词检索适合精确匹配比如查“张三”这个名字或者查某个具体的订单号。优点是快、准缺点是无法处理语义相似但用词不同的情况。向量检索适合语义匹配比如用户问“我上次说的那个关于预算的事情”向量检索能找到“项目预算讨论”相关的记忆。优点是泛化能力强缺点是可能召回不相关的记忆而且需要embedding模型支持。图检索适合关系推理比如“张三负责的项目有哪些”通过实体关系图可以快速遍历。优点是能处理复杂关系缺点是构建和维护成本高。hindsight的设计里我推测它会把这几种检索方式做成可插拔的模块根据查询类型自动路由。比如简单的事实查询走关键词模糊的语义查询走向量关系型查询走图。这样既保证了灵活性又不会让系统过于复杂。2.4 动态更新记忆不是一成不变的记忆系统最容易被忽视的一点是更新和遗忘。用户上周说“我住在北京”这周说“我搬到上海了”如果两条记忆都留着检索的时候就会冲突。所以hindsight需要有一套机制来处理记忆的更新冲突检测当新记忆和旧记忆矛盾时标记出来。时效衰减给每条记忆打一个时间戳和置信度越久远的记忆权重越低。主动遗忘对于明确过期的记忆比如“明天下午三点的会议”过了时间就自动归档或删除。这套机制听起来简单但实际实现的时候需要考虑很多边界情况。比如用户说“我可能下周去北京”这是一个不确定的信息不能当成确定事实来存。再比如用户说“帮我记住我讨厌吃香菜”这是一个长期偏好不应该被时效衰减影响。所以hindsight在记忆写入的时候应该会做一个记忆类型分类不同类型的记忆走不同的更新策略。3. 核心细节解析与实操要点3.1 记忆的写入从原始对话到结构化记忆写入是记忆系统的第一步。我见过很多项目在这一步就做得很粗糙直接把整段对话丢给embedding模型然后存到向量库里。这样做不是不行但检索精度会很差。hindsight应该会采用更精细的写入流程对话分块把长对话按语义边界切成小块比如按轮次、按话题切换点。信息抽取用LLM从每个块里抽取结构化信息包括实体、关系、事实、偏好、任务等。类型标注给每条抽取出来的记忆打上类型标签比如“事实型”、“偏好型”、“事件型”。时效标注判断记忆的时效性是永久、长期、短期还是一次性。向量化对记忆的文本内容做embedding存入向量库。索引构建同时构建关键词索引和图索引方便多路检索。这个流程里信息抽取是最关键也最容易出问题的一步。我试过用不同的prompt让LLM做抽取效果差异很大。一个好的抽取prompt应该包含明确的输出格式JSON schema具体的抽取类别定义几个few-shot示例对不确定信息的处理规则比如下面这个prompt模板是我实测下来比较稳定的EXTRACT_PROMPT 你是一个记忆抽取器。请从以下对话中抽取结构化记忆。 对话内容 {dialogue} 请按以下JSON格式输出 {{ memories: [ {{ type: fact|preference|event|task, content: 记忆内容, entities: [实体1, 实体2], temporal: permanent|long_term|short_term|one_time, confidence: 0.0-1.0 }} ] }} 规则 1. 只抽取明确的信息不要推测。 2. 如果信息不确定confidence设为0.5以下。 3. 偏好类记忆的temporal通常为permanent或long_term。 4. 任务类记忆的temporal通常为short_term或one_time。 这个prompt的关键在于规则明确和格式固定。规则明确可以减少LLM的随意发挥格式固定方便后续程序解析。我踩过的坑是如果不给few-shot示例LLM有时候会输出额外的字段或者把confidence写成字符串导致解析失败。3.2 记忆的检索如何让Agent“想起”该想起的东西检索的核心是相关性排序。给定一个查询系统需要从记忆库里找出最相关的N条记忆按相关性从高到低排列。hindsight应该会采用混合排序策略第一路关键词匹配得分。用BM25或者TF-IDF算一个分数。第二路向量相似度得分。用余弦相似度算一个分数。第三路图关系得分。如果查询涉及实体关系从图里遍历算一个分数。融合排序把三路得分加权求和得到最终排序。权重的设置很关键。我实测下来对于事实型查询关键词权重可以高一点比如0.5对于语义型查询向量权重高一点比如0.6对于关系型查询图权重高一点比如0.5。当然这只是一个起点具体项目里需要根据实际数据调优。还有一个容易被忽视的点是检索的时机。不是每次对话都需要检索记忆。如果用户只是说“你好”那没必要去查记忆库。所以hindsight应该会有一个检索触发器判断当前查询是否需要访问记忆。这个触发器可以是一个简单的分类器也可以是一个规则引擎。我自己的做法是用一个轻量级的LLM做判断prompt大概是TRIGGER_PROMPT 判断以下用户输入是否需要查询历史记忆。 用户输入{query} 需要查询的情况 - 用户提到过去的事情 - 用户询问之前交代过的信息 - 用户使用指代词如“那个”、“上次说的” - 用户询问个人偏好或习惯 不需要查询的情况 - 简单的问候 - 独立的常识性问题 - 明确的当前操作指令 请只输出 YES 或 NO。 这个触发器可以过滤掉大部分不需要检索的请求节省计算资源也减少不相关记忆对模型的干扰。3.3 MCP集成让记忆系统成为Agent的“标准配件”MCPModel Context Protocol是最近很火的一个协议简单说就是让LLM能够以标准化的方式调用外部工具和数据源。hindsight如果支持MCP那意味着它可以作为一个MCP Server运行任何支持MCP的Agent框架都可以直接接入不需要写额外的适配代码。我实测过把记忆系统封装成MCP Server的流程大致是这样的定义工具接口暴露几个核心工具比如memory_write、memory_search、memory_update、memory_forget。实现工具逻辑每个工具背后调用记忆系统的对应模块。启动MCP Server用标准的MCP SDK启动服务监听请求。Agent端配置在Agent的MCP配置里加上这个Server的地址。这样做的好处是解耦。记忆系统可以独立部署、独立升级Agent端不需要关心记忆的具体实现。而且MCP是标准协议今天用这个Agent框架明天换另一个记忆系统都不用改。不过MCP集成也有坑。我遇到的最常见问题是schema不匹配。MCP对工具的输入输出schema有严格要求如果记忆系统返回的数据结构跟schema不一致Agent端就会报错。比如memory_search返回的是一个列表但schema定义的是对象那就会失败。所以定义schema的时候一定要仔细最好用JSON Schema做严格校验。另外MCP Server的超时设置也很重要。记忆检索有时候会比较慢如果超时时间设得太短Agent会频繁报错。我一般会把超时设成10秒左右同时给检索加一个缓存层热门查询直接走缓存。3.4 Docker部署让记忆系统跑得稳、搬得动Docker部署是hindsight这类项目的基本功。我见过太多项目在本地跑得好好的一到服务器上就各种问题。Docker能解决环境一致性问题但前提是Dockerfile写得对。一个典型的hindsight Docker部署架构大概是应用容器跑记忆系统的核心服务包括API、检索、写入等。向量库容器比如Qdrant或者Milvus存向量索引。关系库容器比如PostgreSQL存结构化记忆和元数据。缓存容器比如Redis存热门查询结果和会话状态。这四个容器通过Docker网络互联。我建议用docker-compose来编排这样启动和停止都方便。下面是一个我常用的docker-compose模板version: 3.8 services: hindsight-app: build: . ports: - 8000:8000 environment: - VECTOR_DB_URLhttp://vector-db:6333 - RELATION_DB_URLpostgresql://user:passrelation-db:5432/hindsight - REDIS_URLredis://cache:6379 depends_on: - vector-db - relation-db - cache networks: - hindsight-net vector-db: image: qdrant/qdrant:latest ports: - 6333:6333 volumes: - vector-data:/qdrant/storage networks: - hindsight-net relation-db: image: postgres:15 environment: - POSTGRES_USERuser - POSTGRES_PASSWORDpass - POSTGRES_DBhindsight volumes: - relation-data:/var/lib/postgresql/data networks: - hindsight-net cache: image: redis:7-alpine ports: - 6379:6379 networks: - hindsight-net volumes: vector-data: relation-data: networks: hindsight-net: driver: bridge这个模板里我把数据卷单独挂出来这样容器重启不会丢数据。网络用自定义bridge容器之间可以通过服务名互相访问。环境变量统一管理方便切换配置。Docker部署最常见的坑是网络不通。比如应用容器访问不到向量库容器报连接超时。排查的时候先docker exec进应用容器用curl或者ping测试目标容器的服务名能不能解析。如果解析不了检查是不是在同一个网络里。如果解析了但连不上检查目标容器的端口有没有暴露防火墙有没有拦截。还有一个坑是资源限制。向量库和关系库都比较吃内存如果Docker Desktop默认分配的内存不够容器会频繁OOM。我一般会把Docker Desktop的内存调到8GB以上生产环境的话直接上服务器不跑在本地。4. 实操过程与核心环节实现4.1 环境准备从零开始搭一套hindsight假设你现在有一台Ubuntu 22.04的机器想从零搭一套hindsight。下面是我实测过的完整流程。第一步安装Docker和Docker Compose# 更新包索引 sudo apt-get update # 安装依赖 sudo apt-get install -y ca-certificates curl gnupg lsb-release # 添加Docker官方GPG密钥 sudo mkdir -p /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg # 添加Docker仓库 echo deb [arch$(dpkg --print-architecture) signed-by/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable | sudo tee /etc/apt/sources.list.d/docker.list /dev/null # 安装Docker Engine sudo apt-get update sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin # 验证安装 sudo docker run hello-world如果你用的是Windows那就装Docker Desktop。安装的时候注意勾选WSL2后端性能比Hyper-V好很多。装完之后在设置里把内存调到8GB以上不然跑向量库会卡。第二步拉取hindsight代码git clone https://github.com/your-org/hindsight.git cd hindsight第三步配置环境变量cp .env.example .env然后编辑.env文件填入你的配置# LLM配置 LLM_API_KEYyour_api_key LLM_BASE_URLhttps://api.your-provider.com/v1 LLM_MODELgpt-4 # Embedding配置 EMBEDDING_MODELtext-embedding-3-small EMBEDDING_DIM1536 # 数据库配置 VECTOR_DB_URLhttp://localhost:6333 RELATION_DB_URLpostgresql://user:passlocalhost:5432/hindsight REDIS_URLredis://localhost:6379 # 检索配置 RETRIEVAL_TOP_K10 RETRIEVAL_KEYWORD_WEIGHT0.4 RETRIEVAL_VECTOR_WEIGHT0.5 RETRIEVAL_GRAPH_WEIGHT0.1这里的权重配置是我调过的关键词0.4、向量0.5、图0.1适合大多数场景。如果你的数据里关系型查询比较多可以把图权重调到0.2或0.3。第四步启动服务docker compose up -d启动之后用docker compose ps看一下容器状态四个容器都应该是running。如果有容器不断重启用docker compose logs 服务名看日志。第五步初始化数据库docker compose exec hindsight-app python -m hindsight.init_db这一步会创建必要的表结构和索引。如果报错大概率是数据库连接配置不对检查.env里的URL。4.2 记忆写入的完整实现环境搭好之后下一步是让记忆系统真正跑起来。我先给一个最小可用的写入示例from hindsight import MemorySystem from hindsight.extractors import LLMExtractor from hindsight.stores import QdrantStore, PostgresStore # 初始化存储 vector_store QdrantStore(urlhttp://localhost:6333, collectionmemories) relation_store PostgresStore(urlpostgresql://user:passlocalhost:5432/hindsight) # 初始化抽取器 extractor LLMExtractor( api_keyyour_api_key, base_urlhttps://api.your-provider.com/v1, modelgpt-4 ) # 初始化记忆系统 memory MemorySystem( vector_storevector_store, relation_storerelation_store, extractorextractor ) # 写入一段对话 dialogue 用户我下周要去北京出差大概周三到周五回。 助手好的需要我帮你查一下北京的天气吗 用户可以另外我上次说的那个项目文档你帮我找一下。 助手好的我帮你找一下。 result memory.write(dialogue) print(result)这段代码背后做的事情是把对话切成两个块一个是出差计划一个是文档检索需求。对每个块调用LLM抽取结构化记忆。把抽取出来的记忆分别写入向量库和关系库。返回写入结果包括记忆ID和抽取内容。我实测下来抽取的质量很大程度上取决于prompt和模型。用GPT-4的话抽取准确率大概在85%左右用GPT-3.5的话大概70%。如果对精度要求高建议用大模型或者在抽取之后加一层校验。4.3 记忆检索的完整实现写入之后检索是这样用的# 检索记忆 query 我下周的出差安排是什么 results memory.search(query, top_k5) for r in results: print(f内容{r.content}) print(f类型{r.type}) print(f得分{r.score}) print(---)检索的流程是判断查询是否需要检索记忆触发器。如果需要分别走关键词、向量、图三路检索。融合排序取Top-K。返回结果。我实测下来Top-K设成5到10比较合适。太小了可能漏掉关键信息太大了会引入噪声。如果检索结果里有很多不相关的记忆可以调高相关性阈值过滤掉低分结果。还有一个技巧是检索结果的重排序。第一轮检索出来的Top-K可以用一个更小的模型做一次精排把最相关的排到最前面。我试过用cross-encoder做重排序效果比单纯用向量相似度好不少但会增加延迟。如果对延迟不敏感可以加上这一步。4.4 MCP Server的封装与接入把hindsight封装成MCP Server大概是这样from mcp.server import Server, stdio_server from mcp.types import Tool, TextContent import json app Server(hindsight-mcp) app.list_tools() async def list_tools(): return [ Tool( namememory_write, description写入一段对话到记忆系统, inputSchema{ type: object, properties: { dialogue: {type: string, description: 对话内容} }, required: [dialogue] } ), Tool( namememory_search, description从记忆系统中检索相关记忆, inputSchema{ type: object, properties: { query: {type: string, description: 查询内容}, top_k: {type: integer, default: 5} }, required: [query] } ) ] app.call_tool() async def call_tool(name: str, arguments: dict): if name memory_write: result memory.write(arguments[dialogue]) return [TextContent(typetext, textjson.dumps(result, ensure_asciiFalse))] elif name memory_search: results memory.search(arguments[query], arguments.get(top_k, 5)) return [TextContent(typetext, textjson.dumps([r.dict() for r in results], ensure_asciiFalse))] async def main(): async with stdio_server() as (read, write): await app.run(read, write, app.create_initialization_options()) if __name__ __main__: import asyncio asyncio.run(main())这个Server启动之后Agent端只需要在MCP配置里加上{ mcpServers: { hindsight: { command: python, args: [-m, hindsight.mcp_server] } } }然后Agent就可以通过MCP协议调用memory_write和memory_search了。我实测下来这种方式的延迟大概在100到300毫秒之间主要花在LLM抽取和向量检索上。如果对延迟敏感可以把抽取做成异步的写入的时候先存原始对话后台再慢慢抽取。5. 常见问题与排查技巧实录5.1 记忆检索不准确怎么办这是最常见的问题。用户明明记得之前说过某件事但Agent就是检索不出来。排查思路是这样的问题现象可能原因排查方法解决方案完全检索不到记忆没写入成功查数据库里有没有对应记录检查写入流程看抽取是否失败检索到但不相关向量模型效果差手动测试embedding相似度换更好的embedding模型相关记忆排后面权重配置不合理调整关键词/向量/图权重根据查询类型动态调权检索结果冲突旧记忆没更新查是否有矛盾记忆加冲突检测和时效衰减我踩过的一个坑是embedding维度不匹配。写入的时候用的是1536维的模型检索的时候换成了768维的模型结果向量库直接报错。所以embedding模型一旦确定就不要随便换换了就要重新索引所有记忆。另一个坑是中文分词。关键词检索如果用的是英文分词器中文查询会切得很碎匹配效果很差。解决办法是用jieba之类的中文分词器或者直接用字符级n-gram。5.2 Docker容器频繁重启怎么排查Docker容器频繁重启通常是因为应用启动失败。排查步骤docker compose logs 服务名看日志找报错信息。如果是数据库连接失败检查.env里的URL和端口。如果是内存不足docker stats看内存占用调大Docker Desktop的内存限制。如果是端口冲突netstat -tulpn | grep 端口看端口被谁占了。我遇到过一次是向量库容器一直重启日志显示disk quota exceeded。原因是数据卷满了清理一下旧数据就好了。所以生产环境一定要监控磁盘使用率。5.3 MCP连接失败怎么处理MCP连接失败的表现是Agent端报tool not found或者connection refused。排查思路确认MCP Server进程在跑ps aux | grep mcp看一下。确认Agent端的MCP配置路径正确特别是command和args。如果是远程MCP Server确认网络能通防火墙没拦。看MCP Server的日志有没有收到请求有没有报错。我踩过的一个坑是stdio模式下的日志输出。MCP Server如果用stdio通信那标准输出会被协议占用日志必须写到标准错误或者文件里。如果往标准输出打日志协议就乱了Agent端会解析失败。5.4 记忆写入太慢怎么优化写入慢的主要瓶颈在LLM抽取。优化方法批量抽取把多轮对话攒在一起一次性抽取减少LLM调用次数。异步写入先存原始对话后台异步抽取不阻塞主流程。小模型抽取用更小的模型做抽取牺牲一点精度换速度。缓存抽取结果相似的对话直接复用之前的抽取结果。我实测下来异步写入能把写入延迟从2秒降到200毫秒以内用户体验提升很明显。代价是检索的时候可能查不到刚写入的记忆需要加一个“最近写入”的短期缓存来兜底。5.5 记忆冲突怎么处理记忆冲突的典型场景是用户改了偏好或者事实。处理方法写入时检测新记忆写入前先检索是否有矛盾记忆。标记冲突如果有冲突把旧记忆标记为superseded新记忆标记为active。检索时过滤只检索active状态的记忆。定期清理把长期superseded的记忆归档或删除。这里的关键是冲突检测的准确性。如果检测太激进会把不矛盾的记忆误判为冲突如果太保守又会漏掉真正的冲突。我的做法是用LLM做冲突判断prompt大概是CONFLICT_PROMPT 判断以下两条记忆是否矛盾。 记忆A{memory_a} 记忆B{memory_b} 矛盾的定义两条记忆不能同时为真。 例如 - 用户住在北京 和 用户住在上海 矛盾 - 用户喜欢咖啡 和 用户喜欢茶 不矛盾 - 用户下周去北京 和 用户下月去北京 不矛盾 请只输出 YES 或 NO。 这个判断用GPT-3.5就够了不需要大模型。准确率大概在90%左右剩下的10%可以通过人工审核或者置信度阈值来处理。5.6 记忆系统的安全防护a-memguard这类主动防御框架提醒我们记忆系统本身也是攻击面。恶意用户可能通过注入虚假记忆来污染Agent的行为。防护措施包括输入过滤对写入的记忆做敏感词和注入模式检测。来源标记给每条记忆标记来源用户输入、系统生成、外部工具要区分开。权限控制不同来源的记忆有不同的信任级别检索时按信任级别加权。异常检测监控记忆写入频率和内容分布发现异常及时告警。我自己的做法是给每条记忆打一个trust_score用户直接输入的是0.8系统推断的是0.6外部工具返回的是0.5。检索的时候最终得分乘以trust_score这样低信任度的记忆不容易被召回。6. 一些实操心得和后续扩展方向做Agent Memory这段时间我最大的体会是记忆系统的难点不在存储而在检索和更新。存储可以用现成的数据库但检索的精度和更新的逻辑需要根据具体场景反复调优。没有一套通用的参数能适配所有场景必须结合自己的数据去试。另一个体会是不要过度设计。我一开始想做一个特别复杂的记忆系统又是图数据库又是多级缓存结果维护成本极高效果也没好多少。后来简化成“向量库关系库Redis缓存”的三件套反而更稳定。所以建议刚上手的时候先用最简单的方案跑通再根据实际瓶颈逐步优化。后续如果要扩展我觉得有几个方向值得尝试记忆的可视化做一个界面让用户能看到Agent记住了什么可以手动编辑和删除。这对建立用户信任很有帮助。跨Agent记忆共享多个Agent共享一个记忆库但各自有独立的访问权限。这在多Agent协作场景下很有用。记忆的自动摘要定期对记忆做摘要生成用户画像和行为模式给Agent提供更高层的上下文。与RAG的融合把记忆检索和文档检索统一起来Agent可以在同一个查询里同时查记忆和查知识库。最后分享一个小技巧给记忆加一个“最近使用”的时间戳。每次检索到某条记忆就更新它的last_accessed时间。这样在排序的时候可以给最近使用的记忆一点加权因为最近用过的记忆往往更相关。这个技巧很简单但实测下来对检索精度有5%到10%的提升。
返回列表