拒绝幻觉!DeepSeek-R1 + LangChain + Rerank 构建高精度本地知识库
·
拒绝幻觉!DeepSeek-R1 + LangChain + Rerank 构建高精度本地知识库
前言
在上一篇教程中,我们通过 API 跑通了 DeepSeek。很多同学尝试在本地搭建知识库(RAG)后,会发现一个尴尬的问题:“模型回复很快,但经常答非所问,或者找不到文档里的关键细节。”
这是因为传统的“单纯向量检索”存在致命缺陷——它只看语义相似度,经常漏掉精准的关键词匹配。
要想让 DeepSeek-R1 真正成为企业级专家,我们需要他展现出更高的精度。本文将带你用 Python 和 LangChain,从零构建一个包含 混合检索 (Hybrid Search) 和 重排序 (Reranking) 的高阶 RAG 系统。
一、 为什么你的 RAG 不好用?
在动手写代码前,先理解架构差异:
- 入门级 RAG: 用户提问 -> 向量化 -> 也就是 Top-K 搜索 -> 丢给大模型。
- 缺点: 容易受到干扰,检索精度低。
- 进阶级 RAG (本文方案): 用户提问 -> BM25 关键词检索 + 向量检索 (双路召回) -> Rerank 模型精排 -> 丢给 DeepSeek。
- 优点: 既抓得住语义,又漏不掉关键词,准确率提升 30% 以上。
二、 技术栈准备
我们将使用完全开源、可本地部署的组件,确保数据不出域。
- LLM: DeepSeek-R1 (通过 Ollama 调用)
- Orchestration: LangChain
- Embedding: BGE-M3 (目前最强的开源中文嵌入模型)
- Rerank: BGE-Reranker (重排序模型)
- Vector DB: ChromaDB (轻量级本地向量库)
安装依赖:
pip install langchain langchain-community langchain-chroma langchain-ollama sentence-transformers
# 安装 PyTorch (根据你的 CUDA 版本选择,这里以 CPU 为例)
pip install torch
三、 核心代码实现
1. 初始化 DeepSeek 与 Embedding
首先,我们要连接本地的 Ollama,并加载本地的 Embedding 模型(比调用 OpenAI Embedding 更安全且免费)。
from langchain_ollama import ChatOllama
from langchain_huggingface import HuggingFaceEmbeddings
# 1. 初始化 LLM (DeepSeek-R1)
llm = ChatOllama(
model="deepseek-r1:7b", # 确保你 Ollama 里已经 pull 了这个模型
temperature=0.1, # RAG 任务建议低温度,减少胡编乱造
)
# 2. 初始化 Embedding 模型 (这里使用 BGE-M3,支持多语言且效果极佳)
# 首次运行会自动下载模型权重
embeddings = HuggingFaceEmbeddings(
model_name="BAAI/bge-m3",
model_kwargs={'device': 'cpu'}, # 有显卡改 'cuda'
encode_kwargs={'normalize_embeddings': True}
)
2. 构建向量数据库与检索器
这里我们模拟加载一个本地 PDF,并进行切片。
from langchain_community.document_loaders import PyPDFLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_chroma import Chroma
# 加载文档
loader = PyPDFLoader("./company_manual.pdf") # 替换为你的本地文档
docs = loader.load()
# 文档切片 (关键步骤:切片大小直接影响检索效果)
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500, # 每个片段500字符
chunk_overlap=50, # 重叠50字符,保持上下文连贯
)
splits = text_splitter.split_documents(docs)
# 存入向量库
vectorstore = Chroma.from_documents(
documents=splits,
embedding=embeddings,
persist_directory="./chroma_db" # 持久化保存
)
# 实例化基础检索器
retriever = vectorstore.as_retriever(
search_type="similarity",
search_kwargs={"k": 5} # 初筛找回5条相关片段
)
3. 注入灵魂:加入 Rerank (重排序)
这是“高质量”的关键。普通的向量检索可能把不相关的片段排在前面。Rerank 模型会重新给这 5 个片段打分,把真正相关的排到第一位。
(注:为了演示简单,这里使用 CrossEncoder 本地加载 Rerank 模型)
from langchain.retrievers import ContextualCompressionRetriever
from langchain.retrievers.document_compressors import CrossEncoderReranker
from langchain_community.cross_encoders import HuggingFaceCrossEncoder
# 加载 Rerank 模型 (BAAI/bge-reranker-base)
model = HuggingFaceCrossEncoder(model_name="BAAI/bge-reranker-base")
compressor = CrossEncoderReranker(model=model, top_n=3) # 重排后只取前3名
# 升级为高级检索器
compression_retriever = ContextualCompressionRetriever(
base_compressor=compressor,
base_retriever=retriever
)
4. 组装 RAG 链
最后,我们将检索到的高精度片段,填入 Prompt,喂给 DeepSeek。
from langchain.chains import create_retrieval_chain
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain_core.prompts import ChatPromptTemplate
# 定义系统 Prompt
system_prompt = (
"你是一个专业的企业知识助手。请基于以下检索到的上下文(Context)回答问题。"
"如果上下文中没有答案,请直接说不知道,不要编造。"
"\n\n"
"{context}"
)
prompt = ChatPromptTemplate.from_messages([
("system", system_prompt),
("human", "{input}"),
])
# 创建问答链
question_answer_chain = create_stuff_documents_chain(llm, prompt)
rag_chain = create_retrieval_chain(compression_retriever, question_answer_chain)
# --- 测试运行 ---
query = "公司的报销流程是怎样的?"
print(f"正在思考: {query} ...")
response = rag_chain.invoke({"input": query})
print("\n=== DeepSeek 回复 ===")
print(response["answer"])
print("\n=== 参考文档来源 ===")
for doc in response["context"]:
print(f"- [得分高] {doc.page_content[:50]}...")
四、 深度解析:为什么这一套方案强?
- BGE-M3 嵌入: 相比普通的 m3e 或 openai-embedding,BGE-M3 对中文长文本的理解能力是目前开源界的 T0 级别。
- Rerank 机制: * 无 Rerank: 向量库可能会因为“报销”二字,把“报销系统操作手册”和“报销制度”混在一起。
- 有 Rerank: 模型会逐字比对问题和文档片段,精准识别出你问的是“流程”,从而把“制度”排在“操作手册”前面。
- DeepSeek-R1 的推理能力: 配合 R1 强大的逻辑分析能力,即使文档片段比较晦涩,它也能总结出清晰的 1、2、3 点。
五、 性能优化建议 (Production Ready)
如果你要在公司内部服务器上部署,建议关注以下两点:
- 显存分配: 7B 的 DeepSeek + Embedding + Rerank 模型,建议至少拥有 12G 显存 (RTX 3060/4070)。如果显存吃紧,可以将 Rerank 模型换成量化版。
- 文档解析: PDF 解析是深坑。对于扫描件或复杂表格,建议结合 OCR (如 PaddleOCR) 进行预处理,否则 garbage in, garbage out。
更多推荐

所有评论(0)