
更新:在 2024 年 8 月 31 日,我們發布了 Jina-ColBERT 的第二個版本,改進了性能,支援 89 種語言,並具有靈活的輸出維度。請查看發布文章了解更多詳情。
上週五,Jina AI 在 Hugging Face 上發布的 ColBERT model 在 AI 社群中引起了極大的關注,特別是在 Twitter/X 上。雖然許多人都熟悉突破性的 BERT 模型,但 ColBERT 引發的熱議讓一些人感到疑惑:在擁擠的資訊檢索技術領域中,是什麼讓 ColBERT 脫穎而出?為什麼 AI 社群對 8192 長度的 ColBERT 如此興奮?本文將深入探討 ColBERT 和 ColBERTv2 的細節,強調其設計、改進以及 ColBERT 後期互動的驚人效能。

tag什麼是 ColBERT?
"ColBERT" 代表 Contextualized Late Interaction over BERT,這是一個源自史丹佛大學的模型,它利用了 BERT 的深度語言理解能力,同時引入了一種新穎的互動機制。這種被稱為後期互動的機制,通過在檢索過程的最後階段之前分別處理查詢和文件,實現了高效且精確的檢索。具體來說,該模型有兩個版本:
- ColBERT:初始模型是 Omar Khattab 和 Matei Zaharia 的心血結晶,通過論文"ColBERT: Efficient and Effective Passage Search via Contextualized Late Interaction over BERT"提出了一種全新的資訊檢索方法。他們的研究成果發表於 SIGIR 2020。

介紹"後期互動"的原始 ColBERT 論文。
- ColBERTv2:在原有工作的基礎上,Omar Khattab 繼續他的研究,與 Barlas Oguz、Matei Zaharia 和 Michael S. Bernstein 合作,在 SIGIR 2021 上發表了"ColBERTv2: Effective and Efficient Retrieval via Lightweight Late Interaction"。ColBERT 的這次迭代解決了之前的限制,並引入了關鍵改進,如去噪監督和殘差壓縮,提升了模型的檢索效能和存儲效率。

ColBERTv2 添加去噪監督和殘差壓縮來改善訓練數據質量並減少空間占用。
tag理解 ColBERT 的設計
鑑於 ColBERTv2 的架構與原始 ColBERT 非常相似,其主要創新主要圍繞訓練技術和壓縮機制,我們首先將深入探討原始 ColBERT 的基礎方面。
tag什麼是 ColBERT 中的後期互動?
"互動"指的是通過比較查詢和文檔的表示來評估它們之間相關性的過程。
"後期互動"是 ColBERT 的精髓。這個術語源自模型的架構和處理策略,其中查詢和文檔表示的互動發生在處理過程的後期,在兩者都被獨立編碼之後。這與"早期互動"模型形成對比,在早期互動模型中,查詢和文檔嵌入在較早階段就開始互動,通常是在模型編碼之前或期間。
Interaction Type | Models |
---|---|
Early Interaction | BERT, ANCE, DPR, Sentence-BERT, DRMM, KNRM, Conv-KNRM, etc. |
Late Interaction | ColBERT, ColBERTv2 |
早期互動可能會增加計算複雜性,因為它需要考慮所有可能的查詢-文檔對,這使得它在大規模應用中效率較低。
像 ColBERT 這樣的後期互動模型通過允許預先計算文檔表示並在最後採用更輕量級的互動步驟來優化效率和可擴展性,這種互動步驟專注於已編碼的表示。這種設計選擇能夠實現更快的檢索時間和更低的計算需求,使其更適合處理大型文檔集合。
tag無交互:文件和查詢嵌入的餘弦相似度
許多實用的向量資料庫和神經搜尋解決方案都依賴於文件和查詢嵌入之間的快速餘弦相似度匹配。雖然這種被稱為「無交互」或「非交互式」的方法在直觀性和計算效率方面很有吸引力,但與那些包含某種形式的查詢和文件交互的模型相比,其表現被發現較為遜色。
「無交互」方法的核心限制在於其無法捕捉查詢和文件詞彙之間的複雜細微差別和關係。信息檢索的本質是理解並匹配查詢背後的意圖與文件中的內容。這個過程通常需要對相關詞彙進行深入的、上下文相關的理解,而單一的、聚合的文件和查詢嵌入很難提供這種理解。
tagColBERT 中的查詢和文件編碼器
ColBERT 的編碼策略建立在以深度上下文語言理解著稱的 BERT 模型基礎上。該模型為查詢或文件中的每個詞元生成密集向量表示,分別為查詢和文件創建上下文化嵌入的集合。這促進了在後期交互階段對其嵌入進行細緻的比較。
tagColBERT 的查詢編碼器
對於包含詞元 的查詢 ,處理過程首先將 分詞為基於 BERT 的 WordPiece 詞元,並在前面加上特殊的 [Q]
詞元。這個 [Q]
詞元位於 BERT 的 [CLS]
詞元之後,用於標示查詢的開始。
如果查詢長度短於預定義的詞元數 ,則用 [mask]
詞元填充至 ;否則截斷至前 個詞元。填充後的序列經過 BERT,然後是 CNN(卷積神經網絡)和正規化。輸出是一組嵌入向量,表示如下 :
tagColBERT 的文件編碼器
同樣,對於包含詞元 的文件 ,在前面加上 [D]
詞元以標示文件的開始。這個序列無需填充,經過相同的處理過程,得到一組嵌入向量,表示如下 :
使用 [mask]
詞元填充查詢(在論文中稱為查詢增強)確保了所有查詢的長度統一,便於批次處理。[Q]
和 [D]
詞元明確標記查詢和文件的開始,幫助模型區分這兩種輸入。
tag比較 ColBERT 與交叉編碼器
交叉編碼器同時處理查詢和文件對,使其具有高準確性,但由於評估每個可能的配對的計算成本,在大規模任務中效率較低。它們在需要精確評分句子對的特定場景中表現出色,如語意相似度任務或詳細內容比較。然而,這種設計限制了它們在需要從大型數據集快速檢索的情況下的應用,這些情況需要預計算嵌入和高效的相似度計算。
相比之下,ColBERT 的後期交互模型允許預計算文件嵌入,大大加快了檢索過程,同時不影響語意分析的深度。這種方法雖然與交叉編碼器的直接方法相比似乎不夠直觀,但為即時和大規模信息檢索任務提供了可擴展的解決方案。它代表了計算效率和交互建模質量之間的策略性妥協。
tag使用 ColBERT 尋找前 K 個文件
一旦我們得到查詢和文件的嵌入,找到最相關的前 K 個文件就變得直接了(但不像計算兩個向量的餘弦那麼直接)。
關鍵操作包括批量點積以計算詞元間相似度,在文件詞元中進行最大池化以找到每個查詢詞元的最高相似度,然後對查詢詞元進行求和得到總文件分數,最後根據這些分數對文件進行排序。偽 PyTorch 代碼如下:
import torch
def compute_relevance_scores(query_embeddings, document_embeddings, k):
"""
Compute relevance scores for top-k documents given a query.
:param query_embeddings: Tensor representing the query embeddings, shape: [num_query_terms, embedding_dim]
:param document_embeddings: Tensor representing embeddings for k documents, shape: [k, max_doc_length, embedding_dim]
:param k: Number of top documents to re-rank
:return: Sorted document indices based on their relevance scores
"""
# Ensure document_embeddings is a 3D tensor: [k, max_doc_length, embedding_dim]
# Pad the k documents to their maximum length for batch operations
# Note: Assuming document_embeddings is already padded and moved to GPU
# Compute batch dot-product of Eq (query embeddings) and D (document embeddings)
# Resulting shape: [k, num_query_terms, max_doc_length]
scores = torch.matmul(query_embeddings.unsqueeze(0), document_embeddings.transpose(1, 2))
# Apply max-pooling across document terms (dim=2) to find the max similarity per query term
# Shape after max-pool: [k, num_query_terms]
max_scores_per_query_term = scores.max(dim=2).values
# Sum the scores across query terms to get the total score for each document
# Shape after sum: [k]
total_scores = max_scores_per_query_term.sum(dim=1)
# Sort the documents based on their total scores
sorted_indices = total_scores.argsort(descending=True)
return sorted_indices
請注意,這個程序在訓練和推理時的重新排序中都會使用。ColBERT 模型使用成對排序損失進行訓練,其中訓練數據由三元組 組成,其中 代表查詢, 是與查詢相關的(正面)文件, 是不相關的(負面)文件。模型的目標是學習表示,使得 和 之間的相似度分數高於 和 之間的分數。
訓練目標可以數學表示為最小化以下損失函數:
,其中 表示 ColBERT 計算的查詢 和文件 之間的相似度分數。這個分數是通過聚合查詢和文件之間最佳匹配嵌入的最大相似度分數得到的,遵循模型架構中描述的後期交互模式。這種方法確保模型被訓練為能夠區分給定查詢的相關和不相關文件,通過鼓勵正面和負面文件對的相似度分數有更大的差距。
tagColBERTv2 中的降噪監督
ColBERTv2 中的降噪監督通過選擇具有挑戰性的負面樣本並利用交叉編碼器進行知識蒸餾來改進原始訓練過程。這種優化訓練數據質量的複雜方法包括以下步驟:
- 初始訓練:使用 MS MARCO 數據集的官方三元組,包含查詢、相關文件和不相關文件。
- 索引和檢索:使用 ColBERTv2 的壓縮來索引訓練段落,然後為每個查詢檢索前 k 個段落。
- 交叉編碼器重排序:通過 MiniLM 交叉編碼器的重排序來增強段落選擇,將其分數蒸餾到 ColBERTv2 中。
- 形成訓練元組:生成 w 路元組用於訓練,同時包含高排名和低排名的段落以創建具有挑戰性的範例。
- 迭代優化:重複該過程以持續改進難例選擇,從而提高模型性能。
請注意,這個過程代表了對 ColBERT 訓練制度的複雜增強,而不是對其架構的根本改變。
tagColBERT 的超參數
以下是 ColBERT 的超參數總結:
超參數 | 最佳選擇 | 原因 |
---|---|---|
學習率 | 3 x 10^{-6} | 為確保穩定和有效的模型更新而選用於微調。 |
批次大小 | 32 | 在計算效率和每次更新獲取足夠資訊量之間取得平衡。 |
每個查詢的嵌入數量 (Nq) | 32 | 固定數量以確保查詢間具有一致的表示大小,有助於高效處理。 |
嵌入維度 (m) | 128 | 經證實在表示能力和計算效率之間提供良好平衡。 |
訓練迭代次數 | 200k (MS MARCO), 125k (TREC CAR) | 根據數據集特性調整,確保充分學習同時避免過擬合。 |
每維度嵌入位元組數 | 4 (重排序), 2 (端到端排序) | 在精確度和空間效率之間權衡,並考慮應用場景(重排序 vs. 端到端)。 |
向量相似度函數 | 餘弦 (重排序), (平方) L2 (端到端) | 根據各自檢索場景的性能和效率選擇。 |
FAISS 索引分區 (P) | 2000 | 決定搜索空間分區的粒度,影響搜索效率。 |
搜索最近分區數 (p) | 10 | 在搜索廣度和計算效率之間取得平衡。 |
每個嵌入的子向量數 (s) | 16 | 影響量化的粒度,同時影響搜索速度和記憶體使用。 |
每維度索引表示 | 16 位元值 | 在端到端檢索的第二階段中選用,用於管理準確性和空間的權衡。 |
編碼器層數 | 12 層 BERT | 在上下文理解深度和計算效率之間取得最佳平衡。 |
最大查詢長度 | 128 | 查詢編碼器處理的最大標記數。在 Jina-ColBERT 模型中得到擴展。 |
最大文件長度 | 512 | 文件編碼器處理的最大標記數。在 Jina-ColBERT 模型中擴展至 8192。 |
tagColBERT 的索引策略
與將每個文件編碼為一個嵌入向量的基於表示的方法不同,ColBERT 將文件(和查詢)編碼為嵌入向量集合,文件中的每個標記都有自己的嵌入。這種方法本質上意味著對於較長的文件,需要儲存更多的嵌入,這是原始 ColBERT 的一個痛點,後來在 ColBERTv2 中得到解決。
有效管理這一問題的關鍵在於 ColBERT 使用向量資料庫(如 FAISS)進行索引和檢索,以及其詳細的索引過程,該過程旨在高效處理大量數據。原始 ColBERT 論文提到了幾種提高索引和檢索效率的策略,包括:
- 離線索引:文件表示在離線計算,允許預先計算和儲存文件嵌入。此過程利用批次處理和 GPU 加速來高效處理大量文件集合。
- 嵌入儲存:文件嵌入可以使用 32 位元或 16 位元值來儲存每個維度,在精確度和儲存需求之間提供權衡。這種靈活性使 ColBERT 能夠在效能(檢索性能)和效率(儲存和計算成本)之間保持平衡。
在 ColBERTv2 中引入的殘差壓縮(在原始 ColBERT 中不存在)技術,通過有效捕捉和儲存與固定參考中心點的差異,在保持品質的同時將模型的空間佔用減少了 6-10 倍,這是一個關鍵突破。
tagColBERT 的效能和效率
人們可能最初會認為將 BERT 的深度上下文理解整合到搜索中本質上需要大量計算資源,由於高延遲和計算成本,使這種方法在實時應用中較不可行。然而,ColBERT 通過其創新的後期交互機制挑戰並推翻了這一假設。以下是一些值得注意的要點:
- 顯著的效率提升:與傳統的基於 BERT 的排序模型相比,ColBERT 在計算成本(FLOPs)和延遲方面實現了數量級的減少。具體來說,對於給定的模型大小(如 12 層"基礎"transformer 編碼器),ColBERT 不僅匹配而且在某些情況下超越了 BERT 基礎模型的效能,且計算需求大幅降低。例如,在重排序深度 k=10 時,BERT 需要的 FLOPs 幾乎是 ColBERT 的 180 倍;隨著 k 增加,這個差距進一步擴大,在 k=1000 時達到 13900 倍,在 k=2000 時甚至達到 23000 倍。
- 端到端檢索中改善的召回率和 MRR@10:與最初認為查詢和文件表示之間需要更深入的交互(如早期交互模型所見)才能實現高檢索性能的直覺相反,ColBERT 的端到端檢索設置展示了卓越的效能。例如,其 Recall@50 超過了官方 BM25 的 Recall@1000 和幾乎所有其他模型的 Recall@200,突顯了該模型在不直接比較每個查詢-文件對的情況下,從大量集合中檢索相關文件的卓越能力。
- 實際應用的實用性:實驗結果突顯了 ColBERT 在實際情境中的應用價值。其索引處理量和記憶體效率使其適合在幾小時內索引如 MS MARCO 這樣的大型文件集合,同時保持高效能和可管理的空間佔用。這些特質突顯了 ColBERT 適合部署在性能和計算效率都至關重要的生產環境中。
- 文件集合規模的可擴展性:也許最令人驚訝的結論是 ColBERT 在處理大規模文件集合時的可擴展性和效率。該架構允許預計算文件嵌入,並利用高效的批次處理進行查詢-文件交互,使系統能夠隨著文件集合的大小有效擴展。考慮到有效文件檢索所需的複雜性和理解深度,這種可擴展性是反直覺的,展示了 ColBERT 在平衡計算效率和檢索效能方面的創新方法。
tag使用 jina-colbert-v1-en:一個 8192 長度的 ColBERTv2 模型
Jina-ColBERT 專為快速和準確的檢索而設計,支援最長 8192 的上下文長度,利用 JinaBERT 的進展,由於其架構增強,允許處理更長的序列。
[D],[CLS]
。
tagJina 相對於原始 ColBERT 的改進
Jina-ColBERT 的主要進展在於其骨幹網路 jina-bert-v2-base-en
,它能夠處理顯著更長的上下文(最多 8192 個標記),相比原始使用 bert-base-uncased
的 ColBERT。這種能力對於處理包含大量內容的文件至關重要,能提供更詳細和更具上下文的搜索結果。
tagjina-colbert-v1-en 與 ColBERTv2 的性能比較
我們在 BEIR 數據集和偏好長上下文的新 LoCo 基準上評估了 jina-colbert-v1-en,將其與原始 ColBERTv2 實現和非交互式的jina-embeddings-v2-base-en 模型。
Dataset | ColBERTv2 | jina-colbert-v1-en | jina-embeddings-v2-base-en |
---|---|---|---|
Arguana | 46.5 | 49.4 | 44.0 |
Climate-Fever | 18.1 | 19.6 | 23.5 |
DBPedia | 45.2 | 41.3 | 35.1 |
FEVER | 78.8 | 79.5 | 72.3 |
FiQA | 35.4 | 36.8 | 41.6 |
HotpotQA | 67.5 | 65.9 | 61.4 |
NFCorpus | 33.7 | 33.8 | 32.5 |
NQ | 56.1 | 54.9 | 60.4 |
Quora | 85.5 | 82.3 | 88.2 |
SCIDOCS | 15.4 | 16.9 | 19.9 |
SciFact | 68.9 | 70.1 | 66.7 |
TREC-COVID | 72.6 | 75.0 | 65.9 |
Webis-touch2020 | 26.0 | 27.0 | 26.2 |
LoCo | 74.3 | 83.7 | 85.4 |
Average | 51.7 | 52.6 | 51.6 |
此表顯示 jina-colbert-v1-en 的卓越效能,特別是在需要較長上下文長度的場景相較於原始的 ColBERTv2。請注意,jina-embeddings-v2-base-en 使用了更多訓練資料,而 jina-colbert-v1-en 僅使用 MSMARCO,這可能解釋了 jina-embeddings-v2-base-en 在某些任務上的良好表現。
tag使用 jina-colbert-v1-en 的範例
這個程式碼片段概述了使用 Jina-ColBERT 的索引過程,展示了其對長文件的支援。
from colbert import Indexer
from colbert.infra import Run, RunConfig, ColBERTConfig
n_gpu: int = 1 # Set your number of available GPUs
experiment: str = "" # Name of the folder where the logs and created indices will be stored
index_name: str = "" # The name of your index, i.e. the name of your vector database
if __name__ == "__main__":
with Run().context(RunConfig(nranks=n_gpu, experiment=experiment)):
config = ColBERTConfig(
doc_maxlen=8192 # Our model supports 8k context length for indexing long documents
)
indexer = Indexer(
checkpoint="jinaai/jina-colbert-v1-en",
config=config,
)
documents = [
"ColBERT is an efficient and effective passage retrieval model.",
"Jina-ColBERT is a ColBERT-style model but based on JinaBERT so it can support both 8k context length.",
"JinaBERT is a BERT architecture that supports the symmetric bidirectional variant of ALiBi to allow longer sequence length.",
"Jina-ColBERT model is trained on MSMARCO passage ranking dataset, following a very similar training procedure with ColBERTv2.",
"Jina-ColBERT achieves the competitive retrieval performance with ColBERTv2.",
"Jina is an easier way to build neural search systems.",
"You can use Jina-ColBERT to build neural search systems with ease.",
# Add more documents here to ensure the clustering work correctly
]
indexer.index(name=index_name, collection=documents)
tag在 RAGatouille 中使用 jina-colbert-v1-en
RAGatouille 是一個新的 Python 函式庫,可以讓在 RAG 流程中使用進階檢索方法變得更容易。它的設計著重於模組化和易於整合,讓使用者能夠無縫地運用最先進的研究成果。RAGatouille 的主要目標是簡化在 RAG 流程中應用像 ColBERT 這樣的複雜模型,讓開發者無需深入了解基礎研究就能利用這些方法。感謝 Benjamin Clavié,現在您可以輕鬆使用 jina-colbert-v1-en:
from ragatouille import RAGPretrainedModel
# Get your model & collection of big documents ready
RAG = RAGPretrainedModel.from_pretrained("jinaai/jina-colbert-v1-en")
my_documents = [
"very long document1",
"very long document2",
# ... more documents
]
# And create an index with them at full length!
RAG.index(collection=my_documents,
index_name="the_biggest_index",
max_document_length=8190,)
# or encode them in-memory with no truncation, up to your model's max length
RAG.encode(my_documents)
如需更詳細的資訊和深入了解 Jina-ColBERT,您可以造訪 Hugging Face 頁面。
tag結論
ColBERT 在資訊檢索領域代表了一個重要的進步。透過 Jina-ColBERT 啟用更長的上下文長度,並保持與 ColBERT 後期互動方法的相容性,為尋求實現最先進搜尋功能的開發者提供了一個強大的選擇。
結合 RAGatouille 函式庫,它簡化了將複雜檢索模型整合到 RAG 流程中的過程,開發者現在可以輕鬆運用進階檢索的力量,簡化工作流程並增強應用程式。Jina-ColBERT 和 RAGatouille 之間的協同效應,展示了在使進階 AI 搜尋模型變得容易存取和高效率方面的顯著進展。