如何使用 miniCOIL,Qdrant 的稀疏神经网络检索器

miniCOIL 是一种开源稀疏神经网络检索模型,其作用就像一个基于 BM25 的检索器能够理解关键词的上下文含义并相应地对结果进行排名。

miniCOIL 评分基于 BM25 公式,并根据查询和文档中匹配关键词之间的语义相似度进行缩放。$$ \text{miniCOIL}(D,Q) = \sum_{i=1}^{N} \text{IDF}(q_i) \cdot \text{Importance}^{q_i}_{D} \cdot {\color{YellowGreen}\text{Meaning}^{q_i \times d_j}} \text{,其中关键词 } d_j \in D \text{ 等于 } q_i $$

关于 miniCOIL 背后思想的详细分解可以在 “miniCOIL:迈向可用稀疏神经网络检索之路”文章 中找到,或者在 录制的讲座“miniCOIL:正确实现稀疏神经网络检索” 中找到。

本教程将演示基于 miniCOIL 的稀疏神经网络检索与基于 BM25 的词汇检索相比的表现。

何时使用 miniCOIL

当检索结果中需要精确的关键词匹配,并且所有匹配都应根据关键词的上下文含义进行排名时。

如果结果在语义上相似但表达方式不同,没有重叠关键词,则应使用密集嵌入,或在混合搜索设置中将它们与 miniCOIL 结合使用。

设置

安装 qdrant-clientfastembed 集成。

pip install "qdrant-client[fastembed]"

然后,初始化 Qdrant 客户端。您可以使用 Qdrant Cloud 中的 免费集群 进行实验,或者通过 Docker 运行 本地 Qdrant 实例

我们将在包含关键词“向量”和“搜索”的图书和文章标题列表上运行我们的搜索,这些关键词在不同的上下文中使用,以演示 miniCOIL 如何捕捉这些关键词的含义,而不是 BM25。

数据集
documents = [
    "Vector Graphics in Modern Web Design",
    "The Art of Search and Self-Discovery",
    "Efficient Vector Search Algorithms for Large Datasets",
    "Searching the Soul: A Journey Through Mindfulness",
    "Vector-Based Animations for User Interface Design",
    "Search Engines: A Technical and Social Overview",
    "The Rise of Vector Databases in AI Systems",
    "Search Patterns in Human Behavior",
    "Vector Illustrations: A Guide for Creatives",
    "Search and Rescue: Technologies in Emergency Response",
    "Vectors in Physics: From Arrows to Equations",
    "Searching for Lost Time in the Digital Age",
    "Vector Spaces and Linear Transformations",
    "The Endless Search for Truth in Philosophy",
    "3D Modeling with Vectors in Blender",
    "Search Optimization Strategies for E-commerce",
    "Vector Drawing Techniques with Open-Source Tools",
    "In Search of Meaning: A Psychological Perspective",
    "Advanced Vector Calculus for Engineers",
    "Search Interfaces: UX Principles and Case Studies",
    "The Use of Vector Fields in Meteorology",
    "Search and Destroy: Cybersecurity in the 21st Century",
    "From Bitmap to Vector: A Designer’s Guide",
    "Search Engines and the Democratization of Knowledge",
    "Vector Geometry in Game Development",
    "The Human Search for Connection in a Digital World",
    "AI-Powered Vector Search in Recommendation Systems",
    "Searchable Archives: The History of Digital Retrieval",
    "Vector Control Strategies in Public Health",
    "The Search for Extraterrestrial Intelligence"
]

创建集合

让我们创建一个集合来存储和索引标题。

由于 miniCOIL 的设计考虑了 Qdrant 计算关键词逆文档频率(IDF)的能力,我们需要使用 IDF 修饰符 配置 miniCOIL 稀疏向量。

client.create_collection(
    collection_name="{minicoil_collection_name}",
    sparse_vectors_config={
        "minicoil": models.SparseVectorParams(
            modifier=models.Modifier.IDF #Inverse Document Frequency
        )
    }
)
类似地,我们使用基于 BM25 的稀疏向量配置集合
client.create_collection(
    collection_name="{bm25_collection_name}",
    sparse_vectors_config={
        "bm25": models.SparseVectorParams(
            modifier=models.Modifier.IDF
        )
    }
)

转换为稀疏向量并上传到 Qdrant

接下来,我们需要将标题转换为 miniCOIL 稀疏表示并将其上传到配置的集合中。

Qdrant 和 FastEmbed 的集成允许隐藏推理过程。

这意味着

  • FastEmbed 从 Hugging Face 下载选定的模型;
  • FastEmbed 在内部运行本地推理;
  • 推理出的稀疏表示被上传到 Qdrant。
#Estimating the average length of the documents in the corpus
avg_documents_length = sum(len(document.split()) for document in documents) / len(documents)

client.upsert(
    collection_name="{minicoil_collection_name}",
    points=[
        models.PointStruct(
            id=i,
            payload={
                "text": documents[i]
            },
            vector={
                # Sparse miniCOIL vectors
                "minicoil": models.Document(
                    text=documents[i],
                    model="Qdrant/minicoil-v1",
                    options={"avg_len": avg_documents_length}   
                    #Average length of documents in the corpus 
                     # (a part of the BM25 formula on which miniCOIL is built)
                )
            },
        )
        for i in range(len(documents))
    ],
)
类似地,我们转换并上传基于 BM25 的稀疏向量
#Estimating the average length of the documents in the corpus
avg_documents_length = sum(len(document.split()) for document in documents) / len(documents)

client.upsert(
    collection_name="{bm25_collection_name}",
    points=[
        models.PointStruct(
            id=i,
            payload={
                "text": documents[i]
            },
            vector={
                # Sparse vector from BM25
                "bm25": models.Document(
                    text=documents[i],
                    model="Qdrant/bm25",
                    options={"avg_len": avg_documents_length}   
                    #Average length of documents in the corpus 
                    # (a part of the BM25 formula)
                )
            },
        )
        for i in range(len(documents))
    ],
)

使用 miniCOIL 进行检索

使用查询“医学中的向量”,我们将演示 miniCOIL 和基于 BM25 的检索之间的区别。

所有索引的标题中都没有关键词“医学”,因此它不会对相似性分数产生贡献。
同时,“向量”一词在许多标题中出现一次,并且从基于 BM25 的检索器的角度来看,它在所有标题中的作用大致相等。
然而,miniCOIL 可以捕捉关键词“向量”在“医学”语境中的含义,并匹配使用“向量”在医学相关语境中的文档。

对于基于 BM25 的检索

query = "Vectors in Medicine"

client.query_points(
    collection_name="{bm25_collection_name}",
    query=models.Document(
        text=query, 
        model="Qdrant/bm25"
    ),
    using="bm25",
    limit=1,
)

结果将是

QueryResponse(
    points=[
        ScoredPoint(
            id=18, version=1, score=0.8405092, 
            payload={
                'title': 'Advanced Vector Calculus for Engineers'
            }, 
            vector=None, shard_key=None, order_value=None)
        ]
    )

而对于基于 miniCOIL 的检索

query = "Vectors in Medicine"

client.query_points(
    collection_name="{minicoil_collection_name}",
    query=models.Document(
        text=query, 
        model="Qdrant/minicoil-v1"
    ), 
    using="minicoil",
    limit=1
)

我们将得到

QueryResponse(
    points=[
        ScoredPoint(
            id=28, version=1, score=0.7005557, 
            payload={
                'title': 'Vector Control Strategies in Public Health'
            }, 
            vector=None, shard_key=None, order_value=None)
        ]
    )
此页面有用吗?

感谢您的反馈!🙏

很抱歉听到这个消息。😔 您可以在 GitHub 上编辑此页面,或创建一个 GitHub 问题。