本文纯干货分享,干巴文章大家自带咖啡

带你从零开始搭建一个完整的本地RAG(检索增强生成)应用,使用DeepSeek系列模型、Ollama框架和开源向量数据库,支持中文和多语言文档处理。

一、环境准备与安装

1.1 硬件要求

  • 最低配置:8GB内存 + 4核CPU(运行1.5B小模型)

  • 推荐配置:16GB以上内存 + NVIDIA GPU(运行7B及以上模型)

  • 存储空间:至少20GB可用空间(用于模型和向量数据库)

1.2 软件安装

1.2.1 安装Ollama

Ollama是本地运行大模型的工具,支持Windows/Mac/Linux:

bash

# Linux/macOS一键安装
curl -fsSL https://ollama.com/install.sh | sh

# Windows用户从官网下载安装包
# https://ollama.com/download

验证安装:

bash

ollama --version
1.2.2 安装Python环境

推荐使用Python 3.9+:

bash

# 创建虚拟环境
python -m venv rag_env
source rag_env/bin/activate  # Linux/macOS
# Windows: rag_env\Scripts\activate

# 安装核心依赖
pip install langchain chromadb sentence-transformers unstructured pdfplumber
1.2.3 下载模型

拉取DeepSeek R1生成模型和嵌入模型:

bash

# 生成模型(7B参数版本)
ollama pull deepseek-r1

# 嵌入模型(用于文本向量化)
ollama pull nomic-embed-text

# 备用小模型(低配置设备)
ollama pull deepseek-r1:1.5b

二、项目结构搭建

创建项目目录结构:

my_rag_app/
├── data/                  # 存放原始文档
├── chroma_db/             # 向量数据库存储
├── configs/               # 配置文件
│   └── prompts.yaml       # 提示词模板
├── scripts/               # 辅助脚本
├── app.py                 # 主应用
└── requirements.txt       # 依赖列表

三、文档处理流程

3.1 支持的文件类型

  • PDF

  • Word (.docx)

  • Excel (.xlsx)

  • PowerPoint (.pptx)

  • TXT

  • Markdown

  • HTML

3.2 文档加载与分割

创建document_processor.py

python

from langchain.document_loaders import (
    PDFPlumberLoader,
    UnstructuredWordDocumentLoader,
    UnstructuredExcelLoader,
    TextLoader
)
from langchain.text_splitter import RecursiveCharacterTextSplitter

class DocumentProcessor:
    def __init__(self):
        self.text_splitter = RecursiveCharacterTextSplitter(
            chunk_size=500,
            chunk_overlap=50,
            length_function=len,
            add_start_index=True
        )
    
    def load_document(self, file_path):
        if file_path.endswith('.pdf'):
            loader = PDFPlumberLoader(file_path)
        elif file_path.endswith('.docx'):
            loader = UnstructuredWordDocumentLoader(file_path)
        elif file_path.endswith('.xlsx'):
            loader = UnstructuredExcelLoader(file_path)
        else:
            loader = TextLoader(file_path)
        
        return loader.load()
    
    def process_documents(self, file_paths):
        all_splits = []
        for path in file_paths:
            docs = self.load_document(path)
            splits = self.text_splitter.split_documents(docs)
            all_splits.extend(splits)
        return all_splits

四、向量数据库搭建

4.1 初始化向量数据库

创建vector_db.py

python

from langchain.vectorstores import Chroma
from langchain.embeddings import HuggingFaceEmbeddings
import os

class VectorDB:
    def __init__(self, persist_dir="./chroma_db"):
        self.embedding_model = HuggingFaceEmbeddings(
            model_name="nomic-ai/nomic-embed-text-v1",
            model_kwargs={'device': 'cpu'}  # 有GPU可改为'cuda'
        )
        self.persist_dir = persist_dir
        os.makedirs(persist_dir, exist_ok=True)
        
    def create_store(self, documents):
        return Chroma.from_documents(
            documents=documents,
            embedding=self.embedding_model,
            persist_directory=self.persist_dir
        )
    
    def load_store(self):
        return Chroma(
            persist_directory=self.persist_dir,
            embedding_function=self.embedding_model
        )

4.2 批量导入文档

创建ingest.py脚本:

python

from document_processor import DocumentProcessor
from vector_db import VectorDB
import glob

def main():
    # 获取data目录下所有文档
    doc_paths = glob.glob("./data/*")
    
    # 处理文档
    processor = DocumentProcessor()
    splits = processor.process_documents(doc_paths)
    
    # 创建向量存储
    vector_db = VectorDB()
    vector_store = vector_db.create_store(splits)
    print(f"已成功导入 {len(splits)} 个文档片段")

if __name__ == "__main__":
    main()

运行:

bash

python ingest.py

五、RAG问答系统实现

5.1 配置提示词模板

创建configs/prompts.yaml

yaml

qa_template: |
  请根据以下上下文信息回答问题。如果不知道答案,就说你不知道,不要编造答案。
  
  上下文:
  {context}
  
  问题:{question}
  
  答案:

5.2 构建问答链

创建rag_chain.py

python

from langchain.chains import RetrievalQA
from langchain.prompts import load_prompt
from langchain.llms import Ollama
from vector_db import VectorDB
import os

class RAGChain:
    def __init__(self):
        # 加载向量数据库
        self.vector_db = VectorDB()
        self.vector_store = self.vector_db.load_store()
        
        # 初始化LLM
        self.llm = Ollama(
            model="deepseek-r1",
            temperature=0.3,
            top_p=0.9
        )
        
        # 加载提示词
        self.qa_prompt = load_prompt(os.path.join("configs", "prompts.yaml"))
    
    def get_qa_chain(self):
        return RetrievalQA.from_chain_type(
            llm=self.llm,
            chain_type="stuff",
            retriever=self.vector_store.as_retriever(
                search_type="mmr",  # 最大边际相关性搜索
                search_kwargs={"k": 4}
            ),
            chain_type_kwargs={"prompt": self.qa_prompt},
            return_source_documents=True
        )

5.3 主应用实现

创建app.py

python

from rag_chain import RAGChain
import argparse

def main():
    # 初始化RAG链
    rag = RAGChain()
    qa_chain = rag.get_qa_chain()
    
    # 命令行交互
    parser = argparse.ArgumentParser()
    parser.add_argument("--question", type=str, help="直接提问的问题")
    args = parser.parse_args()
    
    if args.question:
        # 命令行模式
        result = qa_chain({"query": args.question})
        print("\n答案:", result["result"])
        print("\n来源文档:")
        for doc in result["source_documents"]:
            print("-", doc.metadata["source"], "第", doc.metadata.get("page", "N/A"), "页")
    else:
        # 交互模式
        print("RAG系统已启动,输入'exit'退出")
        while True:
            question = input("\n你的问题: ")
            if question.lower() in ['exit', 'quit']:
                break
                
            result = qa_chain({"query": question})
            print("\n答案:", result["result"])
            print("\n来源文档:")
            for doc in result["source_documents"]:
                print("-", doc.metadata["source"], "第", doc.metadata.get("page", "N/A"), "页")

if __name__ == "__main__":
    main()

六、运行与测试

6.1 启动应用

bash

# 交互模式
python app.py

# 命令行直接提问
python app.py --question "你的问题是什么?"

6.2 测试示例

假设我们导入了一份关于人工智能的白皮书:

问题:人工智能的主要应用领域有哪些?

答案:根据文档内容,人工智能的主要应用领域包括:
1. 医疗健康(医学影像分析、辅助诊断)
2. 金融服务(风险管理、量化交易)
3. 智能制造(质量检测、预测性维护)
4. 零售电商(个性化推荐、智能客服)

来源文档:
- AI_白皮书.pdf 第 15 页
- AI_白皮书.pdf 第 23 页

七、高级配置与优化

7.1 性能优化

  1. GPU加速

    python

    # 在vector_db.py中修改
    self.embedding_model = HuggingFaceEmbeddings(
        model_name="nomic-ai/nomic-embed-text-v1",
        model_kwargs={'device': 'cuda'}  # 使用GPU
    )
  2. 量化模型(减少内存占用):

    bash

    ollama pull deepseek-r1:4bit  # 4位量化版本

7.2 多语言支持

  1. 切换嵌入模型:

    bash

    ollama pull multilingual-e5-large  # 多语言嵌入模型
  2. 修改vector_db.py

    python

    self.embedding_model = HuggingFaceEmbeddings(
        model_name="intfloat/multilingual-e5-large"
    )

7.3 自定义检索策略

修改rag_chain.py中的检索参数:

python

retriever=self.vector_store.as_retriever(
    search_type="similarity_score_threshold",
    search_kwargs={
        "k": 5,
        "score_threshold": 0.5  # 相似度阈值
    }
)

八、常见问题解决

8.1 Ollama服务问题

症状:连接Ollama服务失败
解决

bash

# 确保服务运行
ollama serve

# 检查环境变量
export OLLAMA_HOST=127.0.0.1:11434

8.2 内存不足

症状:加载模型时崩溃
解决

  1. 使用小模型:ollama pull deepseek-r1:1.5b

  2. 添加交换空间(Linux):

    bash

    sudo fallocate -l 4G /swapfile
    sudo chmod 600 /swapfile
    sudo mkswap /swapfile
    sudo swapon /swapfile

8.3 中文支持不佳

症状:中文回答质量差
解决

  1. 使用中文提示词模板

  2. 尝试专用中文模型:

    bash

    ollama pull qwen:7b  # 阿里通义千问

九、部署选项

9.1 本地Web界面

安装Gradio创建简单UI:

bash

pip install gradio

创建web_ui.py

python

import gradio as gr
from rag_chain import RAGChain

rag = RAGChain()
qa_chain = rag.get_qa_chain()

def respond(question):
    result = qa_chain({"query": question})
    sources = "\n".join([f"- {doc.metadata['source']}" for doc in result["source_documents"]])
    return f"{result['result']}\n\n来源文档:\n{sources}"

iface = gr.Interface(
    fn=respond,
    inputs="text",
    outputs="text",
    title="DeepSeek RAG 问答系统"
)

iface.launch(server_name="0.0.0.0")

运行:

bash

python web_ui.py

9.2 Docker部署

创建Dockerfile

dockerfile

FROM python:3.9-slim

WORKDIR /app
COPY . .

RUN apt-get update && apt-get install -y \
    gcc \
    python3-dev \
    && rm -rf /var/lib/apt/lists/*

RUN pip install -r requirements.txt

EXPOSE 7860
CMD ["python", "web_ui.py"]

构建并运行:

bash

docker build -t rag-app .
docker run -p 7860:7860 rag-app

十、项目扩展思路

  1. 多文档管理:添加文档删除/更新功能

  2. 对话历史:实现多轮对话记忆

  3. API服务:使用FastAPI创建REST接口

  4. 定时同步:监控文档目录自动更新向量库

  5. 混合检索:结合关键词和向量搜索


通过本文,你已经成功搭建了一个功能完整的本地RAG应用。这个系统可以处理多种文档格式,支持中文问答,并且完全在本地运行,保障了数据隐私。根据你的需求,可以进一步扩展功能或优化性能。

Logo

GitCode 天启AI是一款由 GitCode 团队打造的智能助手,基于先进的LLM(大语言模型)与多智能体 Agent 技术构建,致力于为用户提供高效、智能、多模态的创作与开发支持。它不仅支持自然语言对话,还具备处理文件、生成 PPT、撰写分析报告、开发 Web 应用等多项能力,真正做到“一句话,让 Al帮你完成复杂任务”。

更多推荐