DeepSeek-R1-Distill-Qwen-1.5B实战教程:对接RAG系统扩展本地知识问答能力

1. 项目概述

DeepSeek-R1-Distill-Qwen-1.5B是一个超轻量级的智能对话模型,融合了DeepSeek优秀的逻辑推理能力和Qwen成熟的模型架构。经过蒸馏优化后,模型在保留核心能力的同时大幅降低了计算资源需求,仅1.5B的参数规模使其完美适配低显存GPU和轻量计算环境。

本教程将指导您如何将这个强大的本地对话模型与RAG(检索增强生成)系统对接,构建一个能够访问和利用本地知识库的智能问答系统。通过这种组合,您可以突破模型本身的知识限制,让AI助手能够基于您的专属文档和数据提供精准回答。

2. 环境准备与快速部署

2.1 系统要求

在开始之前,请确保您的系统满足以下要求:

  • Python 3.8或更高版本
  • 至少8GB系统内存
  • GPU显存至少4GB(推荐)或纯CPU运行
  • 磁盘空间至少10GB用于存储模型和知识库

2.2 安装依赖包

pip install torch transformers streamlit sentence-transformers faiss-cpu langchain

如果您使用GPU加速,请安装对应的CUDA版本:

pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
pip install faiss-gpu

2.3 模型下载与配置

模型文件通常存储在本地路径 /root/ds_1.5b,如果您还没有模型文件,可以通过以下方式获取:

from transformers import AutoTokenizer, AutoModelForCausalLM

# 下载并加载模型
model_name = "DeepSeek-R1-Distill-Qwen-1.5B"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(model_name)

# 保存到本地路径
model.save_pretrained("/root/ds_1.5b")
tokenizer.save_pretrained("/root/ds_1.5b")

3. RAG系统基础概念

3.1 什么是RAG系统

RAG(Retrieval-Augmented Generation)即检索增强生成,是一种将信息检索与文本生成相结合的技术。它通过以下步骤工作:

  1. 检索:从知识库中查找与问题相关的文档片段
  2. 增强:将检索到的信息与原始问题结合
  3. 生成:基于增强后的上下文生成最终回答

这种方法让模型能够访问外部知识源,大大扩展了其知识范围和回答准确性。

3.2 为什么需要RAG

单纯依赖预训练模型存在以下限制:

  • 知识截止日期固定,无法获取最新信息
  • 无法访问私有或特定领域的知识
  • 可能产生事实性错误或幻觉

RAG系统通过引入外部知识库,有效解决了这些问题。

4. 构建本地知识库

4.1 准备知识文档

首先收集您想要让模型能够访问的文档,这些可以是:

  • 公司内部文档
  • 产品说明书
  • 技术文档
  • 常见问题解答
  • 任何其他相关文本资料

将文档保存为txt、pdf或docx格式,并统一存放在一个目录中。

4.2 文档处理与向量化

使用sentence-transformers将文档转换为向量表示:

from sentence_transformers import SentenceTransformer
import numpy as np

# 加载嵌入模型
embed_model = SentenceTransformer('all-MiniLM-L6-v2')

# 读取和处理文档
def process_documents(doc_paths):
    documents = []
    for path in doc_paths:
        with open(path, 'r', encoding='utf-8') as f:
            content = f.read()
            # 按段落分割
            paragraphs = [p for p in content.split('\n\n') if len(p.strip()) > 50]
            documents.extend(paragraphs)
    return documents

# 生成向量数据库
def create_vector_db(documents, embed_model):
    embeddings = embed_model.encode(documents)
    return documents, embeddings

# 保存向量数据库
doc_paths = ["doc1.txt", "doc2.txt", "doc3.txt"]  # 替换为您的文档路径
documents = process_documents(doc_paths)
documents, embeddings = create_vector_db(documents, embed_model)

# 保存到文件
np.save("knowledge_vectors.npy", embeddings)
with open("knowledge_texts.txt", "w", encoding='utf-8') as f:
    for doc in documents:
        f.write(doc + "\n---\n")

4.3 建立检索系统

使用FAISS构建高效的向量检索系统:

import faiss
import numpy as np

def setup_faiss_index(embeddings):
    dimension = embeddings.shape[1]
    index = faiss.IndexFlatL2(dimension)
    index.add(embeddings)
    return index

# 加载之前保存的向量
embeddings = np.load("knowledge_vectors.npy")
index = setup_faiss_index(embeddings)

# 检索相关文档
def retrieve_documents(query, embed_model, index, documents, top_k=3):
    query_embedding = embed_model.encode([query])
    distances, indices = index.search(query_embedding, top_k)
    
    results = []
    for i in indices[0]:
        results.append(documents[i])
    
    return results

5. 对接RAG与对话模型

5.1 构建RAG增强的问答流程

现在我们将RAG系统与DeepSeek模型对接:

from transformers import AutoTokenizer, AutoModelForCausalLM
import torch

# 加载对话模型
tokenizer = AutoTokenizer.from_pretrained("/root/ds_1.5b")
model = AutoModelForCausalLM.from_pretrained("/root/ds_1.5b")

def rag_enhanced_qa(question, embed_model, faiss_index, knowledge_docs, top_k=3):
    # 检索相关知识
    relevant_docs = retrieve_documents(question, embed_model, faiss_index, knowledge_docs, top_k)
    
    # 构建增强的提示
    context = "\n".join(relevant_docs)
    prompt = f"""基于以下参考信息,请回答用户的问题。如果参考信息中没有相关答案,请根据你的知识回答。

参考信息:
{context}

问题:{question}

请先思考再回答:"""
    
    # 生成回答
    inputs = tokenizer(prompt, return_tensors="pt")
    with torch.no_grad():
        outputs = model.generate(
            inputs.input_ids,
            max_new_tokens=1024,
            temperature=0.6,
            top_p=0.95,
            do_sample=True,
            pad_token_id=tokenizer.eos_token_id
        )
    
    response = tokenizer.decode(outputs[0], skip_special_tokens=True)
    # 提取新生成的部分
    response = response[len(prompt):].strip()
    
    return response, relevant_docs

5.2 优化提示工程

为了获得更好的效果,我们可以优化提示模板:

def build_enhanced_prompt(question, context_docs):
    context = "\n".join([f"[参考{i+1}] {doc}" for i, doc in enumerate(context_docs)])
    
    prompt = f"""你是一个专业的助手,请基于提供的参考信息回答用户问题。遵循以下规则:

1. 仔细分析每个参考信息与问题的相关性
2. 如果参考信息能完全回答问题,直接基于参考信息回答
3. 如果参考信息部分相关,结合参考信息和自身知识回答
4. 如果参考信息完全不相关,仅使用自身知识回答
5. 保持回答准确、简洁、有帮助

参考信息:
{context}

用户问题:{question}

请逐步思考然后给出最终答案:"""
    
    return prompt

6. 完整系统集成

6.1 创建Streamlit交互界面

现在我们将所有组件集成到Streamlit界面中:

import streamlit as st
import numpy as np
import faiss
from sentence_transformers import SentenceTransformer
from transformers import AutoTokenizer, AutoModelForCausalLM
import torch

# 初始化session state
if "messages" not in st.session_state:
    st.session_state.messages = []
if "knowledge_loaded" not in st.session_state:
    st.session_state.knowledge_loaded = False

# 侧边栏配置
st.sidebar.title("配置选项")
top_k = st.sidebar.slider("检索文档数量", 1, 5, 3)
temperature = st.sidebar.slider("生成温度", 0.1, 1.0, 0.6)

# 加载资源
@st.cache_resource
def load_resources():
    # 加载嵌入模型
    embed_model = SentenceTransformer('all-MiniLM-L6-v2')
    
    # 加载向量数据库
    embeddings = np.load("knowledge_vectors.npy")
    with open("knowledge_texts.txt", "r", encoding='utf-8') as f:
        documents = f.read().split("\n---\n")
    
    # 创建FAISS索引
    dimension = embeddings.shape[1]
    index = faiss.IndexFlatL2(dimension)
    index.add(embeddings)
    
    # 加载对话模型
    tokenizer = AutoTokenizer.from_pretrained("/root/ds_1.5b")
    model = AutoModelForCausalLM.from_pretrained("/root/ds_1.5b")
    
    return embed_model, index, documents, tokenizer, model

# 主界面
st.title("DeepSeek-R1 + RAG 智能问答系统")

# 显示聊天记录
for message in st.session_state.messages:
    with st.chat_message(message["role"]):
        st.markdown(message["content"])
        if "sources" in message:
            with st.expander("查看参考来源"):
                for i, source in enumerate(message["sources"]):
                    st.write(f"来源 {i+1}: {source[:200]}...")

# 用户输入
if prompt := st.chat_input("请输入您的问题..."):
    # 添加用户消息
    st.session_state.messages.append({"role": "user", "content": prompt})
    with st.chat_message("user"):
        st.markdown(prompt)
    
    # 加载资源(如果尚未加载)
    if not st.session_state.knowledge_loaded:
        with st.spinner("正在加载知识库和模型..."):
            embed_model, index, documents, tokenizer, model = load_resources()
            st.session_state.update({
                "embed_model": embed_model,
                "index": index,
                "documents": documents,
                "tokenizer": tokenizer,
                "model": model,
                "knowledge_loaded": True
            })
    
    # 生成回答
    with st.chat_message("assistant"):
        with st.spinner("正在检索和生成回答..."):
            # 检索相关文档
            query_embedding = st.session_state.embed_model.encode([prompt])
            distances, indices = st.session_state.index.search(query_embedding, top_k)
            
            relevant_docs = []
            for i in indices[0]:
                relevant_docs.append(st.session_state.documents[i])
            
            # 构建提示
            context = "\n".join([f"[参考{i+1}] {doc}" for i, doc in enumerate(relevant_docs)])
            enhanced_prompt = f"""基于以下参考信息回答用户问题。如果参考信息不相关,请基于自身知识回答。

参考信息:
{context}

问题:{prompt}

请先思考再回答:"""
            
            # 生成回答
            inputs = st.session_state.tokenizer(enhanced_prompt, return_tensors="pt")
            with torch.no_grad():
                outputs = st.session_state.model.generate(
                    inputs.input_ids,
                    max_new_tokens=1024,
                    temperature=temperature,
                    top_p=0.95,
                    do_sample=True,
                    pad_token_id=st.session_state.tokenizer.eos_token_id
                )
            
            response = st.session_state.tokenizer.decode(outputs[0], skip_special_tokens=True)
            response = response[len(enhanced_prompt):].strip()
            
            # 显示回答和来源
            st.markdown(response)
            with st.expander("查看参考来源"):
                for i, doc in enumerate(relevant_docs):
                    st.write(f"来源 {i+1}: {doc[:200]}...")
            
            # 保存到历史
            st.session_state.messages.append({
                "role": "assistant", 
                "content": response,
                "sources": relevant_docs
            })

# 清空对话按钮
if st.sidebar.button("清空对话历史"):
    st.session_state.messages = []
    st.rerun()

6.2 系统优化建议

为了获得更好的性能体验,可以考虑以下优化措施:

内存优化

# 使用更轻量的嵌入模型
embed_model = SentenceTransformer('all-MiniLM-L6-v2')

# 模型量化加载
model = AutoModelForCausalLM.from_pretrained(
    "/root/ds_1.5b",
    torch_dtype=torch.float16,
    device_map="auto"
)

检索优化

# 使用更高效的索引
index = faiss.IndexIVFFlat(faiss.IndexFlatL2(dimension), dimension, 100)
index.train(embeddings)
index.add(embeddings)

7. 实际应用案例

7.1 企业内部知识问答

假设您有一家科技公司,可以将以下文档纳入知识库:

  • 产品开发文档
  • 客户常见问题
  • 技术白皮书
  • 市场研究报告

员工可以直接向系统提问,如:"我们产品X的主要技术特点是什么?"系统会从内部文档中检索相关信息并生成准确回答。

7.2 学术研究助手

研究人员可以将论文库、实验数据、研究方法文档导入系统,然后询问:"关于神经网络优化方法的最新研究进展有哪些?"系统会从学术文献中提取相关信息。

7.3 客户支持系统

将产品手册、故障排除指南、客户案例等文档纳入系统,客户支持团队可以快速获取准确信息,提高服务效率。

8. 总结

通过本教程,您已经学会了如何将DeepSeek-R1-Distill-Qwen-1.5B模型与RAG系统对接,构建一个强大的本地知识问答系统。这种组合方案具有以下优势:

  1. 知识实时性:可以随时更新知识库,保持信息的最新性
  2. 领域特异性:能够针对特定领域或企业需求进行定制
  3. 数据安全性:所有处理和问答都在本地完成,保障数据隐私
  4. 成本效益:利用轻量级模型实现高质量问答,降低计算成本
  5. 可解释性:可以查看回答所依据的参考来源,增强可信度

实际部署时,建议根据具体需求调整检索策略、提示模板和生成参数,以获得最佳效果。这种架构不仅适用于文本问答,还可以扩展到多模态检索、代码检索等多种场景。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐