E5 前缀机制
E5 系列是为非对称检索训练的句向量模型:文档侧必须加固定前缀 passage: ,查询侧加 query: ,两侧表示才落在同一套语义空间里。前缀是训练时约定的一部分,不是可选的优化项——漏加或加反都不会报错,只会静默地把检索质量拉低,因此要在封装层强制拼接而不是靠调用方自觉。除 E5 外,BGE 系列的部分版本要求查询侧加一句自然语言指令,规则各不相同,一律以模型卡为准。
基本信息
| 前缀规则 | 查询 query: 文档 passage: (冒号后带空格) |
|---|---|
| 常用模型 | intfloat/multilingual-e5-base(768 维)、large(1024 维)、small(384 维) |
| 训练目标 | 对比学习,明确区分查询与文档两种角色 |
| 归一化 | 模型卡建议开启 normalize_embeddings |
| 易错点 | 前缀写反或只加一侧,效果下降且无任何报错 |
典型使用场景
- 多语言知识库:中英混排语料用同一个模型,前缀规则统一处理
- 自建检索服务:把前缀拼接写进 encode_query 与 encode_document 两个函数里,杜绝遗漏
- 模型迁移评估:换模型时先核对前缀规则与维度,再跑评测集对照
- 排查“检索结果都很相似”:先确认前缀是否缺失导致向量塌缩到同一个区域
- 离线批量入库:入库脚本独立拼接 passage 前缀,避免与在线查询逻辑不一致
正确的前缀用法
正确的前缀用法
from sentence_transformers import SentenceTransformer
model = SentenceTransformer('intfloat/multilingual-e5-large')
q = model.encode('query: 如何申请差旅报销', normalize_embeddings=True)
d = model.encode(['passage: 差旅费报销流程说明'], normalize_embeddings=True)
print(q.shape, d.shape) # 都是 (1024,)
print(float(q @ d[0])) # 归一化后内积即余弦相似度常见错误与后果
| 错误 | 后果 | 规避 |
|---|---|---|
| 两侧都不加前缀 | 相关性整体下降,排序接近随机 | 在编码封装函数里强制拼接 |
| 只加查询侧 | 非对称训练优势消失 | 文档与查询用同一套封装 |
| 前缀写反 | 两侧表示错位,反而比不加更差 | 用常量定义前缀,避免手写字符串 |
| 冒号后漏空格 | 与训练时的 token 序列不一致 | 前缀写成不可变常量并做单元测试 |
不同模型的规则互不通用:E5 用固定前缀,BGE-zh 系列建议查询侧加一句检索指令,有的模型完全不加。换模型时先把新模型卡读一遍,再动代码。