Sentence Transformers v6.0:ColBERT 式多向量检索正式收编,第四种模型类型,一行代码接入 RAG
sentence-transformers-v6-colbert-multi-vector-late-interaction-rag
by Mycelium Protocol
GitHub:UKPLab/sentence-transformers → huggingface/sentence-transformers
版本:v6.0.0
发布日期:2026-08-18
HF 博客:huggingface.co/blog/multi-vector-encoder
一、这次更新做了什么
Sentence Transformers 之前有三种模型类型:
SentenceTransformer——稠密单向量嵌入CrossEncoder——交叉编码器重排SparseEncoder——稀疏向量
v6.0 加了第四个:MultiVectorEncoder——ColBERT 式晚交互(Late Interaction)多向量检索。
这意味着 ColBERT 不再需要通过 PyLate 这类第三方库接入。从训练到推理,一套 API 处理四种模型类型。
二、多向量(晚交互)是什么
普通稠密嵌入把整段文字压成一个向量,信息有损。ColBERT 给每个 token 保留一个向量(通常 128 维),打分时用 MaxSim 算子:
$$\text{MaxSim}(Q, D) = \sum_{Q_i \in Q} \max_{D_j \in D} Q_i \cdot D_j$$
每个查询 token 在文档里找最匹配的 token,加和得到总分。这是一种软对齐:每个查询 token 都找到了一个「最能解释它」的文档 token,不要求词形完全一致(token 嵌入是上下文化的),但当确实需要精确匹配时(产品编号、人名、函数名),MaxSim 有一个 token 专门做这件事——稠密模型已经把它折叠进了平均值。
三、上手
pip install sentence-transformers==6.0.0
from sentence_transformers import MultiVectorEncoder
model = MultiVectorEncoder("lightonai/LateOn")
query_embeddings = model.encode_query(["Which planet is known as the Red Planet?"])
document_embeddings = model.encode_document([
"Venus is often called Earth's twin because of its similar size and proximity.",
"Mars, known for its reddish appearance, is often referred to as the Red Planet.",
"Jupiter, the largest planet in our solar system, has a prominent red spot.",
"Saturn, famous for its rings, is sometimes mistaken for the Red Planet.",
])
print(query_embeddings[0].shape) # (12, 128) ← 12 个 token,每个 128 维
scores = model.similarity(query_embeddings, document_embeddings)
# tensor([[10.7942, 11.1104, 10.9743, 11.0811]]) ← 火星胜,排名准确
注意返回的是列表,每个元素是 2D 张量,形状 (num_tokens, embedding_dim),不是统一的矩形张量(因为每段文字的 token 数不同)。传 convert_to_numpy=True 得到 numpy 数组列表,适合大语料库场景。
查询和文档必须分开编码:encode_query 和 encode_document 走不同的前缀、不同的长度上限、不同的打分掩码,不可互换。
四、加载所有历史检查点格式
# PyLate / 原生 ST 格式
model = MultiVectorEncoder("lightonai/LateOn")
model = MultiVectorEncoder("mixedbread-ai/mxbai-edge-colbert-v0-17m")
model = MultiVectorEncoder("LiquidAI/LFM2-ColBERT-350M")
# Stanford-NLP ColBERT 格式(HF_ColBERT 架构标记)
model = MultiVectorEncoder("colbert-ir/colbertv2.0")
model = MultiVectorEncoder("answerdotai/answerai-colbert-small-v1")
# ColPali / ColQwen 视觉检索格式
model = MultiVectorEncoder("vidore/colqwen2.5-v0.2")
# 裸 Transformer(附加随机投影层,需训练)
model = MultiVectorEncoder("answerdotai/ModernBERT-base")
五、检索质量:同 backbone 比稠密模型高约 1 点
LightOn 用同一个 ModernBERT backbone(149M 参数)训了两个模型:LateOn(多向量 128d)和 DenseOn(稠密 768d)。13 个 NanoBEIR 数据集对比:
| 数据集 | LateOn(多向量) | DenseOn(稠密) |
|---|---|---|
| MSMARCO | 0.7194 | 0.6517 |
| NQ | 0.7810 | 0.7511 |
| HotpotQA | 0.9295 | 0.8802 |
| ArguAna | 0.5562 | 0.5660 |
| FiQA2018 | 0.5871 | 0.6491 |
| 均值 | 0.6868 | 0.6764 |
13 个数据集赢 9 个,均值高约 1 个 NDCG 点。输的 4 个(ArguAna、FiQA2018、SCIDOCS、SciFact)是这类方法的典型权衡——不是万能的,特别是 FiQA 这类需要语义聚合的财务问答场景稠密模型更好。
六、索引代价与 Token Pooling
代价:4,874 段自然问答文本,稠密模型产生 4,874 个向量;LateOn 产生 608,414 个 token 向量(平均 124.8 个/段)。
| 表示方式 | 向量数 | 维度 | float32 索引 |
|---|---|---|---|
| 稠密,MiniLM-L6-v2 | 4,874 | 384 | 7.5 MB |
| 稠密,gte-modernbert-base | 4,874 | 768 | 15.0 MB |
| 多向量,LateOn | 608,414 | 128 | 311.5 MB |
fast-plaid PLAID 压缩后约 88 MB,和 4096 维稠密索引差不多。
Token Pooling(Ward 聚类,几乎无质量损失):
from sentence_transformers.multi_vector_encoder.modules import HierarchicalTokenPooling
model = MultiVectorEncoder("lightonai/LateOn")
pooling = HierarchicalTokenPooling(pool_factor=2)
# 方式一:单次编码时传入
document_embeddings = model.encode_document(documents, token_pooling=pooling)
# 方式二:烘焙进模型,所有下游用户自动获得压缩
model.append(HierarchicalTokenPooling(pool_factor=2))
model.save_pretrained("my-pooled-colbert")
| pool_factor | 向量数 | 压缩比 | float32 | 质量保留 |
|---|---|---|---|---|
| 1(关闭) | 608,414 | 1.00x | 311.5 MB | 100% |
| 2 | 305,438 | 1.99x | 156.4 MB | 100.6% |
| 3 | 204,407 | 2.98x | 104.7 MB | 99.0% |
| 4 | 153,936 | 3.95x | 78.8 MB | — |
pool_factor=2:存储减半,质量还比原版略高(实验误差范围内)。
七、视觉文档检索(无需 OCR)
这是多向量检索的另一个杀手级场景:文字查询直接匹配 页面图片(含图表、表格、复杂排版),不需要 OCR,不需要文本提取。
model = MultiVectorEncoder("vidore/colqwen2.5-v0.2")
queries = ["What is the variable on the y-axis?", "Total outlay is maximum in which year?"]
images = [
"https://huggingface.co/datasets/sentence-transformers/example-documents/resolve/main/doc1.jpg",
# ...
]
query_embeddings = model.encode_query(queries)
document_embeddings = model.encode_document(images)
# query_embeddings[0].shape = (25, 128)
# document_embeddings[0].shape = (755, 128) ← 一页图片产生 755 个 patch 向量
scores = model.similarity(query_embeddings, document_embeddings)
代码和文本检索完全相同,底层处理器负责把图片转成 patch 向量,MaxSim 负责把文字 token 对齐到最匹配的图像 patch。
视觉检索最优模型:webAI-Official/webAI-ColVec1.1-8b(NanoViDoRe 0.6580),vidore/colqwen2.5-v0.2(NanoViDoRe 0.5402)。
八、实用 RAG 策略
不用重建索引的最佳实践:
第一阶段:稠密召回 top50(现有索引,不用改)
第二阶段:多向量重排 top50(不建索引,直接打分)
对多数 RAG 场景,这个策略能拿到多向量的大部分质量增益,同时避免了巨型索引的运维成本。等业务验证有效再考虑全量多向量索引。
向量数据库支持:Qdrant / Weaviate / Vespa / Milvus 均原生支持 MaxSim,MultiVectorEncoder 是统一入口。
九、其他 v6.0 变化
- 依赖底线升至 transformers v5
- Float32 打分修复:修复了半精度下的静默打分错误(训练和推理均受影响)
- 更快的训练和编码
Sentence Transformers v6.0 把一个原本需要专门工具链才能用的检索范式(ColBERT / 晚交互)变成了 pip install + 几行代码就能上手的标准选项。对于已经在用 ST 的 RAG 栈,升级路径很低:MultiVectorEncoder 加载现有 ColBERT 检查点,打分 API 和其他模型类型一致,第一步先用重排模式,验证效果后再考虑全量索引。
Mycelium Protocol — 追踪 AI 系统的底层演化
关于 Mycelium
菌丝协议。持续追踪 AI 工具、系统和实验的内容节点。
Sentence Transformers v6.0: ColBERT Multi-Vector Late Interaction — Fourth Model Type, One pip Install
by Mycelium Protocol
GitHub: UKPLab/sentence-transformers → huggingface/sentence-transformers
Version: v6.0.0
Released: 2026-08-18
HF blog: huggingface.co/blog/multi-vector-encoder
What Changed
Sentence Transformers previously had three model types: SentenceTransformer (dense single-vector), CrossEncoder (reranker), SparseEncoder (sparse vector).
v6.0 adds a fourth: MultiVectorEncoder — ColBERT-style late interaction retrieval. ColBERT no longer needs PyLate or any third-party library. Training, inference, and interpretation are all in the same unified API.
What Multi-Vector (Late Interaction) Is
A dense embedding compresses the entire text into one vector, losing information. ColBERT keeps one vector per token (typically 128-dim) and scores with the MaxSim operator:
$$\text{MaxSim}(Q, D) = \sum_{Q_i \in Q} \max_{D_j \in D} Q_i \cdot D_j$$
Each query token finds the best-matching document token; the score is the sum of those maxima. This is soft alignment — no lexical constraint, but when exact matching matters (product codes, names, function signatures), MaxSim has a dedicated token for it, where a dense model folded it into an average.
Quickstart
pip install sentence-transformers==6.0.0
from sentence_transformers import MultiVectorEncoder
model = MultiVectorEncoder("lightonai/LateOn")
query_embeddings = model.encode_query(["Which planet is known as the Red Planet?"])
document_embeddings = model.encode_document([
"Venus is often called Earth's twin...",
"Mars, known for its reddish appearance, is often referred to as the Red Planet.",
"Jupiter, the largest planet...",
"Saturn, famous for its rings...",
])
print(query_embeddings[0].shape) # (12, 128) — 12 tokens × 128-dim
scores = model.similarity(query_embeddings, document_embeddings)
# tensor([[10.7942, 11.1104, 10.9743, 11.0811]]) — Mars wins, correctly
Returns a list of 2D tensors — one per input, shape (num_tokens, embedding_dim) — because token counts differ across inputs. encode_query and encode_document are required (different prefix, different length cap, different scoring mask).
Load Any Checkpoint Format
# PyLate / native ST
model = MultiVectorEncoder("lightonai/LateOn")
model = MultiVectorEncoder("LiquidAI/LFM2-ColBERT-350M")
# Stanford-NLP ColBERT (HF_ColBERT architecture marker)
model = MultiVectorEncoder("colbert-ir/colbertv2.0")
model = MultiVectorEncoder("answerdotai/answerai-colbert-small-v1")
# ColPali / ColQwen visual retrieval
model = MultiVectorEncoder("vidore/colqwen2.5-v0.2")
# Bare transformer (random projection appended, training required)
model = MultiVectorEncoder("answerdotai/ModernBERT-base")
Retrieval Quality: +1 NDCG Point Over Dense, Same Backbone
LightOn trained LateOn (multi-vector, 128d) and DenseOn (dense, 768d) on the same data with the same ModernBERT backbone (149M params). NanoBEIR comparison:
| Dataset | LateOn (multi-vector) | DenseOn (dense) |
|---|---|---|
| MSMARCO | 0.7194 | 0.6517 |
| NQ | 0.7810 | 0.7511 |
| HotpotQA | 0.9295 | 0.8802 |
| ArguAna | 0.5562 | 0.5660 |
| FiQA2018 | 0.5871 | 0.6491 |
| Mean | 0.6868 | 0.6764 |
9 of 13 datasets — +1 NDCG point on average. The 4 losses (ArguAna, FiQA2018, SCIDOCS, SciFact) represent the real tradeoff: multi-vector is not universally better, particularly for semantic aggregation tasks like financial QA.
Index Cost and Token Pooling
4,874 NQ passages → dense: 4,874 vectors. LateOn: 608,414 token vectors.
| Representation | Vectors | Dim | float32 index |
|---|---|---|---|
| Dense, MiniLM-L6-v2 | 4,874 | 384 | 7.5 MB |
| Dense, gte-modernbert-base | 4,874 | 768 | 15.0 MB |
| Multi-vector, LateOn | 608,414 | 128 | 311.5 MB |
fast-plaid PLAID compression: ~88 MB — comparable to a 4096-dim dense index.
Token pooling (Ward clustering, near-zero quality loss):
from sentence_transformers.multi_vector_encoder.modules import HierarchicalTokenPooling
model = MultiVectorEncoder("lightonai/LateOn")
pooling = HierarchicalTokenPooling(pool_factor=2)
# Bake into the model
model.append(HierarchicalTokenPooling(pool_factor=2))
model.save_pretrained("my-pooled-colbert")
| pool_factor | Vectors | Size | Quality |
|---|---|---|---|
| 1 (off) | 608,414 | 311.5 MB | 100% |
| 2 | 305,438 | 156.4 MB | 100.6% |
| 3 | 204,407 | 104.7 MB | 99.0% |
At pool_factor=2: half the storage, marginally better performance (within measurement noise).
Visual Document Retrieval: Text Query → Page Images, No OCR
model = MultiVectorEncoder("vidore/colqwen2.5-v0.2")
queries = ["What is the variable on the y-axis?"]
images = ["doc1.jpg", "doc2.jpg", ...]
query_embeddings = model.encode_query(queries)
document_embeddings = model.encode_document(images)
# query_embeddings[0].shape = (25, 128)
# document_embeddings[0].shape = (755, 128) — one vector per image patch
scores = model.similarity(query_embeddings, document_embeddings)
Identical API to text retrieval. The processor converts pages to patch vectors; MaxSim aligns text tokens to the best-matching image patches. Charts, tables, complex layouts — all handled without an OCR step. This is what the ColPali model family does; all those checkpoints load identically.
Practical RAG Strategy
The lowest-friction first step:
Stage 1: Dense recall → top50 (existing index, no changes)
Stage 2: Multi-vector rerank top50 (no index needed, direct scoring)
This captures most of the quality gains without building or maintaining a large token-level index. Validate the improvement on your data, then decide whether full multi-vector indexing is worth the storage cost.
Database support: Qdrant, Weaviate, Vespa, and Milvus all support MaxSim natively. MultiVectorEncoder is the unified entry point.
Other v6.0 Changes
- transformers v5 dependency floor
- Float32 scoring fixes: silent half-precision scoring bugs fixed in both training and inference
- Faster training and encoding
Sentence Transformers v6.0 turns ColBERT-style late interaction from a specialized tool into a pip install away. For RAG stacks already using ST, the upgrade path is low-friction: MultiVectorEncoder loads existing ColBERT checkpoints, the scoring API matches the other model types, and reranker mode requires no new index at all.
Mycelium Protocol — tracking the deep evolution of AI systems
© 2026 Mycelium Protocol. All rights reserved.
关于本站 · 免责声明
🍄 Mushroom Research Blog 是非营利、免费公开的个人科技观察博客与公众号 XStack18,不接受商业合作、不代表任何企业或机构立场,也不谋求商业利益。我们以个人视角客观中立地记录和分析 AI、Web3 等领域的最新模型发布与技术动态——不止转述新闻标题或二手信息,而是给出有独立思考的深入分析,希望帮更多人获得有价值的一手科技认知。
⚠️ 文中介绍的开源代码与模型,仅供学习交流与技术借鉴。它们大多仍处于早期阶段,有待进一步研究和验证,请勿直接用于工作或生产环境;如需采用,请先自行充分测试,并核实其许可证与安全性。
Open-source code and models featured here are shared for learning and reference only. Most are early-stage and still need further study and verification — please don't use them directly in your work or in production. Test them thoroughly and check their licenses and security first.
- 本站文章均为作者基于公开信息的个人研究与观点整理,不代表文中提及的任何公司、产品、模型的官方立场,未与其构成商业关联或合作关系。
- 科技行业信息更新极快,我们尽力保证内容准确、及时,但不对完整性、实时性做绝对保证,具体请以相关企业/项目官方公告为准。
- 文中引用的第三方商标、产品名称、图片、数据等版权归原权利人所有,我们会尽量注明来源;如你认为存在版权疑问或侵权,请通过下方邮箱联系我们,收到通知后会尽快核实处理(更正、加注来源或删除)。
- 文章内容仅为技术科普与个人观点,不构成投资、法律或其他专业建议,据此进行任何决策的后果需自行判断和承担。
📮 侵权 / 勘误 / 合作咨询:hello@mushroom.cv
💬 评论与讨论
使用 GitHub 账号登录后发表评论