一句话定义
ColBERT(Contextual Late Interaction over BERT)是一种检索架构:它不只把一句话压成一个向量,而是给查询和文档里的每个 token 各留一个向量,打分时让查询的每个词去文档的所有词里找最相似的那一个,再把分数加总(这个操作叫 MaxSim)。这套"编码后再逐词比对"的思路,就叫后期交互(late interaction)。
用招聘打个比方
把检索想成"岗位要求匹配简历",业内有两种极端做法。
一种是把整份简历浓缩成一句话印象,和岗位要求的一句话印象比一比。快,但"会写 SQL""带过三人小组"这类具体点很容易被平均掉——这就是双塔(bi-encoder)稠密检索,两边各出一个向量,只在最后算一次AI 词典:余弦相似度">余弦相似度。
另一种是让面试官把简历和 JD 逐字对照读一遍。最准,但每份简历都这么读,几百万份根本读不完——这是交叉编码器(cross-encoder),查询和文档拼在一起过模型,交互发生得最早,也最贵,通常只能用来给少量候选精排。
ColBERT 走中间路线:先把简历拆成一条条经历,各自留档(这一步离线做,可以预先建好索引);岗位要求来了,就把每条要求分别去简历里找最贴合的那条经历,取最佳匹配分,再汇总。既保留了细粒度信息,又不用把两边拼起来重跑一遍模型。
和相邻概念的区别
| 方案 | 文档怎么表示 | 交互发生在什么时候 | 典型位置 |
|---|---|---|---|
| 双塔检索 | 一个向量 | 打分时算一次相似度 | 大规模召回 |
| 交叉编码器 | 不预存向量 | 编码过程中就互相看(早期交互) | 小候选集精排 |
| ColBERT / 后期交互 | 每个 token 一个向量 | 两边各自编码完之后 | 召回或中间层精排 |
"后期"是相对于交叉编码器的"早期"而言的:交互没有消失,只是被推迟到编码完成之后,因此文档侧可以离线算好、反复复用。
代价在哪里
多向量不是白拿的。token 级别的向量数量比文档数高好几个量级,存储会膨胀,所以实践中通常要把每个向量压到很低的维度,再配专门的剪枝索引(例如基于倒排的思路)来控制延迟。查询侧的每个 token 也要参与 MaxSim,计算量随文档长度增长。所以它常被放在召回之后、精排之前,或者用在需要细粒度匹配的场景:长文档、专业术语密集的语料、代码检索。
对从业者的实际意义
第一,检索效果取决于两件事:表示得够不够细,以及比对方式够不够聪明。只盯着"换个更好的 embedding 模型"容易忽略后者。第二,多向量表示在"一句话里只有一个关键点命中"时优势明显——单向量会把这点信号稀释掉。第三,选型先看瓶颈:卡延迟就用双塔,卡精度又只有小候选集就用交叉编码器,两者之间可以试试后期交互。
具体实现、参数与最新进展,以相关项目的官方页面为准。
