在大模型应用落地过程中,“本地知识库问答” 是最核心、最常见的场景之一 —— 通过将私有文档(PDF/TXT/Excel)转化为结构化向量,结合大模型实现 “基于私有数据的精准问答”,既解决了大模型 “知识过时” 的问题,又保障了数据隐私(无需将敏感数据上传到公有云)。

    本文将从背景、核心原理、技术路线、完整实现四个维度,手把手教你搭建一套支持 PDF / 多文件 / 长文本的本地 RAG(检索增强生成)问答系统,所有核心流程和代码均可直接复用。

一、RAG 核心背景:为什么需要检索增强生成?

1. 纯大模型问答的痛点

  • 知识时效性差

    大模型的训练数据有时间截止(比如 GPT-3.5 截止 2021 年 9 月),无法回答最新的私有文档内容;

  • 幻觉问题

        纯大模型易生成 “看似合理但错误” 的内容,尤其对专业领域知识;

  • 数据隐私风险

        将企业 / 个人敏感文档上传到公有大模型 API,存在数据泄露风险;

  • 长文本处理能力弱

        大模型有上下文窗口限制(比如 8k/16k),无法直接处理万字级的长文档。

2. RAG 的核心价值

   RAG(Retrieval-Augmented Generation,检索增强生成)通过 “先检索、后生成” 的模式,完美解决上述问题:

  • 知识私有化:基于本地文档构建知识库,所有数据不上云;
  • 回答精准化:从私有文档中检索相似内容,作为大模型回答的依据,大幅降低幻觉;
  • 长文本适配:通过 “分块 + 检索”,突破大模型上下文窗口限制;
  • 低成本落地:无需重新训练大模型,仅需适配本地文档即可快速落地。

二、RAG 核心原理:5 步全流程(必须掌握)

     RAG 的核心逻辑是 “将非结构化文档转化为可检索的向量,结合检索结果辅助大模型回答”,完整流程可拆解为 5 个核心步骤:

核心步骤解析

  1. 加载文档

        将 PDF/TXT/MD 等非结构化文件转化为程序可处理的文本格式;

  2. 文本分块

        将长文本拆分为大小适中的 “文本块”(Chunk),适配大模型上下文窗口,同时保证语义完整;

  3. 文本向量化

        通过 Embedding 模型将每个文本块转化为数值型向量(Embedding),向量的相似度代表文本语义的相似度;

  4. 存入向量库

        将向量和对应的文本块存入向量数据库(如 FAISS/Chroma),支持快速的相似度检索;

  5. 问答阶段

        用户提问→提问向量化→向量库检索 Top-N 相似文本块→将 “提问 + 检索结果” 传给大模型→生成精准回答。

三、RAG 技术路线:核心组件选型(本地优先)

搭建本地 RAG 系统的核心是 “组件选型适配本地环境”,以下是经过验证的最优技术路线(新手直接抄)

环节

核心组件

选型理由

文档加载

PyPDFLoader/TextLoader

LangChain 原生支持,适配 PDF/TXT,轻量无依赖

文本分块

RecursiveCharacterTextSplitter

对中文友好,支持按语义分隔(换行 / 句号 / 逗号),长文本分块最优选择

嵌入模型

Ollama 兼容的 OpenAIEmbeddings

基于本地 Ollama 部署的大模型,无需调用公有 API,数据本地化

向量库

FAISS

Facebook 开源,本地轻量,检索速度快,支持百万级向量

检索器

VectorStoreRetriever

LangChain 原生适配,支持自定义检索数量(k 值),可直接对接向量库

LLM 模型

Ollama(qwen3:8b/llama3:8b)

本地部署的大模型,无需联网,支持中文,8B 参数级模型性能足够满足日常需求

问答链

RetrievalQA

LangChain 封装的 RAG 核心链,支持 stuff/map_reduce 等多种生成模式

四、完整实现:本地 RAG 知识库问答系统

4.1 环境准备

1. 基础依赖安装
# 核心依赖pip install langchain langchain-community faiss-cpu pypdf python-dotenv ollama# 注意:faiss-cpu为CPU版本,GPU版本安装faiss-gpu(需适配CUDA)
2. 本地大模型部署
  • 安装 Ollama:访问Ollama 官网下载对应系统的安装包,一键安装;

  • 拉取本地模型:终端执行ollama pull qwen3:8b(通义千问 3,8B 参数,中文友好);

  • 启动 Ollama 服务:安装完成后自动启动,默认地址http://127.0.0.1:11434(可通过ollama serve手动启动)。

3. 目录准备

创建如下目录结构:

├── knowledge_base/  # 存放私有文档(PDF/TXT)│   ├── 产品手册.pdf│   ├── 技术文档.txt├── faiss_local_kb/  # 自动生成:存储向量库(首次运行后生成)└── rag_demo.py      # 核心代码文件

4.2 完整代码实现(带详细注释)​​​​​​​

import osfrom dotenv import load_dotenvimport sys# 兼容LangChain 0.3版本的内存模块(可选,解决版本兼容问题)sys.modules['langchain_core.memory'] = __import__('langchain.memory.base')# ========== 1. 核心组件导入(适配LangChain 0.3+) ==========# 本地大模型适配器(Ollama)from langchain.llms import Ollama# 文档加载器:支持TXT/PDF(可扩展Excel/MD等)from langchain_community.document_loaders import TextLoader, PyPDFLoader# 文本分块器:RecursiveCharacterTextSplitter(中文长文本最优)from langchain.text_splitter import RecursiveCharacterTextSplitter# 嵌入模型:适配Ollama的OpenAI兼容接口from langchain_community.embeddings import OpenAIEmbeddings# 向量库:FAISS(本地轻量级)from langchain_community.vectorstores import FAISS# RAG核心链:检索问答链from langchain.chains import RetrievalQA# 加载环境变量(可选,也可直接在代码中配置)load_dotenv()# ========== 2. 初始化核心组件 ==========# 2.1 初始化本地LLM(Ollama部署的大模型)llm = Ollama(    model="qwen3:8b",  # 替换为你的Ollama模型(llama3:8b/qwen2:7b等)    base_url="http://192.168.2.205:11434",  # Ollama服务地址(本地默认127.0.0.1:11434)    temperature=0.1,  # 低温度(0.1)保证回答精准,减少幻觉    timeout=60  # 超时时间,避免长文本处理卡顿)# 2.2 初始化嵌入模型(适配Ollama的OpenAI兼容接口)embeddings = OpenAIEmbeddings(    openai_api_base="http://192.168.2.205:11434/v1",  # Ollama嵌入接口(固定/v1后缀)    openai_api_key="ollama",  # 固定占位符,无需真实API Key    model="qwen3:8b"  # 与LLM模型保持一致,保证嵌入和生成的一致性)# ========== 3. RAG核心流程实现 ==========def build_local_rag_kb(folder_path="knowledge_base"):    """    构建本地RAG知识库:加载文档→分块→向量化→存入FAISS    :param folder_path: 文档存放目录    :return: 构建好的FAISS向量库对象    """    # 步骤1:加载多类型文档(TXT/PDF)    documents = []  # 存储所有加载的文档内容    # 遍历目录下的所有文件    for file_name in os.listdir(folder_path):        file_path = os.path.join(folder_path, file_name)        # 处理TXT文件(指定UTF-8编码,避免中文乱码)        if file_name.endswith(".txt"):            loader = TextLoader(file_path, encoding="utf-8")            documents.extend(loader.load())  # 加载并追加到文档列表        # 处理PDF文件(PyPDFLoader自动解析PDF每页内容)        elif file_name.endswith(".pdf"):            loader = PyPDFLoader(file_path)            documents.extend(loader.load())
    # 步骤2:长文本分块(核心:保证语义完整+适配上下文窗口)    text_splitter = RecursiveCharacterTextSplitter(        chunk_size=500,  # 每个文本块500字符(可根据模型调整,如8k模型可设1000)        chunk_overlap=50,  # 块重叠50字符,避免语义割裂(比如一句话被拆成两个块)        # 中文优先分隔符:按“空行→换行→句号→感叹号→问号→逗号→分号→空格”依次分割        separators=["\n\n", "\n", "。", "!", "?", ",", ";", " "]    )    split_docs = text_splitter.split_documents(documents)    print(f"文档分块完成,共生成 {len(split_docs)} 个文本块")    # 步骤3:向量化 + 存入FAISS向量库    vector_db = FAISS.from_documents(split_docs, embeddings)    # 保存向量库到本地(下次可直接加载,无需重复处理文档)    vector_db.save_local("faiss_local_kb")    print("本地向量库构建完成,已保存到 faiss_local_kb 文件夹")    return vector_dbdef rag_qa(query, vector_db):    """    RAG问答核心逻辑:用户提问→检索相似内容→LLM生成回答    :param query: 用户提问    :param vector_db: FAISS向量库对象    """    # 步骤4:创建检索器(k=3:返回最相似的3个文本块,可根据需求调整)    retriever = vector_db.as_retriever(search_kwargs={"k": 3})    # 步骤5:创建RetrievalQA链(RAG核心)    qa_chain = RetrievalQA.from_chain_type(        llm=llm,  # 本地大模型        chain_type="stuff",  # 适合短文本:直接将所有检索结果拼接传给LLM        # chain_type="map_reduce"  # 适合长文本:先分块生成,再汇总结果(可选)        retriever=retriever,  # 检索器        return_source_documents=True  # 返回检索到的源文档,便于溯源和验证    )    # 步骤6:执行问答并输出结果    result = qa_chain({"query": query})    # 格式化输出回答    print("\n===== RAG 问答结果 =====")    print(f"问题:{query}")    print(f"回答:{result['result']}")    # 输出检索到的源文档(便于验证回答的依据)    print("\n===== 参考文档 =====")    for i, doc in enumerate(result["source_documents"]):        print(f"【参考{i + 1}】来源:{doc.metadata['source']}")        # 只显示前200字符,避免输出过长        print(f"内容:{doc.page_content[:200]}...")# ========== 4. 主流程执行 ==========if __name__ == "__main__":    # 首次运行:构建知识库(加载→分块→向量化→入库)    # 后续运行:注释该行,直接加载本地向量库(提升速度)    vector_db = build_local_rag_kb(folder_path="knowledge_base")    # 后续运行:直接加载本地已保存的向量库(无需重复处理文档)    # vector_db = FAISS.load_local("faiss_local_kb", embeddings, allow_dangerous_deserialization=True)    # 交互式问答:输入q退出    while True:        query = input("\n请输入你的问题(输入q退出):")        if query.lower() == "q":            break        rag_qa(query, vector_db)

4.3 关键代码解析

1. 文档加载模块​​​​​​​
for file_name in os.listdir(folder_path):    file_path = os.path.join(folder_path, file_name)    if file_name.endswith(".txt"):        loader = TextLoader(file_path, encoding="utf-8")        documents.extend(loader.load())    elif file_name.endswith(".pdf"):        loader = PyPDFLoader(file_path)        documents.extend(loader.load())
  • 核心:遍历指定目录,根据文件后缀选择对应的 Loader;

  • 关键:TXT 文件指定encoding="utf-8",避免中文解码错误;

  • 扩展:可新增CSVLoader/UnstructuredExcelLoader支持 Excel/CSV 文件。

2. 文本分块模块​​​​​​​

text_splitter = RecursiveCharacterTextSplitter(    chunk_size=500,    chunk_overlap=50,    separators=["\n\n", "\n", "。", "!", "?", ",", ";", " "])split_docs = text_splitter.split_documents(documents)
  • chunk_size=500:每个块 500 字符(适配 8B 模型的上下文窗口);
  • chunk_overlap=50:块之间重叠 50 字符,保证语义连贯(比如 “人工智能” 不会被拆成 “人工” 和 “智能”);
  • separators:中文优先分隔符,按 “语义从大到小” 排序,保证分块符合中文阅读习惯。

3. 向量库构建与保存​​​​​​​

vector_db = FAISS.from_documents(split_docs, embeddings)vector_db.save_local("faiss_local_kb")
  • FAISS.from_documents:自动将分块后的文档向量化并存入 FAISS;
  • save_local:将向量库保存到本地,避免每次运行都重新处理文档(首次运行耗时,后续秒级加载)

4. 检索与问答模块​​​​​​​

retriever = vector_db.as_retriever(search_kwargs={"k": 3})qa_chain = RetrievalQA.from_chain_type(    llm=llm,    chain_type="stuff",    retriever=retriever,    return_source_documents=True)
  • search_kwargs={"k": 3}:检索最相似的 3 个文本块(k 值越大,参考信息越多,但可能增加上下文长度);
  • chain_type="stuff":将所有检索结果直接拼接传给 LLM(适合短文本,速度快);
  • return_source_documents=True:返回检索到的源文档,便于验证回答的准确性(溯源)。

4.4 运行与测试

  • 将 PDF/TXT 文档放入knowledge_base目录;

  • 执行python rag_demo.py,程序会自动:

    1.  加载文档→分块→向量化;

    2. 生成faiss_local_kb向量库目录;

    3. 进入交互式问答界面。

请输你的问题(输入q退出):产品手册中提到的核心功能有哪些?===== RAG 问答结果 =====问题:产品手册中提到的核心功能有哪些?回答:产品手册中明确的核心功能包括:1. 多端数据同步,支持PC/移动端实时同步;2. 智能检索,可按关键词/语义检索文档内容;3. 权限管理,支持多角色分级权限控制;4. 离线访问,下载文档后无需联网即可查看。===== 参考文档 =====【参考1】来源:knowledge_base/产品手册.pdf内容:产品核心功能:1. 多端数据同步:支持Windows/Mac/Android/iOS多端实时同步,数据更新延迟≤1秒;2. 智能检索:基于语义的全文检索,支持关键词高亮、模糊匹配;...
3. 后续运行优化

首次运行后,注释vector_db = build_local_rag_kb(...),取消注释vector_db = FAISS.load_local(...),直接加载本地向量库,大幅提升启动速度。

最后

从0到1!大模型(LLM)最全学习路线图,建议收藏!

想入门大模型(LLM)却不知道从哪开始? 我根据最新的技术栈和我自己的经历&理解,帮大家整理了一份LLM学习路线图,涵盖从理论基础到落地应用的全流程!拒绝焦虑,按图索骥~~

因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取

因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取

因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取

因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取

因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取

因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取

因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐