用于后期交互模型的多向量
许多嵌入模型将数据表示为单个向量。基于 Transformer 的编码器通过将最后一层的每个 token 向量矩阵池化为单个向量来实现此目的。这在大多数情况下效果很好。但是,当您的文档变得更复杂、涵盖多个主题或需要上下文敏感性时,这种“一刀切”的压缩就开始失效了。您会失去粒度和语义对齐(尽管分块和学习池化在一定程度上缓解了这个问题)。
后期交互模型(例如 ColBERT)保留了每个 token 的文档向量。在搜索时,它们通过比较所有查询 token 和所有文档 token 来识别最佳匹配。这种 token 级别的精度保留了局部语义匹配,并提供了卓越的相关性,特别是对于复杂的查询和文档。
后期交互:Token 级精度
Qdrant 通过多向量表示实现了这种强大的技术。多向量字段包含一个有序的子向量列表,每个子向量捕获文档的不同 token。
在查询时,Qdrant 执行后期交互评分。它将每个查询 token 嵌入 $ q_i $ 与每个文档 token 嵌入 $ d_j $ 进行比较。每个查询 token 只保留最高分数,然后将这些最高分数相加。这种机制称为 MaxSim,它提供尊重内容结构的细粒度相关性。
$$ MaxSim_{\text{norm}}(Q, D) = \frac{1}{|Q|} \sum_{i=1}^{|Q|} \max_{j=1}^{|D|} \text{sim}(q_i, d_j) $$
要在 Qdrant 中启用此功能,您需要创建一个包含密集向量的集合,并提供一个多向量比较器。
生成 Token 级嵌入
您可以使用 FastEmbed 生成所需的 token 级嵌入
from fastembed import LateInteractionTextEmbedding
encoder = LateInteractionTextEmbedding("colbert-ir/colbertv2.0")
doc_multivectors = list(encoder.embed(["A long document about AI in medicine."]))
# Returns [[token_vec1, token_vec2, ...]]
模型colbert-ir/colbertv2.0输出 128 维向量,并通过 FastEmbed 优化的 ONNX 运行时提供。文档使用.embed,查询使用.query_embed。
集合配置:多向量设置
要使用 ColBERT 进行检索,请创建一个配置为后期交互评分的多向量字段的集合
from qdrant_client import QdrantClient, models
import os
client = QdrantClient(url=os.getenv("QDRANT_URL"), api_key=os.getenv("QDRANT_API_KEY"))
# For Colab:
# from google.colab import userdata
# client = QdrantClient(url=userdata.get("QDRANT_URL"), api_key=userdata.get("QDRANT_API_KEY"))
client.create_collection(
collection_name="my_colbert_collection",
vectors_config={
"colbert": models.VectorParams(
size=128,
distance=models.Distance.COSINE,
multivector_config=models.MultiVectorConfig(
comparator=models.MultiVectorComparator.MAX_SIM
),
# Disable HNSW to save RAM - it won't typically be used with multivectors
hnsw_config=models.HnswConfigDiff(m=0),
)
}
)
通过指定MAX_SIM,您告诉 Qdrant 在查询时应用后期交互评分。我们通过m=0明确禁用 HNSW 索引,因为图形通常不会用于多向量(除了极少数的边缘情况),因此禁用它可以节省 RAM。如果没有 HNSW,查询将使用所有点的暴力 MaxSim 评分,这提供了最大精度,但对于大型集合可能会较慢。为了在大型数据集上获得更好的性能,您将在下一课中学习检索-重排序模式。
使用 ColBERT 进行查询
要使用您的 ColBERT 多向量字段进行搜索,请嵌入您的查询并将其直接传递给query_points
from fastembed import LateInteractionTextEmbedding
# Encode the query
colbert = LateInteractionTextEmbedding("colbert-ir/colbertv2.0")
colbert_query = next(colbert.query_embed(["what is the policy?"])).tolist()
# Search using ColBERT multivector
hits = client.query_points(
collection_name="my_colbert_collection",
query=colbert_query,
using="colbert",
limit=20,
)
Qdrant 对集合中所有点的查询 token 和文档 token 执行暴力 MaxSim 评分。这基于细粒度的 token 级匹配提供了高度精确的结果。请记住,如果没有 HNSW 索引,这种方法在大型集合上可能会较慢——在下一课中,您将看到如何将快速近似检索与 ColBERT 重排序相结合以获得更好的性能。
用于视觉文档的 ColPali
对于具有丰富布局、PDF、发票、幻灯片演示文稿的文档,ColPali (Contextualized Late Interaction over PaliGemma) 将相同的思想扩展到视觉领域。ColPali 将每个页面划分为 32×32 网格(1,024 个补丁),使用视觉-语言模型将每个补丁编码为 128 维向量,并将这些补丁嵌入视为子向量。您使用相同的多向量配置,Qdrant 对 token 嵌入应用 MaxSim,无论它们是如何创建的。
这种视觉方法消除了传统的 OCR 和布局检测步骤,直接处理文档图像,一次性捕获文本内容和视觉结构。这使得 ColPali 对于布局和视觉元素对理解至关重要的复杂文档特别有效。
下一步
通过您的工具包中的多向量,您可以实现文本和视觉文档的高精度检索。在下一课中,我们将探索通用查询 API,您将学习如何组合多种检索策略并使用 ColBERT 进行重排序——这是一种更常见的生产模式,可以在处理大型集合时平衡速度和精度。