为什么重要:RAG 的效果 80% 取决于检索质量,而检索质量的基础就是 Embedding 和向量数据库。理解这层基础设施,才能在 RAG 出问题时知道该调什么——是换 Embedding 模型、换相似度算法、换向量库,还是调 Chunk 策略。

一、什么是 Embedding

Embedding 的本质是把文本(或图片、音频)转换成一组高维数字向量。语义相近的内容,在向量空间中的距离也相近。这就是机器"理解"语义的方式。

"猫吃鱼"  →  [0.12, -0.34, 0.56, ..., 0.78] (1536 维)
"狗啃骨头"  →  [0.15, -0.31, 0.52, ..., 0.75] (1536 维)
↑ 两个向量距离很近 —— 语义相似
📐

维度

向量的维度由 Embedding 模型决定。OpenAI text-embedding-3-small 是 1536 维,text-embedding-3-large 是 3072 维。维度越高,表达能力越强,但计算和存储成本也越高。

🎯

语义相似

不是字面匹配,而是语义匹配。"如何退款"和"退货流程"字面不同,但向量距离很近。这正是 Embedding 比关键词搜索强大的地方。

🔧

应用基石

语义搜索、RAG 检索、推荐系统、聚类分析——所有这些应用的最底层都是 Embedding。选对 Embedding 模型,等于打好地基。

Embedding 模型的选择直接影响检索效果。常见选择:OpenAI text-embedding-3-small(性价比高)、text-embedding-3-large(精度最高)、BGE-M3(开源,中文优秀)、Cohere embed-v3(多语言强)。选型时务必用你自己的数据测试,不要只看榜单

二、相似度计算:三种方法

有了向量,下一步就是计算"两个向量有多近"。有三种主流方法,适用场景各不相同:

余弦相似度

计算两个向量的夹角,关注方向而非大小。

  • 最常用,绝大多数场景首选
  • 对向量长度不敏感
  • 值域 [-1, 1],越接近 1 越相似
  • 适合文本语义搜索

欧氏距离

计算两个向量在空间中的直线距离。

  • 关注向量的绝对位置
  • 对向量长度敏感
  • 值越小越相似(距离为 0 即相同)
  • 适合图像 / 聚类场景

点积

最简单的计算方式,两个向量对应位相乘再求和。

  • 计算最快
  • 当向量已归一化时,等价于余弦相似度
  • 很多向量库默认使用
  • 适合对性能要求极高的场景
实践建议:大多数 RAG 场景直接用余弦相似度即可。如果你的 Embedding 模型已经做了归一化(OpenAI 的模型默认归一化),点积和余弦的结果完全一致,此时用点积更快。不要在这个环节过度纠结——Embedding 模型本身的质量远比相似度算法的选择重要

三、ANN 近似最近邻:为什么不能暴力搜索

当向量库有 100 万条数据时,每次查询都要和所有向量算一遍相似度?这就是暴力搜索(Brute Force),时间复杂度 O(N)。100 万条还能扛住,1 亿条就完全不可行了。

解决方案是 ANN(Approximate Nearest Neighbor,近似最近邻)——牺牲一点点精度,换取数量级的速度提升。核心思想是:不找绝对最近的,而是找"足够近"的

算法 原理 速度 内存 适用场景
HNSW 图结构 最快 最多 对速度要求高,内存充足(最主流)
IVF 聚类 中等 较少 数据量大、内存敏感、可调精度
LSH 哈希 理论价值高,实际工程中较少使用
暴力搜索 逐个比对 最慢 最少 数据量极小(<1 万),需要 100% 精确
🕸️

HNSW · 分层小世界图

构建多层图结构,查询时从顶层快速定位区域,再逐层细化。查询最快,但内存占用最高(需要存图结构)。FAISS、Qdrant、Milvus 均支持。99% 的场景默认选它。

📊

IVF · 倒排文件

先用 K-Means 把向量聚成若干簇,查询时只搜索最近的几个簇。nprobe 参数可调精度:搜的簇越多越精确但越慢。内存友好,适合超大规模数据。

#️⃣

LSH · 局部敏感哈希

把相近的向量哈希到同一个桶里。理论优雅但实际效果不稳定,工程中已被 HNSW 大幅取代。了解原理即可,不必深入实践。

四、向量数据库选型:六选一

向量数据库是 RAG 的存储和检索引擎。选型取决于数据规模、运维能力和功能需求。Reddit 等大型平台通过结构化评测从十余种方案中选出最终方案,以下是最主流的六个:

数据库 类型 规模 最适合 运维 亮点
Chroma 嵌入式 <100 万 原型验证、POC、学习 零运维 pip install 即用
FAISS 任意 极致速度、研究场景 手动持久化 Meta 开源,最快
Qdrant 服务器 100 万-10 亿 最佳平衡、混合搜索 Docker 单容器 Rust 实现,推荐
Milvus 分布式 10 亿+ 企业级、功能最全 K8s,最重 支持 GPU 加速
pgvector PG 扩展 <100 万 已有 PostgreSQL 零额外运维 SQL 查询,简单
Weaviate 服务器 100 万-10 亿 混合搜索、多模态 Docker 内置 Embedding
混合检索(Hybrid Search):纯向量检索在某些场景(如精确匹配产品名、人名)不如关键词搜索。将向量检索与 BM25 关键词检索结合(混合检索),效果显著优于纯向量。Qdrant 和 Weaviate 对混合检索有原生支持,这是它们在生产环境中的关键优势。

五、选型决策树

不要被选项吓到。根据你的数据规模和现有技术栈,决策路径其实非常清晰:

<100 万向量 + 已有 PostgreSQL
pgvector
<100 万向量 + 没有 PostgreSQL
Chroma
100 万 - 10 亿向量,需要平衡性能和运维
Qdrant(推荐)
10 亿+ 向量,企业级需求
Milvus
需要混合搜索(向量 + 关键词)
Qdrant / Weaviate
需要极致速度,研究场景
FAISS
多模态(图片 + 文本混合检索)
Weaviate
🚀

快速启动

90% 的个人项目和早期产品,Chroma 或 pgvector 就够了。不要为了"以后可能需要"而一上来就搭 Milvus 集群。

📈

规模化

数据过了百万级,Qdrant 是最佳选择——Rust 实现性能强,单 Docker 容器运维简单,原生支持混合搜索。

🏢

企业级

数据到了十亿级、需要高可用和水平扩展,才考虑 Milvus。它的运维复杂度最高,没有专职团队不要碰。

六、RAG 中的完整流程

把前面的所有概念串起来,就是 RAG 检索的完整管线。从文档到最终回答,每一步都有可调参数:

Step 1📄 文档
Step 2✂️ 分块 Chunk
Step 3🔢 Embedding
Step 4💾 存入向量库
Step 5❓ 用户查询
Step 6🔍 检索 Top-K
Step 7📊 Rerank 重排
Step 8🤖 LLM 生成
步骤 参数 说明
分块 chunk_size: 500-1000 字符 太小会丢失上下文,太大会稀释相关性。中文建议 500-800 字,英文 500-1000 字符
重叠 overlap: 10-20% of chunk_size 相邻块之间重叠一部分,避免关键信息被切断在边界上
Embedding 模型选择 用同一模型编码文档和查询,不能混用不同模型
检索 top_k: 5-20 先粗检索较多的候选,再用 Rerank 精排。top_k 太小会漏掉相关内容
重排 Reranker 模型 用 Cross-Encoder 对候选重新打分,精度远高于 Embedding 相似度。常用 BGE-Reranker、Cohere Rerank
生成 context 注入 把检索到的 Top-K(重排后取前 3-5 条)作为上下文拼入 Prompt,让 LLM 基于上下文回答
性能优化关键点:Chunk 策略对效果的影响远超大多数人的预期。不要只调 top_k 和 Embedding 模型——先确保 Chunk 大小和重叠合理,再优化其他环节。混合检索(向量 + BM25)在大多数场景下比纯向量检索提升 10-20% 准确率,值得优先尝试。

参考资料:Reddit 工程博客向量数据库选型评测;FAISS 官方文档;Qdrant / Milvus / Weaviate 官方文档;HNSW 原始论文(Malkov & Yashunin);pgvector GitHub;LangChain RAG 最佳实践。