稀疏向量 milvus存储检索RAG使用案例

参考:
https://milvus.io/docs/hybrid_search_with_milvus.md

milvus使用不方便:
1)离线计算向量很慢BGEM3EmbeddingFunction
2)milvus安装环境支持很多问题,不支持windows、centos等

在线demo:
https://colab.research.google.com/drive/1OGvOyJH2NUQB1Ft3rqAFLQ_5Dzi8aHk_?usp=sharing

暂时只能在linux ubuntu或mac上使用,因为windows、centos暂时不支持milvus_lite:https://github.com/milvus-io/milvus/issues/34854

安装:

pip install --upgrade pymilvus "pymilvus[model]"  -i https://pypi.tuna.tsinghua.edu.cn/simple

environs-9.5.0 milvus-lite-2.4.10 milvus-model-0.2.5 onnxruntime-1.16.3 pymilvus-2.4.6

数据:

 wget http://qim.fs.quoracdn.net/quora_duplicate_questions.tsv

代码:

##data
import pandas as pd

file_path = "quora_duplicate_questions.tsv"
df = pd.read_csv(file_path, sep="\t")
questions = set()
for _, row in df.iterrows():
    obj = row.to_dict()
    questions.add(obj["question1"][:512])
    questions.add(obj["question2"][:512])
    if len(questions) > 500:  # Skip this if you want to use the full dataset
        break

docs = list(questions)

print(docs[0])

# bge m3
from milvus_model.hybrid import BGEM3EmbeddingFunction

ef = BGEM3EmbeddingFunction(use_fp16=False, device="cpu")
dense_dim = ef.dim["dense"]

docs_embeddings = ef(docs)
##创建向量库
from pymilvus import (
    connections,
    utility,
    FieldSchema,
    CollectionSchema,
    DataType,
    Collection,
)

connections.connect(uri="./milvus.db")

fields = [
    # Use auto generated id as primary key
    FieldSchema(
        name="pk", dtype=DataType.VARCHAR, is_primary=True, auto_id=True, max_length=100
    ),
    # Store the original text to retrieve based on semantically distance
    FieldSchema(name="text", dtype=DataType.VARCHAR, max_length=512),
    # Milvus now supports both sparse and dense vectors,
    # we can store each in a separate field to conduct hybrid search on both vectors
    FieldSchema(name="sparse_vector", dtype=DataType.SPARSE_FLOAT_VECTOR),
    FieldSchema(name="dense_vector", dtype=DataType.FLOAT_VECTOR, dim=dense_dim),
]
schema = CollectionSchema(fields)

col_name = "hybrid_demo"
if utility.has_collection(col_name):
    Collection(col_name).drop()
col = Collection(col_name, schema, consistency_level="Strong")

sparse_index = {"index_type": "SPARSE_INVERTED_INDEX", "metric_type": "IP"}
col.create_index("sparse_vector", sparse_index)
dense_index = {"index_type": "AUTOINDEX", "metric_type": "IP"}
col.create_index("dense_vector", dense_index)
col.load()

#插入数据
for i in range(0, len(docs), 50):
    batched_entities = [
        docs[i : i + 50],
        docs_embeddings["sparse"][i : i + 50],
        docs_embeddings["dense"][i : i + 50],
    ]
    col.insert(batched_entities)
print("Number of entities inserted:", col.num_entities)

##数据查询



from pymilvus import (
    AnnSearchRequest,
    WeightedRanker,
)


def dense_search(col, query_dense_embedding, limit=10):
    search_params = {"metric_type": "IP", "params": {}}
    res = col.search(
        [query_dense_embedding],
        anns_field="dense_vector",
        limit=limit,
        output_fields=["text"],
        param=search_params,
    )[0]
    return [hit.get("text") for hit in res]


def sparse_search(col, query_sparse_embedding, limit=10):
    search_params = {
        "metric_type": "IP",
        "params": {},
    }
    res = col.search(
        [query_sparse_embedding],
        anns_field="sparse_vector",
        limit=limit,
        output_fields=["text"],
        param=search_params,
    )[0]
    return [hit.get("text") for hit in res]


def hybrid_search(
    col,
    query_dense_embedding,
    query_sparse_embedding,
    sparse_weight=1.0,
    dense_weight=1.0,
    limit=10,
):
    dense_search_params = {"metric_type": "IP", "params": {}}
    dense_req = AnnSearchRequest(
        [query_dense_embedding], "dense_vector", dense_search_params, limit=limit
    )
    sparse_search_params = {"metric_type": "IP", "params": {}}
    sparse_req = AnnSearchRequest(
        [query_sparse_embedding], "sparse_vector", sparse_search_params, limit=limit
    )
    rerank = WeightedRanker(sparse_weight, dense_weight)
    res = col.hybrid_search(
        [sparse_req, dense_req], rerank=rerank, limit=limit, output_fields=["text"]
    )[0]
    return [hit.get("text") for hit in res]



query = input("Enter your search query: ")
print(query)

query_embeddings = ef([query])

dense_results = dense_search(col, query_embeddings["dense"][0])
sparse_results = sparse_search(col, query_embeddings["sparse"][[0]])
hybrid_results = hybrid_search(
    col,
    query_embeddings["dense"][0],
    query_embeddings["sparse"][[0]],
    sparse_weight=0.7,
    dense_weight=1.0,
)

在这里插入图片描述

在这里插入图片描述

<think>好的,我现在需要帮用户介绍如何搭建一个最优的本地知识库,核心需求是问答,并且要快速回答。首先,我应该从用户的需求出发,分析他们可能需要的技术栈和步骤。用户提到的是“本地”知识库,所以可能需要考虑数据隐私和离线处理。核心是问答,所以重点在检索和生成答案的效率。 首先,知识库搭建的基本流程应该是数据准备、处理、存储检索和生成。我需要分步骤来思考每个环节的最优方案。数据准备方面,可能需要支持多种格式,比如PDF、Word、TXT等,所以需要文档解析工具,比如Unstructured或PyMuPDF。然后是文本处理,包括分块和向量化。分块策略很重要,块的大小和重叠会影响检索效果,可能需要用LangChain的TextSplitter或者自定义方法。 接下来是向量数据库的选择,本地部署的话,FAISS和Chroma都是不错的选择。FAISS由Facebook开发,适合快速检索,而Chroma更轻量,易于集成。用户需要快速回答,所以向量检索的速度和准确率是关键。可能还需要结合传统的检索方式,比如BM25,做混合检索提高准确性。 然后是模型部分,用户可能不想依赖云端服务,所以本地部署的模型很重要。像ChatGLM3-6B、BGE系列的Embedding模型可以在本地运行。但如果资源有限,可能需要在效果和资源消耗之间做权衡,比如使用较小的模型或者量化技术。 在问答系统构建方面,可能需要将检索到的文档作为上下文输入到生成模型中,比如用LlamaIndex做检索增强生成(RAG)。Prompt工程也很重要,要设计清晰的提示词让模型准确回答问题,并处理未知情况。 性能优化方面,缓存、预处理和硬件加速(如GPU)都是需要考虑的点。用户可能需要指导如何选择硬件配置,或者使用量化模型减少内存占用。 最后,给出一个具体的方案示例,比如使用Chroma+ChatGLM3+BGE,或者FAISS+Llama3+混合检索,这样用户可以根据自己的资源选择。还要提到工具推荐,比如AnythingLLM、PrivateGPT,方便不想编码的用户。 需要检查是否有遗漏的环节,比如数据安全、扩展性、维护成本等。用户可能关心如何更新知识库,是否需要定期重新处理数据,或者如何监控系统性能。此外,是否需要多语言支持,或者是否支持实时更新等。 可能用户是技术人员,想要自己搭建,所以需要详细的技术栈和步骤;或者是非技术人员,需要更简单的解决方案。但根据问题描述,用户可能有一定的技术背景,所以重点放在技术方案上,同时提供开源工具选项。 总结下来,结构应该是:流程步骤分点讲解,每个步骤的最优工具选择,示例方案,以及注意事项。确保回答清晰,覆盖关键点,帮助用户快速实现目标。</think>搭建一个高效的本地知识库问答系统(RAG架构),需重点关注数据预处理、检索效率、模型选择三大核心环节。以下是最新优化方案及技术选型建议: ### 一、核心架构流程 1. **数据预处理** - 文档解析:使用 `Unstructured` 或 `LlamaParse` 解析PDF/Word/网页等格式 - 分块策略:采用自适应分块(滑动窗口+语义分割),推荐 `semchunk` 工具 - 向量编码:选用 `BGE-M3` 多语言模型(支持密集/稀疏向量混合检索) 2. **检索系统** - 混合检索:`BM25`(关键词)+ 向量检索(语义) - 向量数据库:本地部署推荐 `Chroma`(轻量级)或 `Milvus`(高性能) - 检索优化:加入 `reranker` 模型(如BGE-Reranker)提升精度 3. **生成系统** - 本地大模型:优先选择 `Qwen1.5-4B`(中英双语/4G显存)或 `DeepSeek-MoE-16b-chat`(高性价比) - 量化部署:使用 `ollama` + `GGUF` 格式实现CPU/GPU混合推理 - RAG框架:推荐 `LangChain` + `LlamaIndex`(文档树索引) ### 二、性能优化方案 ```python # 混合检索示例代码(LangChain) from langchain_community.retrievers import BM25Retriever, EnsembleRetriever from langchain_community.vectorstores import Chroma # 初始化双检索器 bm25_retriever = BM25Retriever.from_texts(texts) vector_retriever = Chroma.from_documents(docs, embeddings).as_retriever() # 构建混合检索(权重可调) ensemble_retriever = EnsembleRetriever( retrievers=[bm25_retriever, vector_retriever], weights=[0.3, 0.7] ) # 加入重排序 from langchain.retrievers import ContextualCompressionRetriever from langchain_cohere import CohereRerank compressor = CohereRerank(top_n=5) compression_retriever = ContextualCompressionRetriever( base_compressor=compressor, base_retriever=ensemble_retriever ) ``` ### 三、硬件配置建议 - 基础版:16GB内存 + CPU(使用量化后的2B模型) - 进阶版:24GB显存GPU(如RTX4090)可运行Qwen1.5-72B-4bit - 分布式方案:使用 `vLLM` 实现多卡并行推理 ### 四、推荐技术栈组合 1. **轻量级方案** - 工具链:`TextSplitter` + `Chroma` + `Ollama` - 模型:`BGE-M3` + `Qwen1.5-4B-Chat-GGUF` 2. **企业级方案** - 工具链:`LlamaParse` + `Milvus` + `vLLM` - 模型:`voyage-large-2` + `DeepSeek-R1-Embedding` + `Yi-34B-Chat` ### 五、关键优化指标 1. **检索阶段**:召回率 >85%(Hit@5),响应时间 <200ms 2. **生成阶段**:生成延迟 <3s(7B模型),幻觉率 <15% 3. **端到端**:首次响应时间 <1.5s,准确率 >92% ### 六、避坑指南 1. 避免使用通用embedding模型(如text-embedding-ada-002) 2. 分块长度不要超过模型上下文窗口的25% 3. 定期更新知识库时,建议增量更新而非全量重建 4. 对于专业领域,建议使用领域模型继续预训练(DAPT) 当前最前沿方案可考虑使用 `ColBERTv2` 神经检索模型 + `DPR` 双编码器架构,但实现复杂度较高。建议初建系统时优先采用成熟RAG方案,后续逐步加入复杂优化策略。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

loong_XL

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值