微信分享缩略图
  • {{ post.title }}

    {{ post.excerpt }}

    {{ post.author_name || settings.site_author || 'Admin' }} {{ formatDate(post.published_at || post.created_at) }} {{ post.view_count }} {{ post.comment_count }}

向量数据库入门指南:从原理到实战,彻底搞懂 Embedding、HNSW 与 RAG

向量数据库入门指南:从原理到实战

什么是向量数据库

向量数据库(Vector Database)是一种专门存储和检索向量数据的数据库。

要理解它,先要搞清楚"向量"在这里指的是什么。

向量的本质

一段文字经过 embedding 模型(比如 BGE-M3、text-embedding-3)处理后,会输出一串浮点数:

"国际货代系统" → [0.023, -0.156, 0.891, ..., 0.342]

这串数字通常有 768 维、1024 维甚至 1536 维。每个数字代表一个语义特征。模型在海量语料上训练过,学会把"语义"压缩成数值。

关键特性:

  • 语义相近的句子,向量在空间里挨得近
  • 语义无关的句子,向量在空间里离得远
  • 不同语言的同义内容,也会靠近(多语言模型)
"报关单"     → [0.12, -0.34, 0.78, ...]
"customs dec" → [0.15, -0.31, 0.81, ...]  ← 挨得很近
"今晚吃什么"   → [-0.67, 0.92, -0.13, ...] ← 离得很远

这就是整个系统的魔法基础。

和传统数据库的区别

MySQL:精确匹配

SELECT * FROM users WHERE id = 123;
-- 对就对,错就错

向量库:模糊匹配

找和"报关单怎么写"最相似的 5 条文档片段
-- 不比谁一模一样,比谁最接近

打个比方:

  • MySQL 像查字典 — 按拼音找到唯一那条
  • 向量库像在茫茫人海里找"长得最像你的人" — 算距离,返回相似度最高的几条

Embedding — 文字怎么变成向量

你输入一段文字,经过 embedding 模型,输出就是一串数字。

核心原理:

模型通过训练学会了"语义的数学表达"。同一个词在不同语境下的含义不同,embedding 会捕捉这种差异。

from sentence_transformers import SentenceTransformer

model = SentenceTransformer("BAAI/bge-m3")

sentences = ["报关单", "海关申报文件", "今晚吃什么"]
vectors = model.encode(sentences)

# 报关单 和 海关申报文件 的相似度:0.89
# 报关单 和 今晚吃什么 的相似度:0.12

不同语言的同义内容也会靠近,这就是多语言 embedding 模型的厉害之处。

向量空间 — 高维世界

人类只能想象 3 维。但向量数据库工作在 1024 维、1536 维的空间里。

不用试图想象它,用 2 维类比就行:

        y
        ↑
   "猫"  ·
        |         · "狗"
        |
  · "报关"      |
        |        · "物流"
        |
  ──────+────────────→ x
        |
        · "今晚吃什么"

在这个空间里,"猫"和"狗"挨着,"报关"和"物流"挨着,但它们两组之间离很远。

1024 维就是 1024 个这样的轴。每个轴捕捉一种语义特征,只是人类没法给它命名。

相似度计算 — 怎么判断"谁最像"

最常用的是余弦相似度

cos(θ) = A · B / (|A| × |B|)

两个向量的夹角越小,相似度越高:

  • 结果 = 1.0 → 完全一致
  • 结果 = 0.8 → 非常相似
  • 结果 = 0.3 → 关系不大
  • 结果 = 0.0 → 完全无关

另一个是欧氏距离,算两个点之间的直线距离。距离越短越相似。

大多数向量库默认用余弦相似度(内积),因为对向量长度不敏感,只关心"方向",也就是语义。

索引算法 — 为什么快

这才是向量库的核心技术。

最笨的方法是遍历所有向量,一个一个算相似度。10 万条数据就要算 10 万次,这叫暴力搜索,慢但准确。

ANN(Approximate Nearest Neighbor):近似最近邻搜索,牺牲一点点准确率,换来百倍千倍的速度。

HNSW — 最常用

Hierarchical Navigable Small World。把向量空间想象成一张地图:

  • 最上层:只有一些"地标城市",大跨度跳跃
  • 中间层:城市 + 大镇,中距离导航
  • 最底层:每个村镇都有,精细定位

搜索时先从顶层粗略定位区域,然后逐层细化。像高德地图从全国到省到市到街道的缩放。

速度:百万级数据,几毫秒出结果。

IVF — 分区索引

Inverted File Index。先把向量空间划分成 1000 个"小区",每个小区有自己的向量列表。

搜索时:

  1. 判断查询向量落在哪几个小区
  2. 只在这几个小区里暴力搜索

相当于你要找"朝阳区所有川菜馆",不用搜全北京,只搜朝阳区就行。

速度:比暴力搜索快 10-50 倍,适合亿级数据。

PQ — 乘积量化

Product Quantization。把 1024 维向量切成 8 段,每段 128 维。每段的向量都被压缩成一个"代号"(比如 1-256 的数字)。

原来存一个向量要 1024 × 4 字节 = 4KB。压缩后只要 8 字节。

10 亿条向量:

  • 原始:4TB
  • PQ 压缩后:8GB

代价是精度损失 1-3%,但内存占用降到原来的 1/500。

主流产品对比

产品 语言 特点 适合场景
Qdrant Rust 性能好,支持过滤 中小项目,本地部署
Milvus Go/C++ 企业级,分布式 大规模生产环境
Chroma Python 极简,嵌入式 原型开发,单机
Pinecone 云端 托管服务,零运维 SaaS,不想管服务器
Weaviate Go 支持图+向量混合 知识图谱场景
FAISS C++ Meta 出品,纯算法库 底层研究,自己封装

实际应用场景

RAG(检索增强生成)

用户问:报关单怎么生成?
    ↓
问题向量化 → [0.12, -0.34, ...]
    ↓
在向量库里找最相似的 3 条文档片段
    ↓
把找到的内容 + 原始问题一起给大模型
    ↓
大模型基于找到的内容回答

没有向量库,大模型只能靠训练记忆回答(可能过时)。有了向量库,它能查到你的最新文档再回答。

推荐系统

用户喜欢了文章 A → 找到 A 的最相似 10 篇文章 → 推荐给用户。这就是今日头条、抖音的底层逻辑之一。

图像搜索

上传一张图片 → 图片向量化 → 在图片库里找最相似的 → 返回外观相似的图片。淘宝"拍立淘"就是这样工作的。

语义去重

新来一条数据 → 向量化 → 在库里找相似度 > 0.95 的 → 找到了就是重复的,丢弃;没找到就入库。

完整数据流

以立刻云系统的 AI 会话查询为例:

1. 原始数据准备

历史订单、报关单、客户沟通记录,整理为文本格式。

2. 分块(Chunking)

每条记录切分成 500-1000 字的片段,重叠 10% 防止切断语义。

3. 向量化(Embedding)

每个片段调用 BGE-M3 生成 1024 维向量。1000 条片段 = 1000 个向量。

4. 入库

向量存进 Qdrant,原文存进 MySQL(带 ID 关联)。

5. 用户查询

用户问"上个月越南那批货的报关单号?" → 问题向量化 → 在 Qdrant 里找 top-5 相似片段 → 拿到 5 段原文 → 交给大模型 → 大模型综合回答。

核心总结

三句话记住向量数据库:

1. 向量是语义的数学表达 — 文字变数字,让机器能"理解"语义

2. 索引是速度的保证 — 暴力搜索太慢,HNSW/IVF/PQ 让亿级数据毫秒级响应

3. 向量库不替代关系库 — 它们互补。向量管"像不像",MySQL 管"准不准"

{{ currentPost.title }}

评论 ({{ comments.length }})

正在回复 @{{ replyTo.author_name }} 取消回复

暂无评论,来说两句吧

{{ settings.about_title || '个人简介' }}

搜索中...
没有找到相关文章
{{ r.title }}
{{ r.category_name }} {{ formatDate(r.published_at || r.created_at) }} {{ r.view_count }} 次阅读

{{ r.excerpt }}

评论通过

评论未通过

等待审核

{{ aiModalData.review || aiModalData.message }}

{{ toast.message }}