| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465 |
- """BM25、Milvus 向量和混合检索。"""
- from langchain_classic.retrievers import EnsembleRetriever
- from langchain_community.retrievers import BM25Retriever
- from langchain_core.documents import Document
- from langchain_milvus import Milvus
- class MultiRetrieverSystem:
- """多路召回检索系统,默认使用混合检索。"""
- def __init__(self, documents, embedding_model, llm):
- self.documents = documents
- self.embedding_model = embedding_model
- self.llm = llm
- self.setup_retrievers()
- def setup_retrievers(self):
- """初始化 BM25、向量和混合检索器。"""
- self.bm25 = BM25Retriever.from_documents(self.documents)
- self.bm25.k = 10
- self.vectorstore = Milvus(
- embedding_function=self.embedding_model,
- connection_args={"uri": "http://localhost:19530"},
- collection_name="car_info_collection",
- primary_field="id",
- text_field="content",
- vector_field="embedding",
- auto_id=True,
- search_params={"metric_type": "COSINE", "params": {}},
- )
- self._index_documents_if_empty()
- self.vector = self.vectorstore.as_retriever(search_kwargs={"k": 10})
- # LangChain 当前版本使用 RRF 融合排序,不需要 normalize_scores 参数。
- self.ensemble = EnsembleRetriever(
- retrievers=[self.bm25, self.vector],
- weights=[0.4, 0.6],
- )
- def _index_documents_if_empty(self):
- """Milvus 集合为空时才写入分块,避免重复入库。"""
- rows = self.vectorstore.client.query(
- collection_name="car_info_collection",
- filter="id >= 0",
- output_fields=["id"],
- limit=1,
- consistency_level="Strong",
- )
- if not rows:
- self.vectorstore.add_documents(self.documents)
- def search(self, query, mode="ensemble") -> list[Document]:
- """执行检索,mode 可选 bm25、vector、ensemble。"""
- retriever_map = {
- "bm25": self.bm25,
- "vector": self.vector,
- "ensemble": self.ensemble,
- }
- if mode not in retriever_map:
- choices = ", ".join(retriever_map)
- raise ValueError(f"不支持的检索模式: {mode},可选: {choices}")
- return retriever_map[mode].invoke(query)[:10]
|