目录
- 一、什么是向量嵌入
- 二、嵌入的三种基本类型
- 三、本项目涉及的嵌入模型
- 四、嵌入模型对比总览
- 五、关键概念总结
- 六、词向量嵌入技术发展历史
- 七、关键词匹配 vs 语义嵌入
- 八、余弦相似度与欧氏距离的区别
- 九、维度选择的权衡
- 十、模型选型补充
- 十一、常见误解
- 十二、实战问题与解决方案
- 十三、面试题库
一、什么是向量嵌入
向量嵌入是将文本、图片等非结构化数据转换为固定长度的数值向量的过程。嵌入后的向量在高维空间中保留了原始数据的语义信息——语义相近的内容,其向量距离也更近。
"猢狲施展烈焰拳" → [0.023, -0.117, 0.089, ..., 0.041] (1536维)
"猴子使用火拳攻击" → [0.019, -0.108, 0.092, ..., 0.038] (1536维)
↑ 语义相近 → 向量距离近
在 RAG 流水线中,嵌入是连接"文本切块"和"向量检索"的关键桥梁:
原始文档 → 文本切块 → 【向量嵌入】→ 存入向量数据库 → 检索 → LLM 生成回答
二、嵌入的三种基本类型
2.1 密集嵌入(Dense Embedding)
- 原理:将文本压缩为固定长度的稠密实数向量(如 768 维、1024 维、1536 维)
- 特点:每一维都有非零值,信息高度压缩,适合语义相似度计算
- 代表模型:OpenAI
text-embedding-3-small、Jinajina-embeddings-v3、BGE 系列 - 相似度计算:余弦相似度(Cosine Similarity)
# 余弦相似度公式
cosine_similarity(A, B) = (A · B) / (||A|| × ||B||)
# 值域 [-1, 1],越接近 1 表示越相似
2.2 稀疏嵌入(Sparse Embedding)
- 原理:基于词频统计生成高维但大部分维度为零的向量
- 特点:保留了精确的词汇匹配能力,对关键词检索友好
- 代表算法:BM25(TF-IDF 的改进版本)
- BM25 核心公式:
BM25(q, d) = Σ IDF(qi) × (f(qi, d) × (k1 + 1)) / (f(qi, d) + k1 × (1 - b + b × |d| / avgdl))
参数说明:
f(qi, d) — 词 qi 在文档 d 中的词频(TF)
|d| — 文档 d 的长度
avgdl — 所有文档的平均长度
k1 — 词频饱和参数(通常 1.2~2.0),控制词频增长对分数的影响上限
b — 文档长度归一化参数(通常 0.75),b=0 忽略长度,b=1 完全归一化
IDF(qi) — 逆文档频率,衡量词的稀有程度
2.3 多向量嵌入(Multi-Vector Embedding / ColBERT)
- 原理:为文本中的每个 Token 都生成一个向量,而不是将整段文本压缩为单个向量
- 特点:保留 Token 级别的细粒度语义信息,检索精度更高
- 代表模型:BGE-M3 的 ColBERT 模式
密集嵌入: "猢狲施展烈焰拳" → [1个向量] (整体语义)
多向量嵌入:"猢狲施展烈焰拳" → [5个向量] (每个 Token 一个)
↑ 猢狲 ↑ 施展 ↑ 烈焰 ↑ 拳
三、本项目涉及的嵌入模型
3.1 OpenAI Embedding — 推荐系统应用
📄 对应代码:
01-openai-embedding-recomendation-system.py
模型:text-embedding-3-small(1536 维)
应用场景:游戏推荐系统
核心流程:
1. 获取每个游戏的描述文本 → 调用 OpenAI API 生成嵌入向量
2. 对每个用户:将其评价过的所有游戏的嵌入向量 → 取平均值 → 作为用户偏好向量
3. 计算用户偏好向量与目标游戏向量的余弦相似度
4. 按相似度排序 → 推荐最可能喜欢该游戏的用户
关键代码模式:
# 获取嵌入
response = openai.embeddings.create(input=[text], model="text-embedding-3-small")
embedding = response.data[0].embedding
# 用户画像 = 历史偏好的平均向量
user_vector = np.mean(user_game_vectors, axis=0)
# 相似度计算
similarity = cosine_similarity(user_vector.reshape(1, -1), target_vector.reshape(1, -1))
要点:用嵌入向量的平均值作为用户画像,是一种简单但有效的协同过滤替代方案。
3.2 Jina Embeddings v3 — 聚类分析应用
📄 对应代码:
02-jina-embeddings-v3-clustering.py
模型:jina-embeddings-v3(支持 1024 维,可调)
应用场景:游戏描述文本聚类
核心流程:
1. 批量获取游戏描述的嵌入向量
2. 使用 KMeans 进行聚类(K=3)
3. 同一簇内的游戏语义相近
Jina v3 的特色参数:
{
"model": "jina-embeddings-v3",
"task": "text-matching", # 任务类型:文本匹配
"dimensions": 1024, # 输出维度可调
"normalized": True, # 自动归一化(L2 范数 = 1)
"input": texts # 支持批量输入
}
| 参数 | 说明 |
|---|---|
task | 可选 text-matching、classification、retrieval.query、retrieval.passage 等,针对不同任务优化 |
dimensions | 支持降维(Matryoshka 套娃表示),灵活权衡精度与存储 |
normalized | 归一化后余弦相似度 = 点积,计算更快 |
要点:Jina v3 支持任务感知嵌入——同一个模型,指定不同 task 会生成针对该任务优化的向量。
3.3 BM25 — 稀疏检索(手写实现)
📄 对应代码:
03-BM25.py
模型:BM25(从零手写实现,不依赖外部库)
核心流程:
1. 分词 → 构建词表
2. 计算 IDF(逆文档频率):衡量词的稀有程度
3. 对每条文本计算 TF(词频)
4. 代入 BM25 公式生成稀疏嵌入(只保留非零维度的字典表示)
稀疏嵌入的特点:
# 稀疏嵌入用字典存储,key=词表索引,value=BM25 分数
sparse_embedding = {
0: 1.234, # "猢狲" 的 BM25 分数
5: 0.891, # "烈焰拳" 的 BM25 分数
12: 0.567, # "妖怪" 的 BM25 分数
# 其余几千维全是 0,不存储
}
要点:BM25 是稀疏嵌入的经典算法,无需神经网络,纯统计方法,计算极快,精确匹配能力强。
3.4 LangChain BM25 + Chroma — 混合检索
📄 对应代码:
03-LangChain-BM25.py
核心思想:将 BM25(稀疏检索)与向量检索(密集检索)结合,互补各自短板。
查询:"猢狲有什么装备和招数?"
│
┌───────────┴───────────┐
▼ ▼
BM25 检索 Chroma 向量检索
(关键词匹配) (语义匹配)
│ │
│ 找到:"猢狲身披锁子甲" │ 找到:"猢狲使用铜云棒抵挡"
│ ("装备"关键词命中) │ (语义相近,但缺关键词)
│ │
└───────────┬───────────┘
▼
混合检索结果(去重合并)
▼
LLM 生成回答
关键代码:
# 稀疏检索
bm25_retriever = BM25Retriever.from_texts(battle_logs)
bm25_response = bm25_retriever.invoke(request)
# 密集检索
chroma_vs = Chroma.from_documents(docs, embedding=OpenAIEmbeddings())
chroma_response = chroma_vs.as_retriever().invoke(request)
# 混合 = 简单去重合并
hybrid_response = list({doc.page_content for doc in bm25_response + chroma_response})
| 检索方式 | 能找到 | 可能漏掉 |
|---|---|---|
| BM25 稀疏检索 | 包含查询关键词的文档 | 语义相关但用词不同的文档 |
| 向量密集检索 | 语义相关的文档 | 关键词精确匹配但语义距离远的文档 |
| 混合检索 | 两者都能找到 | — |
要点:混合检索是 RAG 工程实践中的最佳实践,兼顾精确匹配和语义理解。
3.5 BGE-M3 — 多功能嵌入模型
📄 对应代码:
04-BGE-M3.py
模型:BAAI/bge-m3(BAAI 北京智源人工智能研究院出品)
三大能力(M3 = Multi-lingual, Multi-granularity, Multi-Function):
passage_embeddings = model.encode(
passage,
return_sparse=True, # 稀疏嵌入(类 BM25)
return_dense=True, # 密集嵌入(传统向量)
return_colbert_vecs=True # 多向量嵌入(ColBERT,Token 级别)
)
| 输出类型 | 维度 | 用途 |
|---|---|---|
dense_vecs | (1024,) | 整体语义相似度 |
lexical_weights | {词索引: 权重} | 精确词匹配(稀疏) |
colbert_vecs | (seq_len, 1024) | Token 级别精细匹配 |
BGE-M3 的核心价值:一个模型同时输出三种嵌入,天然支持混合检索,无需分别部署 BM25 + 密集嵌入两个系统。
BGE-M3 一个模型 → 同时产出:
├─ 密集向量 → 语义检索
├─ 稀疏向量 → 关键词检索
└─ ColBERT 多向量 → 精细匹配
3.6 Visualized-BGE — 多模态嵌入
📄 对应代码:
05-多模态嵌入.py
模型:BAAI/bge-visualized(基于 BGE 的视觉扩展)
核心能力:将图片编码为与文本同一向量空间的嵌入向量。
model = Visualized_BGE(model_name_bge="BAAI/bge-base-en-v1.5", model_weight=model_path)
# 纯图片嵌入
image_embedding = model.encode(image=image_path)
# 图片+文本联合嵌入
multimodal_embedding = model.encode(image=image_path, text="这是一张悟空战斗示例图片")
多模态嵌入的意义:
传统 RAG:只能处理文本
多模态 RAG:可以跨模态检索
"孙悟空的战斗画面"(文本查询)
↓ 余弦相似度
[图片A的向量] → 0.92 ✅ 高度匹配
[图片B的向量] → 0.31 ❌ 不相关
四、嵌入模型对比总览
| 模型 | 嵌入类型 | 维度 | 部署方式 | 特色 |
|---|---|---|---|---|
OpenAI text-embedding-3-small | 密集 | 1536 | API 调用 | 稳定可靠,适合通用场景 |
Jina jina-embeddings-v3 | 密集 | 可调(最高 1024) | API 调用 | 任务感知,维度可调 |
| BM25 | 稀疏 | 词表大小 | 本地计算 | 无需模型,精确匹配 |
| BGE-M3 | 密集 + 稀疏 + ColBERT | 1024 | 本地模型 | 一个模型三种嵌入 |
| Visualized-BGE | 多模态密集 | 768 | 本地模型 | 支持图片编码 |
五、关键概念总结
5.1 稠密 vs 稀疏 vs 多向量
| 特性 | 密集嵌入 | 稀疏嵌入 | 多向量嵌入(ColBERT) |
|---|---|---|---|
| 向量形式 | 每维非零 | 大部分为零 | 多个向量 |
| 存储开销 | 中 | 低(只存非零) | 高 |
| 语义理解 | ✅ 强 | ❌ 弱 | ✅ 最强 |
| 精确匹配 | ❌ 弱 | ✅ 强 | ✅ 强 |
| 计算速度 | 快 | 快 | 较慢 |
| 代表 | OpenAI Embedding | BM25 | ColBERT / BGE-M3 |
5.2 检索策略选择
只需要语义搜索?
└─ 是 → 密集嵌入(OpenAI / Jina)
└─ 否 → 需要关键词精确匹配?
└─ 是 → 稀疏嵌入(BM25)
└─ 否 → 需要同时兼顾?
└─ 是 → 混合检索
├─ 方案A:BM25 + 密集嵌入(两套系统)
└─ 方案B:BGE-M3(一个模型搞定)
└─ 否 → 需要跨模态?
└─ 是 → 多模态嵌入(Visualized-BGE)
5.3 实践建议
- 起步阶段:用 OpenAI Embedding + Chroma 快速搭建原型
- 优化检索:引入 BM25 做混合检索,显著提升召回率
- 进阶部署:用 BGE-M3 替代分离的 BM25 + 密集嵌入方案,一个模型统一管理
- 多模态需求:涉及图片/表格检索时,使用 Visualized-BGE 等多模态模型
- 降本策略:Jina v3 的可调维度 + 任务感知能力,可以在精度和成本间灵活权衡
六、词向量嵌入技术发展历史
时间线总览
1950s 1970s 2013 2014 2016 2018 2019 2022 2023+
│ │ │ │ │ │ │ │ │
One-Hot TF-IDF Word2Vec GloVe FastText ELMo Sentence OpenAI BGE-M3
CBOW 全局共现 子词 BERT -BERT Embedding 多模态
Skip-Gram 矩阵分解 n-gram GPT v3 嵌入
6.1 第一阶段:离散表示(1950s — 2000s)
One-Hot 编码
最早的词表示方法,每个词对应词表中唯一的一个位置:
词表 = ["猢狲", "施展", "烈焰拳", "妖怪"]
"猢狲" → [1, 0, 0, 0]
"施展" → [0, 1, 0, 0]
"烈焰拳"→ [0, 0, 1, 0]
"妖怪" → [0, 0, 0, 1]
致命缺陷:
- 维度灾难:词表多大,向量就多长(几万到几十万维)
- 完全稀疏:只有一个 1,其余全 0
- 无语义信息:任意两个词的"距离"完全相同,"猢狲"和"妖怪"的距离 = "猢狲"和"施展"的距离
TF-IDF(1972)
在 One-Hot 基础上引入了统计权重:
TF-IDF(t, d) = TF(t, d) × IDF(t)
TF(词频):词 t 在文档 d 中出现的频率
IDF(逆文档频率):log(总文档数 / 包含词 t 的文档数)
→ 高频常见词("的"、"是")权重低
→ 稀有但信息量大的词("烈焰拳")权重高
进步:区分了词的重要性
局限:仍然是稀疏向量,词与词之间没有语义关系
TF-IDF 的改进版 BM25(1980s-1990s)加入了文档长度归一化和词频饱和机制,成为稀疏检索的黄金标准,至今仍是搜索引擎的基石。本项目中 03-BM25.py 就是用它实现的。
6.2 第二阶段:静态词向量(2013 — 2017)
Word2Vec(2013)
里程碑事件:Mikolov 等人在 Google 发表论文,证明用简单的神经网络可以从海量文本中学习到有意义的词向量。
两种训练架构:
CBOW(连续词袋模型):上下文 → 预测中心词
输入:"猢狲" "施展" [?] "击退" "妖怪"
输出:预测 [?] = "烈焰拳"
Skip-Gram(跳字模型):中心词 → 预测上下文
输入:"烈焰拳"
输出:预测周围可能出现 "猢狲" "施展" "击退" "妖怪"
核心思想:上下文相似的词,语义也相似(分布假设/Distributional Hypothesis)
经典成果——词向量代数运算:
king - man + woman ≈ queen
巴黎 - 法国 + 中国 ≈ 北京
局限:
- 一词一向量:无法区分多义词。"苹果"无论是水果还是公司,都是同一个向量
- 窗口太小:只看局部上下文(通常 ±5 个词),缺少全局信息
GloVe(2014)
Stanford 的 Pennington 等人提出,结合了全局统计和局部上下文。
Word2Vec:基于局部上下文窗口 → 只看"邻居"
GloVe: 基于全局共现矩阵 → 看所有文档中的共现统计
核心公式:w_i · w_j + b_i + b_j = log(X_ij)
w_i, w_j:词 i 和词 j 的向量
X_ij:词 i 和词 j 在语料库中共现的次数
优势:利用了全局统计信息,训练更快,在小语料上效果更好。
FastText(2016)
Facebook 的 Joulin 等人提出,在 Word2Vec 基础上引入**子词(subword)**表示。
Word2Vec: "烈焰拳" → 1 个向量(整词)
FastText: "烈焰拳" → "烈" + "焰" + "拳" → 3 个子词向量的和
优势:
1. 能处理未登录词(OOV):"火焰拳" 没见过,但 "火"+"焰"+"拳" 都见过
2. 天然适合形态丰富的语言(德语、土耳其语等)
3. 对中文也有效——汉字本身就是有意义的子词单元
Word2Vec / GloVe / FastText 三者统称为静态词向量(Static Embedding),它们的特点是:训练完成后,每个词的向量就固定不变了。
6.3 第三阶段:上下文词向量(2018)
ELMo(2018.02)
Allen AI 的 Peters 等人提出,首次实现了一词多义的动态表示。
静态词向量:
"苹果" 永远是 [0.23, -0.11, ...]
无论上下文是 "吃了一个苹果" 还是 "苹果发布了新手机"
ELMo:
"吃了一个 苹果" → "苹果" 的向量 = [0.15, 0.32, ...] ← 偏向食物语义
"苹果 发布新手机" → "苹果" 的向量 = [0.41, -0.08, ...] ← 偏向公司语义
原理:双向 LSTM,根据整个句子的上下文动态生成词向量
突破:同一个词在不同语境下有不同的向量表示。
BERT(2018.10)
Google 的 Devlin 等人发表,彻底改变了 NLP 领域。
ELMo:双向 LSTM → 串行处理,速度慢
BERT:双向 Transformer → 并行处理,效果好
预训练任务:
1. MLM(掩码语言模型):随机遮住 15% 的词,让模型预测
输入:"猢狲施展 [MASK] 击退妖怪"
目标:预测 [MASK] = "烈焰拳"
2. NSP(下一句预测):判断两个句子是否相邻
如何从 BERT 中提取嵌入:
方法1:取 [CLS] token 的向量作为整个句子的表示
方法2:取所有 token 向量的平均值作为句子表示
问题:BERT 的句子嵌入质量并不好(各向异性问题,向量分布在高维空间的狭窄锥形区域)
GPT 系列(2018 — 至今)
GPT-1 (2018) → GPT-2 (2019) → GPT-3 (2020) → ChatGPT (2022) → GPT-4 (2023)
与 BERT 的区别:
BERT:双向编码器 → 理解语言(适合分类、检索、嵌入)
GPT: 单向解码器 → 生成语言(适合对话、写作、推理)
注意:GPT 系列本身是生成模型,不是嵌入模型。但 OpenAI 后来基于类似的 Transformer 架构推出了专门的嵌入模型(text-embedding-ada-002、text-embedding-3-small 等)。
6.4 第四阶段:句子/文档嵌入(2019 — 2021)
Sentence-BERT(2019)
专门解决 BERT 句子嵌入质量差的问题。
BERT 原始方案:
句子A → BERT → 向量A
句子B → BERT → 向量B
计算相似度
问题:需要在 GPU 上跑 BERT,且效果不如简单的 GloVe 平均
Sentence-BERT:
用孪生网络(Siamese Network)对 BERT 做微调
训练目标:让相似句子的向量靠近,不相似的远离
"猢狲施展烈焰拳" → SBERT → [0.23, -0.11, ...] ← 高质量的句子向量
"猴子使用火拳攻击" → SBERT → [0.21, -0.09, ...] ← 语义相近,向量也近
SimCSE(2021)
Stanford 提出,用**对比学习(Contrastive Learning)**进一步提升句子嵌入质量。
核心思想:同一个句子经过两次 Dropout,生成两个"正样本"
"猢狲施展烈焰拳" → Encoder(Dropout¹) → 向量 v1
"猢狲施展烈焰拳" → Encoder(Dropout²) → 向量 v2
训练目标:拉近距离 (v1, v2),推远距离 (v1, 其他句子的向量)
无监督、不需要标注数据!
6.5 第五阶段:现代嵌入模型(2022 — 至今)
OpenAI Embedding(2022)
text-embedding-ada-002 (2022) — 1536 维,统一文本搜索、代码搜索、相似度
text-embedding-3-small (2024) — 1536 维,性能提升
text-embedding-3-large (2024) — 3072 维,支持可调维度(Matryoshka)
本项目 01-openai-embedding-recomendation-system.py 使用的就是
text-embedding-3-small。
BGE 系列(2023 — 2024)
北京智源人工智能研究院(BAAI)出品,开源嵌入模型的标杆。
BGE-base-en-v1.5 (2023) — 英文,768 维
BGE-large-zh-v1.5 (2023) — 中文,1024 维
BGE-M3 (2024) — 多语言 + 多功能(密集 + 稀疏 + ColBERT)
Visualized-BGE (2024) — 多模态(图片 + 文本)
BGE-M3 在本项目 04-BGE-M3.py 中演示,同时输出三种嵌入。Visualized-BGE 在 05-多模态嵌入.py 中演示图片编码。
Jina Embeddings v3(2024)
特色:
├─ 任务感知(Task-Aware):指定 retrieval.query / retrieval.passage / text-matching 等
├─ 可调维度(Matryoshka Representation):128/256/512/1024 自由选择
├─ 8192 token 长文本支持
└─ 多语言
本项目 02-jina-embeddings-v3-clustering.py 演示了 Jina v3 用于文本聚类。
6.6 演进脉络总结
离散表示 静态词向量 上下文词向量 现代嵌入模型
─────────────────────────────────────────────────────────────────────────────────────────
One-Hot (1950s) OpenAI Embedding (2022)
↓ Word2Vec (2013) BGE 系列 (2023)
TF-IDF (1972) ↓ Jina v3 (2024)
↓ 没有语义 → GloVe (2014) ELMo (2018.02) 多模态嵌入
BM25 (1990s) ↓ ↓
↓ FastText (2016) BERT (2018.10) 核心进步:
稀疏 ─────────────→ 静态,一词一向量 → 动态,看上下文 → 多功能统一
─────────────────→ ─────────────→ 长文本支持
第一次飞跃: 第二次飞跃: 多模态融合
有了语义空间 有了上下文理解 维度可调
三次关键飞跃:
| 飞跃 | 时间 | 从 → 到 | 本质变化 |
|---|---|---|---|
| 第一次 | 2013 | 离散稀疏 → 连续稠密 | 词有了语义空间中的位置 |
| 第二次 | 2018 | 静态 → 上下文感知 | 同一个词在不同语境有不同表示 |
| 第三次 | 2022+ | 单一密集 → 多功能统一 | 一个模型同时支持密集/稀疏/多向量/多模态 |
七、关键词匹配 vs 语义嵌入
传统关键词匹配(如 BM25)和语义嵌入(Embedding)各有优劣,实际系统中通常两者结合使用:
| 关键词匹配局限 | Embedding 解决方式 |
|---|---|
| 同义词不匹配 | 语义相近即可匹配 |
| 多义词无法区分 | 上下文感知,一词多义 |
| 语义相关但无共同词 | 向量距离衡量语义关系 |
| 否定/修饰语理解不了 | 深层语义理解 |
| 跨语言不行 | 多语言向量空间统一 |
| 拼写错误找不到 | 向量相似度容忍噪声 |
关键词匹配:字面匹配,速度快、可解释,但无法理解语义
语义嵌入:语义匹配,能理解含义,但计算成本高
最佳实践:两者结合(混合检索)
八、余弦相似度与欧氏距离的区别
核心区别
余弦相似度 = "方向一样吗?" → 衡量方向的相似性,忽略向量长度
欧氏距离 = "离得多远?" → 衡量绝对距离,受向量长度影响
| 指标 | 衡量内容 | 受长度影响 | 适合场景 |
|---|---|---|---|
| 余弦相似度 | 方向夹角 | ❌ 不受 | 文本、Embedding 等语义场景 |
| 欧氏距离 | 绝对距离 | ✅ 受影响 | 物理空间、坐标等场景 |
为什么文本场景选余弦相似度?
向量 A = [1, 1] → 方向东北
向量 B = [100, 100] → 方向东北
欧氏距离:很远!(因为长度差很多)
余弦相似度:= 1(完全同方向,因为夹角为 0°)
文本 Embedding 关注的是"语义方向是否一致",而非向量绝对大小,因此余弦相似度更适合。
夹角与相似度对应关系
| 夹角 | cos 值 | 含义 |
|---|---|---|
| 0° | 1 | 完全相同方向 |
| 60° | 0.5 | 有点像 |
| 90° | 0 | 无关 |
| 120° | -0.5 | 有点相反 |
| 180° | -1 | 完全相反 |
九、维度选择的权衡
维度越高能捕捉越细微的差别
128 维:能分辨 "猫" vs "汽车" ✅
512 维:能分辨 "开心" vs "快乐" ✅
1536 维:能分辨 "开心" vs "愉悦" vs "欣喜" ✅
3072 维:能分辨更细微的差别
但边际效益递减:384 → 1536 提升明显,1536 → 3072 提升有限,3072 → 6144 几乎没区别。
维度高的四项代价
| 代价 | 计算示例 |
|---|---|
| 存储空间 | 1536维 → 6KB/条,3072维 → 12KB/条;100万条差 6GB |
| 计算速度 | 维度翻倍 → 相似度计算量翻倍 |
| 内存占用 | 1536维 100万条 ≈ 6GB,3072维 ≈ 12GB |
| 模型费用 | OpenAI small $0.02/百万token vs large $0.13/百万token(贵 6.5 倍) |
实际建议
| 场景 | 推荐维度 |
|---|---|
| 简单搜索 | 384 - 512 |
| 一般 RAG 应用 | 1024 - 1536 |
| 精细语义区分 | 2048 - 3072 |
| 大规模生产环境 | 512 - 1024 |
维度是「精度」和「成本」的权衡。不确定时先用中等(1024-1536)。
十、模型选型补充
10.1 OpenAI small vs large
| text-embedding-3-small | text-embedding-3-large | |
|---|---|---|
| 维度 | 1536 | 3072 |
| 价格 | $0.02 / 100万 token | $0.13 / 100万 token |
| 最大输入 | 8191 token | 8191 token |
| 适合 | 大规模、简单任务 | 高精度、复杂语义 |
small = 手机拍照:日常够用,传得快、存得多
large = 单反相机:细节更丰富,但文件大、处理慢、贵
10.2 Voyage AI
| 模型 | 谁家的 | 开源? | 语言支持 | 特点 |
|---|---|---|---|---|
| Voyage | Voyage AI | ❌ | 多语言 | 检索专家,效果顶尖 |
Voyage 专注于检索场景,在多项检索基准测试中表现突出,适合追求最佳检索效果的项目。
10.3 模型选择决策树
你的需求是什么?
│
├─ 🇨🇳 中文为主 / 中英混合
│ └─ 选 BGE-M3(免费开源,多语言强)
│
├─ 💰 预算有限 / 想省钱
│ ├─ 能自己部署 → BGE-M3(免费)
│ └─ 要用 API → OpenAI small(最便宜)
│
├─ 🏆 追求最佳检索效果
│ └─ 选 Voyage(检索专业户)
│
├─ 🔒 数据敏感 / 不能外传
│ └─ 选 BGE / BGE-M3(本地运行)
│
├─ 🌍 多语言 / 跨语言检索
│ ├─ 免费 → BGE-M3
│ └─ 付费 → Voyage / OpenAI large
│
└─ 📱 已经在用 OpenAI 生态
└─ 选 text-embedding-3(省事)
10.4 自建 vs API
| 自建(BGE-M3) | API(OpenAI/Voyage) | |
|---|---|---|
| 优点 | 🆓 免费、🔒 数据安全、⚡ 低延迟 | 🚀 开箱即用、📈 自动扩容 |
| 缺点 | 💰 GPU 成本、🔧 需要运维 | 💰 长期成本高、🔒 数据外传 |
中文选 BGE-M3,英文选 Voyage,省事选 OpenAI,敏感选本地部署。
十一、常见误解
8 个常见误解与真相
| # | 误解 | 真相 |
|---|---|---|
| 1 | 单个数字越大越好 | 单个数字没意义,要看整体方向 |
| 2 | 相似度高 = 内容一样 | 只是语义接近,不是内容相同 |
| 3 | 维度越高效果越好 | 边际效益递减,够用就行 |
| 4 | Embedding 能理解一切 | 有盲区:最新事件、专业术语、反讽 |
| 5 | 不同模型的向量可以互相比较 | 向量空间不同,不能跨模型比较 |
| 6 | 相似度 0.9 就是匹配成功 | 高相似度 ≠ 正确答案 |
| 7 | 最相似 = 用户想要 | 语义相似 ≠ 满足需求 |
| 8 | 模型越大越好 | 要看任务,小任务用小模型 |
误解 6 的典型例子
用户问:"iPhone 15 多少钱?"
文档 A:"iPhone 15 Pro Max 价格" → 相似度 0.91(更相似,但不是答案)
文档 B:"iPhone 15 售价 5999 元" → 相似度 0.89(虽然分数低,但才是答案)
误解 5 的关键提醒
OpenAI 的 [0.8, ...] 和 BGE 的 [0.3, ...]
就像华氏度和摄氏度,不能直接比较
要比较,必须用同一个模型生成所有向量!
Embedding 是工具,不是魔法。它能捕捉语义相似性,但不能替代真正的「理解」。
十二、实战问题与解决方案
12.1 相似度翻车案例
案例 1:反义词反而相似
"开心" vs "快乐" → 0.95 ✅ 符合预期
"开心" vs "难过" → 0.72 ❓ 为什么不是很低?
原因:它们都在讨论「情绪」,Embedding 捕捉的是语义空间中的关系。
案例 2:「不相关」的词反而相似
"苹果" vs "三星" → 0.88 ❓ 水果和韩国公司?
"小米" vs "华为" → 0.91 ❓ 谷物和建筑?
原因:模型学到的是「共现关系」,这些词经常在相似上下文出现(都是手机品牌)。
案例 3:同义词相似度反而不高
"买" vs "购买" → 0.85 ✅
"买" vs "下单" → 0.68 ❓ 怎么低了这么多?
原因:使用场景不同,上下文差异大 → Embedding 差异大。
12.2 翻车的核心原因
| 原因 | 解释 |
|---|---|
| 学的是「共现」不是「定义」 | 模型通过「这个词周围经常出现什么词」来学习 |
| 多义词无法区分 | “苹果” = 水果 + 手机品牌 + 电影公司,混在一起 |
| 缺乏上下文 | 单独的词 vs 有上下文的句子,Embedding 不同 |
| 模型世界观 ≠ 你的世界观 | 模型不知道你的微妙差异 |
| 领域知识缺失 | 通用模型不懂专业领域的细微差别 |
12.3 解决方案
| 方法 | 说明 |
|---|---|
| 用更大的上下文 | ❌ 差:单独搜 “苹果”;✅ 好:搜 “苹果 手机 价格” |
| 用专业领域模型 | 医学 Embedding 模型懂 “感冒” vs “流感” 的区别 |
| 加关键词过滤 | 先用 Embedding 召回,再用关键词精确筛选 |
| 用重排序模型 | Embedding 召回 → 粗筛;Reranker 重排 → 精筛 |
12.4 相似度阈值设定指南
经验阈值参考
| 相似度范围 | 含义 | 建议 |
|---|---|---|
| > 0.9 | 几乎相同 | 直接用,置信度很高 |
| 0.8 - 0.9 | 非常相关 | 大多数场景够用 |
| 0.7 - 0.8 | 比较相关 | 需要人工确认 |
| 0.6 - 0.7 | 有点关系 | 可能噪音,看场景 |
| < 0.6 | 关系不大 | 通常直接丢弃 |
不同场景的推荐阈值
| 场景 | 推荐阈值 | 策略 |
|---|---|---|
| 严格匹配(客服问答) | 0.85 - 0.90 | 高于阈值才回答,否则说"没找到" |
| 推荐系统 | 0.65 - 0.75 | 召回 Top 10-20,让用户自己筛选 |
| 知识库搜索 | 0.70 - 0.80 | 召回 Top 5-10,显示相似度分数 |
| 去重 / 聚类 | 0.90 - 0.95 | 高于 0.95 视为重复 |
更好的策略:不用硬阈值
| 策略 | 说明 |
|---|---|
| Top K 召回 + 重排序 | 召回 Top 10,用 Reranker 重排序 |
| 动态阈值 | 查询具体 → 阈值高;查询模糊 → 阈值低 |
| 显示分数让用户判断 | 展示相似度分数,让用户自己决定 |
| 置信度区间 | >0.85 高置信;0.70-0.85 中置信;<0.70 低置信 |
从 0.75 开始,用你的数据测试调整。更好的做法:召回 Top K + 重排序,不要硬用阈值。
十三、面试题库
13.1 基础概念题
Q1:什么是 Embedding?用一句话解释。
Embedding 是将离散对象(如单词、图片、用户 ID)映射到连续向量空间的技术,使语义相近的对象在向量空间中距离接近。
加分展开(3 点):
- 核心思想:将离散符号或复杂数据,映射为固定长度的连续稠密向量,保留语义、结构或相似性关系
- 关键特性:语义保持(相似的输入 → 向量距离近)、可计算(可做数学运算)、可学习(通过训练自动优化)
- 应用场景:NLP(Word2Vec、句子嵌入)、推荐系统(用户/物品 Embedding)、搜索(语义搜索)、RAG(文档向量化检索)
加分项:“Embedding 的本质是表示学习(Representation Learning)——让模型自己学会什么是好的特征表示,而不是依赖人工设计特征。”
Q2:Embedding 和 One-Hot 编码有什么区别?
| 对比维度 | One-Hot | Embedding |
|---|---|---|
| 向量形式 | 稀疏,只有一个 1,其余全 0 | 稠密,每个维度都有非零值 |
| 维度 | 等于词表大小(几万到几十万) | 固定长度(通常几百到几千) |
| 语义信息 | ❌ 任意两个词距离完全相同 | ✅ 语义相近的词距离近 |
| 可计算性 | 只能判断是否相同 | 可以做加减法、相似度计算 |
| 存储开销 | 极大 | 较小 |
One-Hot: "猫" → [0,0,0,1,0,0,0] ← 无法表达"猫"和"狗"的相似性
Embedding:"猫" → [0.23, -0.45, 0.89, ...] ← "猫"和"狗"的向量很接近
Q3:Embedding 的维度是什么意思?维度越高越好吗?
维度 = 描述一个对象需要几个数字。2 维描述平面位置,1536 维描述文本的语义特征。
不是越高越好,维度是精度与成本的权衡:
- 高维度的好处:能捕捉更细微的语义差别(如"开心" vs “愉悦” vs “欣喜”)
- 高维度的代价:存储翻倍、计算变慢、内存占用增大、模型费用更高
- 边际效益递减:384→1536 提升明显,1536→3072 提升有限
一般 RAG 应用推荐 1024-1536 维,不确定时先用中等维度。
Q4:向量、维度、相似度这三个概念怎么理解?
| 概念 | 通俗理解 | 类比 |
|---|---|---|
| 向量 | 一串有顺序的数字 | RPG 角色的属性面板 [攻击力, 防御力, 速度] |
| 维度 | 这串数字有几个 | 了解一个人知道多少细节 |
| 相似度 | 两个向量「有多像」的分数 | 两个同学有多像 |
Q5:什么是向量数据库?和普通数据库有什么区别?
| 对比 | 普通数据库 | 向量数据库 |
|---|---|---|
| 存储内容 | 结构化数据(表格) | 向量(高维数值) |
| 查询方式 | 精确匹配(WHERE name = ‘xxx’) | 相似度搜索(找最近的向量) |
| 排列逻辑 | 按索引/主键排列 | 按「语义主题」排列 |
| 类比 | 按书名排的图书馆 | 按内容主题排的图书馆 |
常见的向量数据库:Chroma、Milvus、Pinecone、Weaviate、FAISS。
13.2 原理深入题
Q6:余弦相似度和欧氏距离有什么区别?各自适合什么场景?
余弦相似度 = "方向一样吗?" → 忽略长度,只看方向夹角
欧氏距离 = "离得多远?" → 看绝对距离,受长度影响
| 指标 | 衡量内容 | 受长度影响 | 适合场景 |
|---|---|---|---|
| 余弦相似度 | 方向夹角 | ❌ | 文本/Embedding 语义场景 |
| 欧氏距离 | 绝对距离 | ✅ | 物理空间/坐标场景 |
为什么文本场景选余弦? 因为 [1,1] 和 [100,100] 方向相同、语义一致,但欧氏距离会很远,余弦相似度 = 1。
Q7:余弦相似度的公式是什么?值域和含义?
cos(θ) = (A · B) / (||A|| × ||B||)
分子:点积(对应维度相乘再相加)
分母:两个向量的长度(模)相乘
值域:[-1, 1]
| 值 | 夹角 | 含义 |
|---|---|---|
| 1 | 0° | 完全相同方向 |
| 0.5 | 60° | 有点像 |
| 0 | 90° | 完全无关 |
| -1 | 180° | 完全相反 |
Q8:密集嵌入、稀疏嵌入、多向量嵌入(ColBERT)有什么区别?
| 特性 | 密集嵌入 | 稀疏嵌入(BM25) | 多向量嵌入(ColBERT) |
|---|---|---|---|
| 向量形式 | 每维非零 | 大部分为 0 | 每个 Token 一个向量 |
| 语义理解 | ✅ 强 | ❌ 弱(字面匹配) | ✅ 最强(Token 级精细) |
| 精确匹配 | ❌ 弱 | ✅ 强 | ✅ 强 |
| 存储开销 | 中 | 低 | 高 |
| 计算速度 | 快 | 快 | 较慢 |
| 典型代表 | OpenAI Embedding | BM25 | BGE-M3 ColBERT |
最佳实践:混合检索(Dense + Sparse 互补),或用 BGE-M3 一个模型同时输出三种嵌入。
Q9:Word2Vec 是怎么训练的?它有什么局限性?
两种训练架构:
CBOW:上下文 → 预测中心词 ("猢狲""施展"[?]"击退""妖怪" → 预测"烈焰拳")
Skip-Gram:中心词 → 预测上下文 ("烈焰拳" → 预测周围可能出现"猢狲""施展")
核心思想:上下文相似的词,语义也相似(分布假设)。
局限性:
- 一词一向量:无法区分多义词(“苹果”=水果还是公司?)
- 窗口有限:只看局部上下文(±5 词),缺少全局信息
- 静态不变:训练完成后每个词的向量就固定了,不考虑当前语境
Q10:BERT 是如何解决多义词问题的?和 Word2Vec 有什么本质区别?
Word2Vec(静态):
"苹果" → 永远是 [0.23, -0.11, ...] ← 不管上下文
BERT(上下文感知):
"吃了一个苹果" → "苹果" = [0.15, 0.32, ...] ← 偏向食物
"苹果发布新手机" → "苹果" = [0.41, -0.08, ...] ← 偏向公司
本质区别:Word2Vec 是静态词向量(一词一向量),BERT 是上下文词向量(同一词在不同语境有不同表示)。
原理:BERT 使用双向 Transformer,通过 MLM(掩码语言模型)预训练,能根据整个句子的上下文动态生成词向量。
Q11:从 BERT 中提取句子嵌入有哪些方法?各有什么问题?
| 方法 | 做法 | 问题 |
|---|---|---|
| [CLS] token | 取 [CLS] 位置的向量 | 效果一般 |
| 平均池化 | 取所有 Token 向量的平均值 | 略好,但仍有各向异性问题 |
| Sentence-BERT | 用孪生网络微调 BERT | ✅ 专门优化,效果好 |
| SimCSE | 对比学习(Dropout 数据增强) | ✅ 无需标注,效果优秀 |
各向异性问题:BERT 的向量分布在高维空间的狭窄锥形区域,导致所有句子的余弦相似度都偏高,区分度差。
13.3 模型与选型题
Q12:常见的 Embedding 模型有哪些?怎么选?
| 模型 | 厂家 | 开源 | 特色 | 适合场景 |
|---|---|---|---|---|
| OpenAI small | OpenAI | ❌ | 通用稳定 | 快速验证、OpenAI 生态 |
| OpenAI large | OpenAI | ❌ | 3072 维高精度 | 高精度复杂语义 |
| BGE-M3 | 北京智源 | ✅ | 三合一(Dense+Sparse+ColBERT) | 中文、混合检索、本地部署 |
| Voyage | Voyage AI | ❌ | 检索效果顶尖 | 追求最佳检索质量 |
| Jina v3 | Jina AI | ❌ | 任务感知、维度可调 | 灵活权衡精度与成本 |
选择口诀:中文选 BGE-M3,英文选 Voyage,省事选 OpenAI,敏感选本地部署。
Q13:BGE-M3 的 M3 是什么意思?它为什么受欢迎?
M3 = Multi-Lingual(多语言)+ Multi-Functionality(多功能)+ Multi-Granularity(多粒度)
| 能力 | 说明 |
|---|---|
| 多语言 | 支持 100+ 种语言,跨语言检索强 |
| 多功能 | 一个模型同时输出 Dense + Sparse + ColBERT 三种嵌入 |
| 多粒度 | 句子、段落、长文档都能处理 |
受欢迎的原因:开源免费 + 一个模型替代 BM25+Dense 两套系统 + 中文效果好 + 支持本地部署(数据安全)。
Q14:自建 Embedding 模型和调用 API 各有什么优劣?
| 自建(如 BGE-M3) | API(如 OpenAI/Voyage) | |
|---|---|---|
| 优点 | 免费、数据安全不出域、低延迟(本地推理) | 开箱即用、自动扩容、无需运维 |
| 缺点 | 需要 GPU 硬件成本、需要运维能力 | 长期使用费用高、数据需发送到外部 |
建议:
- 数据敏感/企业内网 → 自建
- 快速上线/MVP → API
- 大规模 + 长期使用 → 自建(成本可控)
Q15:不同 Embedding 模型生成的向量可以直接比较吗?
❌ 绝对不行。
OpenAI 生成的 [0.8, ...] 和 BGE 生成的 [0.3, ...]
就像华氏度和摄氏度,不能直接比较
原因:不同模型的向量空间完全不同
- 维度可能不同(1536 vs 1024)
- 即使维度相同,每维的含义也完全不同
- 相似度的数值范围和分布也不同
规则:要比较,必须用同一个模型生成所有向量
13.4 RAG 与应用题
Q16:简述 RAG(检索增强生成)的核心流程。
【准备阶段 — 只做一次】
文档库 → 分块(Chunking)→ Embedding 向量化 → 存入向量数据库
【查询阶段 — 每次用户提问】
用户问题 → Embedding 向量化 → 向量相似度检索 → 找到相关文档片段 → LLM 生成回答
Embedding 在 RAG 中出现两次:① 把文档向量化存入数据库;② 把用户问题向量化进行检索。
三个关键作用:
- 翻译:把人类语言翻译成计算机能理解的数字
- 压缩:把一段话压缩成一组数字,保留核心语义
- 连接:让问题和答案能在同一个数学空间里相遇
Q17:RAG 中为什么要对文档进行切分(Chunking)?常见策略有哪些?
为什么切分:
- LLM 有输入长度限制(如 8K/128K token),无法一次处理整篇文档
- 文档太长时检索效率低,噪音多,相关内容被淹没
- 切分后能精准定位到最相关的段落
常见切分策略:
| 策略 | 原理 | 优缺点 |
|---|---|---|
| 固定长度切分 | 按 token/字符数切割 | 简单,但可能截断句子 |
| 递归字符切分 | 按分隔符层级递归切割 | 最常用,兼顾语义完整性 |
| 按句子切分 | 以句号/换行分段 | 语义完整,但块大小不均 |
| 按语义切分 | 用 Embedding 计算相邻句子相似度,在语义断裂处切分 | 效果最好,但计算成本高 |
关键参数:chunk_size(块大小)和 chunk_overlap(重叠部分)。overlap 太小会丢失上下文,太大则冗余。
Q18:为什么 RAG 中推荐混合检索?如何实现?
单一检索的局限:
| 检索方式 | 能找到 | 可能漏掉 |
|---|---|---|
| 仅 BM25(关键词) | 包含查询关键词的文档 | 语义相关但用词不同的文档 |
| 仅向量(语义) | 语义相关的文档 | 关键词精确匹配但语义距离远的文档 |
混合检索 = 两者互补,能同时覆盖精确匹配和语义理解。
实现方案:
| 方案 | 做法 | 优劣 |
|---|---|---|
| 双系统 | BM25 + Dense Embedding 分别检索,结果去重合并 | 灵活但需维护两套系统 |
| BGE-M3 | 一个模型同时输出 Dense + Sparse + ColBERT | ✅ 推荐,统一管理 |
Q19:RAG 检索结果不相关,你会从哪些角度排查?
| 排查角度 | 可能原因 | 解决方法 |
|---|---|---|
| 文本切分 | chunk_size 太小、overlap 不够,上下文断裂 | 调大 chunk_size,增加 overlap |
| Embedding 模型 | 中文支持差,或未针对专有名词训练 | 换用 BGE-M3 或领域模型 |
| 检索策略 | 仅用向量检索,缺少关键词匹配 | 引入混合检索 |
| 相似度阈值 | 阈值过高导致漏召回,或过低导致噪音 | 从 0.75 开始测试调整 |
| 查询理解 | 用户问题表述模糊或过于简短 | 优化 query(加上下文、扩展关键词) |
| 文档质量 | 文档本身内容混乱、格式不规范 | 清洗文档、优化切分策略 |
Q20:什么是 Reranker(重排序)?为什么需要它?
流程:Embedding 召回(粗筛 Top K)→ Reranker 重排(精筛 Top N)→ 送入 LLM
Embedding 召回:速度快,但只看整体语义相似度,精度有限
Reranker:用交叉编码器(Cross-Encoder)对 query 和 document 做深度交互,精度更高
为什么需要:Embedding 是双编码器(Query 和 Document 分别编码再算相似度),无法捕捉 Query-Doc 之间的细粒度交互。Reranker 将两者一起输入模型,能理解更精确的相关性。
类比:Embedding 是"看标题挑书",Reranker 是"翻开书细读再打分"。
13.5 实战与调优题
Q21:相似度阈值怎么定?有什么更好的做法?
经验参考:
| 相似度 | 含义 | 建议 |
|---|---|---|
| > 0.9 | 几乎相同 | 直接用 |
| 0.8 - 0.9 | 非常相关 | 大多数场景够用 |
| 0.7 - 0.8 | 比较相关 | 需确认 |
| < 0.6 | 关系不大 | 通常丢弃 |
更好的做法——不要硬用阈值:
- Top-K 召回 + Reranker:召回 Top 10 → 重排序 → 取 Top 3(最推荐)
- 动态阈值:查询具体时阈值高,查询模糊时阈值低
- 标注测试集:准备 100-200 个"问题-文档"对,人工标注,画分布图找分界线
⚠️ 不同模型的阈值标准不同,OpenAI 的 0.8 ≠ BGE 的 0.8,必须用自己的数据验证。
Q22:"开心"和"难过"的相似度竟然有 0.72,为什么?
这是 Embedding 的正常行为,不是 bug:
- Embedding 捕捉的是语义空间中的关系,“开心"和"难过"都在讨论"情绪”
- 模型学到的是共现关系,这些词经常在相似上下文出现
- 它们比"开心"和"汽车"(≈0.1)相似得多,但比"开心"和"快乐"(≈0.95)差很多
本质:Embedding 学的是统计规律,不是人类定义。
解决方法:如果业务需要区分情绪正负,应使用专业情感分析模型,而非通用 Embedding。
Q23:Embedding 有哪些"搞不定"的场景?
| 搞不定的场景 | 例子 | 解决方案 |
|---|---|---|
| 最新事件 | “昨天刚发生的新闻” | 结合实时搜索 |
| 专业术语 | 医学/法律黑话 | 用领域微调模型 |
| 反讽/讽刺 | “你真聪明啊”(实际骂人) | 加情感分析模块 |
| 精确匹配 | ID 号、订单号、邮箱 | 混合 BM25 关键词检索 |
| 数值比较 | “价格低于 5000 的手机” | 结构化过滤 + Embedding 检索 |
Embedding 是工具,不是魔法。实际系统需要结合多种技术。
Q24:如何评估一个 Embedding 模型在自己业务上的效果?
方法 1:构建评测集
1. 准备 100-200 个「查询 - 相关文档 - 不相关文档」三元组
2. 用模型计算相似度
3. 计算 Recall@K(前 K 个结果中包含正确答案的比例)和 MRR(正确答案的排名倒数均值)
方法 2:A/B 测试
对比两个模型:用户满意度、检索命中率、回答质量评分
方法 3:可视化
用 t-SNE/UMAP 将向量降维到 2D,观察相似内容是否聚在一起
常见指标:
| 指标 | 含义 |
|---|---|
| Recall@K | 前 K 个结果中正确答案的召回率 |
| MRR | 正确答案排名倒数的均值 |
| NDCG | 考虑排序位置的加权指标 |
| Hit Rate | 至少包含一个正确答案的查询比例 |
13.6 场景设计题
Q25:如果要你设计一个客服 RAG 系统,文档是产品手册,你会怎么搭建?
1. 数据准备
├─ 清洗文档(去除无关格式、广告)
├─ 递归字符切分(chunk_size=500, overlap=100)
└─ 用 BGE-M3 生成 Dense + Sparse 双重嵌入
2. 检索策略
├─ 混合检索(Dense 语义 + Sparse 关键词)
├─ Top-10 召回 → Reranker 精排 → 取 Top-3
└─ 相似度阈值 0.75,低于阈值回答"未找到相关信息"
3. 生成策略
├─ 将 Top-3 文档片段 + 用户问题送入 LLM
├─ System Prompt 约束:只根据检索内容回答,不确定时说明
└─ 加入引用来源(方便用户验证)
4. 优化方向
├─ 监控"未找到"的比例,补充缺失文档
├─ 收集用户反馈(有用/没用),持续优化切分和检索参数
└─ 对高频问题缓存答案,减少 LLM 调用成本
Q26:如何构建一个"以图搜文"的多模态检索系统?
核心思路:图片和文本映射到同一个向量空间
技术方案:
1. 用 Visualized-BGE / CLIP 等多模态模型
2. 文档 → 文本 Embedding → 存入向量数据库
3. 用户上传图片 → 图片 Embedding → 在同一空间检索最近文本
示例:
用户上传一张"孙悟空战斗"的图片
↓ 图片 Embedding
检索到:[0.92] "猢狲施展烈焰拳击退妖怪"
[0.31] "唐僧骑白马西行取经"
关键:文本和图片必须用同一个多模态模型编码,确保在同一向量空间中可比。
Q27:公司有 100 万条商品描述要做语义搜索,你会怎么选型?
分析维度:
├─ 数据量:100 万条(中等规模)
├─ 语言:中文为主
├─ 精度要求:商品搜索需要区分细微差别(型号、规格)
└─ 延迟要求:用户搜索需要 < 200ms 响应
选型方案:
Embedding 模型:BGE-M3(免费、中文强、支持本地部署)
向量数据库:Milvus(支持百万级、高性能)
检索策略:Dense + Sparse 混合检索
维度选择:1024 维(平衡精度和存储)
存储:100 万 × 1024 × 4字节 ≈ 4GB(可控)
如果预算充足追求效果:
Embedding → Voyage(检索效果顶尖)
数据库 → Pinecone(全托管,免运维)

知识总结&spm=1001.2101.3001.5002&articleId=161611808&d=1&t=3&u=2409f22fc6c9472da24fb607d82587bb)
359

被折叠的 条评论
为什么被折叠?



