跳到主要内容

33 篇博文 含有标签「vector-search」

查看所有标签

按摄入日期分片的向量索引

· 阅读需 11 分钟
Tian Pan
Software Engineer

在按时间分区的向量索引中,隐藏着一种特定类型的召回率谎言,而构建离线评估的人通常是最后才发现它的人。仪表盘显示 recall@10 为 0.94。检索器在 94% 的情况下都能提供正确的片段。产品团队正基于这个数字发布更多以检索为基础的功能。接着,客服工单接踵而至:“助手引用的指南与答案不符”、“助手链接到了上周版本的政策”、“助手找不到我两个月前上传的文档”。这些工单都不与 0.94 这个数字冲突。它们证明了 0.94 衡量的是错误的东西。

这种机制很简单,也很容易被忽视。向量索引按摄入日期进行分片,因为这是保持高写入吞吐量、停用旧数据以及将热工作集保留在快速内存中的最简单方法。离线测试集每晚从生产日志中生成,这意味着查询是从最新分片恰好持有的同一个近期窗口中提取的。召回率是根据存在于一两个分片深处的基准真相(ground truth)来衡量的。检索器在这些查询上表现出色,因为在生产环境中,路由层会将这些查询保留在同一个分片内。

语义过时的 Embedding:当向量不再理解当下

· 阅读需 10 分钟
Tian Pan
Software Engineer

你曾在十八个月前嵌入了知识库。模型没变。分块(chunks)没变。索引很健康,延迟也正常,召回率仪表盘是一条 0.86 的水平线。然而,客服团队正悄无声息地在工单回复中粘贴错误的文章链接,销售机器人在潜在客户询问新产品时不断翻出已弃用的 SKU,而一名内部用户刚告诉你助手“感觉变笨了”,却说不出具体原因。

一切都没坏。是你的嵌入(embeddings)老了。在你的领域中,“post”一词以前指的是博客文章;现在,语料库中有一半的地方用它指代 Slack 帖子、论坛帖子和职位发布(job posting),而你那十八个月前的向量仍将其视为同一个概念。编码这些向量的模型从未见过这些新含义,从未见过新的产品名称,从未见过品牌重塑,也从未见过引入了三个新术语的监管规定——而你的客户现在正不假思索地使用这些术语。检索系统回答了它知道如何回答的问题,但这已不再是你的用户正在提出的问题。

当 RAG 本该是一次 JOIN 时

· 阅读需 10 分钟
Tian Pan
Software Engineer

一个支持团队向他们的新 AI 助手提了一个简单的问题:“上周有哪些企业客户提交了工单?”助手给出了一个自信、流利的回答,列出了六个账户。其中五个是正确的。有一个客户在两个月前就已经流失了,而另一个提交了三个工单的企业账户却完全遗漏了。直到一次续约会议谈崩了,才有人发现这个问题。

错误不在于模型,而在于架构。在设计评审的某个环节,一个带有硬性谓词(如方案层级、日期范围、工单计数)的问题被路由到了向量索引。团队因为拥有检索系统,所以就选择了检索。他们将工单记录向量化,将问题向量化,然后试图让余弦相似度(cosine similarity)来完成 WHERE 子句的工作。它做不到,也从来都做不到。

这是生产环境 AI 系统中最常见且讨论最少的故障模式之一:当真正的查询是关系型时,却动用了语义搜索。数据明明整齐地存储在带有外键的行中,答案本可以通过一个 JOIN 轻松获得。结果却经过了嵌入模型,导致精度化为乌有。

那些在悄无声息中重新排列你整个语料库的嵌入模型升级

· 阅读需 11 分钟
Tian Pan
Software Engineer

一个新的嵌入模型登上了排行榜。它比你 18 个月前发布的模型得分更高,API 只需更改一行代码,甚至维度也一致。有人提了一个工单:“升级嵌入模型”。这看起来就像更换一个日志库一样简单。

事实并非如此。嵌入模型并不是你检索系统的一个普通组件——它就是你检索系统所处的坐标系。更换它并不会改进你的索引,而是会让索引失效。而最残酷的地方在于,系统并不会崩溃。没有异常,没有失败的健康检查。你的搜索只是开始返回微妙不同的结果,而在 RAG 管道中,“微妙不同”意味着不同的文档被喂给了模型,也就意味着不同的答案最终传达给用户。

向量索引存在一个没人定义的陈旧度 SLO

· 阅读需 11 分钟
Tian Pan
Software Engineer

一个用户询问你的智能体(agent)企业版的当前价格档位。智能体检索了一个分块(chunk),读取并回答:“每月 2,000 美元。” 信心满满,来源明确,格式优美。问题在于价格在四天前已经变了。智能体引用的数字在上周是真实的。它检索到的分块是在变更之前嵌入的,而索引还没有赶上进度。

没人决定让这种情况发生。没有设计评审说“智能体可以根据长达四天前的数据进行回答”。只是有一个每晚或每周运行的重新索引任务,以及一个随心所欲编辑内容的团队,而这两个时钟之间存在一个没人衡量的缺口。那个缺口就是一个服务等级目标(SLO)。无论你是否写下来,它都存在。唯一的问题是你是有意设定它的,还是由于意外继承下来的。

嵌入模型迁移黑洞:向量模型升级如何悄然重写你的业务规则

· 阅读需 12 分钟
Tian Pan
Software Engineer

迁移工单只有一行:“将 Embedding 模型从 v3-small 升级到 v3-large。”新模型在公开基准测试(Benchmark)中胜出 12%。流水线代码改动只有六行 Python。团队预计需要两天的开发时间,加上一个周末就能跑完的重嵌入(Re-embedding)任务。两个月后,查重功能的误报率比更换前翻了一倍,“相关项目”栏目悄然变成了废话生成器,语义缓存的命中率更是断崖式下跌,因为在旧空间运行良好的 0.95 阈值在现在几乎匹配不到任何内容。

没人动过这些功能。没人提交过 Bug。这个在迁移计划中被归类为“基础设施”的模型切换,悄无声息地改写了每一个使用相似度得分的业务规则。

RAG 中的新鲜度与相关度权衡:为什么你无法在查询时同时优化两者

· 阅读需 13 分钟
Tian Pan
Software Engineer

一名用户询问你的助手公司的育儿假政策。机器人返回了 12 周,并附带了引用。被引用的文档是 2023 年的正确答案;而人力资源部门在上个季度发布了更新,将其延长到了 16 周。这两个版本都在你的知识库中。由于旧版页面的表述更简洁且模棱两可的内容较少,余弦相似度给 2023 年版本的评分是 0.87,而 2024 年版本的评分是 0.84。较新的文档以 3 个百分点的差距落败,用户得到了一个看似经过审计的错误答案。

这就是时效性与相关性的权衡(freshness-relevance tradeoff),令人不安的是,这在查询时并没有完美的解决方案。如果你增加时效性的权重,检索结果就会偏向于昨天刚编辑过的任何内容——在大多数知识库中,这些通常是高频变动的嘈杂区域,不应作为事实来源。如果你不增加时效性的权重,你给出的答案将基于几个月前就被取代的文档。没有一个全局按钮能同时搞定这两点,大多数团队只有在一些令人尴尬的答案绕过评估套件泄露出去后,才会发现这个问题。

嵌入模型更迭:当你的提供商悄然导致整个向量索引失效

· 阅读需 10 分钟
Tian Pan
Software Engineer

你花了数周时间构建检索流水线。分块策略已调整,相似度阈值已校准,用户反馈看起来很积极。然后,在某个周一的早晨,在你没有任何部署的情况下,检索质量开始下降。以前能搜出正确文档的查询,现在返回的却是关联度极低的噪音。没有错误日志。没有异常。流水线运行顺畅。

发生变化的是你的嵌入(Embedding)提供商更新了模型。你的整个向量索引——那些费尽心力嵌入的数百万个文档——现在填充的是来自一套坐标系统的向量,而这套系统与你的查询编码器生成的向量已不再匹配。结果不是系统崩溃,而是不可见的垃圾数据。

向量维度税:嵌入维度如何悄然侵蚀你的预算

· 阅读需 9 分钟
Tian Pan
Software Engineer

大多数构建 RAG 系统的团队从不思考嵌入维度的问题。他们直接选用 text-embedding-3-large,保留默认的 3072 维度,然后继续推进。在处理 1 万份文档时,这无关紧要。但在处理 1000 万份文档时,你已经给云服务商每月多付了 30 美元的存储费用,而实际上只需 3.75 美元。在处理 1 亿份文档时,你面对的是 1TB 的 float32 数据,其中大部分并没有物尽其用。

嵌入维度与实际检索质量之间的关系,远弱于维度与运营成本之间的关系。这个差距——你实际支付的成本与所获得的质量之间的鸿沟——就是向量维度税。

面向 Agent 与 RAG 的分块:为什么一套方案会同时拖累两者

· 阅读需 11 分钟
Tian Pan
Software Engineer

大多数团队选择一个分块大小,针对检索质量进行调优,然后就此止步。接着,他们在同一个索引上构建一个 Agent,并纳闷为什么 Agent 会以奇怪的方式失败——它只执行了一半的工作流,忽略了条件逻辑,或者根据不完整的指令自信地采取行动。使你的 NDCG 分数最高的分块大小,恰恰是让你的 Agent 变得不可靠的原因。

RAG 检索和 Agent 执行并不是同一个问题。它们有不同的目标、不同的失败模式,以及对什么是“好的分块”有着根本不同的定义。当你针对其中之一优化分块时,你就在系统性地削弱另一个。大多数团队直到已经在错误的架构基础上构建完产品后才意识到这一点。

嵌入微调差距:通用向量并不理解你特定领域的“相关性”含义

· 阅读需 13 分钟
Tian Pan
Software Engineer

你的 RAG 流水线在理论上看起来很扎实:分块很清晰,向量库已建立索引,延迟也在可接受范围内。但用户一直在抱怨结果是错的 —— 并不是完全错误,而是在关键细节上“稍微”有些偏差。检索到的片段讨论了正确的概念,但时间点不对。它涵盖了正确的主题,但司法管辖区不对。它提到了正确的产品,但缺少了使其真正有用的库存信号。

这就是嵌入微调鸿沟。通用嵌入模型被训练用来编码语义相似性 —— 即两个文本意思大致相同的属性。但这并不等同于相关性。相关性是特定于领域的、对上下文敏感的,并且对于在互联网规模的通用语料库上训练的模型来说通常是不可见的。

重排序才是核心:为什么检索系统的瓶颈从来不在索引

· 阅读需 12 分钟
Tian Pan
Software Engineer

构建 RAG 系统的团队几乎普遍都会遇到同样的瓶颈:他们花一周时间调整 HNSW 索引参数,添加乘积量化(product quantization),将 recall@100 从 0.81 提高到 0.87 —— 然后发现 LLM 的输出质量几乎没有任何改观。投入数月努力所基于的假设是:更好的索引等于更好的回答。事实并非如此。瓶颈从来不在索引上。

真正的卡点在于候选集与上下文窗口(context window)之间的重排序(ranking)步骤。你喂给 LLM 的内容决定了它的输出,而重排序的工作就是确保那些真正相关的文档,而不仅仅是语义上最相似的文档,能够进入上下文。这种区别比你调整的任何 HNSW 配置都更重要。