一、核心原理
加载文档:PDF/Markdown/Word/TXT/网页笔记 文本切分:长文档切成小块chunk(避免上下文丢失) Embedding嵌入:文本转数值向量,语义相近向量靠近 向量数据库:存储向量+原文,做相似度检索 检索Rerank:用户提问转向量,匹配最相关片段 Prompt拼接:把检索到的资料+问题发给大模型 LLM输出:基于你的私有资料回答,不瞎编 二、方案1:零代码一键搭建(新手首选,10分钟可用)
推荐工具列表
支持Windows/Mac/Linux,本地运行 内置向量库Chroma,自带本地嵌入模型 兼容Ollama本地大模型、OpenAI、通义千问等 支持PDF/MD/TXT/网页/Notion导入,文件夹批量上传 功能:多知识库区分、对话历史、网页抓取、Rerank重排序 操作步骤:
安装Ollama,本地下载模型:ollama pull qwen:7b 下载AnythingLLM客户端 创建工作区(独立知识库),上传文档 选择本地Ollama模型+本地嵌入模型 直接对话,只会基于上传文档回答
三、方案2:代码自研本地RAG(可控、可二次开发,技术向)
全套技术选型
模块 | 推荐开源工具 | 作用 |
文档加载 | LangChain / LlamaIndex | 解析 PDF、Word、MD、txt |
文本分割 | RecursiveCharacterTextSplitter | 智能切块,保留完整句子 |
向量嵌入模型 | all-MiniLM-L6-v2(轻量 CPU) | 离线文本向量化,无 API 费用 |
向量数据库 | Chroma(最简单)/ FAISS / Qdrant | 本地存储向量,相似度检索 |
本地大模型 | Ollama(Qwen/Llama3/Gemma) | 离线推理,不需要联网 API |
前端交互 | Gradio / Streamlit | 快速做网页对话界面 |
完整最小可运行Python代码(LangChain + Chroma + Ollama)
1. 安装依赖
pip install langchain langchain-community chromadb sentence-transformers pypdf ollama streamlit
2. 完整RAG主代码(rag_local.py)
from langchain.document_loaders import PyPDFLoader, DirectoryLoaderfrom langchain.text_splitter import RecursiveCharacterTextSplitterfrom langchain.embeddings import HuggingFaceEmbeddingsfrom langchain.vectorstores import Chromafrom langchain_community.llms import Ollamafrom langchain.chains import RetrievalQA# 1. 配置路径DOC_FOLDER = ”./docs”# 存放你的PDF/TXT文档VECTOR_DB_PATH = ”./chroma_db”EMBED_MODEL = ”all-MiniLM-L6-v2”LLM_MODEL = ”qwen:7b”# 2. 加载所有文档loader = DirectoryLoader(DOC_FOLDER, glob=”**/*.pdf”, loader_cls=PyPDFLoader)documents = loader.load()# 3. 文本切块text_splitter = RecursiveCharacterTextSplitter(chunk_size=500,chunk_overlap=80,separators=[”\n\n”, ”\n”, ”。”, ”,”, ” ”])texts = text_splitter.split_documents(documents)# 4. 本地离线Embeddingembeddings = HuggingFaceEmbeddings(model_name=EMBED_MODEL)# 5. 构建/加载向量库vectordb = Chroma.from_documents(documents=texts,embedding=embeddings,persist_directory=VECTOR_DB_PATH)vectordb.persist()# 6. 加载本地大模型Ollama(提前执行 ollama pull qwen:7b)llm = Ollama(model=LLM_MODEL)# 7. 检索链:召回3段最相关内容retriever = vectordb.as_retriever(search_kwargs={”k”: 3})qa_chain = RetrievalQA.from_chain_type(llm=llm,chain_type=”stuff”,retriever=retriever,return_source_documents=True# 返回参考文档片段)# 对话循环if __name__ == ”__main__”:print(”本地RAG知识库就绪,输入exit退出”)while True:query = input(”提问:”)if query == ”exit”:breakres = qa_chain.invoke({”query”: query})print(”\n回答:”, res[”result”])print(”\n参考来源片段:”)for idx, doc inenumerate(res[”source_documents”]):print(f”{idx+1}. {doc.page_content[:200]}...”)
使用方法
在代码同目录新建 docs 文件夹,放入PDF文档 终端执行 ollama serve,另开终端运行代码 提问只会读取你本地文档,不会调用互联网知识
四、进阶优化(提升回答精准度)
1. 文本分割优化
chunk_size:书籍/论文设400-800,短句笔记300 chunk_overlap:60-100,防止段落被切断丢失上下文
2. 增加Rerank重排序(大幅减少无关内容)
3. 多格式文档支持
Word:python-docx Markdown:UnstructuredMarkdownLoader 网页笔记:BeautifulSoup抓取网页内容存入本地
4. 向量库选型对比
5. Prompt工程优化(约束模型只使用知识库)
你是基于本地知识库的问答助手,仅使用下方提供的参考资料回答用户问题。如果资料中没有对应信息,直接回复“知识库未收录相关内容”,禁止编造、猜测外部知识。参考资料:{context}用户问题:{question}
6. 前端网页界面
Streamlit 可视化个人本地RAG完整代码
前置准备
1. 安装依赖
pip install streamlit langchain langchain-community chromadb sentence-transformers pypdf2 ollama python-multipart2. 提前拉取本地模型
# 大模型ollama pull qwen:7b# 嵌入模型代码自动下载,无需手动操作
3. 目录结构
rag_streamlit/├── streamlit_rag.py #主程序├── docs_upload/ # 自动生成,存放上传文件└── chroma_db/ # 向量库持久化目录
完整代码 streamlit_rag.py
import osimport streamlit as stfrom PyPDF2 import PdfReaderfrom langchain.text_splitter import RecursiveCharacterTextSplitterfrom langchain.embeddings import HuggingFaceEmbeddingsfrom langchain.vectorstores import Chromafrom langchain_community.llms import Ollamafrom langchain.chains import RetrievalQAfrom langchain.prompts import PromptTemplate# ===================== 全局配置 =====================UPLOAD_FOLDER = ”./docs_upload”CHROMA_DB_DIR = ”./chroma_db”EMBED_MODEL_NAME = ”all-MiniLM-L6-v2”LLM_MODEL_NAME = ”qwen:7b”# 创建文件夹os.makedirs(UPLOAD_FOLDER, exist_ok=True)os.makedirs(CHROMA_DB_DIR, exist_ok=True)# 页面基础设置st.set_page_config(page_title=”个人本地RAG知识库”, layout=”wide”)st.title(”📚 私有化本地RAG知识库”)# ===================== 初始化模型与向量库 =====================@st.cache_resource(show_spinner=”加载嵌入模型...”)def get_embedding_model():return HuggingFaceEmbeddings(model_name=EMBED_MODEL_NAME)@st.cache_resource(show_spinner=”加载本地大模型...”)def get_llm():return Ollama(model=LLM_MODEL_NAME, temperature=0.1)def load_vector_db():embeddings = get_embedding_model()db = Chroma(persist_directory=CHROMA_DB_DIR, embedding_function=embeddings)return db# 自定义Prompt,禁止模型编造内容CUSTOM_PROMPT_TPL = ”””你是专属本地知识库问答助手,严格遵守以下规则:1. 仅使用下方【参考资料】中的内容回答用户问题;2. 如果参考资料没有相关信息,直接回复:「知识库未收录相关内容,无法解答」;3. 禁止凭空猜测、补充外部互联网知识;4. 回答简洁清晰,分点说明。【参考资料】{context}用户问题:{question}”””PROMPT = PromptTemplate(template=CUSTOM_PROMPT_TPL,input_variables=[”context”, ”question”])# ===================== 文件处理工具 =====================def extract_pdf_text(file_path):text = ””pdf_reader = PdfReader(file_path)for page in pdf_reader.pages:page_text = page.extract_text()if page_text:text += page_text + ”\n”return textdef extract_txt_text(file_path):with open(file_path, ”r”, encoding=”utf-8”) as f:return f.read()def split_text(text):splitter = RecursiveCharacterTextSplitter(chunk_size=600,chunk_overlap=80,separators=[”\n\n”, ”\n”, ”。”, ”,”, ” ”])return splitter.split_text(text)def add_text_to_vector_db(text_list, source_name):db = load_vector_db()metadatas = [{”source”: source_name} for _ in text_list]db.add_texts(texts=text_list, metadatas=metadatas)db.persist()# ===================== 侧边栏:文件上传 & 库管理 =====================with st.sidebar:st.header(”📂 文档上传管理”)uploaded_files = st.file_uploader(”上传 PDF / TXT 文件”, type=[”pdf”, ”txt”], accept_multiple_files=True)if uploaded_files:for file in uploaded_files:save_path = os.path.join(UPLOAD_FOLDER, file.name)# 保存本地文件with open(save_path, ”wb”) as f:f.write(file.read())st.success(f”已保存:{file.name}”)# 提取文本if file.name.endswith(”.pdf”):content = extract_pdf_text(save_path)else:content = extract_txt_text(save_path)# 切片入库chunks = split_text(content)add_text_to_vector_db(chunks, file.name)st.info(f”{file.name} 已完成向量化入库,切片数量:{len(chunks)}”)st.divider()st.header(”🗑️ 向量库操作”)if st.button(”清空全部知识库”, type=”secondary”):db = load_vector_db()db.delete_collection()st.cache_resource.clear()st.rerun()# ===================== 主页面对话区域 =====================st.subheader(”💬 基于私有文档问答”)user_query = st.chat_input(”输入你的问题...”)if user_query:with st.spinner(”检索知识库 + 生成回答中...”):db = load_vector_db()llm = get_llm()# 检索器,返回top3相关片段retriever = db.as_retriever(search_kwargs={”k”: 3})qa_chain = RetrievalQA.from_chain_type(llm=llm,chain_type=”stuff”,retriever=retriever,return_source_documents=True,chain_type_kwargs={”prompt”: PROMPT})result = qa_chain.invoke({”query”: user_query})# 输出回答st.markdown(”### 回答”)st.write(result[”result”])# 输出引用来源st.markdown(”### 📄 参考文档片段”)source_docs = result[”source_documents”]if not source_docs:st.write(”无匹配文档”)else:seen_source = set()for idx, doc in enumerate(source_docs):src = doc.metadata[”source”]if src not in seen_source:seen_source.add(src)st.expander(f”来源文件:{src}”).write(doc.page_content)
运行启动命令
streamlit run streamlit_rag.py使用流程
侧边栏上传PDF/TXT笔记、书籍、技术文档 程序自动解析、切片、存入本地Chroma向量库 主对话框提问,模型只会读取你上传的文件作答 下方可展开查看每一条回答对应的原文片段,溯源核对 侧边栏一键清空向量库,重建知识库
进阶扩展点(可自行加功能)
增加BGE-Rerank重排序,提升检索精准度 支持Word、Markdown文件解析 多知识库切换(多个Chroma集合分开存储) 对话历史保存、导出问答记录 网页链接抓取入库(接入BeautifulSoup) 向量库备份/导入功能
五、硬件与部署方案
低配电脑优化方案
有N卡(1660/3060及以上)Ollama自动GPU加速,嵌入、LLM推理速度提升5~10倍 云端部署(多设备访问)服务器部署Qdrant向量库+FastAPI后端,搭配WebUI,手机电脑均可访问个人知识库
六、常见落地场景
个人书籍/论文知识库:上传电子书,快速检索知识点 工作笔记知识库:整合会议纪要、文档、技术手册 私人知识库:日记、学习笔记、项目资料私有化存储 技术文档助手:读取开源项目文档,提问解决代码问题
七、隐私关键点
全部组件本地运行(Ollama+Chroma+本地Embedding),不上传任何文件到第三方平台 向量数据库文件保存在本地文件夹,可随时备份/删除 拒绝使用在线Embedding(OpenAI、阿里云向量API),避免文档泄露
夜雨聆风