从0到1搭建本地RAG知识库:完全离线的AI问答系统实操

📅 2026-06-13  ·  📂 实战宝典  ·  ⏱ 约 10 分钟读完

2025 年以来,大语言模型(LLM)在企业落地中最成功的范式莫过于 RAG(Retrieval-Augmented Generation,检索增强生成)。然而,大多数 RAG 方案依赖 OpenAI / 百度文心等云端 API,存在数据外泄风险、网络延迟和按量计费三大痛点。本文手把手教你用 LangChain + Chroma(本地向量数据库)+ 开源嵌入模型 + 本地 LLM,从零搭建一套完全离线的知识问答系统。

💡 适用场景:企业内部文档问答、涉密资料检索、个人知识管理、无网络环境下的 AI 助手。

一、架构概览

一个完整的本地 RAG 系统包含以下组件:

  1. 文档加载与切分 —— 读取 PDF、Markdown、TXT 等格式,按语义切块(Chunk)
  2. 嵌入模型(Embedding Model) —— 将文本块转为向量,纯本地运行
  3. 向量数据库(Chroma) —— 存储向量并支持近似搜索
  4. 大语言模型(LLM) —— 基于检索结果生成最终答案
  5. LangChain 编排层 —— 串联检索 → 生成流程

全链路数据不出本机,彻底杜绝隐私泄露。

二、环境准备

推荐 Python 3.10+,操作系统不限(Windows / macOS / Linux 均可)。

# 创建虚拟环境(推荐)
python3 -m venv rag_env
source rag_env/bin/activate   # Linux/macOS

# 安装核心依赖
pip install langchain langchain-community \
            chromadb sentence-transformers \
            transformers torch
# 如需解析 PDF 等文档
pip install pypdf python-docx markdown
💡 如果 GPU 显存充足(≥ 6GB),安装 CUDA 版 PyTorch 可大幅加速嵌入计算:pip install torch --index-url https://download.pytorch.org/whl/cu121

三、文档加载与分块

假设我们有一批公司内部技术文档(Markdown 格式),放在 ./docs/ 目录下:

from langchain_community.document_loaders import DirectoryLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter

# 1. 加载目录下所有 .md 文件
loader = DirectoryLoader("./docs", glob="**/*.md")
docs = loader.load()
print(f"已加载 {len(docs)} 个文档")

# 2. 按语义分块:每块 512 字符,重叠 64
splitter = RecursiveCharacterTextSplitter(
    chunk_size=512,
    chunk_overlap=64,
    separators=["\n## ", "\n### ", "\n\n", "\n", " ", ""]
)
chunks = splitter.split_documents(docs)
print(f"共切分为 {len(chunks)} 个文本块")

RecursiveCharacterTextSplitter 会按 Markdown 标题层级优先切分,保证同一段落的内容不被割裂。chunk_size 可根据文档长度动态调整,建议 256–1024 之间。

四、初始化嵌入模型与向量库

嵌入模型选择 BAAI/bge-base-zh-v1.5(中文语义效果优秀,仅 300MB+),完全本地加载:

from langchain_community.embeddings import HuggingFaceBgeEmbeddings
from langchain_community.vectorstores import Chroma

# 加载本地嵌入模型
embedding_model = HuggingFaceBgeEmbeddings(
    model_name="BAAI/bge-base-zh-v1.5",
    model_kwargs={ "device": "cpu" },   # 改为 "cuda" 使用 GPU
    encode_kwargs={ "normalize_embeddings": "true" }
)

# 创建 Chroma 向量库并写入
vector_store = Chroma.from_documents(
    documents=chunks,
    embedding=embedding_model,
    persist_directory="./chroma_db"   # 持久化到本地磁盘
)
vector_store.persist()
print("✅ 向量库已构建,保存在 ./chroma_db/")

首次运行会自动下载模型(约 300MB),后续加载直接从缓存读取。Chroma 默认将向量数据持久化到本地目录,重启程序无需重新构建索引。

🔍 可选的国产嵌入模型:shibing324/m3e-baseinfgrad/stella-base-zh-v3-1792d,效果各有侧重,建议用自己的数据集对比 Recall@K。

五、接入本地 LLM

LLM 选用开源的 Qwen2.5-7B-Instruct(通义千问),通过 llama.cpp 或 Ollama 本地推理。此处使用 Ollama 方案,最省心:

# 终端安装 Ollama(Linux / macOS)
curl -fsSL https://ollama.com/install.sh | sh

# 拉取模型(约 4.1GB)
ollama pull qwen2.5:7b

# 测试
ollama run qwen2.5:7b "你好,请用中文回复"

然后在 Python 中通过 LangChain 调用:

from langchain_community.llms import Ollama

llm = Ollama(
    model="qwen2.5:7b",
    temperature=0.3,          # 低温度保证回答稳定性
    num_predict=2048          # 最大生成长度
)

# 简单测试
resp = llm.invoke("请介绍一下 RAG 技术")
print(resp)

硬件要求:7B 模型在 CPU 上约 4–6 token/s(够用),推荐 16GB 内存以上;GPU 量化后可跑 20+ token/s。显存不足可选 qwen2.5:1.5bqwen2.5:3b

⚡ Ollama 自动做 4-bit 量化,7B 模型约需 5–6GB 内存,绝大多数家用电脑都能跑。

六、搭建 RAG 问答链

核心环节:用 LangChain 的 RetrievalQA 把向量检索与 LLM 生成串成一条链:

from langchain.chains import RetrievalQA
from langchain.prompts import PromptTemplate

# 自定义提示词模板,让 LLM 基于检索内容回答
prompt_template = """
你是一个专业的技术支持助手。
请根据以下资料,用中文简洁准确地回答问题。

【已知资料】
{context}

【问题】
{question}

请基于上述资料回答。如果资料中找不到答案,
请说"资料中未找到相关信息",不要编造。
"""

QA_CHAIN_PROMPT = PromptTemplate.from_template(prompt_template)

# 构建检索器:返回前 4 个最相关文本块
retriever = vector_store.as_retriever(search_kwargs={ "k": 4 })

# 组装问答链
qa_chain = RetrievalQA.from_chain_type(
    llm=llm,
    chain_type="stuff",        # 所有检索结果拼入 context
    retriever=retriever,
    chain_type_kwargs={ "prompt": QA_CHAIN_PROMPT },
    return_source_documents="true"  # 返回引用来源
)

# 开始问答
query = "我们的系统如何配置日志级别?"
result = qa_chain.invoke({ "query": query })

print("🤖 回答:", result["result"])
print("📄 参考来源:", [d.metadata.get("source") for d in result["source_documents"]])

这里 chain_type="stuff" 是将所有检索结果拼入提示词,适合文本块总量不超过 LLM 上下文窗口的场景。如果知识库庞大,可改用 map_reducerefine 策略。

七、完整运行与效果测试

将以上代码整合为一个脚本 rag_qa.py,执行一次即可完成索引构建 + 问答:

# 运行
python rag_qa.py

# 输出示例
已加载 12 个文档
共切分为 246 个文本块
✅ 向量库已构建,保存在 ./chroma_db/
🤖 回答:系统日志级别在 config.yaml 中的 logger.level
字段配置,支持 DEBUG / INFO / WARNING / ERROR 四级。
📄 参考来源:['./docs/运维手册.md', './docs/config-guide.md']

如果回答质量不理想,可以:

八、进阶方向

基础 RAG 跑通后,还可以继续优化:

下一篇文章将详解 Reranker 重排序 + HyDE 技术如何让 RAG 准确率提升 30%,欢迎持续关注乾坤Bot 实战宝典系列。

📌 总结:本文完整演示了从文档加载、向量化存储、本地 LLM 推理到最终问答的全流程。全套代码 完全离线,数据不出本机,适合对数据安全有高要求的企业和个人使用。所有依赖均为开源项目,零商业授权成本。