Qdrant BM42使用

BM42

这里介绍的是qdrant中的bm42,qdrant版本1.10.0以上

BM42 是 Qdrant 提出的新型混合搜索算法,旨在结合经典的 BM25 和基于 Transformer 的语义搜索模型。BM42 通过保留 BM25 中最重要的部分——逆文档频率(IDF),并用 Transformer 的注意力机制取代词频来衡量词语在文档中的重要性,从而解决了现代检索系统(如 RAG)中短文档的局限性。

BM42 兼具 BM25 的简单性与 SPLADE 的语义智能,同时避免了 SPLADE 在词汇表处理和计算资源消耗方面的缺点。其主要优势在于速度快、内存占用小,并且在小文档处理、多语言支持及未知词处理上表现良好。BM42 适用于与稀疏和稠密嵌入结合的混合搜索系统。

然而实际测试中效果并没有官网说得好,还需要以结果为主。

图片来自官网

图片来自qdrant官网,官网为:https://qdrant.tech/articles/bm42/

整体架构流程

bm42从构建索引到检索流程

1 构建索引

def stor_in_bm42_qdrant(sparse_embedding, embeddings, data, collection_name, batch_size):
    dimension = embeddings.shape[1]
    nums = embeddings.shape[0]

    client.recreate_collection(
        collection_name=collection_name,
        vectors_config={
            "vector": models.VectorParams(
                size=dimension,
                distance=models.Distance.COSINE,
            )
        },
        sparse_vectors_config={
            "bm42": models.SparseVectorParams(
                modifier=models.Modifier.IDF,
            )
        }
    )
    # Prepare and upload points in batches
    for start_idx in range(0, nums, batch_size):
        end_idx = min(start_idx + batch_size, nums)
        points = []
        for i in range(start_idx, end_idx):
            text= data.iloc[i, 0]
            
            point = PointStruct(
                id=i,
                vector={
                    "vector": embeddings[i].tolist(),
                    "bm42": sparse_embedding[i],
                },
                payload={
                    "文本": text,
                }
            )
            points.append(point)
        
        # Upsert points into collection
        operation_info = client.upsert(
            collection_name=collection_name,
            wait=True,
            points=points
        )

2 其中的sparse embedding为

class BM42():
    def __init__(self, model_path=None):
        self.embedding_model = SparseTextEmbedding(
            cache_dir='/data2/machao/Qdrant/all_miniLM_L6_v2_with_attentions',# 好像没用
            model_name="Qdrant/bm42-all-minilm-l6-v2-attentions"
        )
    
    def encode(self, texts: list, is_query: bool = False, max_length=256):
        if is_query:
            sparse_embedding = self.embedding_model.query_embed(texts)
        else:
            sparse_embedding = self.embedding_model.embed(texts)
        res = []
        for embeddings in sparse_embedding:
            if hasattr(embeddings, 'indices') and hasattr(embeddings, 'values'):
                sparse_vector = models.SparseVector(
                    indices=embeddings.indices.tolist(),
                    values=embeddings.values.tolist()
                )
                res.append(sparse_vector)
            else:
                raise ValueError("The embeddings object does not have 'indices' and 'values' attributes.")
        return res

3 第一步中的embedding为常规嵌入模型的结果
4 接下来为检索qdrant中存储的混合向量

search_result = client.query_points(
                collection_name=collection_name,
                prefetch=[
                    models.Prefetch(
                        query=models.SparseVector(indices=sparse_query_embedding.indices, values=sparse_query_embedding.values),
                        using="bm42",
                        limit=topk,
                    ),
                    models.Prefetch(
                        query=query_embedding.squeeze().tolist(),
                        using="vector",
                        limit=topk,
                    ),
                ],
                query=models.FusionQuery(fusion=models.Fusion.RRF),
                limit=topk,
        )

以上为bm42使用流程

一些试错

纯个人经验

1 要生成sparse embedding,可能需要fastembed等库,安装cpu即可,不需要gpu也很快
2 qdrant需要1.10.0以上
3 需要提前部署好qdrant服务

小结

以上是个人bm42使用经验,纯原创,不接受转载,也欢迎大佬们指认错误,各位大佬喜欢的也可以关注一下!!!

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值