Dify学习笔记 04 · 检索底座:Embedding、Rerank与向量数据库(第46-54集)

李沐深度学习191集课程全解析:模块拆解、学习路径

吴恩达《面向开发者的提示词工程》

吴恩达 MCP 教程(Model Context Protocol)(一)

多模态大模型教程学习笔记 --- ViT · CLIP · SAM · GLIP · Stable Diffusion

一句话总结: RAG 的检索上限由底座决定。本模块讲透三件事:Embedding 如何把文本变成可计算语义的向量(word2vec 的 CBOW/Skip-gram、微调与 MTEB 评估);Rerank 如何用"双编码粗召回 + 交叉编码精排"两阶段架构把准确率拉满(CrossEncoder 微调、RankGPT、模型合并);以及向量数据库如何用相似度度量、ANN 索引(HNSW/IVF)和 k-means 实现毫秒检索,并给出 Chroma / Qdrant / Milvus / pgvector 的选型与代码。

素材覆盖说明: 模块四共 9 集(第 46-54 集),本地视频与字幕齐全,全部据字幕据实整理,无补全小节。

一、可视化导览

本模块的两阶段检索架构、word2vec 双架构、相似度度量、索引算法与向量库选型矩阵已整理成一张知识图谱:模块四 · Embedding · Rerank · 向量库 · 可视化图谱

1.1 为什么说检索的上限由底座决定

模块三我们讲了一整条检索增强链路,你可能会觉得,效果不好就去调提示词、调切分。但这一模块要告诉你一个更底层的事实:你在链路上层做的所有优化,能改善多少,其实被两个更基础的东西死死限制着。一个是把文本变成向量的那个模型,另一个是把候选结果重新排序的那个模型。如果连"两段话意思相近"这件最基本的事都算不准,后面再怎么调提示词都是白搭。这就是为什么本模块叫检索底座------它决定了整个系统的天花板,你在天花板下面再怎么努力,也高不过它。

打个比方。检索问答系统像一个图书管理员帮你找资料。你问一个问题,他先从成千上万本书里挑出可能相关的几十本粗看一遍,这就是粗召回;然后再从这几十本里仔细挑出最相关的三五本递给你,这就是精排。粗召回快但不够准,精排准但很慢。理想的管理员是:粗召回时宁可多挑几本也不漏掉,精排时慢一点但要挑得准。整个检索工程,就是在训练这个管理员的"眼力"------粗召回的眼力靠向量模型,精排的眼力靠重排模型。这一模块就是在讲这两种眼力是怎么练出来的。

1.2 两阶段架构为什么是工程标配

你可能会问:既然交叉编码精排更准,为什么不直接用它对全库逐篇打分?答案是算不过来。一个库里可能有几百万、几千万个文档,用户一问,要是对每篇都做一次又慢又贵的交叉编码打分,那用户得等好几分钟,成本也高得离谱。所以工程上必须分工:先用快的双编码模型,把文档向量提前离线算好存着,用户一问只算问题向量、去库里快速找近似的几十个,这一步很快;再用准的交叉编码,只对这几十个候选慢慢精挑细选。快和准的矛盾,就这样被拆成两步化解了。理解了这个矛盾,你就理解了为什么需要向量库、为什么需要重排------它们都是这个矛盾的产物。

**记忆钩子:**粗召回要"快而全",宁可多捞;精排要"准而精",从候选里挑真相关的。两者不是替代,而是配合。

二、视频清单(9 集 · 约 2.3 小时)

集 标题 时长 核心内容
46 Embedding 原理:word2vec、CBOW 16:13 稠密向量、语义空间、CBOW/Skip-gram、PyTorch 手写
47 Embedding 模型训练:llamaindex 微调 22:02 QA 对生成、SentenceTransformers、AutoTrain
48 Embedding 模型评估:MRR、MTEB 20:38 MRR/hit_rate、MTEB、C-MTEB、主流模型
49 Rerank 原理(一)交叉编码与双编码 15:07 两阶段检索、bi/cross-encoder、ANN/HNSW
50 Rerank 微调(二)rankGPT 15:24 triplet、FlagEmbedding、LM-cocktail、point/list/pair
51 向量数据库简介与相似性测量 15:21 向量库流程、索引类型、欧式/余弦/点积
52 相似性搜索算法:k-means、肘部法则 18:29 k-means、肘部法则、k-means++、Kernel k-means
53 向量数据库选型 09:27 专业库 vs 传统库、分片复制、选型考量
54 向量数据库代码示例:chroma 与 qdrant 07:19 Chroma 原生 API、Spring AI、Qdrant 代码

三、Embedding 原理

3.1 从 one-hot 到稠密向量

embedding 就是把一个物体(词、句子、图片等)表示为低维、稠密的浮点向量 。对比 one-hot:one-hot 维度随词表膨胀(维度灾难)、任意两个词向量正交、语义上毫无关系;稠密向量维度可控,且语义相近的物体在空间中距离相近,还能做向量运算:

经典语义类比:king − man + woman ≈ queen。向量空间里"国王减去男性再加女性"得到的向量,恰好落在"女王"附近------说明关系被编码进了向量方向。

3.2 word2vec 的两种架构(2013,Google)

架构 CBOW 连续词袋 Skip-gram 跳字
预测方向 给上下文 → 预测中心词(完形填空) 给中心词 → 预测上下文
输入处理 上下文词向量需求和 / 取平均 输入不求和
适用 训练更快,高频词表现好 小数据、低频词表现更好

网络结构:输入 one-hot(V 维)× 权重矩阵 W(V×N)→ 隐藏层(N 维,即 embedding 维度)× W'(N×V)→ softmax 输出,用交叉熵损失训练;训练完后矩阵 W 就是词向量表。课程用 PyTorch 手写了一个最小示例(batch_size、embedding_dim、Adam、学习率 1e-4、约 2000 步)。现代 embedding 模型大多基于 Transformer。

python 复制代码
import torch
import torch.nn as nn
import torch.optim as optim
超参数
vocab_size = 5000      # 词表大小 V
embedding_dim = 128    # embedding 维度 N
batch_size = 64
num_steps = 2000
lr = 1e-4
class Word2VecCBOW(nn.Module):
def init(self, vocab_size, embedding_dim):
super().init()
# W: V x N,训练完即为词向量表
self.in_embed = nn.Embedding(vocab_size, embedding_dim)
# W': N x V,输出层
self.out_embed = nn.Linear(embedding_dim, vocab_size, bias=False)
def forward(self, context_ids):
    # context_ids: (batch, context_window)
    emb = self.in_embed(context_ids)      # (batch, window, N)
    hidden = emb.mean(dim=1)              # 上下文向量取平均
    logits = self.out_embed(hidden)       # (batch, V)
    return logits
model = Word2VecCBOW(vocab_size, embedding_dim)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=lr)
伪代码训练循环
for step in range(num_steps):
context_ids, center_ids = get_batch(batch_size)  # 取一批上下文与中心词
logits = model(context_ids)
loss = criterion(logits, center_ids)
optimizer.zero_grad()
loss.backward()
optimizer.step()
训练完成后,词向量表即 model.in_embed.weight
word_vectors = model.in_embed.weight.detach()

3.3 为什么稠密向量能"算"出语义

从一热编码到稠密向量,是一个巨大的观念跨越。一热编码把每个词当成空间里一根互相垂直的坐标轴,任意两个词之间永远是正交的,算出来它们"毫不相关"------这显然不符合我们对语言的直觉,猫和狗明明比猫和汽车更接近。稠密向量的想法是:把每个词放进一个低得多的空间里,让意思相近的词在这个空间里自然靠得近。那模型怎么知道谁和谁近?答案藏在上下文里。它看了海量文本后发现,猫和狗常常出现在相似的语境里,于是慢慢把它们的向量训得靠近。这就是分布式假设的精髓:一个词的意思,由它周围经常出现的词决定。

更妙的是,训出来的向量空间里,方向本身就编码了关系。课程举的那个经典例子,国王减去男性加上女性,得到的向量几乎正好落在女王附近。这说明模型不只是记住了"谁和谁像",还把"男女性别差异"这种关系学进了向量的某个方向里。这在当时是个惊人的发现,也是现代一切语义检索的地基。今天你用的各种句子向量模型,思想源头都在这里。

3.4 为什么今天还用不到手搓词向量

课程带你手写了一遍词向量训练,这是为了让你理解原理,但实际做项目时,你几乎不会自己去训词向量。原因很现实:现在的句子向量模型,都是在海量数据上用大算力预训练好的、并且在权威榜单上反复评测过的成熟模型,直接拿来用,效果远好于你自己从零训。手写训练的价值,是让你明白"向量为什么能表语义"这件事不是魔法,而是从语料里学来的,从而在自己的领域效果不好时,知道可以通过领域微调去改善它。

3.5 什么时候才需要微调向量模型

不是一上来就微调。先用现成的开源中文模型,在你自己那二三十个测试问题上跑一遍,算算命中率和排名指标。如果通用模型在你的专业领域表现已经够用,就别动它,省下来的精力去调切分和精排。只有当你发现,通用模型就是理解不了你这个领域的特殊术语、召回总是差那么点意思,才值得考虑用领域文档生成问答对去微调。而且记住课程反复强调的:微调完必须拿没参与训练的验证集来打分,不然就是自欺欺人。

**一句话:**向量模型是地基,先用现成的,地基确实不够用了再考虑加固,而不是一上来就重浇地基。

四、Embedding 微调

4.1 用 LlamaIndex 微调

  1. 用 SimpleDirectoryReader 读入领域文档(如证券法 PDF),SentenceSplitter 切分。

  2. 让 LLM 基于文本自动生成问答对(generate_qa_embedding_pairs)。

  3. 封装为 EmbeddingQAFinetuneDataset。

  4. 用 SentenceTransformersFinetuneEngine 以 BGE 等为底模微调。

python 复制代码
from llama_index.core import SimpleDirectoryReader
from llama_index.core.node_parser import SentenceSplitter
from llama_index.finetuning import generate_qa_embedding_pairs
from llama_index.finetuning import SentenceTransformersFinetuneEngine
from llama_index.core import Settings
from llama_index.llms.openai import OpenAI
Settings.llm = OpenAI(model="gpt-4o-mini")
1. 读入领域文档并切分
documents = SimpleDirectoryReader("./data").load_data()
splitter = SentenceSplitter(chunk_size=512, chunk_overlap=50)
nodes = splitter.get_nodes_from_documents(documents)
2. 让 LLM 自动生成问答对
qa_dataset = generate_qa_embedding_pairs(
nodes=nodes,
llm=Settings.llm,
)
3. 封装为 EmbeddingQAFinetuneDataset(generate_qa_embedding_pairs 已返回该类型)
qa_dataset.save_json("qa_dataset.json")
4. 以 BGE 为底模微调
finetune_engine = SentenceTransformersFinetuneEngine(
qa_dataset,
model_id="BAAI/bge-small-zh-v1.5",
model_output_path="./bge-finetuned",
epochs=2,
batch_size=16,
)
finetune_engine.finetune()
embed_model = finetune_engine.get_finetuned_model()

4.2 用 AutoTrain 微调(HuggingFace 开源)

  • 提供 Web UI(默认端口 8080),需配置 HF token 环境变量、安装 git-lfs。

  • 任务要选 ST 开头的 sentence-transformer 类任务。

  • 数据格式:pair(成对)、pair_class(成对带类别)、score(带分数)、triplet(anchor 锚点 / positive 正例 / negative 负例)、QA。CSV 或 JSON 均可。

  • 参数:fp16 / bf16 看显卡、cosine 相似度调度、batch size、epoch、学习率约 1e-4、用梯度累积模拟更大 batch。

  • 注意:LlamaIndex 生成的数据集格式与 AutoTrain 不完全兼容,subset 用冒号、split 格式需按要求调整。

bash 复制代码
# 安装并启动 AutoTrain 的 Web UI
pip install autotrain-advanced
export HF_TOKEN=your_huggingface_token
autotrain app --port 8080 --host 0.0.0.0
json 复制代码
[
  {
    "query": "证券法对信息披露的要求是什么?",
    "positive": "发行人应当依法披露信息,内容真实、准确、完整。",
    "negative": "证券交易应当在依法设立的场所进行。"
  }
]

评估微调效果必须使用未被训练污染过的验证集,否则指标虚高、上线即失效。

五、Embedding 评估

  • **hit_rate@k:**正确结果是否出现在 Top-K 中。

  • MRR(Mean Reciprocal Rank,平均倒数排名): 对每个查询取正确结果排名 rank 的倒数 1/rank,再对所有查询求平均:MRR = Σ(1/rank_i) / 查询数。正确答案排得越靠前分越高。

  • **precision / recall@k:**Top-K 中的精确率与召回率。

python 复制代码
def hit_rate_at_k(ranks, k):
    """ranks: 每个查询中正确结果的排名列表(1 起)"""
    return sum(1 for r in ranks if r <= k) / len(ranks)
def mrr(ranks):
"""平均倒数排名"""
return sum(1.0 / r for r in ranks) / len(ranks)
示例:5 个查询,正确结果分别排在第 1、3、2、10、1 位
ranks = [1, 3, 2, 10, 1]
print("hit_rate@3 =", hit_rate_at_k(ranks, 3))  # 0.8
print("MRR =", mrr(ranks))                      # 0.634
榜单 / 模型 说明
MTEB HuggingFace 国际大规模 embedding 榜单:8 类任务、56 个数据集、上千模型、100+ 语言
C-MTEB 中文榜单:6 类任务、35 个数据集(2023.9 论文),选中文模型主要看它
OpenAI text-embedding-3-large(3072 维,可指定降到 256 维)、small(1536)、ada-002
开源代表 阿里 GTE、智源 BGE / BGE-M3、E5、网易有道 BCE(需在其官网下载,不在 HF)

MTEB 支持自定义 encoder、任务与数据集(继承 AbsTaskReranking 等基类)并提交榜单。embedding 模型体积通常几个 G 即可,不必追最大。

六、Rerank 原理:两阶段检索(核心)

对比 Bi-encoder 双编码器 Cross-encoder 交叉编码器
编码方式 query 与文档各自独立编码成向量,再算相似度 query 与每篇文档拼在一起同时过 BERT 打分
能否预计算 文档向量可离线算好,查询时只编码 query 不能预计算,每对都要实时算
速度 / 精度 快、精度略低 慢、成本高,但精度高(上下文长度多为 512)
用途 建索引、粗召回、搜索 Rerank 精排,医疗/法律等高精度场景

标准两阶段: 第一阶段用 bi-encoder + ANN 从全库快速粗召回,把候选集放大到约 Top 30 (宁多勿漏);第二阶段用 cross-encoder 对这 30 篇逐一精排,取 Top 3 / 5。在 LlamaIndex 中用 SentenceTransformerRerank(如网易 BCE rerank base v1)作为 node_postprocessor,设 top_n=15,也可手动 postprocess_nodes。

python 复制代码
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
from llama_index.core.postprocessor import SentenceTransformerRerank
1. 构建向量索引(bi-encoder 粗召回)
documents = SimpleDirectoryReader("./data").load_data()
index = VectorStoreIndex.from_documents(documents)
2. 配置 cross-encoder 精排
reranker = SentenceTransformerRerank(
model="BAAI/bge-reranker-base",
top_n=5,
)
3. 查询:先粗召回 Top30,再精排取 Top5
query_engine = index.as_query_engine(
similarity_top_k=30,
node_postprocessors=[reranker],
)
response = query_engine.query("证券法对信息披露的要求是什么?")
print(response)

向量库能做到毫秒检索,靠的是 ANN(近似最近邻) 而非暴力扫描,主流是 HNSW(分层小世界导航图),千万级数据也能毫秒返回;其他还有 LSH、KD 树 / 球树等。

七、Rerank 微调与大模型重排

7.1 CrossEncoder 微调

  • 训练数据为 triplet:每条含一个 query、一个正例 positive、1~4 个负例 negative,JSONL 格式。

  • 用 CrossEncoder(num_labels=1)(输出一个相关性分)+ InputExample + InformationRetrievalEvaluator 训练评估。

  • **FlagEmbedding(微软):**数据字段缩写为 query / pos / neg,train_group_size = 1 个正例 + (group_size−1) 个负例。

  • 模型合并 LM-cocktail: 把基础模型与领域微调模型按权重(如各 0.5)混合,能有效缓解小数据微调带来的灾难性遗忘。

  • 用 AutoTrain 微调 rerank 时选 triplet 任务 + rerank 底模;评估沿用 C-MTEB 的 Reranking 任务。

7.2 用大模型重排(RankGPT)的三种策略

|-----------------|-----------------------------------------------------------------------------------------------------------------|
| Pointwise 点 | query 配单篇文档,让模型逐篇判断"相不相关 / 相关程度" |
| Listwise 列表 | 把文档列表整体交给模型排序(GPT-4 zero-shot 即可)。受上下文长度限制用滑动窗口:窗口 4、步长 2,每次保留最相关的 2 篇,再与未比较文档重排------经验上 Top2 较准、Top4 不一定准 |
| Pairwise 成对 | 每次给两篇文档,让模型比较哪篇更相关;LlamaIndex 提供 RankGPTRerank |

八、向量数据库与相似度度量

向量库存的是一维浮点数组(float16 / float32),并把原始数据一并保存。流程:embedding 生成 → 存储 → 建索引 → 相似度检索。

三种相似度度量

度量 公式 特点
欧几里得距离 √Σ(x₂−x₁)² 两点直线距离,考虑向量长度(模长)
余弦相似度 A·B / (|A|·|B|) 只看方向、对长度不敏感;范围 -1~1:1 同向、0 正交、-1 反向
点积 / 内积 A · B 未归一化、对长度敏感;>0 正相关、=0 正交、<0 负相关

常见索引类型

  • **FLAT:**暴力精确扫描,精度最高、最慢,适合小数据。

  • **IVF(倒排聚类):**先聚类再只搜最近的若干簇;变体 IVF_FLAT、IVFPQ(乘积量化压缩)。

  • **KD 树 / 球树:**用矩形 / 球形区域递归划分空间并剪枝。

  • **HNSW:**分层小世界图,性能与召回平衡好,工程主流。

  • LSH: 局部敏感哈希,相似向量落同桶;**PQ:**乘积量化压缩省空间。

九、相似性搜索算法:k-means

IVF 聚类的基础是 k-means,算法步骤:

  1. 随机选 K 个初始质心;

  2. 把每个点按欧式距离分配到最近质心所在簇;

  3. 重新计算每个簇的质心(簇内均值);

  4. 重复 2-3 直到质心收敛。

  • **缺点:**对 K 值和初始质心敏感、容易陷入局部最优。

  • **选 K ------ 肘部法则(Elbow):**随 K 增大,簇内误差平方和 SSE 下降,下降曲线的"拐点"即较理想的 K;也可用轮廓系数。

  • **初始化 ------ k-means++:**让各初始质心相互尽可能远(按距离平方做轮盘法概率选择下一个质心),显著改善局部最优。

  • **Kernel k-means:**用核函数把数据映射到高维空间,使原本线性不可分的数据变得可分,适合小规模复杂分布。

  • 工程技巧:用 numpy 广播 data[:, np.newaxis] 把 200×2 扩成 200×3×2,批量计算每个点到 3 个质心的距离。应用包括图像分割、文档聚类、客户细分。

十、向量数据库选型与代码

10.1 向量库 vs 向量数据库

向量库(库) 如 faiss、hnswlib、Annoy,偏静态索引:faiss 和 Annoy 只支持查询,hnswlib 支持增删改查(CRUD)、可视为精简版;向量数据库 在库之上还支持 CRUD、分片、复制、容错与分布式。分布式靠分片 (按向量相似性分区)+ 复制(多副本保可用)。

10.2 选型矩阵

方案 特点与适用
Qdrant(推荐) 可大可小、性能好、生态可;本地支持内存模式(:memory:)免起 server,生产用 Docker(端口 6333)
Milvus 功能全面、适合大规模分布式集群,但学习曲线较陡、偏重
Chroma 单机轻量、Windows 下无需 WSL/Docker,入门门槛最低,但只支持单机
Pinecone 闭源云服务、性能 OK,不能本地部署
Typesense / OpenSearch Typesense 用 C++ 编写,可作为 ES 替代;OpenSearch 支持向量
faiss / hnswlib / Annoy 嵌入式/离线场景;Annoy 适合小规模、内存受限环境
pgvector 需 PostgreSQL,支持约 2000 维;已用 PG 时最省事
ES / Mongo / ClickHouse / Redis ES 7.0 起支持 dense_vector + HNSW/ANN;Mongo Atlas 仅云;ClickHouse 偏 OLAP、向量能力仍实验阶段偏弱;Redis 用 redissearch 模块

选型原则: 专业向量库支持高达 6 万多维与丰富 ANN 索引;传统库一般只到约 2000 维、适合 10 万级向量的补充场景。向量是主角 → 专业向量库(可再配传统库);向量只是小补充 → 直接用 pgvector 等一个库搞定。基准可参考 Qdrant benchmark 与 ann-benchmarks。

10.4 三种相似度到底怎么选

向量库建索引时要选一种距离度量,新手常被这三个名词绕晕。其实抓住一个区别就够了:这个度量在不在意向量的长度。欧氏距离在意,它算的是两点之间的直线长度,向量越长离得越远。余弦相似度完全不在意长度,它只看两个向量指向的方向是不是一致,所以把一个向量拉长一倍,余弦相似度一点不变。点积介于两者之间,它既看方向也看长度。那到底用哪个?经验是:如果你在模型里已经把向量归一化过了(也就是每个向量都缩到同样长度),那点积和余弦其实等价,随便用;如果没归一化,而你又只想比较方向、不想让长文档占便宜,就用余弦。工程里余弦是最常见的默认选择。

10.5 向量库为什么能做到毫秒级

库里有几百万向量,用户一问要立刻返回最近的几个,靠的不是笨办法逐个算距离------那叫暴力扫描,几百万个算下来太慢了。真正的秘密是近似最近邻索引:它放弃了"必须找到绝对最近"这个执念,换成"花极小代价找到差不多最近的那几个"。主流的分层小世界图,原理有点像在城市里找路:它建了好几层路网,上层是稀少的高速公路负责快速跨越大范围,下层是密集的街道负责精确定位,查询时从高速层往下逐层靠近目标,几步就到了。这种结构在千万级数据上也能毫秒返回,代价是极小概率漏掉真正的最近邻,但实际业务里完全够用。

10.6 聚类为什么和向量检索有关

你可能纳闷,课程里为什么要单独讲一遍聚类。因为另一种常用索引思路,就是先拿聚类算法把几百万向量分成几百个簇,每个簇存一个代表中心。查询时不用扫全库,只要先找到离查询最近的几个簇中心,然后只在这几个簇内部细找就行了------一下子把搜索范围缩小了几十倍。这个把数据分成簇的算法,就是聚类。课程讲的怎么选簇的个数、怎么改进初始中心,都是为了让这个分簇既分得均匀又不浪费。理解了这点,你就把分散的几集串成了一条线:聚类是为索引服务的,索引是为快速检索服务的。

**选型再强调:**向量是你系统的主角,就上专业向量库;向量只是顺手加的小功能,别为它单独养一套新运维,直接在你已经用的数据库上加向量能力最省事。

10.3 代码示例

  • Chroma 原生 API: pip install chromadb,create client → get_or_create_collection → add(自动做 embedding、可带 metadata)→ query(支持 CRUD 与元数据过滤),JS/Python 均支持。

  • Qdrant: pip install qdrant-client,轻量可本地内存模式或指定路径,生产拉 Docker 镜像 run 端口 6333;create_collection 指定向量 size 与距离度量,create_index 指定 cosine / HNSW 参数,支持 upsert / query / delete,可从零实现 RAG(更灵活但代码量更大)。

  • Spring AI(Java 栈): 借鉴 LangChain/LlamaIndex,统一大模型接口、支持 Ollama、各向量库、嵌入模型、函数调用、多模态与 ETL;做简单 RAG 够用,但复杂优化力不从心。AI 核心仍建议 Python 技术栈------工具链、GPU 生态与最新算法最全。

十一、核心概念速查表

概念 一句话理解
embedding 把物体映射为低维稠密向量,语义相近则距离相近
CBOW / Skip-gram 上下文预测中心词 / 中心词预测上下文
MRR 平均倒数排名 Σ(1/rank)/查询数
MTEB / C-MTEB 国际 / 中文 embedding 权威榜单
bi / cross-encoder 独立编码算相似度(快、粗召回)/ 拼接编码打分(准、精排)
两阶段检索 双编码粗召回 Top30 → 交叉编码精排 Top3/5
triplet 锚点 + 正例 + 负例的重排训练样本
LM-cocktail 按权重合并基础与微调模型,缓解灾难性遗忘
三种相似度 欧氏距离(看长度)/ 余弦(看方向)/ 点积(未归一化)
HNSW / IVF 分层小世界图 / 倒排聚类,两类主流 ANN 索引
肘部法则 / k-means++ 选 K 的拐点法 / 改进初始质心避免局部最优

十二、学习打卡

  • 能说清 one-hot 与稠密 embedding 的区别,并举出 king-man+woman=queen 的含义

  • 能对比 CBOW 与 Skip-gram 的预测方向、输入处理与适用场景

  • 能描述 word2vec 网络结构(V→N→V、softmax、交叉熵)

  • 能用 LlamaIndex 生成 QA 对并微调一个 embedding,或用 AutoTrain 跑通 ST 任务

  • 能写出 MRR 公式并解释 hit_rate@k,知道选中文模型看 C-MTEB

  • 能清楚对比 bi-encoder 与 cross-encoder,并说出"粗召回 Top30→精排 Top5"流程

  • 能用 triplet 数据 + CrossEncoder 微调一个 rerank,知道 LM-cocktail 解决什么

  • 能区分 pointwise / listwise / pairwise 三种大模型重排及滑动窗口的作用

  • 能写出并区分欧氏距离、余弦相似度、点积,知道各自对长度是否敏感

  • 能说清 FLAT/IVF/HNSW/LSH/PQ 的取舍,以及 k-means、肘部法则、k-means++

  • 能根据"向量是否为主角"在 Qdrant/Milvus/Chroma/pgvector 间做出选型

  • 能用 Chroma 或 Qdrant 代码完成 add/query 的最小检索闭环

**学习建议:**本模块公式和概念密集,建议结合模块三一起学------先在 RAG 里看到"召回不准、排序不好"的现象,再回到本模块理解 embedding 与 rerank 如何决定上限。动手上至少完成三件事:① 用 Chroma 跑通最小向量检索;② 在 RAG 中加一个 cross-encoder rerank 对比前后效果;③ 用 C-MTEB 思路在自己的验证集上算一次 MRR/hit_rate。

十三、面试常考与实战补充

13.1 一道经典面试题:为什么粗召回和精排要分开

这道题几乎必问。标准答法是:因为快和准是一对矛盾。精排用的交叉编码虽然准,但它必须把问题和每篇文档拼在一起完整算一遍,没法提前离线算好,文档一多就慢到不可用;粗召回用的双编码可以把所有文档提前算好向量存着,查询时极快,但因为问题和文档是分开编码的、没充分交互,精度有限。所以工程上让双编码负责从全库快速捞一个不小的候选集,再让交叉编码从容地在小候选集里精挑。这样既不牺牲速度,又保住了精度。能把这个矛盾讲清楚,就说明你真懂了两阶段架构。

13.2 怎么判断要不要上重排

很多人问,是不是所有项目都得上重排。判断标准很简单:看你的业务对准确率的要求有多高。如果只是内部小工具、答案差点无所谓,那粗召回够用就行,重排的钱可以不花。但只要是面向客户、涉及法律医疗金融这类答错代价大的场景,重排几乎必上------它是性价比最高的一步,往往花一点推理成本,就能把准确率明显拉上去。课程里那句"重排必上",就是这个意思。

13.3 给动手党的三个最小练习

第一,用最轻量的向量库,把自己十几篇文档加进去、做一次查询,亲眼看到它返回了哪几篇、为什么是这几篇。第二,在你的问答系统里加一个现成的重排模型,只取前几条,对比加之前和之后,模型拿到的资料有没有变得更相关。第三,拿你最关心的那几个问题,手动数一数正确答案排在第几位,算一遍那个倒数排名指标。这三件事做下来,本模块那些看似抽象的向量、索引、重排,就全变成你手上摸得着的东西了。

十四、整个课程的收尾

到这里,四个模块就全部走完了。回头看这条学习线:模块一认识了平台长什么样、能做哪几类应用;模块二钻进代码,看一个带工具和记忆的智能体是怎么用图编排起来的;模块三搭起了一整条检索增强的业务链路;模块四则一路钻到底,把决定召回上限的向量、重排和向量库讲透了。从会拖拖拽拽搭应用,到懂它背后为什么这么设计,你完成的是一次从使用者到工程实践者的跨越。

这条路还很长,但你已经有了完整的骨架。剩下的,就是在你自己真实的项目里,把这套东西一遍一遍地跑、调、量。记住我们反复强调的那条铁律:没有评测就没有优化,每一次改动都用数据说话。祝你在大模型应用这条路上,走得稳、走得远。

**毕业寄语:**这门课教的所有工具都会过时,但"先跑基线、再建评测、一次改一处、用数据判断"的工程思维永远不会。带着它,去做你自己的下一个项目吧。

  • 我亲手跑通过一次最小向量检索闭环

  • 我在自己的系统上对比过加重排前后的效果差异

  • 我能向别人讲清楚为什么粗召回和精排要分成两步

十五、把底座讲得再透一点

15.1 向量到底是个什么东西

很多同学卡在"向量"这个词上,觉得它很玄。其实它一点不神秘。你可以把它想成一组数字,比如一串七百多个小数,每个小数代表文本在某个抽象维度上的得分。不同的词、不同的句子,就对应一串不同的得分。关键在于,这串得分不是人随便填的,而是模型从海量语料里自动学出来的,学得好的结果就是:意思越像的两段话,它们那串数字算出来的距离就越近。有了这串数字,"两段话像不像"这个模糊的问题,就变成了一个可以用计算器直接算出来的数学问题。这就是向量的全部意义------把语言变成数字,让计算机能算"语义"。

15.2 为什么中文要专门选中文模型

这是个特别实用的提醒。很多人图省事,随便下个网上很火的向量模型就用,结果中文效果怎么调都不理想。原因在于,一个模型对哪种语言学得好,取决于它主要拿什么语料训的。如果它绝大部分训练数据是英文,那它对英文句子的语义拿捏就准,但换成中文,它对中文里那些微妙的近义、反义、专业术语就钝了。所以做中文问答,一定要去看专门评测中文的那个权威榜单,挑榜上靠前的中文模型。这不是崇洋或者排外,而是一个朴素的道理:让一个专门学过中文的模型来读中文,才靠谱。课程实操里特意用中文向量模型,正是这个原因。

15.3 重排模型和粗排模型有什么本质区别

前面说了两阶段,这里再挖一层为什么交叉编码更准。区别在于,粗排模型在编码时,是把问题和文档各自单独处理完再碰头算个距离,问题和文档从头到尾没真正"照过面"。而精排的交叉编码,是把问题和候选文档缝在一起,同时送进模型,让模型在算这一对的时候,能同时看见两边的全部细节,反复权衡。你想,一个是分开看完再打个印象分,一个是把两份材料摆在一起逐条对照,哪个判断更准?显然是后者。代价就是后者慢得多,因为它每一对都得从头算一遍,没法提前准备。这就是为什么它只能用在几十个候选上,而不能用在全库上。

15.4 工程里那些"经验值"是怎么来的

课程里给了很多具体数字,比如粗召回取三十个、精排取前五、重排取十五个。你可能会问,为什么是三十不是五十。这些数字不是拍脑袋,而是大量工程实践攒出来的折中:取太少怕漏,取太多又把慢的精排拖垮、还可能带进噪声。实际项目里,这些数字都该你用自己的评测集去微调。课程给的是一个很好的起点,但不是金科玉律。理解这一点很重要:你学的不是一套死参数,而是一套"先粗后精、逐步收紧"的思想,参数要结合自己的数据定。

**提醒:**课程里的三十、前五这些数字是起点不是标准答案,到你自己的数据上,一定要用评测集重新校准。

十六、给学习者的落地心法

16.1 从"会用"到"懂为什么"的跨越

很多人学这类课程,最后停留在"我会在那个平台上点几下、把文档传上去、问答就出来了"。这当然有用,但在求职和真正做项目时,区分度恰恰来自那些"为什么"。为什么我的召回不准?是向量模型不懂我的术语,还是切分把句子切碎了?为什么加上重排后效果好这么多?因为它把问题和文档真正放一起对照了。你能把这些为什么讲清楚,就和只会点界面的人拉开了差距。这一模块的全部价值,就是帮你补齐这些为什么。

16.2 不要被名词吓住

这个模块名词特别多:双编码、交叉编码、分层小世界、倒排聚类、乘积量化、各种距离度量。第一次看确实头大。但你抓住一条主线就不慌了:所有这些名词,都在解决同一个矛盾------又要快、又要准、又要省地方。向量模型负责让"像不像"算得准;近似索引负责让"在几百万个里找最近"这件事变快;各种压缩手段负责让"存得下"这件事变省。你遇到任何一个新名词,先问它是在解决这三个问题里的哪一个,立刻就有了位置。

16.3 关于选型的真心话

面对那么多向量库,别纠结哪个"最好",没有最好,只有最合适。入门就用最轻量、本地能跑的那个,先把流程跑通,别在环境部署上耗掉所有热情。等你真的要扛生产数据了,再根据团队已经在用什么、数据量多大、要不要分布式这些现实问题来选。课程给的原则------向量是主角就上专业库,向量是点缀就复用已有数据库------足够你应对绝大多数情况了。

16.4 全课程最终回顾

五个分册,从一张学习地图开始,带你认识平台、写代码级智能体、搭检索链路、钻到检索最底层。如果现在让你用一句话总结这门课,那就是:大模型应用的工程落地,无外乎三件事------把流程编排好,把对的知识喂给模型,再用评测不断把它调得更好。工具会换,框架会升级,但这三件事的逻辑不变。愿你带着这份骨架,在自己的项目里长出真正的本事。

**最终寄语:**笔记合起来,动手开始吧。跑通第一个系统的那一刻,你就会发现,这门课讲的一切都活了过来。

  • 我能一句话说清向量为什么能表示语义

  • 我知道中文场景为什么必须优先选中文向量模型

  • 我不再被双编码、交叉编码这些名词吓住,能说出各自解决什么矛盾

十七、常见疑问与答疑

17.1 我一定要学会训练模型吗

不一定。这是很多转行者的共同焦虑。课程带你手写一遍词向量、走一遍微调流程,目的是让你理解这些东西是怎么回事,不是要求你以后天天自己训模型。实际做项目时,九成的情况是:选一个现成的、在权威榜单上评测过的成熟模型直接用。你真正要掌握的,是会判断"什么时候现成的够用、什么时候不够用了该微调",以及微调之后怎么科学地验证效果。会调用、会选型、会评估,比会从零训练重要得多。别被"训练"两个字吓到,那是这一行里相对小众、也最烧钱的环节。

17.2 向量维度是不是越高越好

不是。维度高,理论上能编码更丰富的语义,但代价是存得更占地方、算得更慢,而且维度高到一定程度后,收益递减甚至反而因为噪声变多而变差。课程里也提到,有些服务甚至允许你把一个很高维的向量压缩到很低维,效果损失却很小。所以实践中,选什么维度主要看模型本身和你数据的特点,不是一味求大。和选模型一样,在自己的验证集上比一比,比看理论靠谱。

17.3 召回和精排,哪个更该先优化

如果两个只能保一个,先保粗召回的"全"。为什么?因为粗召回是第一道门,它要是把真正相关的文档一开始就漏掉了,后面精排再厉害也无米下锅。所以工程上粗召回宁可多捞一点、把阈值放宽,宁可让精排多处理几条,也不能在第一道门就把答案挡在外面。当然,粗召回也不是越宽越好,太宽会带进大量噪声、压垮精排。这个"宽到什么程度",同样要靠评测集去试。记住顺序:先保证不漏,再追求精准。

17.4 这套底座和大模型是什么关系

很多人会混淆:既然大模型这么强,为什么还要单独搞一套向量检索?因为大模型本身记不住你公司那堆私有文档,也不知道你昨天才更新的资料。向量检索这套底座,就是给大模型外接了一个"随取随用的知识库"。大模型负责理解和组织语言,向量底座负责快速把相关资料找出来递过去。两者是配合关系:底座决定了模型"能看到什么资料",模型决定了它"怎么用好这些资料"。底座差,模型再有本事也是巧妇难为无米之炊。这就是本模块反复强调"底座决定上限"的原因。

**答疑小结:**不用人人都去训模型;维度不是越高越好;先保粗召回不漏再谈精排;底座是给大模型外接知识库的。

十八、终章

至此,五本笔记全部完成。你已经从一个只听说过大模型的人,成长为能搭应用、懂智能体编排、会建检索链路、还明白向量与重排底层原理的实践者。这条路没有终点,但你已经握住了最关键的那张地图。接下来,去做你自己的项目,让这些知识在真实问题里生根发芽吧。

  • 我不再害怕训练相关的概念,知道自己现阶段该掌握到什么程度

  • 我理解了粗召回先保全、精排再求精的优化顺序

十九、写给坚持到这里的你

能把这五个分册一路学下来,本身就说明你有足够的耐心和定力。这类底层技术内容不轻松,概念密、公式多、还容易串。但你回头看,会发现它们其实非常成体系:从最上面怎么搭一个应用,到中间怎么编排一个会自己思考的智能体,再到怎么把企业的私有知识接进来,最后一路钻到最底层、看清楚向量和重排到底在算什么。这条线是完整的,每一环都咬着下一环。当你把最底层弄懂了,再回头看最上层那些平台按钮,心里就有底了------你知道每一个按钮背后,跑的是什么。

19.1 接下来该做什么

别急着马上学下一个新潮工具。趁现在记忆还新,挑一个你工作或学习里真实存在的小问题,用这门课学的东西,从头到尾做一个能用的小系统。比如把你手头一堆零散的文档,做成一个能问答的小助手。这个过程中你会真实地遇到切分怎么切、召回怎么调、重排加不加这些问题------而这些,正是本笔记反复强调的东西。做出来那一刻,你对这门课的理解会再上一个台阶。

19.2 记住最重要的那句话

整门课如果只让你带走一句话,那就是:没有评测,就没有优化。很多人调系统全凭感觉,今天换个模型、明天改个参数,效果时好时坏却不知道为什么。真正的工程师,是先攒一小批标准问题,每次改动都跑一遍、用数字说话。这个习惯,比记住任何一个具体模型名字都值钱。它会陪着你走完以后所有的技术生涯。

**最后的话:**技术会一直更新,但会学习、会动手、会用数据验证的人,永远不会被淘汰。祝你学有所成。

  • 我已经开始动手做自己的第一个小系统

  • 我把"先建评测集再优化"这条习惯记在了心里

二十、最后的小叮咛

读到这里,你已经把整个课程的笔记翻到了最后。这里没有新的知识点,只有几句想留给你的话。第一,别贪多。这门课信息量很大,与其试图一次全记住,不如把它当成一本工具书,做项目时遇到对应问题再回来查。第二,别轻视动手。看十遍不如亲手跑一遍,哪怕只是把别人的示例代码改两行、换份自己的文档跑通,收获也远大于纯看。第三,保持怀疑精神。笔记里写的一切参数、一切建议,都是某种情境下的经验,到了你自己的数据上,都要重新验证。真正的高手不是记住最多结论的人,而是知道每个结论背后有什么前提、什么时候会失效的人。

祝你在这条路上,既能抬头看清方向,也能低头把每一行代码、每一次检索、每一个指标都调扎实。我们更高处再见。

**本笔记正式结束。**愿你把它真正用起来,而不只是收藏起来。

二十一、结课祝福

五个分册,到这一册真的要合上了。回头望,你从这门课里带走的,不该只是几个名词、几行代码,而是一套看问题的方式:面对一个大模型应用,你会下意识地去拆它的流程、看它的知识从哪来、判断它有没有可量化的好坏标准。这种结构化的眼光,比任何一个具体工具都更能陪你走得远。

技术迭代很快,今天热门的框架明年可能就换了,但你学会的这套拆解、动手、验证的方法,会一直管用。大胆去用,勇敢去试,遇到问题就回来翻这本笔记。祝你学习顺利,早日做出让自己骄傲的作品。我们下门课再见。

**全系列完。**感谢你一路坚持到这里。

愿你在大模型应用这条路上,走得坚定、做得扎实,把每一个想法都变成真正能用的产品。坚持动手,保持好奇,用数据验证每一次优化。我们更高处相逢。

这册笔记的每一段,都是为了帮你把模糊的概念变成手上能用的本事。愿你多读多练,早日做出属于自己的作品。

全系列到此正式结束,祝你学习顺利、项目落地顺利,早日做出属于自己的优秀作品。

二十二、总结与参考资料

把整个模块收束成一句话:检索的上限由底座决定,而底座由向量模型、重排模型和向量库三块拼成。向量模型负责把文本变成可计算语义的稠密向量,重排模型负责在候选集里做精细判断,向量库负责在千万级数据上把"找最近"这件事做到毫秒级。三者各司其职,缺一不可。

22.1 核心要点回顾

  • **Embedding:**从 one-hot 到稠密向量,语义相近则距离相近;word2vec 的 CBOW 与 Skip-gram 是理解"向量为什么能表语义"的起点,但工程上直接用成熟预训练模型,只在领域术语理解不足时才考虑微调。
  • **微调与评估:**LlamaIndex 自动生成问答对、AutoTrain 走 ST 任务,两条路都能落地;评估必须用未参与训练的验证集,看 hit_rate@k 与 MRR,选中文模型优先参考 C-MTEB。
  • **Rerank:**双编码粗召回(Top 30 左右,宁多勿漏)+ 交叉编码精排(Top 3/5),是快与准这对矛盾的工程解法;CrossEncoder 用 triplet 数据微调,大模型重排可用 pointwise / pairwise / listwise 三种策略。
  • **向量库:**三种相似度度量抓住"在不在意向量长度"这一个区别即可;ANN 索引(HNSW、IVF、LSH、PQ)用近似换速度;选型原则是"向量是主角就上专业库,向量是点缀就复用已有数据库"。
  • **工程心法:**没有评测就没有优化;先保粗召回不漏,再谈精排求准;课程里的三十、前五这些数字是起点,不是标准答案。

22.2 官方文档与权威榜单

资源 链接 用途
LlamaIndex 官方文档 docs.llamaindex.ai 索引构建、微调引擎、node postprocessor 重排的完整 API
Sentence Transformers 文档 sbert.net 双编码 / 交叉编码模型训练、评估与 CrossEncoder 用法
HuggingFace AutoTrain huggingface.co/docs/autotrain 无代码微调 ST 任务、数据格式与参数说明
MTEB 榜单 MTEB Leaderboard 国际 embedding 模型横向对比,按任务类型筛选
C-MTEB 中文榜单 C-MTEB Leaderboard 中文场景选模型的第一参考
BGE 模型与 FlagEmbedding github.com/FlagOpen/FlagEmbedding BGE / BGE-M3 / BCE 系列 embedding 与 reranker 的官方实现
Qdrant 文档 qdrant.tech/documentation 集合创建、距离度量、HNSW 参数与过滤查询
Chroma 文档 docs.trychroma.com 轻量本地向量库的快速上手与 CRUD
Milvus 文档 milvus.io/docs 大规模分布式向量检索、索引类型与部署方案
Faiss Faiss Wiki 各类 ANN 索引原理与选型指南,理解底层机制的最佳读物
ann-benchmarks ann-benchmarks.com 主流 ANN 算法在召回率与吞吐上的横向基准

22.3 推荐阅读资料

  • **word2vec 原始论文:**Mikolov 等《Efficient Estimation of Word Representations in Vector Space》(2013)与《Distributed Representations of Words and Phrases and their Compositionality》(2013),CBOW 与 Skip-gram 的出处,篇幅不长,值得通读。
  • **Sentence-BERT:**Reimers 与 Gurevych《Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks》(2019),双编码器做语义相似度的奠基工作,也是理解 bi-encoder 与 cross-encoder 分工的必读。
  • **MTEB 论文:**Muennighoff 等《MTEB: Massive Text Embedding Benchmark》(2022),讲清 8 类任务、56 个数据集的评测设计,读完就知道榜单分数该怎么看。
  • **C-MTEB 论文:**Xiao 等《C-Pack: Packed Resources For General Chinese Embeddings》(2023),中文 embedding 评测体系与 BGE 系列的来源。
  • **HNSW 论文:**Malkov 与 Yashunin《Efficient and robust approximate nearest neighbor search using Hierarchical Navigable Small World graphs》,分层小世界图的原理与参数含义。
  • **RankGPT:**Sun 等《Is ChatGPT Good at Search? Investigating Large Language Models as Re-Ranking Agents》(2023),listwise 重排与滑动窗口策略的原始出处。
  • **LM-cocktail:**Xiao 等《LM-Cocktail: Resilient Tuning of Language Models via Model Merging》(2023),理解模型合并如何缓解灾难性遗忘。
  • **RAG 综述:**Gao 等《Retrieval-Augmented Generation for Large Language Models: A Survey》(2023),把检索、增强、生成三段串成完整图景,适合作为本模块的上层索引。

22.4 下一步的实践建议

  1. 用 Chroma 或 Qdrant 搭一个最小检索闭环,把十几篇自己的文档灌进去,观察返回结果与相似度分数。
  2. 在同一份数据上叠加一个现成的 cross-encoder reranker,用 hit_rate@5 与 MRR 对比加与不加的差异。
  3. 把评测集固定下来(二三十个真实问题即可),之后每次换模型、调参数都跑一遍,用数字判断改动是否有效。
  4. 只有当通用中文模型在你的领域明显不够用时,才走 LlamaIndex 或 AutoTrain 的微调路线,并用独立验证集验收。

**结语:**工具会换,榜单会变,但"先跑基线、再建评测、一次改一处、用数据判断"这套方法不会过时。把这份参考资料当成你的工具箱,遇到具体问题时按图索骥,比一次性读完更有价值。

相关推荐
ljt27249606611 小时前
Python笔记(十一)--Numpy(一)
笔记·python·numpy
芯思路1 小时前
STM32开发学习笔记之十【AI部署】
笔记·stm32·学习
憧憬成为java架构高手的小白2 小时前
langgraph4j学习
学习
江屿风2 小时前
【Plain Language Large Model】【从浏览器到全栈:一课精通Node.js三剑客】流食般投喂
笔记·前端框架·npm·node.js·js·npx
CCIE-Yasuo2 小时前
网络安全-学习web开发-列表、标签
前端·学习·web安全
一只大鸽子2 小时前
游戏开发笔记0-Godot启动
笔记·游戏引擎·godot
旖旎夜光2 小时前
LeetCode 315: 算右侧小于当前元素的个数(归并排序) —— 题解
c++·学习·算法·leetcode·排序算法
Nuanyt3 小时前
LeetCode Hot 100 链表专题2 3 题 (Java)
java·笔记·算法·leetcode·链表
asaotomo3 小时前
截图识题、AI 讲解、笔记沉淀:Chrome 扩展体验
前端·chrome·笔记