源文档更新从未同步到向量索引的那些 Embedding
一名支持工程师在值班频道发了消息。一位客户粘贴了助手上周检索到的一个句子,合规团队回复说:我们已经不再这么说了。他们已经停用这句话四个月了。CMS 中的文档显示是正确的。但向量索引中的嵌入分块(chunk)仍然是旧的内容,且拥有极高的相似度得分,并在每次相关查询时被提供给模型。没人改过检索代码。没人改过模型。真相源(source-of-truth)变了,而索引却对此一无所知。
这是摄取流水线(ingestion pipeline)的一种失败模式:它最初是为“创建”而设计的,后来演变成了一个也要处理“更新”的系统,却没有人专门为“更新”进行设计。“创建时嵌入”的任务在每份文档首次写入的那天运行。一个季度后,CMS 团队发布了一个编辑端点,由另一个团队负责,他们将其接入了搜索、面向公众的渲染器和变更日志 feed —— 接入了每一个消费者,除了那个隐藏在不同名称下的派生数据集。数月过去,语料库发生了漂移。检索系统开始回答那些公司早已正式抛弃的问题,而唯一的信号来自于一位困惑的客户。
创建路径大张旗鼓,更新路径悄无声息
回顾过去,看看组织架构图,失败的原因显而易见。构建向量索引的团队同时也构建了摄取任务,然后就认为大功告成了。负责 CMS 的团队则根据不同的路线图发布功能。当产品中加入编辑功能时,编辑事件被分发给了该团队所知道的消费者:渲染页面、API 响应、分析计数器。向量索引不在列表中,因为它不在他们对 CMS 的心智模型里 —— 它被视为“AI 的东西”,由 AI 团队运行,针对的是 AI 团队曾经提取过的一次性快照。
从各自的职责范围来看,每个团队都是正确的。CMS 团队正在向所有已知的订阅者发布编辑。检索团队拥有一个可以工作的摄取任务。没有人站在交界处,而交界处正是新鲜度契约(freshness contract)必须存在的地方。这种 bug 最常见的形式并不是一个复杂的分布式系统问题;而是两个待办事项列表(backlog)中从未产生过那张名为“将 CMS 更新事件接入嵌入 worker”的工单。
“仅限创建”的摄取任务之所以能存在,是因为它对每份新文档的前几周都是有效的。检索在演示中看起来很棒。评估套件是根据构建索引时使用的同一个快照构建的,因此评估准则永远不会与检索出的内容产生分歧。真相源与索引之间的漂移在看似正常的仪表盘下不断累积。
