作者:来自 Elastic Peter Straßer 及 Benjamin Trent
这篇文章介绍了 ColPali 模型,这是一种 late-interaction 模型,可简化包含图片和表格的复杂文档搜索过程,并讨论了其在 Elasticsearch 中的实现。
在构建搜索应用时,我们经常需要处理具有复杂结构的文档 —— 例如表格、图片、多列等。传统上,这需要设置复杂的检索流程,包括 OCR(光学字符识别)、布局检测、语义分块 等多个处理步骤。2024 年,引入了 ColPali 模型,以解决这些挑战并简化整个流程。
从 Elasticsearch 8.18 版本 开始,我们新增了对 ColPali 等 后交互(late-interaction) 模型的支持,作为技术预览功能。在这篇博客中,我们将探讨如何使用 ColPali 在 Elasticsearch 中搜索文档。
这是否有效?
尽管许多基准测试都是基于 清理过的文本数据 来比较不同的检索策略,但 ColPali 论文的作者 认为,许多企业中的 真实世界数据 往往是 杂乱无章 的,并不总是以 整洁、结构化 的格式提供。

为了更好地代表这些场景,ViDoRe 基准测试与 ColPali 模型一同发布。该基准测试包含来自政府、医疗、研究等多个行业的多样化文档图像,并比较了包括复杂检索管道和图像嵌入模型在内的多种检索方法。
下表显示,ColPali 在该数据集上的表现极为优秀,能够可靠地从这些杂乱的文档中检索出相关信息。

ColPali 的核心思想是直接对图像进行嵌入,而不是通过复杂的管道提取文本。它基于 PaliGemma 模型的视觉能力,并结合了 ColBERT 引入的 late-interaction 机制。

我们首先来看一下如何索引文档。
ColPali 不将文档转换为文本格式,而是通过将截图划分为小矩形,并将每个矩形转换为 128 维向量来处理文档。这些向量代表该文档内各部分的上下文含义。实际上,32x32 网格会为每个文档生成 1024 个向量。
对于查询,ColPali 模型为每个标记生成一个向量。
在搜索时,为了为文档打分,我们计算每个查询向量与每个文档向量之间的距离。我们保留每个查询向量的最高分,并将这些分数加总起来得到最终的文档得分。

可解释性
使用双编码器的向量搜索面临一个问题,即结果有时不太可解释 —— 这意味着我们不知道为什么一个文档匹配。晚期交互模型不同:我们知道每个文档向量与查询向量的匹配程度,因此我们可以确定文档匹配的具体位置和原因。

在 Elasticsearch 中使用 ColPali 进行搜索
我们将采用 ViDoRe 测试集的一个子集来研究如何在 Elasticsearch 中使用 ColPali 索引文档。完整的代码示例可以在 GitHub 上找到。
为了索引文档向量,我们将使用新的 rank_vectors 字段定义一个映射。
mappings = {"mappings": {"properties": {"col_pali_vectors": {"type": "rank_vectors"}}}
}INDEX_NAME = "searchlabs-colpali"
es = Elasticsearch(<ELASTIC_HOST>, api_key=<ELASTIC_API_KEY>)
es.indices.create(index=INDEX_NAME, body=mappings)for image_path in tqdm(images, desc="Index documents"):vectors = create_col_pali_image_vectors(image_path)es_client.index(index=INDEX_NAME, id=image_path, document={"col_pali_vectors": vectors})
我们现在有一个可以搜索的充满 ColPali 向量的索引。为了对我们的文档进行评分,我们可以使用新的 maxSimDotProduct 函数。
query = "What do companies use for recruiting?"
es_query = {"_source": False, "query": {"script_score": {"query": {"match_all": {}},"script": {"source": "maxSimDotProduct(params.query_vector, 'col_pali_vectors')","params": {"query_vector": create_col_pali_query_vectors(query)}}}},"size": 5
}results = es.search(index=INDEX_NAME, body=es_query)
image_ids = [hit["_id"] for hit in results["hits"]["hits"]]html = "<div style='display: flex; flex-wrap: wrap; align-items: flex-start;'>"
for image_id in image_ids:image_path = os.path.join(DOCUMENT_DIR, image_id)html += f'<img src="{image_path}" alt="{image_id}" style="max-width:300px; height:auto; margin:10px;">'
html += "</div>"display(HTML(html))
结论
ColPali 是一个强大的新模型,可以用来高精度地搜索复杂文档。 Elasticsearch 提供了快速且可扩展的搜索解决方案,因此易于使用。自首次发布以来,其他强大的迭代版本(例如 ColQwen)也已发布。我们鼓励您在自己的搜索应用程序中尝试这些模型,并看看它们如何改善你的结果。
在生产环境中实现我们所介绍的内容之前,我们强烈建议你查看本文的第 2 部分。第 2 部分探讨了位向量和令牌池等先进技术,这些技术可以优化资源利用率并实现该解决方案的有效扩展。
敬请关注第二部分!
Elasticsearch 包含许多新功能,可帮助您为您的用例构建最佳的搜索解决方案。深入了解我们的示例笔记本以了解更多信息,开始免费云试用,或立即在本地机器上试用 Elastic。
原文:Searching complex documents with ColPali - part 1 - Elasticsearch Labs