在一次真实的Agent运行中,用户提问:“这次外出晚餐我应该避免吃什么?”而记忆存储中明明写着:dietary_notes: “素食;严重贝类过敏——严格禁止甲壳类或软体动物。” 关键词扫描返回了4个命中,但答案状态是False。答案一直在存储里,却取不出来。 这不是思想实验。问题没有点名任何键,也没有与存储笔记共享词汇,所以上篇文章介绍的那种key-value记忆搜索永远无法发现它。这就是语义搜索的分水岭:你知道的是键(key),还是意图(intent)?当用户提问无法与预设键匹配时,只能按含义检索——每次写入记忆时生成embedding,查询时也生成embedding,然后按余弦相似度取最近邻。 这是系列文章的第二篇,系列开篇曾梳理所有记忆类型;代码使用开源SDK Strands Agents,但模式适用于任何agent框架。 为什么key-value存储会失败?因为key-value读取本质上是预先设计好的搜索。演示数据中存有10条关于旅行者的记忆:个人资料、饮食备注、行程片段。针对“晚餐避免什么”这个问题,key-value存储只有两招,而且都诚实地失败了。 第一招:关键词扫描。在键和值中寻找问题中的词。结果为4次命中,但没有一条是过敏备注。原因很简单:“avoid eating at dinner”和“dietary_notes”“shellfish”没有任何共同词。Answer found: False。 第二招:Dump-all兜底。把全部记忆直接塞给大模型,让它自己找。这个小demo里还能跑,但一旦记忆达到几百条或几千条,这种做法会迅速撑爆上下文,成本不可接受。它回避了问题,而不是解决问题。 语义搜索则不同。它在写入时把每条记忆嵌入向量空间,查询时把问题也嵌入进去,然后用余弦相似度找出最相关的记忆。语义相似性不依赖字面词汇重叠,因此“避免吃的食物”和“贝类过敏”可以建立关联。实验也表明,同一套embedding能在向量存储中正确召回被关键词搜索漏掉的那条饮食备注。 不过,语义搜索并不是银弹。它需要额外的向量存储组件,并引入嵌入计算延迟。项目中我们使用Strands Agents——一个开源SDK——来实现,但这个模式可以移植到任何agent框架。你需要评估的是:向量存储的召回质量、索引延迟、资源占用,以及是否与现有堆栈兼容。这正是文章要测量的事情。 最终结论:当agent的记忆检索从“找键”变成“找意思”,过去丢失的上下文被重新找回。对于依赖长期记忆的agent应用,这是从demo迈向生产的关键一步。
热门跟贴