深色模式
Embedding 模型选型与中文适配
摘要:本文帮助你在 RAG 中选定嵌入(Embedding)模型。嵌入质量决定召回上限,而维度、序列长度、上下文长度与中文适配度决定工程可行性。我们对比开源(BGE 系列、GTE、E5)与商用 API(Cohere Embed v3/v4、OpenAI text-embedding-3),并给出本地部署与量化建议。
嵌入与重排是两件事
嵌入模型(bi-encoder)负责召回,输出单向量;重排模型(cross-encoder,见 rerank.md)负责精排,输出相关性分数。召回阶段必须用嵌入,二者不可互相替代。BGE-M3 同时输出 dense/sparse/multi-vector 三种表示,可一站式支撑混合检索。
核心概念
嵌入把文本映射为稠密向量,相似语义在向量空间邻近。选型看四个维度:
| 维度 | 含义 | 影响 |
|---|---|---|
| 维度 | 向量长度(384/768/1024…) | 存储、ANN 检索速度 |
| 序列长度 | 单次可编码的最大 token | 长文档需切分(见 chunking.md) |
| 多语言 | 是否覆盖中文及跨语言 | 中文召回质量 |
| 许可 | MIT / Apache / 商用限制 | 能否商用、能否本地部署 |
主流模型对比
| 模型 | 维度 | 序列长度 | 语言 | 许可 | 备注 |
|---|---|---|---|---|---|
BAAI/bge-m3 | 1024 | 8192 | 100+ | MIT | dense+sparse+multi-vector,长文本友好 |
BAAI/bge-large-zh-v1.5 | 1024 | 512 | 中文为主 | MIT | 中文强,需 query 前缀"为这个句子生成表示以用于检索:" |
Alibaba-NLP/gte-large-zh | 1024 | 512 | 中文 | 需查最新许可 | 中文榜单靠前 |
intfloat/multilingual-e5-large | 1024 | 512 | 多语言 | MIT | 跨语言通用 |
Cohere embed-v3/v4 | 多档 | 较长 | 100+ | 商用 | API,免运维 |
OpenAI text-embedding-3-large | 3072 | 8191 | 多语言 | 商用 | API,可降维 |
关键事实(来自官方来源,访问日期 2026-10-09)
BAAI/bge-m3:参数约 568M,维度 1024,序列长度 8192,支持 100+ 语言,MIT 许可,输出 dense(1024)/sparse/multi-vector 三种表示。来源:HuggingFaceBAAI/bge-m3README。BAAI/bge-large-zh-v1.5:维度 1024,序列长度 512,中文优化,MIT。来源:HuggingFaceBAAI/bge-large-zh-v1.5。- Cohere Rerank 与 Embed 为商用 API,按 token/query 计费,需查阅最新定价页。
中文适配要点
中文场景的两条硬建议
- 优先多语言模型:若语料含中英混排或跨语言检索,选
bge-m3而非纯中文模型,避免跨语言掉点。BGE-M3 README 明确"单语模型在单语检索上可能更强,但 M3 的多功能性与长文本支持更实用"。 - 注意 query 前缀:
bge-v1.5系列在检索 query 上需加指令前缀(文档侧不加),否则召回显著下降。BGE-M3 已去掉该要求。
生产实践:本地部署 BGE-M3
python
# pip install sentence-transformers FlagEmbedding
from sentence_transformers import SentenceTransformer
model = SentenceTransformer("BAAI/bge-m3")
# 编码文档(无需前缀)
docs = ["退换货政策第七条:定制商品不支持无理由退货。"]
doc_emb = model.encode(docs, normalize_embeddings=True, batch_size=32)
# 编码 query(bge-m3 无需前缀;若用 bge-large-zh-v1.5 需加前缀)
query = "哪些商品不能无理由退货?"
q_emb = model.encode([query], normalize_embeddings=True)1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
normalize_embeddings=True 必须使用:BGE 系列以余弦相似度评测,归一化后点积=余弦,否则相似度计算错误。
量化降本(INT8)
bash
# 568M FP32 -> ~220MB INT8,端侧/小卡可部署;精度略降,建议保留 FP16 提精度
# 使用 optimum 导出 ONNX 后量化,或直接加载量化权重(以 FlagEmbedding 为例)
pip install FlagEmbedding
python -c "from FlagEmbedding import BGEM3FlagModel; m=BGEM3FlagModel('BAAI/bge-m3', use_fp16=True)"1
2
3
4
2
3
4
量化与精度
INT8 可大幅降内存/提速,但中文长尾词召回可能下降。上线前用评测集对比 FP16 与 INT8 的 context_recall(见 evaluation.md)。具体端侧延迟数字因硬件而异,本文不编造实测值,请按你的机型实测。
混合检索:用 BGE-M3 的 sparse 输出
BGE-M3 编码时免费产出 sparse(词权重)表示,可直接当 BM25 用,无需额外语料统计:
python
from FlagEmbedding import BGEM3FlagModel
model = BGEM3FlagModel("BAAI/bge-m3")
out = model.encode(["同一段文本"], return_sparse=True)
# out['sparse'] 为词级权重,可写入 Milvus sparse 向量字段做混合检索1
2
3
4
2
3
4
验证
bash
# 人工探针:相关句应比无关句相似度更高
python -c "
import numpy as np
def cos(a,b): return float(np.dot(a,b)/(np.linalg.norm(a)*np.linalg.norm(b)))
print('相关', cos(q_emb[0], doc_emb[0]))
print('无关', cos(q_emb[0], model.encode(['今天天气晴朗'])[0]))
"
# 若相关 < 无关,检查 normalize / query 前缀 / 模型加载是否正确1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
回滚与清理
换嵌入模型必须重建索引
向量空间随模型变化,不同嵌入模型生成的向量不可混用。更换模型(或维度)需全量重建集合并切换流量,旧集合保留可回滚。降维(如 3072→1024)也会改变空间,同样需重建。
故障排查
- 中文召回差:未归一化、或用了需前缀的模型却没加前缀;检查
normalize_embeddings。 - 维度不匹配报错:schema 维度与模型输出不一致 → 核对
model.get_sentence_embedding_dimension()。 - 长文档没召回:超过序列长度被截断 → 切分或换长上下文模型(bge-m3 支持 8192)。
- 跨语言失效:用了纯单语模型 → 换
bge-m3/e5-multilingual。
安全与合规
嵌入不加密语义
向量本身不可逆推原文(近似表示),但元数据(source/tenant)必须随向量一起做访问控制。嵌入 API 若走公网,文档内容会出域,需确认数据合规与供应商数据处理条款;敏感语料优先本地部署。
成本与性能
量级参考,非实测报价,按自家账单核算。
- 本地嵌入:
bge-m3INT8 ~220MB,单张 T4/A10 可承载千级文档/分钟推理;无按量费用,仅 GPU 折旧/电费。 - API 嵌入:按 token 计费,长文档 × 大批量下成本可观;用本地模型可规避。
- 存储:维度越高、chunk 越多,向量库内存/磁盘越大;可通过降维(PCA/模型原生降维)与量化压缩。