跳转到内容

ColBERT — 让 BERT 检索既准又能扛大规模

是什么

ColBERT 是一种神经信息检索模型——给一句话查询,它从百万级文档库里挑出最相关的几篇。日常类比:像一个图书管理员,他不是把每本书读完总结成一句话再挨个比对,而是事先把每本书每页的关键词都做成小卡片,你问 ‘苹果手机售价’ 时,他用你这句话里的每个词去对所有小卡片,挑配得最齐的那本。

它解决的痛点是 2018 年 BERT 出世后检索界的两难:直接拿 BERT 拼查询和文档过一遍(cross-encoder)精度极高但慢到无法上线;把整篇文档压成一个 768 维向量(DPR)虽然能预先索引,但信息损失太多。ColBERT 用 late interaction 走了第三条路。

为什么重要

不理解 ColBERT,下面这些事都没法解释:

  • 为什么 RAG 系统的检索阶段现在很多用 late interaction,而不是更老的 DPR 单向量
  • 为什么 ColBERTv2 / PLAID / ColPali / SPLADE 这一整个流派全围绕 ‘token 级向量+轻量聚合’ 展开
  • 为什么 ‘BERT 检索’ 不只 ‘把整段压成一个向量’ 这一种做法
  • 为什么 ‘什么时候让查询和文档交互’ 是检索系统设计里最关键的一道开关题

核心要点

ColBERT 的全部巧思可以拆成 三步

  1. 查询和文档各自独立过 BERT:不像 cross-encoder 把两者拼一起,ColBERT 让查询走一个 BERT、文档走另一个(共享权重),各自输出每个 token 的向量。这一步关键在 没有 cross attention,所以文档可预先编码并索引。

  2. 128 维投影:BERT 原生 768 维太大,加一层线性层压到 128 维。索引存储砍到原来的 1/6,精度几乎不掉。

  3. MaxSim 打分:查询有 N 个 token,文档有 M 个。对查询的每个 token,去文档里找最像它的那个 token(max),打个分;N 个分加起来作为文档总分。

加分项:检索时用两阶段——faiss 对查询每个 token 找 top-k 文档候选(粗筛),再对小候选集做完整 MaxSim(精排)。

三种检索范式对比

范式何时交互速度精度可索引
单向量(DPR)不交互极快
late interaction编码后聚合
cross-encoder编码时拼一起极慢极高

ColBERT 占据中间格子:比单向量精,比 cross-encoder 快,文档可预索引

实践案例

案例 1:MaxSim 直观长什么样

查询 ‘苹果手机售价’(3 个 token,简化)。文档 ‘附近店里 iPhone 卖 5999’(6 个 token)。

q='苹果' → 文档里最像它的 token 是 'iPhone' → max sim = 0.85
q='手机' → 文档里最像它的 token 是 'iPhone' → max sim = 0.92
q='售价' → 文档里最像它的 token 是 '5999' → max sim = 0.78
总分 = 2.55

注意 ‘苹果’ 和 ‘手机’ 都直接对上了 ‘iPhone’——它们没有被一个文档向量平均掉。这就是 late interaction 的精度来源。

案例 2:MS MARCO Passage Ranking 实测

模型MRR@10延迟(ms/query)
BM2518.762
DocT5Query27.764
DPR(单向量)31.412
ColBERT36.0458
BERT-base reranker34.710700+

ColBERT 的 MRR 比 BERT reranker 还高 1.3 个点(因为能看更多候选),延迟低 20+ 倍。这是当时唯一兼得 ‘神经精度 + 可索引’ 的方案。

案例 3:为什么文档可预索引

cross-encoder 把 [CLS] q [SEP] d [SEP] 一起过 BERT,q 和 d 互相 attention,每来一条新查询都要重算全部文档。ColBERT 的 q 编码和 d 编码完全独立,没有 cross attention。所以文档的 M 个 128 维向量可以提前算好存进 faiss,查询时只算 N 个查询向量,O(N*M) 的 MaxSim 在 GPU 上飞快。

这就是 ‘late’ 的含义——查询和文档编码时不见面,只在最后聚合分数时见。

踩过的坑

  1. 索引大小爆炸:每个 token 一个 128 维向量,MS MARCO 8.8M 篇文档要 154GB。这是后来 ColBERTv2 用残差压缩压到 16GB 的直接动机。

  2. MaxSim 的 max 不可导:训练时反向传不动。原文用 softmax 近似(带 temperature 参数)来过桥。这是机器学习里 ‘不可导用近似’ 的标准操作。

  3. 查询/文档长度受限:BERT 限 512 token,长查询要截断;长文档要切 chunk,跨 chunk 语义会断。

  4. batch 内负样本敏感:训练用 in-batch negatives,batch 越大效果越好,但 GPU 显存吃紧时降 batch 会损失精度。

  5. domain shift:在 MS MARCO 上训的 ColBERT 直接用到医学/法律/代码等领域时精度下降,需要 domain-specific finetune。

  6. MaxSim 的求和不是平均:N 个查询 token 的 max sim 直接相加,意味着查询越长总分基线越高。论文里靠 ranking loss 抵消了绝对分数的影响,但若拿来做阈值过滤要小心查询长度归一化。

  7. 粗筛阶段的近似:faiss 对查询每个 token 做近似 ANN 搜索,可能漏掉 MaxSim 真正的 top 文档。原文经验是每个 token 取 top-1000 候选并取并集,再做精排。这个 1000 是工程超参,缩太小会丢回归。

适用 vs 不适用场景

适用

  • RAG 系统检索阶段(候选集 10K-10M,要求精度高于单向量但又不能用 cross-encoder)
  • 查询和文档关键词匹配重要的场景(医学术语、法律条文、代码搜索、产品名)
  • 可接受 100ms 量级延迟、能腾出几十 GB 索引空间的服务
  • BEIR 类零样本跨领域检索基线

不适用

  • 极致低延迟(<10ms/query)→ 选 DPR 单向量
  • 候选集很小(<1000)→ 直接 cross-encoder 全量打分
  • 嵌入式设备 / 索引存储是硬上限 → 选 BM25 或 ColBERTv2 残差压缩版
  • 需要可解释打分(业务规则要求)→ 选 BM25 + 神经 reranker

历史小故事(可跳过)

  • 2018 年:BERT 出世,但拿来检索要么慢(cross-encoder)要么糙([CLS] 单向量)
  • 2019 年:Facebook 推出 DPR,用 BERT 把查询和文档各压成一个 768 维向量。快但精度有限
  • 2020 年:Khattab(斯坦福博士生)和 Zaharia(Spark / Databricks 创始人)在 SIGIR 提出 ColBERT,用 late interaction 同时拿到精度和速度
  • 2021-2022 年:作者团队推出 ColBERTv2,用残差压缩把索引从 154GB 砍到 16GB
  • 2023 年:Ben Clavié 写出 RAGatouille 把 ColBERT 系列做成 pip 包,三行代码起步
  • 2024-2025 年:late interaction 思想扩展到视觉检索(ColPali)和稀疏检索(SPLADE),形成一整个学派

学到什么

  1. ‘什么时候交互’ 是检索设计的关键开关——early(拼一起过 BERT)/ late(各编码后聚合)/ no(单向量),三档对应三种 trade-off
  2. 保留 token 粒度+轻量聚合 是把 ‘大模型表达力’ 和 ‘索引可行性’ 兼得的通用模式
  3. 工程权衡可视化:精度 / 延迟 / 索引大小 是检索三角,没有银弹
  4. 不可导问题用近似过桥:MaxSim 的 max 反向传不动,softmax 加 temperature 是常见解法
  5. 为下游而设计的表示比通用表示更管用:128 维投影是为 MaxSim 而生,不是通用 embedding
  6. 预索引能力来自 ‘编码独立’:cross-encoder 慢的根源是查询和文档互相 attention,ColBERT 把这条边切断后立刻获得索引可行性。这条 ‘砍依赖换效率’ 的经验在系统设计里反复出现

延伸阅读

关联

  • bert —— 提供每个 token 的上下文向量,是 ColBERT 索引的原始材料
  • colbert-v2 —— 直接后继,残差压缩 + 蒸馏,索引从 154GB → 16GB,精度还更高
  • dssm-2013 —— 单向量稠密检索的开山祖,ColBERT 用 late interaction 改写其表达力上限
  • drmm-2016 —— 早期把交互矩阵手工聚合,ColBERT 把这一步用 BERT + MaxSim 做得更彻底
  • knrm-2017 —— 用核函数聚合交互信号,late interaction 是同一思想在 BERT 时代的延伸
  • anserini-2017 —— 经典 BM25 检索基线,ColBERT 论文里的对照组
  • transformer —— BERT 的底层架构,late interaction 直接利用其 token 级输出
  • attention —— BERT 内部的核心机制,让每个 token 编码都包含上下文

反向链接

  • ance-2020 —— ANCE — 让模型自己挖训练负例,对比学习的”自给自足”
  • annoy —— Annoy — Spotify 的随机森林近似最近邻索引
  • anserini-2017 —— Anserini — 把工业搜索引擎 Lucene 改造成学术 IR 实验台
  • attention —— Attention Is All You Need
  • bert —— BERT — 双向 Transformer 预训练
  • bpr-2009 —— BPR — 用『i 比 j 更受欢迎』替代『i 是正例 j 是负例』
  • cocondenser-2021 —— coCondenser — 让 BERT 的 [CLS] 在预训练就学会”代表整段话”
  • colbert-v2 —— ColBERTv2 — 让向量检索既精又能扛百万文档
  • doc2query-2019 —— doc2query — 让模型替文档预想”会被怎么搜”再写进倒排表
  • dpr-2020 —— DPR — 用 BERT 双塔把检索从 BM25 时代拉进稠密向量时代
  • drmm-2016 —— DRMM — 检索里的匹配是相关性不是语义相似
  • e5-2022 —— E5 — 用海量”自然出现的文本对”训通用 embedding
  • filip-2021 —— FILIP — 把 CLIP 的图文对齐细化到 token 级
  • knrm-2017 —— K-NRM — 用核函数把交互矩阵变成可微排序信号
  • ms-marco-2016 —— MS MARCO — 1 千万 Bing 真实查询喂饱神经检索的标准评测集
  • replug-2023 —— REPLUG — 不动 LLM 一根毛,只把检索器调到它的”口味”上
  • rm3-2001 —— RM3 — 让搜索引擎自己看一眼结果再重搜一次
  • rocketqa-2021 —— RocketQA — 把稠密检索的训练拧到工业级
  • splade-2021 —— SPLADE — 让神经网络学出稀疏向量,直接复用倒排索引
  • vespa —— Vespa — Yahoo 检索 + 排序引擎