rag混合检索

文章目录

rag检索分类

(1)向量查询

python 复制代码
# 单一向量
.query_points(query=vector, limit=10)

# 多个向量(加权平均)
.query_points(query=[vec1, vec2], query_weights=[0.7, 0.3])

(2) 过滤查询

python 复制代码
.query_points(
    query=vector,
    query_filter=Filter(
        must=[FieldCondition(key="category", match=MatchValue(value="AI"))]
    ),
    limit=10
)

(3) 预置查询(Named Vectors)

复制代码
# 如果入库时给向量起了名字
.query_points(
    collection_name="docs",
    query_name="document_vector",  # 指定使用哪个向量字段
    using="text_vector",           # 使用命名的向量
    with_vector=True
)

(4) 稀疏向量查询(Sparse Vector / BM25)

复制代码
# 需要配置 sparse vector 索引
.query_points(
    query=sparse_vector,  # 稀疏向量(词袋表示)
    using="sparse_text"    # 指定稀疏向量字段
)

(5) 混合查询(Hybrid Search)

复制代码
# 结合稠密和稀疏向量
.query_points(
    prefetch=[
        Prefetch(query=dense_vector, using="dense", limit=100),
        Prefetch(query=sparse_vector, using="sparse", limit=100),
    ],
    query=Filter(...),  # 重排序阶段
    limit=10
)

入库和检索

入库

入库

python 复制代码
# 创建 collection 时配置
from qdrant_client.http.models import (
    VectorParams, 
    HnswConfigDiff,
    PayloadIndexType
)

client.create_collection(
    collection_name="my_docs",
    vectors_config={
        "text_vector": VectorParams(
            size=768,           # 向量维度
            distance=Distance.COSINE,
            hnsw_config=HnswConfigDiff(
                m=16,           # 每个节点最大连接数
                ef_construct=100
            )
        )
    },
    # 对 payload 字段建索引(用于过滤)
    optimizers_config=OptimizersConfigDiff(
        indexing_threshold=10000
    )
)

# 对 payload 字段创建倒排索引(用于快速过滤)
client.create_payload_index(
    collection_name="my_docs",
    field_name="category",
    field_type=PayloadIndexType.KEYWORD
)

# 对 text 内容建全文索引(稀疏向量/BM25)
client.create_payload_index(
    collection_name="my_docs",
    field_name="text_content",
    field_type=PayloadIndexType.TEXT
)

混合检索工程方案

python 复制代码
class HybridRetriever:
    async def retrieve(self, query: str, top_k: int = 10):
        # 1. 扩大召回
        dense_limit = max(top_k * 3, 10)
        
        # 2. 并行检索
        dense_task = self._dense_search(query, dense_limit)
        bm25_task = self._bm25_search(query, dense_limit)
        
        dense_hits, bm25_hits = await asyncio.gather(dense_task, bm25_task)
        
        # 3. 融合(RRF 或加权)
        combined = self._reciprocal_rank_fusion(dense_hits, bm25_hits)
        
        # 4. 重排序(Cross-Encoder)
        reranked = await self._cross_encoder_rerank(query, combined[:top_k*2])
        
        # 5. 返回最终 top_k
        return reranked[:top_k]

需要注意的是混合检索不能直接采用并集,

错误代码如下,不可用于实际生产环境,(最优解应该使用加权融合)

python 复制代码
        results = self.client.query_points(
            collection_name=self.collection_name,
            prefetch=[
                # 语义检索(稠密向量)
                Prefetch(
                    query=dense_embedding,
                    using="dense_text",  # 使用稠密向量字段
                    limit=recall_limit,
                    filter=query_filter
                ),
                # 关键词检索(稀疏向量)
                Prefetch(
                    query=sparse_embedding,
                    using="sparse_text",  # 使用稀疏向量字段
                    limit=recall_limit,
                    filter=query_filter
                )
            ],
            # query参数在这里用于最终的融合和排序
            # 传入None表示只做融合,不再额外检索
            query=None,
            limit=top_k,
            with_payload=True,
            with_vectors=False
        )

但是以下代码又是可以的

复制代码
response = client.query_points(
    collection_name="my_collection",
    prefetch=[
        models.Prefetch(
            query=models.Document(
                text=query,
                model="Qdrant/bm25",  
            ),
            using="sparse",
            limit=20,
        ),
        models.Prefetch(
            query=models.Document(
                text=query,
                model="sentence-transformers/all-MiniLM-L6-v2", 
            ),
            using="dense",
            limit=20,
        )
    ],
    query=models.FusionQuery(fusion=models.Fusion.RRF),  
    limit=10,
)
相关推荐
xyz_CDragon6 分钟前
从 RTL 到 GDSII:人与 AI 协作,用开源 EDA 工具链完成 SHA-256 芯片的 SoC 集成与签核全流程(附完整流程+代码)
人工智能·开源·芯片设计·开源 eda·caravel
咕咕AI学堂19 分钟前
检索引擎深度对比:Elasticsearch vs Milvus vs Redis 在 RAG 中的定位
人工智能
Java牛马23 分钟前
AI Agent 技术栈梳理(Skill / 蒸馏 / MCP / Harness)
人工智能·ai agent·蒸馏·skill·mcp·harness
IT_陈寒37 分钟前
Vue的computed属性把我坑惨了,原来我一直用错姿势
前端·人工智能·后端
千维百策66640 分钟前
降低 AI 辅助开发摩擦的五种模式
人工智能
大鹏说大话40 分钟前
从爬虫到决策引擎:大数据下自媒体如何用Python挖掘用户痛点
开发语言·爬虫·python
Niuguangshuo41 分钟前
silero-vad:超轻量级开源 VAD 实践指南
开发语言·python
有脚就行1 小时前
第38篇-LLM-API网关进阶-流式代理与内容安全
人工智能
AI英德西牛仔1 小时前
从Excel乱象到批量交付:秘塔Excel与“AI导出鸭”PC版的底层重构逻辑
人工智能·重构·excel·deepseek·ai导出鸭
w57w0001 小时前
AI可见度监测方案选型:电商、媒体公关、全球市场等场景的差异化需求与避坑指南
人工智能