文章目录
- 1. 前言
- 2. ColBERT 是什么?
- 2.1 BERT 模型
- 2.2 ColBERT 检索模型
- 2.3 三种架构对比
- 3. 工作流程
- 3.1 文档离线编码
- 3.2 用户查询编码
- 3.3 MaxSim 匹配
- 3.4 计算得分
- 4. 两种场景
- 4.1 召回
- 4.2 重排序
1. 前言
在之前我们介绍了两种编码器:
Bi-encoders:效果尚可,速度很快,向量存储开销小。Cross-encoders:检索质量最高,但速度极慢,常用于重排序。
那么在召回阶段,有没有一种既能接近Cross‑Encoder的细粒度匹配能力,又能保留Bi‑Encoder可做大规模向量检索的特性的模型?
2. ColBERT 是什么?
2.1 BERT 模型
BERT即Bidirectional Encoder Representations from Transformers,中文全称:基于Transformer的双向编码器表征模型。
原始Transformer由Encoder(理解文本)、Decoder(生成文本)两部分构成;BERT仅使用Encoder模块,面向文本理解任务,如文本分类、语义匹配、语义向量提取、实体抽取等。
BERT本质是基于Transformer Encoder的预训练语言模型,采用双向自注意力,每个词可以同时看到上下文全部token,擅长文本理解类任务(情感分析、分类等),原生不适合文本生成。
BERT的核心特点:
- 双向无掩码自注意力,读取词语时同时看到整句左右全部内容,不会续写新 Token;
- 模型输出向量,可用于文本分类、实体抽取,经过微调(如
Sentence-BERT)后用于语义检索、相似度计算。
2.2 ColBERT 检索模型
核心思想:每个词一个向量,而不是每个句子一个向量
由斯坦福Omar Khattab&Matei Zaharia在2020年正式提出,相关资料地址:
V1版本论文地址:ColBERT: Efficient and Effective Passage Search via Contextualized Late Interaction over BERTV2版本论文地址:ColBERTv2: Effective and Efficient Retrieval via Lightweight Late Interaction- GitHub 地址
ColBERT(Contextualized Late Interaction Over BERT) 即基于BERT的延迟交互检索模型,它是一种介于Bi-Encoder和Cross-Encoder之间的折衷方案,旨在平衡检索速度与匹配精度。
ColBERT采用词粒度向量+延迟交互打分,既能离线预计算实现海量文档快速召回,又拥有细粒度语义匹配的高分效果。
核心机制:
- 逐
Token生成向量:不为文本生成单一全局向量,每个词元独立编码为向量;文档向量支持离线预存储,保留高速检索能力。 - 延迟交互/
MaxSim打分:编码时查询与文档互不干涉;打分阶段做细粒度匹配:查询每个词元匹配文档最优词元,取最大相似度求和。以更低算力,获得接近Cross‑Encoder的高精度。
延迟交互是指:文档向量仍然离线预计算好,交互只在查询时、在token级进行。这样既保留了token级的细粒度匹配能力,又不用像cross-encoder那样每次查询都把query和doc拼起来重跑一遍BERT。
2.3 三种架构对比
| 双编码器 Bi-Encoder | ColBERT(延迟交互) | 交叉编码器 Cross-Encoder | |
|---|---|---|---|
| 编码方式 | query、doc各自独立过 BERT | query、doc各自独立过 BERT | query+doc拼接成一对过 BERT |
| 交互时机 | 无交互,只用[CLS]向量算余弦 | 编码后逐 token 做 MaxSim 交互 | 编码中全 token 双向交互(自注意力) |
| 文档预计算 | ✅ 可离线建索引 | ✅可离线建索引 | ❌ 每对都要实时算 |
| 打分粒度 | 粗(一个向量 vs 一个向量) | 细(token 级) | 最细(token 级双向) |
| 速度 | 最快 | 中(MaxSim 计算略贵) | 最慢(无法缓存) |
| 效果 | 一般 | 接近交叉编码器 | 最好(通常作精排) |
3. 工作流程
工作流程示意图:
3.1 文档离线编码
离线编码属于预处理阶段,只在构建知识库的时候执行一次,后续线上检索不再重复运行文档编码器,以此节省查询耗时。
步骤说明:
- 文档分句与分词:对每一篇原始文档做文本清洗,再通过
BERT的分词器拆分为独立Token;每个Token代表一个最小语义单元。 - 上下文编码:将
Token序列送入文档编码器f D f_DfD(BERT主干网络),为每一个Token单独输出一条 768 维上下文向量。这里不会做全局池化操作,不会把整篇文档压缩成单个向量,完整保留每个词语独立的语义信息。 - 向量持久化与索引构建:保存每一组
Token向量,同时维护「向量→文档ID」的映射关系,构建ANN近似检索索引,用于后续快速粗召回候选文档。
示例,候选文档:
Doc1:明珠最喜欢吃桂花糕,软糯香甜。Doc2:小红爱吃糖葫芦,小明爱吃糖炒栗子。Doc3:周末一起去爬山,风景很美。
处理结果:
| 文档 | Token 分词列表 | 文档向量集合 |
|---|---|---|
| Doc1 | 明珠 / 最 / 喜欢 / 吃 / 桂花糕 | D 1 = { d 11 , d 12 , d 13 , d 14 , d 15 } D_1=\{d_{11},d_{12},d_{13},d_{14},d_{15}\}D1={d11,d12,d13,d14,d15} |
| Doc2 | 小红 / 爱吃 / 糖葫芦 / 小明 / 爱吃 / 糖炒栗子 | D 2 = { d 21 , d 22 , d 23 , d 24 , d 25 , d 26 } D_2=\{d_{21},d_{22},d_{23},d_{24},d_{25},d_{26}\}D2={d21,d22,d23,d24,d25,d26} |
| Doc3 | 周末 / 一起 / 去 / 爬山 / 风景 / 很美 | D 3 = { d 31 , d 32 , d 33 , d 34 , d 35 , d 36 } D_3=\{d_{31},d_{32},d_{33},d_{34},d_{35},d_{36}\}D3={d31,d32,d33,d34,d35,d36} |
阶段特点:文档与查询完全分开编码,向量之间不会提前计算相似度交互,这就是
ColBERT「晚交互」范式的前置基础。
3.2 用户查询编码
查询编码属于在线实时阶段,每接收一条用户提问,都需要即时执行一次编码流程。
- 问句分词:对用户输入的原始问句
明珠爱吃啥使用和文档侧完全一致的分词器,拆分出Query Token序列,保证两边分词规则对齐。 - Query 编码器生成多向量:将分词结果送入查询编码器f Q f_QfQ(与文档侧权重共享的
BERT模型),每一个 Query Token 生成一条独立的上下文向量。和文档编码逻辑保持一致,不做均值池化、CLS池化,不合并成单一全局向量。 - 保留完整 Query 向量列表,传递给后续
MaxSim打分模块。
查询示例:
| Query 文本 | Query 分词 | Query 向量集合 |
|---|---|---|
| 明珠爱吃啥 | 明珠 / 爱吃 / 啥 | Q = { q 1 , q 2 , q 3 } Q=\{q_1,q_2,q_3\}Q={q1,q2,q3} |
阶段特点:直到当前步骤结束,
Query向量和文档向量之间没有任何相似度运算;语义匹配的交互过程延迟到后面打分环节执行。
3.3 MaxSim 匹配
MaxSim是ColBERT的核心匹配算子,针对每一篇召回后的候选文档独立计算。
- 取出当前待打分文档的全部
Token向量集合。 - 遍历
Query里的每一个独立Token向量q i q_iqi,和该文档全部的Token向量d j d_jdj依次做点积运算,得到一组相似度数值。 - 在这一组相似度结果中,选取最大值作为这个
Query Token对当前文档的匹配得分,该运算定义为:M a x S i m ( q i , D ) = max j ( q i ⋅ d j ) \boldsymbol{\mathrm{MaxSim}(q_i,D)=\max_j(q_i\cdot d_j)}MaxSim(qi,D)=maxj(qi⋅dj)。 - 对
Query中所有Token重复执行上面的操作,得到一组独立的MaxSim值。
该机制的核心逻辑:每个查询词自动在文档里寻找语义最贴合的那个词做匹配,不要求词语位置严格对齐,实现细粒度的语义对齐。
示例,查询语句中每个Token向量和每个文档计算出来的相似度:
| Query Token | Doc1最大相似度 | Doc2最大相似度 | Doc3最大相似度 |
|---|---|---|---|
| q 1 q_1q1(明珠) | 0.9 | 0.1 | 0.05 |
| q 2 q_2q2(爱吃) | 0.8 | 0.9 | 0.02 |
| q 3 q_3q3(啥) | 0.3 | 0.2 | 0.10 |
其中:
Doc1:明珠精准命中文档同名token,得分0.9;爱吃和文档中的吃语义贴近,得分0.8;疑问词啥没有直接匹配对象,分数偏低。Doc2:不存在明珠这个主体,因此q 1 q_1q1相似度仅0.1;但是包含关键词爱吃,q 2 q_2q2拿到高分0.9。Doc3:整段文本和用户问句语义无关,全部Token的匹配数值都维持在很低的水平。
3.4 计算得分
步骤详解:
- 对单篇文档,把上一步得到的全部 Query Token 的 MaxSim 最大值进行累加求和,求和结果就是这篇文档最终的全局相关性分数,完整公式:S c o r e ( Q , D ) = ∑ i M a x S i m ( q i , D ) \displaystyle \boldsymbol{Score}(Q,D)=\sum_{i}\mathrm{MaxSim}(q_i,D)Score(Q,D)=i∑MaxSim(qi,D)。
- 将所有候选文档计算完毕后,按照最终得分从高到低降序排列。
- 根据业务需求截取
Top‑N结果返回给用户,完成检索排序。
示例:
| 文档 | MaxSim分数累加过程 | 最终得分 | 相关性排序 |
|---|---|---|---|
| Doc1 | 0.9 + 0.8 + 0.3 0.9 + 0.8 + 0.30.9+0.8+0.3 | 2.00 | 1 |
| Doc2 | 0.1 + 0.9 + 0.2 0.1 + 0.9 + 0.20.1+0.9+0.2 | 1.20 | 2 |
| Doc3 | 0.05 + 0.02 + 0.10 0.05 + 0.02 + 0.100.05+0.02+0.10 | 0.17 | 3 |
结果解读:
Doc1总分最高:人物主体、动作语义全部完成高匹配,是最贴合用户问题的结果;Doc2仅有局部关键词爱吃命中,但核心人物不匹配,分数低于Doc1;对比普通单向量模型,ColBERT不会因为单个关键词命中就给出虚高的分数;Doc3几乎没有任何语义重合,得分最低,排在最后。
对比传统单向量稠密检索:普通模型把整句话压缩为
1个向量,容易丢失主体细节;ColBERT依靠逐词MaxSim累加的方式,区分「局部关键词匹配」和「完整语义匹配」,检索精度更高。
4. 两种场景
ColBERT本身是Late Interaction 模型,既可以做召回,也可以做重排。
4.1 召回
ColBERT v2论文原生能力:
- 文档拆成
token,每个token单独编码成向量,构建token级ANN索引 Query编码成query token向量,直接在全文档索引里做MaxSim匹配,一次性召回候选段落。
在召回场景ColBERT的优势:
- 比
Bi-encoder:多向量细粒度匹配,不把整句压缩为单一向量,避免语义丢失,召回准确率更高、歧义适配更强。 - 比
Cross‑Encoder:支持向量索引、可做全局召回,推理速度更快。
Bi-encoder快但粗,Cross-Encoder精但不能召回,ColBERT兼顾细粒度精度与检索速度。
4.2 重排序
在LlamaIndex中只看到ColBERT作为Rerank,没看到召回相关:
ColBERT重排:只对这一小批候选文档,计算Query token和Passage token的MaxSim细粒度相似度,重新打分排序,再取TopN交给LLM
✅ 优点:算力可控,精度接近CrossEncoder,速度远快于CrossEncoder。