Transformer与大语言模型:第18章 向量数据库

第18章 向量数据库

本章目标:

理解向量数据库的工作原理,以及 HNSW、IVF、PQ 等索引算法。


18.1 为什么需要向量数据库?

假设你有 100 万篇文章,每篇文章都有一个 768 维的 Embedding 向量。

用户输入一个 query,你需要找到最相似的 10 篇文章。

暴力搜索

text 复制代码
计算 query 与 100万个向量的余弦相似度
时间复杂度:O(N × d) = O(100万 × 768) ≈ 7.68亿次乘法

太慢了!

向量数据库的作用:

用近似最近邻(ANN)算法,在牺牲少量精度的情况下,大幅提升检索速度。


18.2 相似度度量

度量方式 公式 适用场景
余弦相似度 cos⁡(a,b)=a⋅b∣a∣∣b∣\cos(a,b) = \frac{a \cdot b}{|a| |b|}cos(a,b)=∣a∣∣b∣a⋅b 文本语义相似度
欧氏距离 d(a,b)=∑(ai−bi)2d(a,b) = \sqrt{\sum(a_i-b_i)^2}d(a,b)=∑(ai−bi)2 图像特征
内积 a⋅b=∑aibia \cdot b = \sum a_i b_ia⋅b=∑aibi 归一化后等价于余弦

对于 Embedding Model 的输出(L2 归一化后),余弦相似度 = 内积。


HNSW 是目前最流行的 ANN 算法,被 Chroma、Milvus 等广泛使用。

18.3.1 核心思想

HNSW 构建一个多层图结构:
#mermaid-svg-jbqfFsbJCZMO6xiV{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-jbqfFsbJCZMO6xiV .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-jbqfFsbJCZMO6xiV .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-jbqfFsbJCZMO6xiV .error-icon{fill:#552222;}#mermaid-svg-jbqfFsbJCZMO6xiV .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-jbqfFsbJCZMO6xiV .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-jbqfFsbJCZMO6xiV .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-jbqfFsbJCZMO6xiV .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-jbqfFsbJCZMO6xiV .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-jbqfFsbJCZMO6xiV .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-jbqfFsbJCZMO6xiV .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-jbqfFsbJCZMO6xiV .marker{fill:#333333;stroke:#333333;}#mermaid-svg-jbqfFsbJCZMO6xiV .marker.cross{stroke:#333333;}#mermaid-svg-jbqfFsbJCZMO6xiV svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-jbqfFsbJCZMO6xiV p{margin:0;}#mermaid-svg-jbqfFsbJCZMO6xiV .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-jbqfFsbJCZMO6xiV .cluster-label text{fill:#333;}#mermaid-svg-jbqfFsbJCZMO6xiV .cluster-label span{color:#333;}#mermaid-svg-jbqfFsbJCZMO6xiV .cluster-label span p{background-color:transparent;}#mermaid-svg-jbqfFsbJCZMO6xiV .label text,#mermaid-svg-jbqfFsbJCZMO6xiV span{fill:#333;color:#333;}#mermaid-svg-jbqfFsbJCZMO6xiV .node rect,#mermaid-svg-jbqfFsbJCZMO6xiV .node circle,#mermaid-svg-jbqfFsbJCZMO6xiV .node ellipse,#mermaid-svg-jbqfFsbJCZMO6xiV .node polygon,#mermaid-svg-jbqfFsbJCZMO6xiV .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-jbqfFsbJCZMO6xiV .rough-node .label text,#mermaid-svg-jbqfFsbJCZMO6xiV .node .label text,#mermaid-svg-jbqfFsbJCZMO6xiV .image-shape .label,#mermaid-svg-jbqfFsbJCZMO6xiV .icon-shape .label{text-anchor:middle;}#mermaid-svg-jbqfFsbJCZMO6xiV .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-jbqfFsbJCZMO6xiV .rough-node .label,#mermaid-svg-jbqfFsbJCZMO6xiV .node .label,#mermaid-svg-jbqfFsbJCZMO6xiV .image-shape .label,#mermaid-svg-jbqfFsbJCZMO6xiV .icon-shape .label{text-align:center;}#mermaid-svg-jbqfFsbJCZMO6xiV .node.clickable{cursor:pointer;}#mermaid-svg-jbqfFsbJCZMO6xiV .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-jbqfFsbJCZMO6xiV .arrowheadPath{fill:#333333;}#mermaid-svg-jbqfFsbJCZMO6xiV .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-jbqfFsbJCZMO6xiV .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-jbqfFsbJCZMO6xiV .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-jbqfFsbJCZMO6xiV .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-jbqfFsbJCZMO6xiV .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-jbqfFsbJCZMO6xiV .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-jbqfFsbJCZMO6xiV .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-jbqfFsbJCZMO6xiV .cluster text{fill:#333;}#mermaid-svg-jbqfFsbJCZMO6xiV .cluster span{color:#333;}#mermaid-svg-jbqfFsbJCZMO6xiV div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-jbqfFsbJCZMO6xiV .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-jbqfFsbJCZMO6xiV rect.text{fill:none;stroke-width:0;}#mermaid-svg-jbqfFsbJCZMO6xiV .icon-shape,#mermaid-svg-jbqfFsbJCZMO6xiV .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-jbqfFsbJCZMO6xiV .icon-shape p,#mermaid-svg-jbqfFsbJCZMO6xiV .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-jbqfFsbJCZMO6xiV .icon-shape .label rect,#mermaid-svg-jbqfFsbJCZMO6xiV .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-jbqfFsbJCZMO6xiV .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-jbqfFsbJCZMO6xiV .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-jbqfFsbJCZMO6xiV :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 第 0 层 密集短程连接(出口层)
第 1 层 中等密度
第 2 层 稀疏长程连接(入口层)
向下降落
向下降落
节点A
节点D
节点G
节点A
节点B
节点D
节点E
节点G
节点A
节点B
节点C
节点D
节点E
节点F
节点G

搜索从最顶层(第 2 层,入口) 进入,利用稀疏的长程连接快速跳到目标附近;然后逐层向下降落 ,每一层的图越来越密;最终在第 0 层(出口) 用密集的短程连接做精确搜索,找到最近邻。

注:层数(这里画了 3 层)只是示意,实际 HNSW 的层数由构建时随机决定(每个节点的最高层数按指数分布采样)。其中 第 0 层(Layer 0)是官方约定的最底层,包含全部节点;层号越大越往上、图越稀疏。

一个好用的类比:多粒度导航

HNSW 的分层,本质上很像对同一批数据建立不同粗细粒度的导航图------就像看地图时从世界地图逐级放大到城市街区:
#mermaid-svg-lBma3EshD2vy4fZ6{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-lBma3EshD2vy4fZ6 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-lBma3EshD2vy4fZ6 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-lBma3EshD2vy4fZ6 .error-icon{fill:#552222;}#mermaid-svg-lBma3EshD2vy4fZ6 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-lBma3EshD2vy4fZ6 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-lBma3EshD2vy4fZ6 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-lBma3EshD2vy4fZ6 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-lBma3EshD2vy4fZ6 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-lBma3EshD2vy4fZ6 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-lBma3EshD2vy4fZ6 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-lBma3EshD2vy4fZ6 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-lBma3EshD2vy4fZ6 .marker.cross{stroke:#333333;}#mermaid-svg-lBma3EshD2vy4fZ6 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-lBma3EshD2vy4fZ6 p{margin:0;}#mermaid-svg-lBma3EshD2vy4fZ6 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-lBma3EshD2vy4fZ6 .cluster-label text{fill:#333;}#mermaid-svg-lBma3EshD2vy4fZ6 .cluster-label span{color:#333;}#mermaid-svg-lBma3EshD2vy4fZ6 .cluster-label span p{background-color:transparent;}#mermaid-svg-lBma3EshD2vy4fZ6 .label text,#mermaid-svg-lBma3EshD2vy4fZ6 span{fill:#333;color:#333;}#mermaid-svg-lBma3EshD2vy4fZ6 .node rect,#mermaid-svg-lBma3EshD2vy4fZ6 .node circle,#mermaid-svg-lBma3EshD2vy4fZ6 .node ellipse,#mermaid-svg-lBma3EshD2vy4fZ6 .node polygon,#mermaid-svg-lBma3EshD2vy4fZ6 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-lBma3EshD2vy4fZ6 .rough-node .label text,#mermaid-svg-lBma3EshD2vy4fZ6 .node .label text,#mermaid-svg-lBma3EshD2vy4fZ6 .image-shape .label,#mermaid-svg-lBma3EshD2vy4fZ6 .icon-shape .label{text-anchor:middle;}#mermaid-svg-lBma3EshD2vy4fZ6 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-lBma3EshD2vy4fZ6 .rough-node .label,#mermaid-svg-lBma3EshD2vy4fZ6 .node .label,#mermaid-svg-lBma3EshD2vy4fZ6 .image-shape .label,#mermaid-svg-lBma3EshD2vy4fZ6 .icon-shape .label{text-align:center;}#mermaid-svg-lBma3EshD2vy4fZ6 .node.clickable{cursor:pointer;}#mermaid-svg-lBma3EshD2vy4fZ6 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-lBma3EshD2vy4fZ6 .arrowheadPath{fill:#333333;}#mermaid-svg-lBma3EshD2vy4fZ6 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-lBma3EshD2vy4fZ6 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-lBma3EshD2vy4fZ6 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-lBma3EshD2vy4fZ6 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-lBma3EshD2vy4fZ6 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-lBma3EshD2vy4fZ6 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-lBma3EshD2vy4fZ6 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-lBma3EshD2vy4fZ6 .cluster text{fill:#333;}#mermaid-svg-lBma3EshD2vy4fZ6 .cluster span{color:#333;}#mermaid-svg-lBma3EshD2vy4fZ6 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-lBma3EshD2vy4fZ6 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-lBma3EshD2vy4fZ6 rect.text{fill:none;stroke-width:0;}#mermaid-svg-lBma3EshD2vy4fZ6 .icon-shape,#mermaid-svg-lBma3EshD2vy4fZ6 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-lBma3EshD2vy4fZ6 .icon-shape p,#mermaid-svg-lBma3EshD2vy4fZ6 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-lBma3EshD2vy4fZ6 .icon-shape .label rect,#mermaid-svg-lBma3EshD2vy4fZ6 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-lBma3EshD2vy4fZ6 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-lBma3EshD2vy4fZ6 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-lBma3EshD2vy4fZ6 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 世界地图

只标大洲/大城市
国家地图

标主要城市
省级地图

标城市和主干道
城市地图

标每条街道

对应到 HNSW:

粒度 地图类比
顶层(最稀疏) 最粗粒度:极少节点 + 超长程跳跃 世界地图(只标大洲/大城市)
上中层 粗粒度 国家地图(标主要城市)
中间层 中粒度 省级地图(标城市和主干道)
第 0 层(最密集,含全部点) 最细粒度:全部节点 + 短程连接 城市地图(每条街道都有)

搜索就是从粗到细逐级放大:先在"世界地图"上快速跳到目标国家/城市附近,再逐级切到"国家地图""省级地图"缩小范围,最后在"城市地图"上精确定位。层数越多,放大过程就分得越细。

但要注意 HNSW 和传统"多级索引"(如 B+ 树、分层聚类)有一个本质区别:

  • 传统分层索引 :上层是下层的摘要/聚合,一个上层节点"代表"下面一堆点(父子隶属关系)。
  • HNSW :上层的点本身就是下层点的抽样子集 。节点 A 出现在第 2 层,意味着 A 也存在于第 1 层和第 0 层,只是它在高层额外拥有长程连接。层与层之间靠"同一个点的副本"连接(就是上图 A2 → A1 → A0 那条降落线),不是父子摘要关系。

传统分层索引:上层 = 下层的"压缩摘要"HNSW:上层 = 下层的"抽样子集"\text{传统分层索引:上层 = 下层的"压缩摘要"} \qquad \text{HNSW:上层 = 下层的"抽样子集"}传统分层索引:上层 = 下层的"压缩摘要"HNSW:上层 = 下层的"抽样子集"

18.3.2 搜索过程

#mermaid-svg-T4iQqElYVa7O50cq{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-T4iQqElYVa7O50cq .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-T4iQqElYVa7O50cq .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-T4iQqElYVa7O50cq .error-icon{fill:#552222;}#mermaid-svg-T4iQqElYVa7O50cq .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-T4iQqElYVa7O50cq .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-T4iQqElYVa7O50cq .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-T4iQqElYVa7O50cq .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-T4iQqElYVa7O50cq .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-T4iQqElYVa7O50cq .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-T4iQqElYVa7O50cq .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-T4iQqElYVa7O50cq .marker{fill:#333333;stroke:#333333;}#mermaid-svg-T4iQqElYVa7O50cq .marker.cross{stroke:#333333;}#mermaid-svg-T4iQqElYVa7O50cq svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-T4iQqElYVa7O50cq p{margin:0;}#mermaid-svg-T4iQqElYVa7O50cq .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-T4iQqElYVa7O50cq .cluster-label text{fill:#333;}#mermaid-svg-T4iQqElYVa7O50cq .cluster-label span{color:#333;}#mermaid-svg-T4iQqElYVa7O50cq .cluster-label span p{background-color:transparent;}#mermaid-svg-T4iQqElYVa7O50cq .label text,#mermaid-svg-T4iQqElYVa7O50cq span{fill:#333;color:#333;}#mermaid-svg-T4iQqElYVa7O50cq .node rect,#mermaid-svg-T4iQqElYVa7O50cq .node circle,#mermaid-svg-T4iQqElYVa7O50cq .node ellipse,#mermaid-svg-T4iQqElYVa7O50cq .node polygon,#mermaid-svg-T4iQqElYVa7O50cq .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-T4iQqElYVa7O50cq .rough-node .label text,#mermaid-svg-T4iQqElYVa7O50cq .node .label text,#mermaid-svg-T4iQqElYVa7O50cq .image-shape .label,#mermaid-svg-T4iQqElYVa7O50cq .icon-shape .label{text-anchor:middle;}#mermaid-svg-T4iQqElYVa7O50cq .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-T4iQqElYVa7O50cq .rough-node .label,#mermaid-svg-T4iQqElYVa7O50cq .node .label,#mermaid-svg-T4iQqElYVa7O50cq .image-shape .label,#mermaid-svg-T4iQqElYVa7O50cq .icon-shape .label{text-align:center;}#mermaid-svg-T4iQqElYVa7O50cq .node.clickable{cursor:pointer;}#mermaid-svg-T4iQqElYVa7O50cq .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-T4iQqElYVa7O50cq .arrowheadPath{fill:#333333;}#mermaid-svg-T4iQqElYVa7O50cq .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-T4iQqElYVa7O50cq .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-T4iQqElYVa7O50cq .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-T4iQqElYVa7O50cq .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-T4iQqElYVa7O50cq .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-T4iQqElYVa7O50cq .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-T4iQqElYVa7O50cq .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-T4iQqElYVa7O50cq .cluster text{fill:#333;}#mermaid-svg-T4iQqElYVa7O50cq .cluster span{color:#333;}#mermaid-svg-T4iQqElYVa7O50cq div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-T4iQqElYVa7O50cq .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-T4iQqElYVa7O50cq rect.text{fill:none;stroke-width:0;}#mermaid-svg-T4iQqElYVa7O50cq .icon-shape,#mermaid-svg-T4iQqElYVa7O50cq .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-T4iQqElYVa7O50cq .icon-shape p,#mermaid-svg-T4iQqElYVa7O50cq .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-T4iQqElYVa7O50cq .icon-shape .label rect,#mermaid-svg-T4iQqElYVa7O50cq .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-T4iQqElYVa7O50cq .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-T4iQqElYVa7O50cq .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-T4iQqElYVa7O50cq :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 从最高层开始

粗粒度导航
找到大致方向
下降到下一层

更精细搜索
重复直到第0层
在第0层精确搜索

找到最近邻

18.3.3 HNSW 的参数

参数 说明 默认值
M 每个节点的最大连接数 16
ef_construction 构建时的搜索宽度 200
ef_search 搜索时的候选集大小 50

M 越大,精度越高,但内存和构建时间也越大。


18.4 IVF(Inverted File Index)

IVF 是另一种常用的 ANN 算法:

18.4.1 核心思想

  1. 训练阶段 :用 K-Means 把所有向量聚成 nlist 个簇
  2. 索引阶段:每个向量存入最近的簇
  3. 搜索阶段 :只在最近的 nprobe 个簇中搜索

#mermaid-svg-nBpq05PwMg6XbwEO{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-nBpq05PwMg6XbwEO .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-nBpq05PwMg6XbwEO .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-nBpq05PwMg6XbwEO .error-icon{fill:#552222;}#mermaid-svg-nBpq05PwMg6XbwEO .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-nBpq05PwMg6XbwEO .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-nBpq05PwMg6XbwEO .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-nBpq05PwMg6XbwEO .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-nBpq05PwMg6XbwEO .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-nBpq05PwMg6XbwEO .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-nBpq05PwMg6XbwEO .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-nBpq05PwMg6XbwEO .marker{fill:#333333;stroke:#333333;}#mermaid-svg-nBpq05PwMg6XbwEO .marker.cross{stroke:#333333;}#mermaid-svg-nBpq05PwMg6XbwEO svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-nBpq05PwMg6XbwEO p{margin:0;}#mermaid-svg-nBpq05PwMg6XbwEO .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-nBpq05PwMg6XbwEO .cluster-label text{fill:#333;}#mermaid-svg-nBpq05PwMg6XbwEO .cluster-label span{color:#333;}#mermaid-svg-nBpq05PwMg6XbwEO .cluster-label span p{background-color:transparent;}#mermaid-svg-nBpq05PwMg6XbwEO .label text,#mermaid-svg-nBpq05PwMg6XbwEO span{fill:#333;color:#333;}#mermaid-svg-nBpq05PwMg6XbwEO .node rect,#mermaid-svg-nBpq05PwMg6XbwEO .node circle,#mermaid-svg-nBpq05PwMg6XbwEO .node ellipse,#mermaid-svg-nBpq05PwMg6XbwEO .node polygon,#mermaid-svg-nBpq05PwMg6XbwEO .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-nBpq05PwMg6XbwEO .rough-node .label text,#mermaid-svg-nBpq05PwMg6XbwEO .node .label text,#mermaid-svg-nBpq05PwMg6XbwEO .image-shape .label,#mermaid-svg-nBpq05PwMg6XbwEO .icon-shape .label{text-anchor:middle;}#mermaid-svg-nBpq05PwMg6XbwEO .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-nBpq05PwMg6XbwEO .rough-node .label,#mermaid-svg-nBpq05PwMg6XbwEO .node .label,#mermaid-svg-nBpq05PwMg6XbwEO .image-shape .label,#mermaid-svg-nBpq05PwMg6XbwEO .icon-shape .label{text-align:center;}#mermaid-svg-nBpq05PwMg6XbwEO .node.clickable{cursor:pointer;}#mermaid-svg-nBpq05PwMg6XbwEO .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-nBpq05PwMg6XbwEO .arrowheadPath{fill:#333333;}#mermaid-svg-nBpq05PwMg6XbwEO .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-nBpq05PwMg6XbwEO .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-nBpq05PwMg6XbwEO .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-nBpq05PwMg6XbwEO .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-nBpq05PwMg6XbwEO .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-nBpq05PwMg6XbwEO .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-nBpq05PwMg6XbwEO .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-nBpq05PwMg6XbwEO .cluster text{fill:#333;}#mermaid-svg-nBpq05PwMg6XbwEO .cluster span{color:#333;}#mermaid-svg-nBpq05PwMg6XbwEO div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-nBpq05PwMg6XbwEO .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-nBpq05PwMg6XbwEO rect.text{fill:none;stroke-width:0;}#mermaid-svg-nBpq05PwMg6XbwEO .icon-shape,#mermaid-svg-nBpq05PwMg6XbwEO .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-nBpq05PwMg6XbwEO .icon-shape p,#mermaid-svg-nBpq05PwMg6XbwEO .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-nBpq05PwMg6XbwEO .icon-shape .label rect,#mermaid-svg-nBpq05PwMg6XbwEO .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-nBpq05PwMg6XbwEO .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-nBpq05PwMg6XbwEO .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-nBpq05PwMg6XbwEO :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 所有向量
K-Means 聚类

nlist=100个簇
每个向量分配到最近的簇
搜索时只查 nprobe=10 个簇
在这些簇中精确搜索

参数 说明 权衡
nlist 簇的数量 大→精度高,慢
nprobe 搜索的簇数 大→精度高,慢

18.5 PQ(Product Quantization)

PQ 用于压缩向量,减少内存占用:

18.5.1 核心思想

把 768 维向量分成 8 段,每段 96 维,对每段独立量化:
#mermaid-svg-X0jd2BkO0P7QLRxV{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-X0jd2BkO0P7QLRxV .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-X0jd2BkO0P7QLRxV .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-X0jd2BkO0P7QLRxV .error-icon{fill:#552222;}#mermaid-svg-X0jd2BkO0P7QLRxV .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-X0jd2BkO0P7QLRxV .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-X0jd2BkO0P7QLRxV .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-X0jd2BkO0P7QLRxV .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-X0jd2BkO0P7QLRxV .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-X0jd2BkO0P7QLRxV .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-X0jd2BkO0P7QLRxV .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-X0jd2BkO0P7QLRxV .marker{fill:#333333;stroke:#333333;}#mermaid-svg-X0jd2BkO0P7QLRxV .marker.cross{stroke:#333333;}#mermaid-svg-X0jd2BkO0P7QLRxV svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-X0jd2BkO0P7QLRxV p{margin:0;}#mermaid-svg-X0jd2BkO0P7QLRxV .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-X0jd2BkO0P7QLRxV .cluster-label text{fill:#333;}#mermaid-svg-X0jd2BkO0P7QLRxV .cluster-label span{color:#333;}#mermaid-svg-X0jd2BkO0P7QLRxV .cluster-label span p{background-color:transparent;}#mermaid-svg-X0jd2BkO0P7QLRxV .label text,#mermaid-svg-X0jd2BkO0P7QLRxV span{fill:#333;color:#333;}#mermaid-svg-X0jd2BkO0P7QLRxV .node rect,#mermaid-svg-X0jd2BkO0P7QLRxV .node circle,#mermaid-svg-X0jd2BkO0P7QLRxV .node ellipse,#mermaid-svg-X0jd2BkO0P7QLRxV .node polygon,#mermaid-svg-X0jd2BkO0P7QLRxV .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-X0jd2BkO0P7QLRxV .rough-node .label text,#mermaid-svg-X0jd2BkO0P7QLRxV .node .label text,#mermaid-svg-X0jd2BkO0P7QLRxV .image-shape .label,#mermaid-svg-X0jd2BkO0P7QLRxV .icon-shape .label{text-anchor:middle;}#mermaid-svg-X0jd2BkO0P7QLRxV .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-X0jd2BkO0P7QLRxV .rough-node .label,#mermaid-svg-X0jd2BkO0P7QLRxV .node .label,#mermaid-svg-X0jd2BkO0P7QLRxV .image-shape .label,#mermaid-svg-X0jd2BkO0P7QLRxV .icon-shape .label{text-align:center;}#mermaid-svg-X0jd2BkO0P7QLRxV .node.clickable{cursor:pointer;}#mermaid-svg-X0jd2BkO0P7QLRxV .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-X0jd2BkO0P7QLRxV .arrowheadPath{fill:#333333;}#mermaid-svg-X0jd2BkO0P7QLRxV .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-X0jd2BkO0P7QLRxV .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-X0jd2BkO0P7QLRxV .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-X0jd2BkO0P7QLRxV .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-X0jd2BkO0P7QLRxV .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-X0jd2BkO0P7QLRxV .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-X0jd2BkO0P7QLRxV .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-X0jd2BkO0P7QLRxV .cluster text{fill:#333;}#mermaid-svg-X0jd2BkO0P7QLRxV .cluster span{color:#333;}#mermaid-svg-X0jd2BkO0P7QLRxV div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-X0jd2BkO0P7QLRxV .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-X0jd2BkO0P7QLRxV rect.text{fill:none;stroke-width:0;}#mermaid-svg-X0jd2BkO0P7QLRxV .icon-shape,#mermaid-svg-X0jd2BkO0P7QLRxV .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-X0jd2BkO0P7QLRxV .icon-shape p,#mermaid-svg-X0jd2BkO0P7QLRxV .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-X0jd2BkO0P7QLRxV .icon-shape .label rect,#mermaid-svg-X0jd2BkO0P7QLRxV .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-X0jd2BkO0P7QLRxV .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-X0jd2BkO0P7QLRxV .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-X0jd2BkO0P7QLRxV :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 原始向量

768维 × float32

= 3072 bytes
分成8段

每段96维
每段量化为

1个字节(256个码字)
压缩后

8 bytes

压缩比 384:1

方案 内存 精度
原始 float32 3072 bytes 100%
float16 1536 bytes ~100%
PQ (8段) 8 bytes ~90%

18.6 主流向量数据库对比

数据库 特点 适用场景
FAISS Facebook 开源,纯内存,速度最快 研究、小规模
Chroma 轻量,易用,本地部署 开发、原型
Milvus 分布式,生产级 大规模生产
Qdrant Rust 实现,高性能 生产
Weaviate 支持混合搜索 生产
Pinecone 云服务,全托管 快速上线

18.7 FAISS 使用示例

python 复制代码
import faiss
import numpy as np

# 创建索引
d = 768  # 向量维度
n = 100000  # 向量数量

# 生成随机向量(实际使用时替换为真实 Embedding)
vectors = np.random.random((n, d)).astype('float32')
faiss.normalize_L2(vectors)  # L2 归一化

# 创建 HNSW 索引
index = faiss.IndexHNSWFlat(d, 32)  # M=32
index.add(vectors)

# 搜索
query = np.random.random((1, d)).astype('float32')
faiss.normalize_L2(query)

k = 10  # 返回最近的 10 个
distances, indices = index.search(query, k)
print("最近邻索引:", indices[0])
print("相似度:", distances[0])

18.8 Chroma 使用示例

python 复制代码
import chromadb
from chromadb.utils import embedding_functions

# 创建客户端
client = chromadb.Client()

# 使用 BGE 作为 Embedding 函数
ef = embedding_functions.SentenceTransformerEmbeddingFunction(
    model_name="BAAI/bge-base-zh-v1.5"
)

# 创建集合
collection = client.create_collection(
    name="my_docs",
    embedding_function=ef
)

# 添加文档
collection.add(
    documents=[
        "苹果是一种水果",
        "香蕉也是水果",
        "苹果公司发布了新产品",
        "深度学习是人工智能的一个分支"
    ],
    ids=["doc1", "doc2", "doc3", "doc4"]
)

# 查询
results = collection.query(
    query_texts=["什么是水果?"],
    n_results=2
)
print(results['documents'])
# [['苹果是一种水果', '香蕉也是水果']]

18.9 混合搜索(Hybrid Search)

只用向量搜索有时不够,现代系统通常结合关键词搜索:
#mermaid-svg-nPmAbtxhrjpcDYvg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-nPmAbtxhrjpcDYvg .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-nPmAbtxhrjpcDYvg .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-nPmAbtxhrjpcDYvg .error-icon{fill:#552222;}#mermaid-svg-nPmAbtxhrjpcDYvg .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-nPmAbtxhrjpcDYvg .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-nPmAbtxhrjpcDYvg .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-nPmAbtxhrjpcDYvg .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-nPmAbtxhrjpcDYvg .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-nPmAbtxhrjpcDYvg .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-nPmAbtxhrjpcDYvg .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-nPmAbtxhrjpcDYvg .marker{fill:#333333;stroke:#333333;}#mermaid-svg-nPmAbtxhrjpcDYvg .marker.cross{stroke:#333333;}#mermaid-svg-nPmAbtxhrjpcDYvg svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-nPmAbtxhrjpcDYvg p{margin:0;}#mermaid-svg-nPmAbtxhrjpcDYvg .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-nPmAbtxhrjpcDYvg .cluster-label text{fill:#333;}#mermaid-svg-nPmAbtxhrjpcDYvg .cluster-label span{color:#333;}#mermaid-svg-nPmAbtxhrjpcDYvg .cluster-label span p{background-color:transparent;}#mermaid-svg-nPmAbtxhrjpcDYvg .label text,#mermaid-svg-nPmAbtxhrjpcDYvg span{fill:#333;color:#333;}#mermaid-svg-nPmAbtxhrjpcDYvg .node rect,#mermaid-svg-nPmAbtxhrjpcDYvg .node circle,#mermaid-svg-nPmAbtxhrjpcDYvg .node ellipse,#mermaid-svg-nPmAbtxhrjpcDYvg .node polygon,#mermaid-svg-nPmAbtxhrjpcDYvg .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-nPmAbtxhrjpcDYvg .rough-node .label text,#mermaid-svg-nPmAbtxhrjpcDYvg .node .label text,#mermaid-svg-nPmAbtxhrjpcDYvg .image-shape .label,#mermaid-svg-nPmAbtxhrjpcDYvg .icon-shape .label{text-anchor:middle;}#mermaid-svg-nPmAbtxhrjpcDYvg .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-nPmAbtxhrjpcDYvg .rough-node .label,#mermaid-svg-nPmAbtxhrjpcDYvg .node .label,#mermaid-svg-nPmAbtxhrjpcDYvg .image-shape .label,#mermaid-svg-nPmAbtxhrjpcDYvg .icon-shape .label{text-align:center;}#mermaid-svg-nPmAbtxhrjpcDYvg .node.clickable{cursor:pointer;}#mermaid-svg-nPmAbtxhrjpcDYvg .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-nPmAbtxhrjpcDYvg .arrowheadPath{fill:#333333;}#mermaid-svg-nPmAbtxhrjpcDYvg .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-nPmAbtxhrjpcDYvg .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-nPmAbtxhrjpcDYvg .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-nPmAbtxhrjpcDYvg .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-nPmAbtxhrjpcDYvg .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-nPmAbtxhrjpcDYvg .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-nPmAbtxhrjpcDYvg .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-nPmAbtxhrjpcDYvg .cluster text{fill:#333;}#mermaid-svg-nPmAbtxhrjpcDYvg .cluster span{color:#333;}#mermaid-svg-nPmAbtxhrjpcDYvg div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-nPmAbtxhrjpcDYvg .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-nPmAbtxhrjpcDYvg rect.text{fill:none;stroke-width:0;}#mermaid-svg-nPmAbtxhrjpcDYvg .icon-shape,#mermaid-svg-nPmAbtxhrjpcDYvg .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-nPmAbtxhrjpcDYvg .icon-shape p,#mermaid-svg-nPmAbtxhrjpcDYvg .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-nPmAbtxhrjpcDYvg .icon-shape .label rect,#mermaid-svg-nPmAbtxhrjpcDYvg .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-nPmAbtxhrjpcDYvg .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-nPmAbtxhrjpcDYvg .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-nPmAbtxhrjpcDYvg :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 用户 Query
向量搜索

语义相关
BM25 关键词搜索

精确匹配
RRF 融合

Reciprocal Rank Fusion
最终排序结果

搜索方式 优点 缺点
向量搜索 语义理解,同义词 精确词匹配差
关键词搜索 精确匹配 不理解语义
混合搜索 两者兼顾 实现复杂

本章总结

#mermaid-svg-AjMT9Jigood016YY{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-AjMT9Jigood016YY .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-AjMT9Jigood016YY .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-AjMT9Jigood016YY .error-icon{fill:#552222;}#mermaid-svg-AjMT9Jigood016YY .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-AjMT9Jigood016YY .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-AjMT9Jigood016YY .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-AjMT9Jigood016YY .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-AjMT9Jigood016YY .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-AjMT9Jigood016YY .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-AjMT9Jigood016YY .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-AjMT9Jigood016YY .marker{fill:#333333;stroke:#333333;}#mermaid-svg-AjMT9Jigood016YY .marker.cross{stroke:#333333;}#mermaid-svg-AjMT9Jigood016YY svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-AjMT9Jigood016YY p{margin:0;}#mermaid-svg-AjMT9Jigood016YY .edge{stroke-width:3;}#mermaid-svg-AjMT9Jigood016YY .section--1 rect,#mermaid-svg-AjMT9Jigood016YY .section--1 path,#mermaid-svg-AjMT9Jigood016YY .section--1 circle,#mermaid-svg-AjMT9Jigood016YY .section--1 polygon,#mermaid-svg-AjMT9Jigood016YY .section--1 path{fill:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-AjMT9Jigood016YY .section--1 text{fill:#ffffff;}#mermaid-svg-AjMT9Jigood016YY .node-icon--1{font-size:40px;color:#ffffff;}#mermaid-svg-AjMT9Jigood016YY .section-edge--1{stroke:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-AjMT9Jigood016YY .edge-depth--1{stroke-width:17;}#mermaid-svg-AjMT9Jigood016YY .section--1 line{stroke:hsl(60, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-AjMT9Jigood016YY .disabled,#mermaid-svg-AjMT9Jigood016YY .disabled circle,#mermaid-svg-AjMT9Jigood016YY .disabled text{fill:lightgray;}#mermaid-svg-AjMT9Jigood016YY .disabled text{fill:#efefef;}#mermaid-svg-AjMT9Jigood016YY .section-0 rect,#mermaid-svg-AjMT9Jigood016YY .section-0 path,#mermaid-svg-AjMT9Jigood016YY .section-0 circle,#mermaid-svg-AjMT9Jigood016YY .section-0 polygon,#mermaid-svg-AjMT9Jigood016YY .section-0 path{fill:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-AjMT9Jigood016YY .section-0 text{fill:black;}#mermaid-svg-AjMT9Jigood016YY .node-icon-0{font-size:40px;color:black;}#mermaid-svg-AjMT9Jigood016YY .section-edge-0{stroke:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-AjMT9Jigood016YY .edge-depth-0{stroke-width:14;}#mermaid-svg-AjMT9Jigood016YY .section-0 line{stroke:hsl(240, 100%, 83.5294117647%);stroke-width:3;}#mermaid-svg-AjMT9Jigood016YY .disabled,#mermaid-svg-AjMT9Jigood016YY .disabled circle,#mermaid-svg-AjMT9Jigood016YY .disabled text{fill:lightgray;}#mermaid-svg-AjMT9Jigood016YY .disabled text{fill:#efefef;}#mermaid-svg-AjMT9Jigood016YY .section-1 rect,#mermaid-svg-AjMT9Jigood016YY .section-1 path,#mermaid-svg-AjMT9Jigood016YY .section-1 circle,#mermaid-svg-AjMT9Jigood016YY .section-1 polygon,#mermaid-svg-AjMT9Jigood016YY .section-1 path{fill:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-AjMT9Jigood016YY .section-1 text{fill:black;}#mermaid-svg-AjMT9Jigood016YY .node-icon-1{font-size:40px;color:black;}#mermaid-svg-AjMT9Jigood016YY .section-edge-1{stroke:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-AjMT9Jigood016YY .edge-depth-1{stroke-width:11;}#mermaid-svg-AjMT9Jigood016YY .section-1 line{stroke:hsl(260, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-AjMT9Jigood016YY .disabled,#mermaid-svg-AjMT9Jigood016YY .disabled circle,#mermaid-svg-AjMT9Jigood016YY .disabled text{fill:lightgray;}#mermaid-svg-AjMT9Jigood016YY .disabled text{fill:#efefef;}#mermaid-svg-AjMT9Jigood016YY .section-2 rect,#mermaid-svg-AjMT9Jigood016YY .section-2 path,#mermaid-svg-AjMT9Jigood016YY .section-2 circle,#mermaid-svg-AjMT9Jigood016YY .section-2 polygon,#mermaid-svg-AjMT9Jigood016YY .section-2 path{fill:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-AjMT9Jigood016YY .section-2 text{fill:#ffffff;}#mermaid-svg-AjMT9Jigood016YY .node-icon-2{font-size:40px;color:#ffffff;}#mermaid-svg-AjMT9Jigood016YY .section-edge-2{stroke:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-AjMT9Jigood016YY .edge-depth-2{stroke-width:8;}#mermaid-svg-AjMT9Jigood016YY .section-2 line{stroke:hsl(90, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-AjMT9Jigood016YY .disabled,#mermaid-svg-AjMT9Jigood016YY .disabled circle,#mermaid-svg-AjMT9Jigood016YY .disabled text{fill:lightgray;}#mermaid-svg-AjMT9Jigood016YY .disabled text{fill:#efefef;}#mermaid-svg-AjMT9Jigood016YY .section-3 rect,#mermaid-svg-AjMT9Jigood016YY .section-3 path,#mermaid-svg-AjMT9Jigood016YY .section-3 circle,#mermaid-svg-AjMT9Jigood016YY .section-3 polygon,#mermaid-svg-AjMT9Jigood016YY .section-3 path{fill:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-AjMT9Jigood016YY .section-3 text{fill:black;}#mermaid-svg-AjMT9Jigood016YY .node-icon-3{font-size:40px;color:black;}#mermaid-svg-AjMT9Jigood016YY .section-edge-3{stroke:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-AjMT9Jigood016YY .edge-depth-3{stroke-width:5;}#mermaid-svg-AjMT9Jigood016YY .section-3 line{stroke:hsl(120, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-AjMT9Jigood016YY .disabled,#mermaid-svg-AjMT9Jigood016YY .disabled circle,#mermaid-svg-AjMT9Jigood016YY .disabled text{fill:lightgray;}#mermaid-svg-AjMT9Jigood016YY .disabled text{fill:#efefef;}#mermaid-svg-AjMT9Jigood016YY .section-4 rect,#mermaid-svg-AjMT9Jigood016YY .section-4 path,#mermaid-svg-AjMT9Jigood016YY .section-4 circle,#mermaid-svg-AjMT9Jigood016YY .section-4 polygon,#mermaid-svg-AjMT9Jigood016YY .section-4 path{fill:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-AjMT9Jigood016YY .section-4 text{fill:black;}#mermaid-svg-AjMT9Jigood016YY .node-icon-4{font-size:40px;color:black;}#mermaid-svg-AjMT9Jigood016YY .section-edge-4{stroke:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-AjMT9Jigood016YY .edge-depth-4{stroke-width:2;}#mermaid-svg-AjMT9Jigood016YY .section-4 line{stroke:hsl(150, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-AjMT9Jigood016YY .disabled,#mermaid-svg-AjMT9Jigood016YY .disabled circle,#mermaid-svg-AjMT9Jigood016YY .disabled text{fill:lightgray;}#mermaid-svg-AjMT9Jigood016YY .disabled text{fill:#efefef;}#mermaid-svg-AjMT9Jigood016YY .section-5 rect,#mermaid-svg-AjMT9Jigood016YY .section-5 path,#mermaid-svg-AjMT9Jigood016YY .section-5 circle,#mermaid-svg-AjMT9Jigood016YY .section-5 polygon,#mermaid-svg-AjMT9Jigood016YY .section-5 path{fill:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-AjMT9Jigood016YY .section-5 text{fill:black;}#mermaid-svg-AjMT9Jigood016YY .node-icon-5{font-size:40px;color:black;}#mermaid-svg-AjMT9Jigood016YY .section-edge-5{stroke:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-AjMT9Jigood016YY .edge-depth-5{stroke-width:-1;}#mermaid-svg-AjMT9Jigood016YY .section-5 line{stroke:hsl(180, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-AjMT9Jigood016YY .disabled,#mermaid-svg-AjMT9Jigood016YY .disabled circle,#mermaid-svg-AjMT9Jigood016YY .disabled text{fill:lightgray;}#mermaid-svg-AjMT9Jigood016YY .disabled text{fill:#efefef;}#mermaid-svg-AjMT9Jigood016YY .section-6 rect,#mermaid-svg-AjMT9Jigood016YY .section-6 path,#mermaid-svg-AjMT9Jigood016YY .section-6 circle,#mermaid-svg-AjMT9Jigood016YY .section-6 polygon,#mermaid-svg-AjMT9Jigood016YY .section-6 path{fill:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-AjMT9Jigood016YY .section-6 text{fill:black;}#mermaid-svg-AjMT9Jigood016YY .node-icon-6{font-size:40px;color:black;}#mermaid-svg-AjMT9Jigood016YY .section-edge-6{stroke:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-AjMT9Jigood016YY .edge-depth-6{stroke-width:-4;}#mermaid-svg-AjMT9Jigood016YY .section-6 line{stroke:hsl(210, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-AjMT9Jigood016YY .disabled,#mermaid-svg-AjMT9Jigood016YY .disabled circle,#mermaid-svg-AjMT9Jigood016YY .disabled text{fill:lightgray;}#mermaid-svg-AjMT9Jigood016YY .disabled text{fill:#efefef;}#mermaid-svg-AjMT9Jigood016YY .section-7 rect,#mermaid-svg-AjMT9Jigood016YY .section-7 path,#mermaid-svg-AjMT9Jigood016YY .section-7 circle,#mermaid-svg-AjMT9Jigood016YY .section-7 polygon,#mermaid-svg-AjMT9Jigood016YY .section-7 path{fill:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-AjMT9Jigood016YY .section-7 text{fill:black;}#mermaid-svg-AjMT9Jigood016YY .node-icon-7{font-size:40px;color:black;}#mermaid-svg-AjMT9Jigood016YY .section-edge-7{stroke:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-AjMT9Jigood016YY .edge-depth-7{stroke-width:-7;}#mermaid-svg-AjMT9Jigood016YY .section-7 line{stroke:hsl(270, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-AjMT9Jigood016YY .disabled,#mermaid-svg-AjMT9Jigood016YY .disabled circle,#mermaid-svg-AjMT9Jigood016YY .disabled text{fill:lightgray;}#mermaid-svg-AjMT9Jigood016YY .disabled text{fill:#efefef;}#mermaid-svg-AjMT9Jigood016YY .section-8 rect,#mermaid-svg-AjMT9Jigood016YY .section-8 path,#mermaid-svg-AjMT9Jigood016YY .section-8 circle,#mermaid-svg-AjMT9Jigood016YY .section-8 polygon,#mermaid-svg-AjMT9Jigood016YY .section-8 path{fill:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-AjMT9Jigood016YY .section-8 text{fill:black;}#mermaid-svg-AjMT9Jigood016YY .node-icon-8{font-size:40px;color:black;}#mermaid-svg-AjMT9Jigood016YY .section-edge-8{stroke:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-AjMT9Jigood016YY .edge-depth-8{stroke-width:-10;}#mermaid-svg-AjMT9Jigood016YY .section-8 line{stroke:hsl(330, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-AjMT9Jigood016YY .disabled,#mermaid-svg-AjMT9Jigood016YY .disabled circle,#mermaid-svg-AjMT9Jigood016YY .disabled text{fill:lightgray;}#mermaid-svg-AjMT9Jigood016YY .disabled text{fill:#efefef;}#mermaid-svg-AjMT9Jigood016YY .section-9 rect,#mermaid-svg-AjMT9Jigood016YY .section-9 path,#mermaid-svg-AjMT9Jigood016YY .section-9 circle,#mermaid-svg-AjMT9Jigood016YY .section-9 polygon,#mermaid-svg-AjMT9Jigood016YY .section-9 path{fill:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-AjMT9Jigood016YY .section-9 text{fill:black;}#mermaid-svg-AjMT9Jigood016YY .node-icon-9{font-size:40px;color:black;}#mermaid-svg-AjMT9Jigood016YY .section-edge-9{stroke:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-AjMT9Jigood016YY .edge-depth-9{stroke-width:-13;}#mermaid-svg-AjMT9Jigood016YY .section-9 line{stroke:hsl(0, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-AjMT9Jigood016YY .disabled,#mermaid-svg-AjMT9Jigood016YY .disabled circle,#mermaid-svg-AjMT9Jigood016YY .disabled text{fill:lightgray;}#mermaid-svg-AjMT9Jigood016YY .disabled text{fill:#efefef;}#mermaid-svg-AjMT9Jigood016YY .section-10 rect,#mermaid-svg-AjMT9Jigood016YY .section-10 path,#mermaid-svg-AjMT9Jigood016YY .section-10 circle,#mermaid-svg-AjMT9Jigood016YY .section-10 polygon,#mermaid-svg-AjMT9Jigood016YY .section-10 path{fill:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-AjMT9Jigood016YY .section-10 text{fill:black;}#mermaid-svg-AjMT9Jigood016YY .node-icon-10{font-size:40px;color:black;}#mermaid-svg-AjMT9Jigood016YY .section-edge-10{stroke:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-AjMT9Jigood016YY .edge-depth-10{stroke-width:-16;}#mermaid-svg-AjMT9Jigood016YY .section-10 line{stroke:hsl(30, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-AjMT9Jigood016YY .disabled,#mermaid-svg-AjMT9Jigood016YY .disabled circle,#mermaid-svg-AjMT9Jigood016YY .disabled text{fill:lightgray;}#mermaid-svg-AjMT9Jigood016YY .disabled text{fill:#efefef;}#mermaid-svg-AjMT9Jigood016YY .section-root rect,#mermaid-svg-AjMT9Jigood016YY .section-root path,#mermaid-svg-AjMT9Jigood016YY .section-root circle,#mermaid-svg-AjMT9Jigood016YY .section-root polygon{fill:hsl(240, 100%, 46.2745098039%);}#mermaid-svg-AjMT9Jigood016YY .section-root text{fill:#ffffff;}#mermaid-svg-AjMT9Jigood016YY .section-root span{color:#ffffff;}#mermaid-svg-AjMT9Jigood016YY .section-2 span{color:#ffffff;}#mermaid-svg-AjMT9Jigood016YY .icon-container{height:100%;display:flex;justify-content:center;align-items:center;}#mermaid-svg-AjMT9Jigood016YY .edge{fill:none;}#mermaid-svg-AjMT9Jigood016YY .mindmap-node-label{dy:1em;alignment-baseline:middle;text-anchor:middle;dominant-baseline:middle;text-align:center;}#mermaid-svg-AjMT9Jigood016YY :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 向量数据库
索引算法
HNSW 多层图
IVF 倒排索引
PQ 向量压缩
主流数据库
FAISS 研究
Chroma 开发
Milvus 生产
搜索策略
纯向量搜索
混合搜索
重排序


本章思考题

  1. 为什么 ANN(近似最近邻)比精确最近邻更实用?
  2. HNSW 的多层结构为什么能加速搜索?
  3. PQ 压缩会损失精度,在什么场景下可以接受这种损失?
  4. 混合搜索中,如何平衡向量搜索和关键词搜索的权重?

下一章预告

下一章我们讲 RAG(Retrieval-Augmented Generation)

这是目前最实用的 LLM 应用架构,把向量数据库和 LLM 结合起来。

相关推荐
oradh1 小时前
Oracle UNDO 数据文件丢失处理(案例一)
数据库·oracle
Mr数据杨1 小时前
二手车价格预测实战案例 从 Kaggle 回归赛题到可落地估价建模
人工智能·数据分析·kaggle竞赛
Cho1yon1 小时前
【AI Agent 第十五期: AI Agent 从 0 到 1 系统学习大纲】
javascript·人工智能·学习
空堂与归1 小时前
ChatGPT的视觉模型:ChatGPT Images 2.5:快与准拆成两个模型
人工智能·gpt·ai·chatgpt
Behaviour1 小时前
DeepSeek V4.1 Flash 发布开源,Harness v0.1.5同日适配
人工智能·语言模型·开源·aigc·ai编程
降临-max1 小时前
从零开始快速开发一个 AI 辅助测试设计智能体(附完整源码)
软件测试·人工智能·大模型·agent·ai测试智能体
武子康1 小时前
SGLang 和 vLLM,拿自己的请求测一轮再选
人工智能·llm·agent
hiahiahia1231 小时前
SSE 到底是什么?
前端·人工智能
aixingkong9211 小时前
华为麒麟9050 系列芯片深度解析:韬折叠的奇迹
服务器·人工智能·硬件架构·硬件工程