DeepSeek-R1-Distill-Qwen-1.5B实战教程:对接RAG增强本地知识库检索能力
DeepSeek-R1-Distill-Qwen-1.5B实战教程:对接RAG增强本地知识库检索能力
1. 引言:为什么需要给本地对话助手“装个大脑”?
想象一下,你有一个非常聪明的本地AI助手,它能和你流畅聊天、解答逻辑题、甚至写点代码。但当你问它一些关于你公司内部文档、个人笔记或者某个特定领域(比如法律、医疗)的专业问题时,它可能就“卡壳”了,因为它只知道自己训练时学到的通用知识。
这就是我们今天要解决的问题:如何让这个本地的、聪明的DeepSeek-R1-Distill-Qwen-1.5B模型,也能回答你私有的、特定的知识问题?
答案就是给它“装个大脑”——一个基于你自有文档构建的本地知识库。通过RAG(检索增强生成)技术,我们能让模型在回答问题时,先从这个知识库里找到相关材料,然后结合这些材料生成更准确、更专业的回答。
本教程将手把手带你,在已有的“DeepSeek-R1-Distill-Qwen-1.5B本地智能对话助手”基础上,无缝集成RAG能力。整个过程完全在本地运行,你的数据不出本地,隐私安全有保障,而且效果立竿见影。
学完本教程,你将能:
- 理解RAG技术如何让大模型“记住”你的专属知识。
- 掌握一套完整的本地知识库构建流程(文档处理、向量化、存储)。
- 改造现有的Streamlit聊天应用,使其具备“先检索后回答”的智能。
- 拥有一个完全私有化、能回答你特定领域问题的AI助手。
前置准备:
- 一个已经部署好的“DeepSeek-R1-Distill-Qwen-1.5B本地智能对话助手”(基于Streamlit)。
- 一些你想要让AI学习的文档(支持.txt, .md, .pdf等格式)。
- 基础的Python编程环境。
2. RAG核心原理:三分钟搞懂“检索增强生成”
别被“RAG”这个词吓到,它的核心思想非常简单,就像我们人类回答问题时一样:
- 遇到问题:先不急着回答,而是去“资料库”(比如书本、笔记、记忆)里查找相关的信息。
- 找到资料:把找到的最相关的几段资料拿出来。
- 组织答案:结合找到的资料和自己的理解,组织成完整的回答。
RAG技术就是让AI模仿这个过程:
传统大模型回答:
用户问题 -> 大模型 -> 生成答案
(模型只能依赖训练时学到的通用知识)
RAG增强后的大模型回答:
用户问题 -> 检索器(从知识库找资料)-> (问题 + 相关资料)-> 大模型 -> 生成答案
(模型在回答时,手里多了你提供的“参考资料”)
对我们这个项目来说,关键就是构建一个本地的“资料库”(向量知识库)和一个高效的“检索器”。
3. 环境搭建与核心库安装
我们需要在原有项目环境的基础上,新增几个专门用于处理文档和向量检索的库。打开终端,执行以下命令:
pip install langchain langchain-community sentence-transformers faiss-cpu pypdf
简单解释一下这些库是干什么的:
langchain&langchain-community:当今构建AI应用最流行的框架之一,它提供了处理文档、构建检索链等一系列好用的工具,能让我们省去大量底层代码。sentence-transformers:一个专门用于将文本转换成“向量”(一种计算机能理解的数字表示)的库。我们将用它来把我们的文档和用户问题都转换成向量。faiss-cpu:Facebook开源的向量数据库库(CPU版本)。想象它是一个超级高效的“图书馆索引系统”,能快速从海量向量中找到和问题最相关的几个。pypdf:用来读取PDF格式的文档。
安装完成后,我们就可以开始构建知识库了。
4. 实战第一步:构建你的本地向量知识库
知识库不是简单地把文档堆在一起,而是需要经过“读取->切分->向量化->存储”四步。我们在项目根目录下创建一个新的Python脚本,比如叫 build_knowledge_base.py。
# build_knowledge_base.py
import os
from langchain_community.document_loaders import DirectoryLoader, TextLoader, PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_community.vectorstores import FAISS
# 1. 指定你的文档所在文件夹
documents_folder = "./my_documents" # 创建一个文件夹,把你的txt、md、pdf文档放进去
if not os.path.exists(documents_folder):
os.makedirs(documents_folder)
print(f"请将您的文档放入 '{documents_folder}' 文件夹,然后重新运行此脚本。")
exit()
# 2. 加载文档(支持多种格式)
print("开始加载文档...")
loaders = []
# 加载文本文件
if any(fname.endswith('.txt') for fname in os.listdir(documents_folder)):
loaders.append(DirectoryLoader(documents_folder, glob="**/*.txt", loader_cls=TextLoader))
# 加载Markdown文件
if any(fname.endswith('.md') for fname in os.listdir(documents_folder)):
loaders.append(DirectoryLoader(documents_folder, glob="**/*.md", loader_cls=TextLoader))
# 加载PDF文件
if any(fname.endswith('.pdf') for fname in os.listdir(documents_folder)):
loaders.append(DirectoryLoader(documents_folder, glob="**/*.pdf", loader_cls=PyPDFLoader))
all_documents = []
for loader in loaders:
try:
all_documents.extend(loader.load())
except Exception as e:
print(f"加载部分文档时出错: {e}")
if not all_documents:
print(f"在 '{documents_folder}' 中未找到支持的文档(.txt, .md, .pdf)。")
exit()
print(f"成功加载 {len(all_documents)} 个文档。")
# 3. 切分文档(大文档切成小片段,方便检索)
print("正在切分文档...")
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500, # 每个片段的字符数,可根据需要调整
chunk_overlap=50 # 片段间的重叠字符,保证上下文连贯
)
doc_splits = text_splitter.split_documents(all_documents)
print(f"文档被切分为 {len(doc_splits)} 个文本片段。")
# 4. 向量化并存储
print("正在生成向量并构建知识库(这可能需要几分钟)...")
# 使用一个轻量且效果不错的中文嵌入模型
embeddings = HuggingFaceEmbeddings(model_name="BAAI/bge-small-zh-v1.5")
# 创建向量存储
vectorstore = FAISS.from_documents(doc_splits, embeddings)
# 保存到本地
save_path = "./faiss_index"
vectorstore.save_local(save_path)
print(f"✅ 知识库构建完成!已保存至 '{save_path}' 文件夹。")
print(f"你可以删除或更新 '{documents_folder}' 中的文档,然后重新运行此脚本以更新知识库。")
运行这个脚本:
- 在项目根目录下创建一个名为
my_documents的文件夹。 - 把你想要AI学习的文档(比如公司制度.txt、产品手册.pdf、学习笔记.md)放进这个文件夹。
- 在终端运行
python build_knowledge_base.py。 - 等待程序运行完毕,你会看到一个名为
faiss_index的新文件夹,里面就是构建好的向量知识库。
关键点说明:
- 文档切分:为什么要把文档切碎?因为直接检索整篇文档效率低,且可能包含无关信息。切成500字左右的小片段,检索更精准。
- 向量模型:我们选用
BAAI/bge-small-zh-v1.5,这是一个专门为中文优化的轻量级模型,效果和速度平衡得很好。 - 完全本地:整个过程,从文档读取到向量生成,全部在你的机器上完成,数据不会上传到任何地方。
5. 实战第二步:改造Streamlit应用,集成RAG问答链
现在,我们有了知识库,需要修改原来的Streamlit聊天应用,让它具备检索能力。我们主要修改模型加载和回答生成的部分。
找到你原来的Streamlit应用主文件(比如叫 app.py),我们需要在其中添加RAG相关的代码。以下是关键的修改和新增部分:
# 在原有导入的基础上,新增以下导入
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_community.vectorstores import FAISS
from langchain.chains import RetrievalQA
from langchain.prompts import PromptTemplate
# ... (原有的模型和分词器加载代码保持不变) ...
# --- 新增:加载本地向量知识库 ---
print("🚀 加载本地知识库...")
try:
embeddings = HuggingFaceEmbeddings(model_name="BAAI/bge-small-zh-v1.5")
vectorstore = FAISS.load_local("./faiss_index", embeddings, allow_dangerous_deserialization=True)
retriever = vectorstore.as_retriever(search_kwargs={"k": 3}) # 检索最相关的3个片段
print("✅ 知识库加载成功!")
except Exception as e:
st.error(f"加载知识库失败: {e}")
retriever = None
# --- 新增:定义RAG提示词模板 ---
# 这个模板告诉模型如何利用检索到的资料来回答问题
rag_prompt_template = """请根据以下提供的背景资料来回答问题。如果资料中包含答案,请基于资料回答;如果资料不相关或没有答案,请根据你自己的知识来回答,并说明这一点。
背景资料:
{context}
问题:
{question}
请用中文给出清晰、有条理的回答:"""
RAG_PROMPT = PromptTemplate.from_template(rag_prompt_template)
# --- 修改:在侧边栏添加RAG开关 ---
with st.sidebar:
st.title("⚙️ 设置")
# ... (原有的清空按钮等) ...
use_rag = st.checkbox("启用知识库增强 (RAG)", value=True, help="开启后,AI将优先从您上传的文档中寻找答案。")
st.divider()
# --- 修改:处理用户消息的函数 ---
def generate_response(user_input):
"""生成AI回复,集成RAG逻辑"""
if not user_input:
return "请输入您的问题。"
# 准备对话历史(原有逻辑)
messages_for_model = st.session_state.messages + [{"role": "user", "content": user_input}]
prompt = tokenizer.apply_chat_template(messages_for_model, tokenize=False, add_generation_prompt=True)
# **RAG核心逻辑:如果开启且知识库加载成功,先检索**
context_text = ""
if use_rag and retriever is not None:
try:
# 1. 检索相关文档片段
relevant_docs = retriever.invoke(user_input)
# 2. 将检索结果拼接成上下文
context_text = "\n\n".join([doc.page_content for doc in relevant_docs])
# 3. 将原始问题 + 检索到的上下文,构造成新的、更详细的问题给模型
# 这里我们采用一种简单有效的方式:将上下文直接插入到最新一轮用户消息前
enhanced_user_message = f"请参考以下资料回答问题:\n【资料开始】\n{context_text}\n【资料结束】\n\n我的问题是:{user_input}"
# 替换最后一轮用户消息为增强版
messages_for_model[-1]["content"] = enhanced_user_message
# 重新生成prompt
prompt = tokenizer.apply_chat_template(messages_for_model, tokenize=False, add_generation_prompt=True)
except Exception as e:
st.warning(f"知识库检索出错,将使用模型通用知识回答: {e}")
# 原有生成逻辑(保持不变)
inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
with torch.no_grad():
outputs = model.generate(**inputs,
max_new_tokens=2048,
temperature=0.6,
top_p=0.95,
do_sample=True,
pad_token_id=tokenizer.eos_token_id)
response = tokenizer.decode(outputs[0][inputs['input_ids'].shape[1]:], skip_special_tokens=True)
# 原有的标签格式化逻辑(保持不变)
response = format_response(response)
return response
# ... (Streamlit聊天界面主循环代码保持不变) ...
关键改造点解析:
- 加载知识库:应用启动时,除了加载大模型,还会加载我们之前构建好的
faiss_index向量库。 - 添加控制开关:在侧边栏增加了一个复选框,让你可以随时开启或关闭RAG功能。关闭时,模型就变回原来的通用聊天模式。
- 增强提问逻辑:在
generate_response函数中,如果RAG开启,会先进行检索。我们将检索到的资料,以清晰的标记(【资料开始】...【资料结束】)插入到用户的最新问题之前。这样,模型在生成回答时,就能“看到”这些资料。 - 优雅降级:如果检索过程出错(比如知识库没加载),代码会发出警告并回退到使用模型的通用知识来回答,保证服务可用性。
6. 效果对比与使用演示
完成改造后,重启你的Streamlit应用。现在你的聊天界面侧边栏会多出一个“启用知识库增强 (RAG)”的选项。
让我们来做个对比测试:
测试1:关闭RAG(通用模式)
- 你问:“我们公司的年假制度是怎样的?”
- AI答:(基于训练数据泛泛而谈)“年假制度通常根据国家法律法规和公司规定制定,一般员工工作满一年后享有5-15天不等的年假...”(可能不准确)
测试2:开启RAG(增强模式)
- 你问:“我们公司的年假制度是怎样的?”
- AI内部动作:先从你的
my_documents文件夹里的《员工手册.pdf》中,检索到关于年假的段落。 - AI答:“根据您提供的资料《员工手册》第三章第四节规定:本公司员工转正后,每年享有10天带薪年假。工作每满一年增加1天,上限为15天。年假申请需提前一周在OA系统提交...”(回答具体、准确、有出处)
你可以尝试的各种玩法:
- 问答个人笔记:上传你的读书笔记.md,然后问它“这本书第三章主要讲了什么观点?”
- 分析技术文档:上传某个软件API文档.pdf,然后问它“如何调用用户登录接口?”
- 总结会议纪要:上传会议记录.txt,然后让它“总结一下上周项目会的主要决议和待办事项。”
7. 总结与进阶思考
恭喜!你现在已经拥有了一个具备“专属大脑”的本地AI助手。我们来回顾一下核心成果:
- 能力升级:你的DeepSeek-R1助手不再只是一个通用的聊天机器人,而是一个能深度理解并运用你私有知识的智能伙伴。
- 全程私有:从文档处理、向量化、存储到检索和生成,所有环节均在本地完成,确保了最高级别的数据隐私和安全。
- 开箱即用:我们提供了一键构建知识库的脚本和即插即用的应用改造方案,你只需要准备好文档,几步操作就能完成部署。
可能的进阶优化方向:
- 知识库更新:当你有新文档时,重新运行
build_knowledge_base.py脚本即可更新整个索引。对于频繁更新的场景,可以考虑增量更新策略。 - 检索优化:调整
search_kwargs={"k": 3}中的k值,控制每次检索返回的文档片段数量。太多可能引入噪音,太少可能信息不足。 - 提示词工程:微调
rag_prompt_template,让模型更好地利用上下文。例如,要求它注明答案来源于哪份资料。 - 前端展示:可以在AI回答旁边,增加一个“查看参考来源”的折叠区域,展示它具体引用了哪几个文档片段,增加可信度。
- 混合检索:结合基于关键词的传统检索和向量检索,提升召回率。
这个项目展示了如何将强大的开源大模型与灵活的RAG技术相结合,以极低的成本(一个轻量模型+本地CPU)构建出真正实用、私有的企业级或个人知识助手。希望你能在此基础上,继续探索,打造出更贴合自己需求的AI应用。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。
更多推荐


所有评论(0)