最近在搭一个带记忆的Agent,用的Chroma存对话历史。目前是把所有历史消息直接塞进collection里,查询的时候top_k取20条。但发现两个问题:一是多轮对话后记忆太碎片化,经常抓到一些无关紧要的旧消息;二是想给记忆分权重,比如最近说的应该比三天前的重要,但Chroma好像只支持元数据过滤,不支持时间衰减排序?
用向量数据库做Agent记忆,短期和长期记忆该怎么分开存?
全部回复
共 86 条短期长期分开存确实更清晰,我是短期用内存队列、长期才落库,再按时间戳加权打分。
我也踩过这个坑,Chroma确实没有内置的时间衰减排序。后来我是把短期记忆放内存队列里只留最近N轮,长期记忆才写向量库,查询时两路结果合并再用时间戳加权。你那个top_k取20条太粗暴了,可以先做一轮相关性过滤再按时间重排。另外元数据里加个last_access_time,定期淘汰冷数据,碎片化会好很多。
我之前也踩过这个坑,把所有历史扔一个collection里检索,结果就是越聊越乱,top_k拿回来的全是些“好的”“嗯嗯”这种废话。后来我的做法是短期和长期分开两个collection,短期就存最近N轮原始对话,检索时直接按时间倒序取,根本不用向量相似度,因为上下文本来就该是连续的。长期记忆则走另一条路,先做一轮摘要或者抽取事实,只把值得记的信息写进去,这样噪声少很多。至于时间衰减,Chroma确实没有内置的排序衰减,我的做法是在metadata里存timestamp,查询后自己在应用层做一次加权重排,比如score乘一个指数衰减因子再排序。虽然多了一步,但灵活得多,还能按记忆类型给不同权重。另外提醒一点,长期记忆最好带个“最后访问时间”,被反复召回的记忆可以适当提权,不然容易变成只写不用的死档案。
短期和长期分两个collection存,长期做摘要压缩,权重排序得自己写个rerank,Chroma本身干不了这活。
有没有更详细的教程推荐?
我也踩过这个坑,全塞一个collection里检索质量确实会崩。后来我是短期记忆单独放一个collection只存最近N轮,长期记忆走另一条链路做摘要压缩再入库,查询时两边各取再合并。时间衰减Chroma确实不直接支持,我是在检索后自己按时间戳加个指数衰减重排,top_k放大到50再筛。你说的碎片化问题,可以试试把同一轮的user和assistant拼成一条再存,别拆太散。