)
混合检索BM25 向量为什么纯向量检索不够纯向量检索语义检索它有一个弱点查询Python 3.11 有什么新特性 向量检索可能返回编程语言的演化历史语义相关但没提 3.11 BM25 检索会返回包含 Python 3.11 关键词的文档精确匹配检索方式对比检索方式优势劣势向量检索擅长语义相近但用词不同的内容精确关键词匹配弱BM25关键词擅长精确词匹配不理解语义同义词失效混合检索两者兼得需要分数融合混合检索原理查询 ├── 向量检索 → [doc_A: 0.92, doc_C: 0.85, doc_E: 0.81] └── BM25检索 → [doc_B: 15.3, doc_A: 12.1, doc_D: 9.8] ↓ RRF 融合Reciprocal Rank Fusion ↓ 最终排序: [doc_A, doc_B, doc_C, ...]RRF 公式RRF 公式记住思路就行不用背score(doc) Σ 1 / (k rank_i)rank_i该文档在第 i 个检索结果里的名次第 1 名 rank1第 2 名 rank2…k常取 60用来压低高名次的优势、抬高低名次的贡献避免「只要某一路排第一就碾压一切」Σ对每个检索器分别算一项再相加例如向量A C EBM25B A D融合时通常不看原始分数只看排名。文档向量项BM25 项总分约doc_A1/(601) ≈ 0.01641/(602) ≈ 0.0161≈ 0.0325doc_B—1/(601) ≈ 0.0164≈ 0.0164doc_C1/(602) ≈ 0.0161—≈ 0.0161doc_D—1/(603) ≈ 0.0159≈ 0.0159doc_E1/(603) ≈ 0.0159—≈ 0.0159最终排序doc_A doc_B doc_C doc_D ≈ doc_E前置概念rank_bm25 是什么了解即可pipinstallrank_bm25BM25 是一个关键词打分算法rank_bm25 是这个算法的 Python 实现包BM25Retriever 在底层调用了它故使用BM25Retriever要安装rank_bm25jieba 是什么BM25 的工作方式是把句子拆成词再匹配英文: machine learning → [machine, learning] ← 空格天然分词 中文: 机器学习 → ??? ← 没有空格不能直接拆字jieba 是中文分词库专门解决这个问题importjieba jieba.lcut(机器学习是人工智能的子领域)# → [机器, 学习, 是, 人工智能, 的, 子, 领域]不加 jieba中文会被逐字拆开“机”、“器”、“学”、“习”匹配效果很差。LangChain 的实现方式LangChain 提供了 EnsembleRetriever直接组合多个检索器importjiebafromlangchain.retrieversimportEnsembleRetrieverfromlangchain_community.retrieversimportBM25Retrieverfromlangchain_qdrantimportQdrantVectorStore# BM25 检索器基于原始文档bm25_retrieverBM25Retriever.from_documents(chunks,k3,preprocess_funcjieba.lcut)# bm25_retriever.k 3# 向量检索器## 方式一从文档直接创建内部会建 collection 并写入vector_storeQdrantVectorStore.from_documents(documentschunks,embeddingembeddings,location:memory:,# 或 urlhttp://localhost:6333collection_namemy_docs,)# 方式二连接已有 Qdrant 服务# client QdrantClient(urlhttp://localhost:6333)# vector_store QdrantVectorStore(# clientclient,# collection_namemy_docs,# embeddingembeddings,# )# vector_store.add_documents(chunks) # ← 在这里embed upsert# 或# vector_store.add_texts([文本1, 文本2]) # 只传纯文本也行vector_retrievervector_store.as_retriever(search_kwargs{k:3})# 混合ensembleEnsembleRetriever(retrievers[bm25_retriever,vector_retriever],weights[0.5,0.5],# BM25 和向量各占 50%)resultsensemble.invoke(你的查询)混合检索输出list[Document]ensemble_retriever().invoke(query) 返回的是 LangChain 的 Document 对象列表。每个 Document 的结构Document(page_content文档正文片段...,metadata{source:xxx.pdf,# 来源文件chunk_id:chunk_001,# 分块 ID})LangChain 的 Documentpage_content metadata会被存成 Qdrant 的 point对应向量库中的每一条point的结构{id:uuid-xxx,# 唯一 IDvector:[0.12,-0.34,...],# embedding 向量scroll 时 with_vectorsFalse 不返回payload:{# 业务数据任意 JSONpage_content:...,metadata:{source:xxx...sample.md,# 固定metadata其他属性可手动添加doc_type:pdf,chunk_id:sample.pdf_p0_c0,page:0}}}QdrantClient 与 QdrantVectorStore二者区别QdrantClientQdrantVectorStore来源qdrant_clientQdrant 官方langchain_qdrantLangChain 生态层级数据库 API 层RAG 业务抽象层职责连接 Qdrant直接操作 collection / point把「文本 Embedding 检索」串成 LangChain 接口是否管 Embedding否只存/取向量是内置 embedding 模型QdrantClientQdrantClient 是连接 Qdrant 向量数据库的原生客户端相当于 SQL 里的 database driver。它负责基础设施级操作例如检查collection_exists()建表create_collection()指定向量维度、距离度量COSINE原始数据读取scroll() 分页拉取 point 的 payload不走向量检索只导出文本做 BM25 索引QdrantVectorStoreQdrantVectorStore 是 LangChain 的 VectorStore 实现内部持有 QdrantClient并额外绑定 Embedding 模型它提供面向 RAG 的高层 API方法作用add_documents(docs)自动 embed 文本 → 写入 Qdrantsimilarity_search(query)自动 embed query → 向量检索as_retriever()转成 LangChain Retriever供 RAG 链路使用