向量搜索,这东西纸面上看挺简单——把一堆 embedding 扔进数据库,写个查询,Duang!结果就出来了。但当你从搞着玩的小项目,真正应用到实际的线上服务时,你会发现这所谓的“魔法”瞬间变成了一个雷区:云服务账单莫名其妙地爆炸、搜索结果各种诡异跑偏(所谓的“幻觉”)、查出来的东西驴唇不对马嘴。
我见过不少团队,吭哧吭哧花了好几周时间搞所谓的“优化” pipeline,结果还是被同样的问题反复折磨:延迟突然飙升、召回一堆不相关的 chunk、成本高到项目差点被砍。
下面,我会分享 8 个我反复看到的“坑”,尤其是在那些没有清晰规划就开始扩展向量搜索规模的团队中。同时,我也会给出切实可行的避坑策略,帮你省时、省钱、省掉大把头发。
1. 从一开始就忽视评估(Evaluation)
为啥是个坑?你搭了一套看起来很牛的 embedding 搜索系统,但很快发现,有些查询效果拔群,有些却惨不忍睹,而且你压根不知道问题出在哪。这就是在没有建立靠谱的评估(eval)框架下,就一头扎进向量搜索的典型后果。无法衡量,就无法改进。
怎么破?
- 建个小而精的评估集: 哪怕只有 50-100 条标注好的查询和预期结果,也足以暴露很多致命问题。用上标准指标: NDCG、MRR、Recall@K……甭管用哪个,先用起来,后面再迭代优化。常见的比如评估 Top K 结果的准确率、召回率等。监控效果变化: 每次你调整 chunking 策略、更换 embedding 模型或者改动其他任何环节,都要重新跑一遍评估,看效果是变好了还是变坏了。
很多团队一上来就对高级分块技术、上下文检索(contextual retrieval),甚至知识图谱这些花哨的东西激动不已,但压根不知道这些改动到底有没有带来实际提升。评估能让你摆脱“我感觉效果变好了”的瞎猜模式。
2. 无视混合搜索(Hybrid Search)
为啥是个坑?单纯依赖 embedding 的语义相似度,可能会漏掉那些非常明显的关键词匹配。如果你的 embedding 模型没有针对你的业务领域进行微调,或者用户搜了一个非常见的技术术语或专有名词,纯向量搜索很可能就“抓瞎”了。但与此同时,传统的关键词搜索(比如 BM25 算法)可能轻松就能命中。
怎么破?
- 结合 embedding 和关键词搜索: “混合搜索”就是把向量搜索和关键词搜索(如 BM25)的结果结合起来。提升召回率: 这种方法在很多向量数据库里都相对容易实现。它能显著提升召回,确保简单的关键词查询不被漏掉。对合并结果进行重排(Re-ranking): 分别从向量搜索和关键词搜索取回 Top N 结果,合并后交给一个重排模型来决定最终的排序。
我见过太多团队一上来就只用 embedding,然后纳闷为啥那么简单的、包含明确关键词的查询都搜不到。要知道,没经过微调的通用 embedding 模型在特定数据集上,效果经常还不如简单的 BM25 关键词搜索。混合搜索通过结合两者的优势,可以在不显著牺牲延迟的情况下,大幅提升召回率。这应该是你优化向量搜索 pipeline 的第一步。
3. 过度优化(尤其是在没有评估指标的情况下)
为啥是个坑?很多工程师(包括我自己!)很容易陷入一个误区:总想追逐各种新潮、花哨的检索技术,却没有先建立一个明确的、可量化的基线(Baseline)。如果你根本没法衡量改动带来的影响,你怎么知道你花大力气搞的东西是真的有效,还是在“瞎忙活”?
怎么破?
- 设定基线: 一个不错的起点通常是:混合搜索 + 一个轻量级的重排器。量化评估: 用你之前建立的评估集来给这个基线“跑个分”。小步快跑,逐步迭代: 每次只引入一个改动(比如尝试一种新的分块方法),然后重新评估,看性能指标(如召回率、NDCG、延迟)是不是真的提升了。
如果你的 pipeline 搞得过于复杂(用像 LlamaIndex 这样的框架很容易不小心搭出非常复杂的 RAG 流程),也许你还不如从头开始,自己动手搭一个更简单、更可控的 RAG pipeline。
即使是一些看起来简单的技术,比如“延迟分块”(late-chunking),虽然通常能用较少工作量提升性能,但也可能在某些情况下反而降低结果质量。最糟糕的是,你花了好几天时间去实现论文里看到的某个复杂方法(我经常看到有人一看到新研究就觉得“这个我必须试试!”),结果发现一顿操作猛如虎,一看效果原地杵,甚至性能(无论是延迟还是召回)还不如第一天简单粗暴的方案。
永远记住:先衡量,拿不准就简化。
4. 不对 Embedding 进行量化(Quantization)
为啥是个坑?动辄几千维(比如 3072 维)的 embedding 可能效果拔群,但当你需要处理几千万甚至上亿个向量时,内存开销就能把你压垮。维度过高的 embedding 不仅吃内存、吃 CPU,还会拖慢查询速度,最终反映在你爆炸的云账单上。
怎么破?
- 拥抱量化技术: 像 Matryoshka Representation Learning (MRL) 或者二值量化(Binary Quantization, BQ)这样的技术,可以在精度损失很小(甚至几乎没有)的情况下,大幅压缩 embedding 的存储大小。大胆尝试低维: 试试 64 维或 128 维,特别是当你的向量数量超过两三百万时。你可能会惊讶地发现,召回率几乎没掉多少,但成本(内存、存储、计算)却实打实地降下来了。相信重排器的力量: 召回阶段(第一阶段检索)的目标是“宁可错杀,不能放过”,可以用量化后、速度更快的索引先捞回一批候选结果(比如 Top 100),然后用更精确但计算量稍大的重排模型(比如 Cross-encoder)对这批候选结果进行精排。考虑二值量化: 二值量化压缩率极高(比如 float32 -> 1 bit,压缩 32 倍),可以和 MRL 等技术叠加使用。但务必确认你选用的 embedding 模型支持且在二值量化后效果依然良好,并通过评估来验证。
我跟一些开发者聊过,他们只有区区 100 万个 1536 维的向量,结果每月要为一个 Serverless 数据库支付 100 多美元。我也见过有工程师坚信,处理他们业务的 PDF 文档就“必须”上 3000 维才能搜得好。我向你保证,绝大多数情况下,真的没必要。把维度降到 64 或 128,存储和 CPU 占用可能直接降一个数量级,成本几乎可以忽略不计。如果再用上二值量化,存储空间还能再压榨 32 倍。
再说一遍,我们的评估体系会告诉我们,可以在多大程度上进行量化,而不会显著牺牲业务所需的召回效果。
5. 规模上去了,却还在硬抗内存索引
- 为啥是个坑?当你的向量数量达到 500 万、1000 万甚至更多时,把所有向量都硬塞在内存里,成本通常会变得非常高昂。你可能被迫选用内存超大的、更贵的硬件实例,或者被云厂商绑在更高规格、更贵的托管数据库套餐上,仅仅是为了能把所有 embedding 都装进内存。怎么破?
- 采用支持磁盘(On-Disk)的索引: 像一些矢量数据库中应用的索引技术,允许你将大部分向量数据存储在成本低得多的 SSD 磁盘上,同时只在内存中保留少量索引结构,从而极大降低内存使用量。预估你的规模: 如果你预计向量规模会增长到 5000 万、1 亿甚至更多,那几乎必须提前规划基于磁盘的向量存储和索引方案。关注延迟变化(并实测!): 现代的基于磁盘的向量索引速度已经非常快了,很多场景下查询延迟和你纯用内存索引(如 HNSW)相比,可能几乎没有区别,甚至在某些负载下吞吐量更高。但切记,一定要在你的实际场景和数据上进行测量验证。
6. 跳过微调(Fine-Tuning)环节(Embedding 或 Re-ranker)
为啥是个坑?市面上现成的(Off-the-shelf)embedding 模型(比如 OpenAI、Cohere 或者一些开源模型)在通用语料上训练,对付日常查询通常不错。但如果你的业务场景涉及非常专业的领域知识,比如特定的医学术语、化学分子式、法律条款、内部项目代号、或者小众的产品型号等,这些通用模型很可能就抓不住这些细微但关键的语义差别了。
怎么破?
- 微调 Embedding 模型: 针对你的业务数据,准备一些“正负样本对”(比如,对于一个查询,哪些文档是相关的,哪些是不相关的),即使只有几百到一千对标注数据,也可能显著提升 embedding 在你特定领域上的表达能力。微调重排器(Re-ranker): 重排器(尤其是 Cross-encoder)通常比微调 embedding 模型需要更少的标注数据。可能几百对高质量的标注数据就能看到明显效果,当然,数据越多一般效果越好。用评估集验证效果: 微调前用评估集测一下基线性能,微调后再测一次。用数据量化微调到底带来了多大提升。
仅仅通过少量的领域相关训练样本,将召回率(或其他关键指标)提升 15-25% 的情况并不少见。如果你的业务领域性很强,“懒得”做微调,基本上等于把唾手可得的精度提升给扔了。而且现在微调 embedding 模型和重排器的工具和教程也越来越成熟方便了。
可以参考这篇 Hugging Face 的博客学习如何训练 Sentence Transformers 模型:huggingface.co/blog/train-…
7. 把向量检索库(Library)当成成熟的向量数据库(Database)
为啥是个坑?很多工程师起步时,可能会直接 pip install faiss-cpu
或者 annoy
,几行代码就实现了一个近似最近邻(ANN)搜索,感觉好像向量搜索就搞定了。但一个能在生产环境稳定运行的系统,需要的远不止是一个简单的 ANN 查找库。它需要处理数据库层面的一系列问题:数据的增删改查、事务性(或至少是原子性操作)、并发控制、备份恢复、权限管理、元数据过滤、水平扩展、高可用等等。很多内存型的向量检索库(比如原生的 Faiss)甚至不支持在持续写入新数据的同时进行稳定的查询。
怎么破?
- 选用一个真正的向量数据库: 像 Milvus、Weaviate、Pinecone 等工具,是按照数据库的标准来设计的,帮你解决了上面提到的那些脏活累活。确认混合搜索是标配: 如前所述,混合搜索对于文本检索场景非常重要,确保你选的数据库原生支持或者很容易实现混合搜索。检查元数据过滤能力: 实际业务查询往往是这样的:“找到与向量 X 相似,并且
created_at > '2024-01-01'
且 tag = 'tech'
的所有文档”。确保你的数据库能高效地执行这种带条件的向量查询。有些数据库还支持基于元数据的分区(Partitioning),如果你的数据有明显的分区特征(如按时间、按租户),这能极大提升查询性能和降低扫描范围。每次数据更新都得把整个索引删掉,然后从头重建一遍,这种体验绝对不好受。但如果你只依赖一个简单的、本地的 Faiss 索引文件,这可能就是你不得不面对的运维噩梦。
8. 不敢直视(甚至修改)你的原始数据和分块(Chunk)
为啥是个坑?太多团队把他们的数据分块(chunk)或者生成的 embedding 看作一个完全的“黑盒”,觉得“这是 AI 的事儿,让模型自己去理解吧”。然后当某些查询总是失败,或者返回一些乱七八糟、毫无逻辑的结果时,就开始抓耳挠腮,不知道问题出在哪里。
怎么破?
- 抽查你的分块结果: 实际去看看你的长文本是怎么被切分成一个个 chunk 的。是不是有些句子被拦腰截断了?关键的段落、表格或者代码块是不是被切得支离破碎了?分块大小是不是合理?手动干预问题数据: 如果发现某个特定的 chunk,明明内容很相关,但在评估中或者实际查询里老是排不上号,别害怕“动手脚”。可以考虑在这个 chunk 的文本里,手动补充一些相关的关键词,或者调整一下它的描述方式,让它更容易被向量模型理解或被关键词搜索命中。根据真实的用户反馈迭代: 如果某个用户经常搜索的查询,总是得不到预期的结果,去分析一下原因。是不是对应的文档分块有问题?或许只需要稍微调整一下那个 chunk 的文本内容,就能让它在下次查询时被正确召回。有时候,最快最有效的修复,就是对原始数据或分块进行一点“人工”调整。
核心洞见:向量数据库和里面的数据,并不是什么碰不得的、神秘的黑魔法盒子。就跟你优化 SQL 查询时会考虑给表加索引、调整表结构一样,你也完全可以、并且应该去检查、甚至修改你的 chunk 文本、调整元数据字段、给重要的部分添加标注。没错,这听起来有点“土”,有点“不够 AI”,但这种直接针对数据的“微操”,往往能快速、有效地解决很多模型层面难以搞定的实际问题。
总结
向量搜索是把双刃剑。用好了,它能给你的应用加上强大的语义理解能力;但如果忽视了上面提到的这 8 个坑,它也可能变成一个吞噬预算、消磨耐心、产出一堆垃圾结果的噩梦。
无论你是刚开始为一个推荐系统处理百万级的向量,还是正在为大型企业的知识库扩展到上亿甚至十亿级的向量规模,都请牢记这些常见的坑点和对应的解法:
- 尽早引入评估体系,用数据指导优化。优先考虑混合搜索,兼顾语义和关键词。不要在没有基线和评估的情况下,过度沉迷高级 RAG 或分块技巧,保持简单、有效。积极采用量化技术,控制内存和成本。规模化后,果断切换到支持磁盘的索引方案,内存很贵。如果业务领域性强,认真考虑微调(Embedding 或 Re-ranker),别放弃免费的精度提升。选择成熟的向量数据库,而不是停留在简单的检索库。敢于查看、分析甚至手动修正你的数据和分块,别把它们当成黑盒。
正视并主动解决这些问题,你就能更有信心地构建出一个性能稳定、结果靠谱、并且成本可控的向量搜索 pipeline。
最后说一句实在的: 如果你的向量数量在 500 万以下,很多时候你完全可以把 embedding 量化到 64 维,使用支持磁盘的索引,整体成本可能低到可以落在很多云服务的免费套餐(Free Tier)里,同时还能获得不错的查询延迟(比如 < 200ms)。而且,真碰到哪个查询效果不好,可能最快的方法就是直接去改改那个对应的 chunk 数据。简单、直接、有效!