本文纯干货分享,干巴文章大家自带咖啡
带你从零开始搭建一个完整的本地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 支持的文件类型
- 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 性能优化
-
GPU加速:
python
# 在vector_db.py中修改 self.embedding_model = HuggingFaceEmbeddings( model_name="nomic-ai/nomic-embed-text-v1", model_kwargs={'device': 'cuda'} # 使用GPU ) -
量化模型(减少内存占用):
bash
ollama pull deepseek-r1:4bit # 4位量化版本
7.2 多语言支持
-
切换嵌入模型:
bash
ollama pull multilingual-e5-large # 多语言嵌入模型 -
修改
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 内存不足
症状:加载模型时崩溃
解决:
-
使用小模型:
ollama pull deepseek-r1:1.5b -
添加交换空间(Linux):
bash
sudo fallocate -l 4G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile
8.3 中文支持不佳
症状:中文回答质量差
解决:
-
使用中文提示词模板
-
尝试专用中文模型:
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
十、项目扩展思路
- 多文档管理:添加文档删除/更新功能
- 对话历史:实现多轮对话记忆
- API服务:使用FastAPI创建REST接口
- 定时同步:监控文档目录自动更新向量库
- 混合检索:结合关键词和向量搜索
通过本文,你已经成功搭建了一个功能完整的本地RAG应用。这个系统可以处理多种文档格式,支持中文问答,并且完全在本地运行,保障了数据隐私。根据你的需求,可以进一步扩展功能或优化性能。