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 结合起来。

相关推荐
ofoxcoding2 分钟前
Jev 模型评测深度解析:核心得分、能力局限与最佳适用任务场景
人工智能·算法·机器学习·ai
Light Gao2 分钟前
LSTM 与 GRU 详解:从门控机制到架构图与数值计算
人工智能·gru·lstm
问商十三载7 分钟前
AI引擎生成式优化服务商怎么选?技术核验清单(附脚本)
数据库·人工智能·机器学习
TDengine (老段)8 分钟前
集群从“能用“到“高可用“:副本、选主与故障切换到底怎么配
大数据·网络·数据库·物联网·oracle·时序数据库·tdengine
ly76899 分钟前
ISR 收缩与 HW 推进:副本同步的边界条件与 UnderReplicated 排障
数据库·kafka·c#·linq·isr·hw·副本同步
EatFan13 分钟前
2026 后端架构进入 AI 原生阶段:事件驱动 + 虚拟线程 + Agent 内嵌三驾马车怎么落地
人工智能·架构·agent·虚拟线程·事件驱动·ai原生·后端架构
奋进的LY17 分钟前
spacy的安装和使用教程
人工智能·python·深度学习·github
小宋102117 分钟前
Diffusion LLM 为什么能并行生成:从逐 Token 解码到多位置去噪实战
人工智能
Evand J18 分钟前
【MATLAB例程】三维A*路径规划与TOA-AOA-TDOA融合定位算法。附下载链接
数据库·算法·matlab
znx93919 分钟前
机器学习赋能量化交易:解锁新时代投资的核心竞争优势
人工智能·python·机器学习·期魔方