1. 从“hindsight”说起:为什么Agent的记忆需要“事后诸葛亮”
第一次看到“hindsight”这个词被拿来命名一个Agent记忆项目,我脑子里蹦出来的不是技术架构,而是一句大白话——事后诸葛亮。这个词在英文里本身就带着“事后才明白”的意思,放在LLM Agent的语境下,它指向一个非常具体且长期被忽视的问题:Agent在完成任务之后,能不能回头审视自己刚才的经历,把有用的东西沉淀下来,把没用的噪音丢掉?
我接触过不少做Agent记忆的方案,大多数思路是“边做边记”——对话过程中实时往向量库里塞内容,检索的时候按相似度捞回来。这套做法能跑通,但用久了就会发现两个致命问题。第一,记忆污染:Agent把一次性的、上下文强相关的临时信息也当成长期知识存了进去,下次遇到相似但不同的场景,捞出来的全是干扰项。第二,缺乏反思:Agent不知道自己刚才哪一步做对了、哪一步做错了,它只是机械地记录,而不是有选择地学习。
hindsight这个项目切入的角度就不一样。它把记忆分成两个阶段:执行阶段和回顾阶段。执行阶段Agent正常干活,该调工具调工具,该推理推理;回顾阶段则是在任务结束后,由一个独立的“反思模块”去审视整个执行轨迹,提取出真正值得保留的经验,再写入长期记忆。这个设计思路,说白了就是让Agent学会“复盘”。
你可能会问,这不就是加了一个总结步骤吗?没那么简单。hindsight的核心价值在于它定义了一套记忆的准入标准。不是所有东西都值得记,也不是所有东西都该忘。它通过一套评分机制,从新颖性、复用性、因果关联度三个维度去判断一条经验是否应该进入长期记忆。这个判断过程本身,就是“hindsight”这个名字的由来——用事后的视角,去筛选事中的信息。
适合谁来参考这个项目?如果你正在做Agent相关的开发,尤其是涉及多轮任务、工具调用、长期陪伴类场景的,hindsight的思路值得仔细拆解。如果你只是刚接触LLM应用开发,也不用慌,我会从最基础的概念讲起,把里面的设计取舍和实操细节都摊开来说。
2. 核心架构拆解:hindsight到底怎么组织Agent的记忆
2.1 三层记忆结构:工作记忆、情景记忆、语义记忆
hindsight把Agent的记忆分成三层,这个分层不是拍脑袋定的,而是对应了认知科学里对人类记忆的经典划分。
工作记忆(Working Memory)是最短命的一层,只存在于当前任务的执行过程中。它相当于Agent的“草稿纸”,记录当前对话的上下文、已经调用的工具、中间产生的临时结果。任务一结束,这一层基本就清空了。它的容量有限,通常只保留最近N轮交互,N的取值一般在10到20之间。为什么要有容量限制?因为LLM的上下文窗口是有限的,你不能把所有历史都塞进去,那样既贵又慢,还会稀释真正重要的信息。
情景记忆(Episodic Memory)是中期存储,记录的是“发生了什么”。每一次任务的执行轨迹,包括用户输入、Agent的决策、工具调用结果、最终输出,都会被压缩成一条情景记录。这条记录不是原始日志的堆砌,而是经过结构化处理的——时间戳、任务类型、关键实体、结果状态,这些字段都会被提取出来。情景记忆的检索方式主要是按时间范围和任务类型过滤,而不是纯向量相似度。
语义记忆(Semantic Memory)是长期存储,记录的是“学到了什么”。这是hindsight最核心的部分,也是它区别于普通RAG方案的关键。语义记忆里存的不是原始对话,而是从多次情景中抽象出来的规律性知识。比如Agent在多次处理“用户询问退款政策”的任务后,语义记忆里可能会形成一条:“当用户情绪激动且涉及金额超过500元时,先安抚再走流程,成功率更高。”这条知识不是从某一次对话里直接抄来的,而是从多次情景中提炼出来的。
这三层记忆的流转关系是这样的:工作记忆在任务执行时不断产生原始数据,任务结束后,反思模块介入,把工作记忆压缩成情景记忆;当情景记忆积累到一定数量,或者某类情景反复出现时,抽象模块启动,把情景记忆升华为语义记忆。检索的时候,Agent优先查语义记忆,找不到再降级到情景记忆,最后才看工作记忆。
2.2 反思模块的触发时机与评分机制
反思模块什么时候启动?hindsight给了三种触发条件,我实测下来觉得这个设计很务实。
第一种是任务结束触发。每次Agent完成一个完整任务,反思模块自动运行。这是最基础的触发方式,保证每条任务轨迹都会被审视一遍。但这里有个细节:不是所有任务都值得反思。如果任务太简单,比如用户只是问了个天气,反思模块会快速跳过,不产生情景记忆。判断标准是任务的决策复杂度——如果Agent在整个过程中没有做任何非平凡的选择,那就不值得记。
第二种是异常触发。当Agent执行过程中出现工具调用失败、用户明确表示不满、或者推理链出现自相矛盾时,反思模块会被立即激活。这种触发方式的价值在于,错误是最好的老师。Agent从失败中学到的东西,往往比从成功中学到的更有价值。hindsight会把异常事件单独标记,在反思时给予更高的权重。
第三种是周期触发。每隔一定数量的任务(比如50个),反思模块会对近期积累的情景记忆做一次批量审视,寻找跨任务的模式。这种触发方式主要用于语义记忆的生成,因为单次任务很难抽象出规律,必须积累足够多的样本。
评分机制是反思模块的核心。每条候选记忆会从三个维度被打分:
| 维度 | 说明 | 权重 |
|---|---|---|
| 新颖性 | 这条经验是否与已有记忆重复 | 0.3 |
| 复用性 | 这条经验在未来任务中再次用到的概率 | 0.5 |
| 因果关联度 | 这条经验是否揭示了明确的因果链条 | 0.2 |
总分超过阈值(默认0.65)的候选记忆才会被写入长期存储。这个阈值是可以调的,调高会让记忆更精简但可能遗漏细节,调低会让记忆更丰富但引入噪音。我一般建议新手从默认值开始,跑一段时间后再根据实际效果微调。
2.3 与MCP协议的集成方式
hindsight支持通过MCP协议对外暴露记忆服务,这意味着任何支持MCP的Agent框架都可以把hindsight当作一个外挂的记忆后端来用。MCP在这里扮演的角色是标准化接口层,它让hindsight不用关心上层Agent是用什么框架写的,只要对方能发MCP请求就行。
具体来说,hindsight暴露了三个MCP工具:
memory_store:写入一条记忆,参数包括内容、类型、元数据memory_retrieve:检索记忆,参数包括查询文本、类型过滤、数量限制memory_reflect:手动触发反思,参数包括任务轨迹ID
这三个工具的粒度设计得比较克制。我见过一些方案把记忆操作拆得特别细,什么创建、更新、删除、合并各一个接口,结果上层调用起来特别繁琐。hindsight这种粗粒度设计反而更实用,因为Agent在大多数场景下只需要“存”和“取”两个动作,反思是自动触发的,不需要频繁手动调用。
MCP的传输层支持stdio和SSE两种模式。stdio适合本地开发,Agent和hindsight跑在同一台机器上,通过标准输入输出通信,延迟极低。SSE适合远程部署,hindsight作为一个独立服务跑在服务器上,多个Agent实例共享同一个记忆库。我实测下来,stdio模式的响应时间在10毫秒以内,SSE模式取决于网络状况,局域网内大概50到100毫秒,公网的话波动会大一些。
3. 动手部署:从Docker环境到第一个可运行的记忆Agent
3.1 Docker环境准备与常见坑排查
hindsight官方推荐用Docker部署,这确实是最省事的方式,但Docker本身的环境问题经常把人卡住。我把自己踩过的坑按顺序列一下。
Windows下的虚拟化支持问题是最常见的拦路虎。Docker Desktop启动时报“Virtualization support not detected”或者“Docker Desktop failed to start because virtualization support is not enabled”,原因通常是BIOS里的虚拟化选项没开。Intel平台叫VT-x,AMD平台叫SVM,进BIOS找到对应选项启用就行。如果BIOS里已经开了但还是报错,检查一下Windows的Hyper-V和WSL2功能有没有启用。在“启用或关闭Windows功能”里勾选“Hyper-V”和“适用于Linux的Windows子系统”,然后重启。
Linux下的权限问题也很典型。安装完Docker后直接运行docker命令报“permission denied”,是因为当前用户不在docker组里。执行sudo usermod -aG docker $USER,然后重新登录或者执行newgrp docker让组权限生效。注意这一步之后不需要每次都加sudo了,但如果你在脚本里用docker命令,记得脚本执行环境也要有正确的组权限。
Docker网络不通的情况我遇到过几次,表现是容器能启动但拉不到镜像,或者容器之间互相访问不了。先检查docker network ls看看默认的bridge网络是否正常,然后docker run --rm alpine ping -c 3 8.8.8.8测试容器内的外网连通性。如果外网不通,大概率是宿主机的DNS配置有问题,在/etc/docker/daemon.json里加上{"dns": ["8.8.8.8", "114.114.114.114"]}然后重启Docker服务。容器之间访问不了的话,检查是不是用了默认bridge网络,默认bridge不支持自动DNS解析,需要手动建一个自定义网络:docker network create hindsight-net,然后把相关容器都挂到这个网络上。
3.2 拉取镜像与启动hindsight服务
环境准备好之后,拉取和启动就很简单了。hindsight的镜像在Docker Hub上可以直接拉:
docker pull hindsight-agent/memory-server:latest启动命令我推荐用docker-compose来管理,因为hindsight依赖一个向量数据库(默认是Qdrant)和一个关系型数据库(默认是SQLite,生产环境建议换PostgreSQL)。docker-compose文件大概长这样:
version: '3.8' services: qdrant: image: qdrant/qdrant:latest ports: - "6333:6333" volumes: - qdrant_data:/qdrant/storage hindsight: image: hindsight-agent/memory-server:latest ports: - "8080:8080" environment: - QDRANT_URL=http://qdrant:6333 - DB_PATH=/data/hindsight.db - REFLECTION_THRESHOLD=0.65 - WORKING_MEMORY_SIZE=15 volumes: - hindsight_data:/data depends_on: - qdrant volumes: qdrant_data: hindsight_data:几个环境变量的含义我解释一下。REFLECTION_THRESHOLD就是前面说的记忆准入阈值,默认0.65。WORKING_MEMORY_SIZE是工作记忆保留的轮数,默认15,如果你的任务交互轮数普遍较多,可以调到20到25,但注意这会增加每次请求的token消耗。DB_PATH是SQLite数据库文件的位置,如果换成PostgreSQL,需要额外配置连接字符串。
启动命令:
docker-compose up -d启动后用docker-compose logs -f hindsight看日志,看到“Memory server listening on 0.0.0.0:8080”就说明服务起来了。然后访问http://localhost:8080/health应该返回{"status": "ok"}。
3.3 配置MCP连接与Agent端接入
hindsight服务跑起来之后,下一步是让Agent端能通过MCP连上它。以Claude Desktop为例,在配置文件里加上:
{ "mcpServers": { "hindsight": { "command": "npx", "args": ["-y", "@hindsight/mcp-client", "--server", "http://localhost:8080"] } } }如果你用的是其他支持MCP的客户端,配置逻辑类似,核心就是指定hindsight服务的地址。有些客户端支持SSE直连,那就把地址写成http://localhost:8080/mcp/sse。
接入之后,Agent在对话过程中会自动调用hindsight的记忆工具。你可以在Agent的system prompt里加一段引导语,让它更主动地使用记忆:
你拥有长期记忆能力。在回答用户问题前,先检索相关记忆;在任务完成后,反思并存储有价值的经验。记忆检索使用memory_retrieve工具,存储使用memory_store工具。
这段引导语不是必须的,但加上之后Agent使用记忆的主动性会明显提升。我实测下来,不加引导语的情况下,Agent大概只有30%的概率会主动检索记忆;加上之后,这个比例能到80%以上。
4. 记忆的写入与检索:核心机制与参数调优
4.1 一条记忆从产生到入库的完整链路
我拿一个具体例子来走一遍完整链路,这样你能看清楚每个环节到底发生了什么。
假设用户问Agent:“帮我查一下上个月的销售数据,然后做个同比分析。”Agent调用了一个数据库查询工具,拿到了数据,又调用了一个图表生成工具,最后输出了一份分析报告。任务结束后,反思模块启动。
第一步是轨迹压缩。反思模块把整个执行过程读一遍,提取出关键节点:用户意图(销售数据同比分析)、调用的工具(数据库查询、图表生成)、遇到的障碍(数据库查询第一次超时,重试后成功)、最终结果(报告生成成功)。这些节点被组织成一个结构化的轨迹摘要,而不是原始日志的全文。
第二步是候选记忆生成。基于轨迹摘要,反思模块生成若干条候选记忆。比如:
- 候选A:“数据库查询工具在数据量较大时容易超时,建议设置更长的超时时间或分批查询。”
- 候选B:“用户要求同比分析时,默认需要对比去年同期数据,如果数据缺失应主动询问。”
- 候选C:“图表生成工具对中文标签的支持需要显式指定字体参数。”
第三步是评分筛选。每条候选记忆按三个维度打分。候选A的新颖性高(之前没记录过超时问题),复用性高(其他任务也可能遇到),因果关联度强(超时导致重试,重试成功),总分0.78,通过。候选B的新颖性中等(可能已有类似记忆),复用性高,因果关联度中等,总分0.66,刚好过线。候选C的新颖性低(可能已有字体参数的记录),复用性中等,因果关联度弱,总分0.52,被丢弃。
第四步是去重与合并。通过的候选记忆会和已有记忆做相似度比对,如果发现高度相似的已有记忆,就做合并更新而不是新增。比如候选B如果和已有记忆“同比分析需要去年同期数据”相似度超过0.9,就把两条合并成一条,更新置信度分数。
第五步是写入存储。最终保留的记忆被写入语义记忆层,同时关联到对应的情景记忆记录。写入时会给每条记忆打上标签,比如“工具使用”、“用户偏好”、“领域知识”,方便后续按标签过滤检索。
4.2 检索策略:什么时候用向量检索,什么时候用结构化过滤
hindsight的检索不是单纯的向量相似度搜索,而是混合检索。这个设计很关键,因为纯向量检索在记忆场景下有几个硬伤。
第一个硬伤是语义漂移。用户问“退款流程”,向量检索可能把“退货政策”的记忆也捞出来,因为这两个词在向量空间里很近。但退款和退货是两回事,捞错了反而干扰Agent判断。hindsight的做法是先用结构化过滤缩小范围,比如按记忆类型过滤(只查“流程类”记忆),再在缩小后的集合里做向量检索。
第二个硬伤是时间衰减。记忆是有时效性的,三个月前的用户偏好可能已经变了。纯向量检索不考虑时间因素,会把旧记忆和新记忆同等对待。hindsight在检索评分里加入了时间衰减因子,记忆越旧,得分越低。衰减曲线是指数型的,半衰期默认30天,可以通过MEMORY_DECAY_HALF_LIFE参数调整。
第三个硬伤是重要性权重。有些记忆天生就比其他的重要,比如用户明确说过的偏好,比Agent自己推断出来的规律权重更高。hindsight给每条记忆维护了一个重要性分数,初始值由写入时的评分决定,后续每次被检索到并确认有用时,重要性分数会小幅提升;如果被检索到但Agent没有采用,分数会小幅下降。这个机制让记忆库能自我进化,常用的记忆越来越突出,没用的记忆逐渐沉底。
具体检索时的参数配置,我一般这样设:
{ "query": "用户询问退款流程", "memory_type": "semantic", "tags": ["流程", "用户偏好"], "top_k": 5, "score_threshold": 0.6, "time_decay": true, "rerank": true }top_k是返回的最大条数,我建议不要设太大,3到5条足够,太多会稀释上下文。score_threshold是得分下限,低于这个值的直接丢弃。rerank开启后会用一个轻量级的交叉编码器对初步检索结果做精排,代价是增加一点延迟,但准确率提升明显。
4.3 记忆冲突的处理:新经验覆盖旧经验还是并存
记忆冲突是实际使用中一定会遇到的问题。比如旧记忆说“用户偏好简洁回答”,新记忆说“用户要求详细解释”,这两条矛盾了,怎么办?
hindsight的处理策略是版本化并存加置信度竞争。两条矛盾记忆不会互相覆盖,而是都保留,但各自维护一个置信度分数。新记忆写入时置信度初始为0.7,旧记忆的置信度会衰减到0.5。检索时两条都会返回,但Agent会看到置信度标注,倾向于采用置信度高的那条。如果后续用户行为持续验证新记忆,新记忆的置信度会升到0.9,旧记忆降到0.2,这时候旧记忆实际上已经被边缘化了,但不会被物理删除。
这个策略的好处是保留了纠错空间。万一新记忆是误判(比如用户那天心情好所以多说了几句,被Agent误读为偏好详细解释),旧记忆还在,置信度会慢慢回升。坏处是记忆库会膨胀,需要定期做清理。hindsight提供了一个memory_compact工具,可以手动触发压缩,把置信度低于0.1且超过90天未被检索的记忆归档到冷存储。
我自己的经验是,对于用户偏好类的记忆,冲突处理要保守一点,宁可并存也不要轻易覆盖;对于工具使用类的记忆,冲突处理可以激进一点,因为工具行为是客观的,新经验大概率比旧经验准确。
5. 实战中的问题排查与性能调优
5.1 记忆检索不准的排查思路
检索不准是最常被反馈的问题,表现是Agent捞出来的记忆和当前任务不相关,或者该捞的没捞到。排查按这个顺序走。
先看记忆本身的质量。如果写入的记忆就是模糊的、缺乏具体信息的,检索自然不准。检查方法是用memory_retrieve不带查询条件捞一批记忆出来,人工看一遍。如果发现大量“用户问了问题,Agent回答了”这种废话记忆,说明反思模块的筛选阈值太低了,调高REFLECTION_THRESHOLD到0.75试试。
再看检索参数。top_k太小会漏,太大会引入噪音。score_threshold太高会漏,太低会引入噪音。这两个参数需要配合调。我的经验值是top_k=5、score_threshold=0.6起步,然后根据实际效果微调。如果发现漏检多,先降score_threshold到0.5;如果发现噪音多,先升到0.7。
然后看嵌入模型。hindsight默认用的嵌入模型是all-MiniLM-L6-v2,这个模型轻量但能力有限。如果你的记忆内容涉及大量专业术语或者中文内容,建议换成更强的模型,比如bge-large-zh或者text-embedding-3-small。换模型需要在配置里指定EMBEDDING_MODEL环境变量,注意换模型后已有记忆的向量需要重新生成,hindsight提供了memory_reindex工具来做这件事。
最后看标签体系。如果记忆写入时标签打得太粗或者太细,检索时结构化过滤就起不到作用。建议在项目初期就定义一套标签规范,比如按“领域-类型-来源”三级打标,领域包括销售、客服、技术等,类型包括流程、偏好、事实等,来源包括用户明示、Agent推断、外部导入等。
5.2 记忆膨胀导致响应变慢的优化方案
跑了一段时间之后,记忆库会越来越大,检索延迟从几十毫秒涨到几百毫秒甚至秒级。这是正常现象,但需要主动优化。
第一招是分层存储。把记忆按访问频率分成热、温、冷三层。热层放最近7天被检索过的记忆,存在内存或SSD上;温层放最近30天被检索过的,存在普通磁盘上;冷层放超过30天没被检索的,压缩后归档。检索时先查热层,不够再查温层,冷层只在明确需要历史回溯时才查。hindsight的memory_tier配置项可以设置分层策略。
第二招是索引优化。Qdrant的向量索引默认是HNSW,参数m和ef_construct影响索引大小和检索速度。m越大索引越精确但越占内存,默认16,可以降到12来省内存。ef_construct越大构建越慢但检索越快,默认100,可以升到200。这两个参数的调整需要在Qdrant的collection配置里改,改完需要重建索引。
第三招是定期压缩。前面提到的memory_compact工具,建议每周跑一次。压缩逻辑是把相似度超过0.95的多条记忆合并成一条,把置信度低于0.1且长期未访问的记忆归档。我实测下来,压缩后记忆库体积能减少30%到50%,检索延迟相应下降。
第四招是缓存。对于高频查询,比如“用户偏好”这类每次对话都可能用到的记忆,可以在Agent端做一层本地缓存,不用每次都走MCP请求。缓存的有效期设短一点,比如5分钟,避免拿到过期记忆。
5.3 常见问题速查表
| 问题现象 | 可能原因 | 排查步骤 | 解决方案 |
|---|---|---|---|
| 服务启动后立即退出 | 端口被占用或依赖服务未就绪 | 查看docker logs,检查8080端口和Qdrant连接 | 换端口或加depends_on健康检查 |
| MCP连接超时 | 网络不通或地址写错 | curl测试hindsight的health端点 | 检查防火墙和地址配置 |
| 记忆写入成功但检索不到 | 嵌入模型不一致或索引未刷新 | 用memory_retrieve不带条件查询 | 统一嵌入模型,触发reindex |
| 检索结果全是旧记忆 | 时间衰减未启用或半衰期太长 | 检查time_decay参数 | 启用衰减,调短半衰期 |
| Agent不主动使用记忆 | system prompt未引导 | 查看Agent日志有无memory调用 | 在prompt里加记忆使用引导 |
| 记忆内容重复率高 | 反思阈值太低或去重未生效 | 抽样检查记忆库 | 调高阈值,检查去重逻辑 |
| 响应延迟突然增大 | 记忆库膨胀或Qdrant性能下降 | 监控记忆数量和检索耗时 | 执行compact,优化索引参数 |
6. 几个容易被忽略的实操细节
6.1 工作记忆的清理时机比容量更重要
很多人只关注工作记忆的容量设置,却忽略了清理时机。工作记忆不是简单地把最旧的扔掉,而是要在任务边界处清理。如果一个任务还没结束,你把中间步骤清了,Agent就断片了。hindsight的做法是监听任务结束信号,收到信号后才触发工作记忆的压缩和清理。如果你自己实现Agent循环,记得在任务结束时显式调用memory_reflect,否则工作记忆会一直堆积。
6.2 反思模块的prompt需要针对领域定制
hindsight自带的反思prompt是通用型的,它问的问题比较泛:“这次任务中有什么值得记住的经验?”在实际领域使用时,这个泛问题往往得不到好答案。我建议根据你的领域定制反思prompt。比如客服领域可以问:“这次对话中,用户的情绪变化节点在哪里?哪个回应让用户情绪好转或恶化?”技术领域可以问:“这次任务中,哪个工具调用出现了意外结果?意外结果的原因是什么?”定制后的反思prompt能显著提升记忆质量。
6.3 不要把所有东西都往语义记忆里塞
语义记忆是稀缺资源,它的价值在于抽象和泛化。如果你把具体的、一次性的信息也塞进语义记忆,它就退化成普通的情景记忆了。判断标准很简单:这条经验换一个具体场景还成立吗?如果只在特定场景下成立,放情景记忆;如果跨场景成立,才放语义记忆。我见过一些项目把语义记忆当垃圾桶用,结果检索时全是噪音,Agent反而变笨了。
6.4 记忆的冷启动问题
新部署的hindsight记忆库是空的,Agent没有记忆可用,表现和没有记忆的Agent一样。这是正常的,但可以通过导入种子记忆来加速冷启动。种子记忆可以是你手动整理的领域知识,也可以是从历史对话记录里批量提取的。hindsight提供了memory_import工具,支持从JSON或CSV批量导入。导入时注意给每条记忆打上正确的标签和初始置信度,置信度建议设0.6左右,让它们在后续使用中自然升降。
6.5 监控记忆库的健康度
记忆库不是建好就不用管了,它需要持续监控。我一般关注四个指标:记忆总量(增长太快说明筛选太松)、检索命中率(低于50%说明记忆质量差或检索参数不对)、记忆复用率(被检索后实际被采用的比例,低于30%说明记忆不实用)、冲突记忆比例(矛盾记忆占比,高于10%说明反思模块判断力有问题)。这四个指标可以在hindsight的/metrics端点拿到,建议接入监控系统做告警。
7. 关于hindsight的一些个人体会
我用hindsight跑了大概三个多月,最大的感受是:Agent的记忆问题,本质上不是存储问题,而是筛选问题。大多数方案把精力花在“怎么存更多”上,hindsight把精力花在“怎么存更对”上。这个方向是对的,因为LLM的上下文窗口再大也有上限,记忆库再大也有检索瓶颈,唯一能无限提升的是记忆的质量。
另一个体会是,反思模块的prompt工程比记忆存储的技术选型更重要。我试过换向量数据库、换嵌入模型、调各种参数,效果提升都不如把反思prompt改好来得明显。反思prompt决定了Agent从经验中学到什么,这是整个系统的灵魂。
最后说一个我觉得hindsight还可以改进的地方:它目前对多模态记忆的支持比较弱,图片、音频这类非文本记忆的处理还不够成熟。如果你的Agent场景涉及大量多模态交互,可能需要自己扩展。不过对于纯文本的Agent场景,hindsight目前的完成度已经足够支撑生产使用了。