🧠 手把手搭建本地 RAG 知识库问答系统:Python + DeepSeek + ChromaDB 全栈实战

🌸你好呀!我是 lbb小魔仙
🌟 感谢陪伴~ 小白博主在线求友
🌿 跟着小白学Linux/Java/Python
📖 专栏汇总:
《Linux》专栏 | 《Java》专栏 | 《Python》专栏

* [🧠 手把手搭建本地 RAG 知识库问答系统:Python + DeepSeek + ChromaDB 全栈实战](#🧠 手把手搭建本地 RAG 知识库问答系统:Python + DeepSeek + ChromaDB 全栈实战 @TOC 📌 前言 一、RAG 原理深度解析 🔍 1.1 为什么需要 RAG? 1.2 RAG 工作流程 1.3 关键指标 二、技术选型与架构设计 🏗️ 2.1 技术栈选择 2.2 项目结构 三、环境搭建 🛠️ 3.1 安装依赖 3.2 配置文件 四、文档加载与分割 📂 五、向量化与入库 🗄️ 六、检索与问答核心实现 💬 七、多格式文档支持 📎 7.1 完整的文档处理管道 八、优化策略:提升检索质量 🎯 8.1 混合检索(Hybrid Search) 8.2 重排序(Reranking) 8.3 查询扩展(Query Expansion) 九、WebUI 界面(Gradio)🖥️ 十、部署与进阶 🚀 10.1 性能优化对比 10.2 替换为完全本地方案(零成本) 总结 🌟 完整代码流程回顾 效果评估指标 进阶方向 🔮 💬 互动区 📎 参考资料)
- [@[TOC]( )](#🧠 手把手搭建本地 RAG 知识库问答系统:Python + DeepSeek + ChromaDB 全栈实战 @TOC 📌 前言 一、RAG 原理深度解析 🔍 1.1 为什么需要 RAG? 1.2 RAG 工作流程 1.3 关键指标 二、技术选型与架构设计 🏗️ 2.1 技术栈选择 2.2 项目结构 三、环境搭建 🛠️ 3.1 安装依赖 3.2 配置文件 四、文档加载与分割 📂 五、向量化与入库 🗄️ 六、检索与问答核心实现 💬 七、多格式文档支持 📎 7.1 完整的文档处理管道 八、优化策略:提升检索质量 🎯 8.1 混合检索(Hybrid Search) 8.2 重排序(Reranking) 8.3 查询扩展(Query Expansion) 九、WebUI 界面(Gradio)🖥️ 十、部署与进阶 🚀 10.1 性能优化对比 10.2 替换为完全本地方案(零成本) 总结 🌟 完整代码流程回顾 效果评估指标 进阶方向 🔮 💬 互动区 📎 参考资料)
- [📌 前言](#🧠 手把手搭建本地 RAG 知识库问答系统:Python + DeepSeek + ChromaDB 全栈实战 @TOC 📌 前言 一、RAG 原理深度解析 🔍 1.1 为什么需要 RAG? 1.2 RAG 工作流程 1.3 关键指标 二、技术选型与架构设计 🏗️ 2.1 技术栈选择 2.2 项目结构 三、环境搭建 🛠️ 3.1 安装依赖 3.2 配置文件 四、文档加载与分割 📂 五、向量化与入库 🗄️ 六、检索与问答核心实现 💬 七、多格式文档支持 📎 7.1 完整的文档处理管道 八、优化策略:提升检索质量 🎯 8.1 混合检索(Hybrid Search) 8.2 重排序(Reranking) 8.3 查询扩展(Query Expansion) 九、WebUI 界面(Gradio)🖥️ 十、部署与进阶 🚀 10.1 性能优化对比 10.2 替换为完全本地方案(零成本) 总结 🌟 完整代码流程回顾 效果评估指标 进阶方向 🔮 💬 互动区 📎 参考资料)
- [一、RAG 原理深度解析 🔍](#🧠 手把手搭建本地 RAG 知识库问答系统:Python + DeepSeek + ChromaDB 全栈实战 @TOC 📌 前言 一、RAG 原理深度解析 🔍 1.1 为什么需要 RAG? 1.2 RAG 工作流程 1.3 关键指标 二、技术选型与架构设计 🏗️ 2.1 技术栈选择 2.2 项目结构 三、环境搭建 🛠️ 3.1 安装依赖 3.2 配置文件 四、文档加载与分割 📂 五、向量化与入库 🗄️ 六、检索与问答核心实现 💬 七、多格式文档支持 📎 7.1 完整的文档处理管道 八、优化策略:提升检索质量 🎯 8.1 混合检索(Hybrid Search) 8.2 重排序(Reranking) 8.3 查询扩展(Query Expansion) 九、WebUI 界面(Gradio)🖥️ 十、部署与进阶 🚀 10.1 性能优化对比 10.2 替换为完全本地方案(零成本) 总结 🌟 完整代码流程回顾 效果评估指标 进阶方向 🔮 💬 互动区 📎 参考资料)
- [1.1 为什么需要 RAG?](#🧠 手把手搭建本地 RAG 知识库问答系统:Python + DeepSeek + ChromaDB 全栈实战 @TOC 📌 前言 一、RAG 原理深度解析 🔍 1.1 为什么需要 RAG? 1.2 RAG 工作流程 1.3 关键指标 二、技术选型与架构设计 🏗️ 2.1 技术栈选择 2.2 项目结构 三、环境搭建 🛠️ 3.1 安装依赖 3.2 配置文件 四、文档加载与分割 📂 五、向量化与入库 🗄️ 六、检索与问答核心实现 💬 七、多格式文档支持 📎 7.1 完整的文档处理管道 八、优化策略:提升检索质量 🎯 8.1 混合检索(Hybrid Search) 8.2 重排序(Reranking) 8.3 查询扩展(Query Expansion) 九、WebUI 界面(Gradio)🖥️ 十、部署与进阶 🚀 10.1 性能优化对比 10.2 替换为完全本地方案(零成本) 总结 🌟 完整代码流程回顾 效果评估指标 进阶方向 🔮 💬 互动区 📎 参考资料)
- [1.2 RAG 工作流程](#🧠 手把手搭建本地 RAG 知识库问答系统:Python + DeepSeek + ChromaDB 全栈实战 @TOC 📌 前言 一、RAG 原理深度解析 🔍 1.1 为什么需要 RAG? 1.2 RAG 工作流程 1.3 关键指标 二、技术选型与架构设计 🏗️ 2.1 技术栈选择 2.2 项目结构 三、环境搭建 🛠️ 3.1 安装依赖 3.2 配置文件 四、文档加载与分割 📂 五、向量化与入库 🗄️ 六、检索与问答核心实现 💬 七、多格式文档支持 📎 7.1 完整的文档处理管道 八、优化策略:提升检索质量 🎯 8.1 混合检索(Hybrid Search) 8.2 重排序(Reranking) 8.3 查询扩展(Query Expansion) 九、WebUI 界面(Gradio)🖥️ 十、部署与进阶 🚀 10.1 性能优化对比 10.2 替换为完全本地方案(零成本) 总结 🌟 完整代码流程回顾 效果评估指标 进阶方向 🔮 💬 互动区 📎 参考资料)
- [1.3 关键指标](#🧠 手把手搭建本地 RAG 知识库问答系统:Python + DeepSeek + ChromaDB 全栈实战 @TOC 📌 前言 一、RAG 原理深度解析 🔍 1.1 为什么需要 RAG? 1.2 RAG 工作流程 1.3 关键指标 二、技术选型与架构设计 🏗️ 2.1 技术栈选择 2.2 项目结构 三、环境搭建 🛠️ 3.1 安装依赖 3.2 配置文件 四、文档加载与分割 📂 五、向量化与入库 🗄️ 六、检索与问答核心实现 💬 七、多格式文档支持 📎 7.1 完整的文档处理管道 八、优化策略:提升检索质量 🎯 8.1 混合检索(Hybrid Search) 8.2 重排序(Reranking) 8.3 查询扩展(Query Expansion) 九、WebUI 界面(Gradio)🖥️ 十、部署与进阶 🚀 10.1 性能优化对比 10.2 替换为完全本地方案(零成本) 总结 🌟 完整代码流程回顾 效果评估指标 进阶方向 🔮 💬 互动区 📎 参考资料)
- [二、技术选型与架构设计 🏗️](#🧠 手把手搭建本地 RAG 知识库问答系统:Python + DeepSeek + ChromaDB 全栈实战 @TOC 📌 前言 一、RAG 原理深度解析 🔍 1.1 为什么需要 RAG? 1.2 RAG 工作流程 1.3 关键指标 二、技术选型与架构设计 🏗️ 2.1 技术栈选择 2.2 项目结构 三、环境搭建 🛠️ 3.1 安装依赖 3.2 配置文件 四、文档加载与分割 📂 五、向量化与入库 🗄️ 六、检索与问答核心实现 💬 七、多格式文档支持 📎 7.1 完整的文档处理管道 八、优化策略:提升检索质量 🎯 8.1 混合检索(Hybrid Search) 8.2 重排序(Reranking) 8.3 查询扩展(Query Expansion) 九、WebUI 界面(Gradio)🖥️ 十、部署与进阶 🚀 10.1 性能优化对比 10.2 替换为完全本地方案(零成本) 总结 🌟 完整代码流程回顾 效果评估指标 进阶方向 🔮 💬 互动区 📎 参考资料)
- [2.1 技术栈选择](#🧠 手把手搭建本地 RAG 知识库问答系统:Python + DeepSeek + ChromaDB 全栈实战 @TOC 📌 前言 一、RAG 原理深度解析 🔍 1.1 为什么需要 RAG? 1.2 RAG 工作流程 1.3 关键指标 二、技术选型与架构设计 🏗️ 2.1 技术栈选择 2.2 项目结构 三、环境搭建 🛠️ 3.1 安装依赖 3.2 配置文件 四、文档加载与分割 📂 五、向量化与入库 🗄️ 六、检索与问答核心实现 💬 七、多格式文档支持 📎 7.1 完整的文档处理管道 八、优化策略:提升检索质量 🎯 8.1 混合检索(Hybrid Search) 8.2 重排序(Reranking) 8.3 查询扩展(Query Expansion) 九、WebUI 界面(Gradio)🖥️ 十、部署与进阶 🚀 10.1 性能优化对比 10.2 替换为完全本地方案(零成本) 总结 🌟 完整代码流程回顾 效果评估指标 进阶方向 🔮 💬 互动区 📎 参考资料)
- [2.2 项目结构](#🧠 手把手搭建本地 RAG 知识库问答系统:Python + DeepSeek + ChromaDB 全栈实战 @TOC 📌 前言 一、RAG 原理深度解析 🔍 1.1 为什么需要 RAG? 1.2 RAG 工作流程 1.3 关键指标 二、技术选型与架构设计 🏗️ 2.1 技术栈选择 2.2 项目结构 三、环境搭建 🛠️ 3.1 安装依赖 3.2 配置文件 四、文档加载与分割 📂 五、向量化与入库 🗄️ 六、检索与问答核心实现 💬 七、多格式文档支持 📎 7.1 完整的文档处理管道 八、优化策略:提升检索质量 🎯 8.1 混合检索(Hybrid Search) 8.2 重排序(Reranking) 8.3 查询扩展(Query Expansion) 九、WebUI 界面(Gradio)🖥️ 十、部署与进阶 🚀 10.1 性能优化对比 10.2 替换为完全本地方案(零成本) 总结 🌟 完整代码流程回顾 效果评估指标 进阶方向 🔮 💬 互动区 📎 参考资料)
- [三、环境搭建 🛠️](#🧠 手把手搭建本地 RAG 知识库问答系统:Python + DeepSeek + ChromaDB 全栈实战 @TOC 📌 前言 一、RAG 原理深度解析 🔍 1.1 为什么需要 RAG? 1.2 RAG 工作流程 1.3 关键指标 二、技术选型与架构设计 🏗️ 2.1 技术栈选择 2.2 项目结构 三、环境搭建 🛠️ 3.1 安装依赖 3.2 配置文件 四、文档加载与分割 📂 五、向量化与入库 🗄️ 六、检索与问答核心实现 💬 七、多格式文档支持 📎 7.1 完整的文档处理管道 八、优化策略:提升检索质量 🎯 8.1 混合检索(Hybrid Search) 8.2 重排序(Reranking) 8.3 查询扩展(Query Expansion) 九、WebUI 界面(Gradio)🖥️ 十、部署与进阶 🚀 10.1 性能优化对比 10.2 替换为完全本地方案(零成本) 总结 🌟 完整代码流程回顾 效果评估指标 进阶方向 🔮 💬 互动区 📎 参考资料)
- [3.1 安装依赖](#🧠 手把手搭建本地 RAG 知识库问答系统:Python + DeepSeek + ChromaDB 全栈实战 @TOC 📌 前言 一、RAG 原理深度解析 🔍 1.1 为什么需要 RAG? 1.2 RAG 工作流程 1.3 关键指标 二、技术选型与架构设计 🏗️ 2.1 技术栈选择 2.2 项目结构 三、环境搭建 🛠️ 3.1 安装依赖 3.2 配置文件 四、文档加载与分割 📂 五、向量化与入库 🗄️ 六、检索与问答核心实现 💬 七、多格式文档支持 📎 7.1 完整的文档处理管道 八、优化策略:提升检索质量 🎯 8.1 混合检索(Hybrid Search) 8.2 重排序(Reranking) 8.3 查询扩展(Query Expansion) 九、WebUI 界面(Gradio)🖥️ 十、部署与进阶 🚀 10.1 性能优化对比 10.2 替换为完全本地方案(零成本) 总结 🌟 完整代码流程回顾 效果评估指标 进阶方向 🔮 💬 互动区 📎 参考资料)
- [3.2 配置文件](#🧠 手把手搭建本地 RAG 知识库问答系统:Python + DeepSeek + ChromaDB 全栈实战 @TOC 📌 前言 一、RAG 原理深度解析 🔍 1.1 为什么需要 RAG? 1.2 RAG 工作流程 1.3 关键指标 二、技术选型与架构设计 🏗️ 2.1 技术栈选择 2.2 项目结构 三、环境搭建 🛠️ 3.1 安装依赖 3.2 配置文件 四、文档加载与分割 📂 五、向量化与入库 🗄️ 六、检索与问答核心实现 💬 七、多格式文档支持 📎 7.1 完整的文档处理管道 八、优化策略:提升检索质量 🎯 8.1 混合检索(Hybrid Search) 8.2 重排序(Reranking) 8.3 查询扩展(Query Expansion) 九、WebUI 界面(Gradio)🖥️ 十、部署与进阶 🚀 10.1 性能优化对比 10.2 替换为完全本地方案(零成本) 总结 🌟 完整代码流程回顾 效果评估指标 进阶方向 🔮 💬 互动区 📎 参考资料)
- [四、文档加载与分割 📂](#🧠 手把手搭建本地 RAG 知识库问答系统:Python + DeepSeek + ChromaDB 全栈实战 @TOC 📌 前言 一、RAG 原理深度解析 🔍 1.1 为什么需要 RAG? 1.2 RAG 工作流程 1.3 关键指标 二、技术选型与架构设计 🏗️ 2.1 技术栈选择 2.2 项目结构 三、环境搭建 🛠️ 3.1 安装依赖 3.2 配置文件 四、文档加载与分割 📂 五、向量化与入库 🗄️ 六、检索与问答核心实现 💬 七、多格式文档支持 📎 7.1 完整的文档处理管道 八、优化策略:提升检索质量 🎯 8.1 混合检索(Hybrid Search) 8.2 重排序(Reranking) 8.3 查询扩展(Query Expansion) 九、WebUI 界面(Gradio)🖥️ 十、部署与进阶 🚀 10.1 性能优化对比 10.2 替换为完全本地方案(零成本) 总结 🌟 完整代码流程回顾 效果评估指标 进阶方向 🔮 💬 互动区 📎 参考资料)
- [五、向量化与入库 🗄️](#🧠 手把手搭建本地 RAG 知识库问答系统:Python + DeepSeek + ChromaDB 全栈实战 @TOC 📌 前言 一、RAG 原理深度解析 🔍 1.1 为什么需要 RAG? 1.2 RAG 工作流程 1.3 关键指标 二、技术选型与架构设计 🏗️ 2.1 技术栈选择 2.2 项目结构 三、环境搭建 🛠️ 3.1 安装依赖 3.2 配置文件 四、文档加载与分割 📂 五、向量化与入库 🗄️ 六、检索与问答核心实现 💬 七、多格式文档支持 📎 7.1 完整的文档处理管道 八、优化策略:提升检索质量 🎯 8.1 混合检索(Hybrid Search) 8.2 重排序(Reranking) 8.3 查询扩展(Query Expansion) 九、WebUI 界面(Gradio)🖥️ 十、部署与进阶 🚀 10.1 性能优化对比 10.2 替换为完全本地方案(零成本) 总结 🌟 完整代码流程回顾 效果评估指标 进阶方向 🔮 💬 互动区 📎 参考资料)
- [六、检索与问答核心实现 💬](#🧠 手把手搭建本地 RAG 知识库问答系统:Python + DeepSeek + ChromaDB 全栈实战 @TOC 📌 前言 一、RAG 原理深度解析 🔍 1.1 为什么需要 RAG? 1.2 RAG 工作流程 1.3 关键指标 二、技术选型与架构设计 🏗️ 2.1 技术栈选择 2.2 项目结构 三、环境搭建 🛠️ 3.1 安装依赖 3.2 配置文件 四、文档加载与分割 📂 五、向量化与入库 🗄️ 六、检索与问答核心实现 💬 七、多格式文档支持 📎 7.1 完整的文档处理管道 八、优化策略:提升检索质量 🎯 8.1 混合检索(Hybrid Search) 8.2 重排序(Reranking) 8.3 查询扩展(Query Expansion) 九、WebUI 界面(Gradio)🖥️ 十、部署与进阶 🚀 10.1 性能优化对比 10.2 替换为完全本地方案(零成本) 总结 🌟 完整代码流程回顾 效果评估指标 进阶方向 🔮 💬 互动区 📎 参考资料)
- [七、多格式文档支持 📎](#🧠 手把手搭建本地 RAG 知识库问答系统:Python + DeepSeek + ChromaDB 全栈实战 @TOC 📌 前言 一、RAG 原理深度解析 🔍 1.1 为什么需要 RAG? 1.2 RAG 工作流程 1.3 关键指标 二、技术选型与架构设计 🏗️ 2.1 技术栈选择 2.2 项目结构 三、环境搭建 🛠️ 3.1 安装依赖 3.2 配置文件 四、文档加载与分割 📂 五、向量化与入库 🗄️ 六、检索与问答核心实现 💬 七、多格式文档支持 📎 7.1 完整的文档处理管道 八、优化策略:提升检索质量 🎯 8.1 混合检索(Hybrid Search) 8.2 重排序(Reranking) 8.3 查询扩展(Query Expansion) 九、WebUI 界面(Gradio)🖥️ 十、部署与进阶 🚀 10.1 性能优化对比 10.2 替换为完全本地方案(零成本) 总结 🌟 完整代码流程回顾 效果评估指标 进阶方向 🔮 💬 互动区 📎 参考资料)
- [7.1 完整的文档处理管道](#🧠 手把手搭建本地 RAG 知识库问答系统:Python + DeepSeek + ChromaDB 全栈实战 @TOC 📌 前言 一、RAG 原理深度解析 🔍 1.1 为什么需要 RAG? 1.2 RAG 工作流程 1.3 关键指标 二、技术选型与架构设计 🏗️ 2.1 技术栈选择 2.2 项目结构 三、环境搭建 🛠️ 3.1 安装依赖 3.2 配置文件 四、文档加载与分割 📂 五、向量化与入库 🗄️ 六、检索与问答核心实现 💬 七、多格式文档支持 📎 7.1 完整的文档处理管道 八、优化策略:提升检索质量 🎯 8.1 混合检索(Hybrid Search) 8.2 重排序(Reranking) 8.3 查询扩展(Query Expansion) 九、WebUI 界面(Gradio)🖥️ 十、部署与进阶 🚀 10.1 性能优化对比 10.2 替换为完全本地方案(零成本) 总结 🌟 完整代码流程回顾 效果评估指标 进阶方向 🔮 💬 互动区 📎 参考资料)
- [八、优化策略:提升检索质量 🎯](#🧠 手把手搭建本地 RAG 知识库问答系统:Python + DeepSeek + ChromaDB 全栈实战 @TOC 📌 前言 一、RAG 原理深度解析 🔍 1.1 为什么需要 RAG? 1.2 RAG 工作流程 1.3 关键指标 二、技术选型与架构设计 🏗️ 2.1 技术栈选择 2.2 项目结构 三、环境搭建 🛠️ 3.1 安装依赖 3.2 配置文件 四、文档加载与分割 📂 五、向量化与入库 🗄️ 六、检索与问答核心实现 💬 七、多格式文档支持 📎 7.1 完整的文档处理管道 八、优化策略:提升检索质量 🎯 8.1 混合检索(Hybrid Search) 8.2 重排序(Reranking) 8.3 查询扩展(Query Expansion) 九、WebUI 界面(Gradio)🖥️ 十、部署与进阶 🚀 10.1 性能优化对比 10.2 替换为完全本地方案(零成本) 总结 🌟 完整代码流程回顾 效果评估指标 进阶方向 🔮 💬 互动区 📎 参考资料)
- [8.1 混合检索(Hybrid Search)](#🧠 手把手搭建本地 RAG 知识库问答系统:Python + DeepSeek + ChromaDB 全栈实战 @TOC 📌 前言 一、RAG 原理深度解析 🔍 1.1 为什么需要 RAG? 1.2 RAG 工作流程 1.3 关键指标 二、技术选型与架构设计 🏗️ 2.1 技术栈选择 2.2 项目结构 三、环境搭建 🛠️ 3.1 安装依赖 3.2 配置文件 四、文档加载与分割 📂 五、向量化与入库 🗄️ 六、检索与问答核心实现 💬 七、多格式文档支持 📎 7.1 完整的文档处理管道 八、优化策略:提升检索质量 🎯 8.1 混合检索(Hybrid Search) 8.2 重排序(Reranking) 8.3 查询扩展(Query Expansion) 九、WebUI 界面(Gradio)🖥️ 十、部署与进阶 🚀 10.1 性能优化对比 10.2 替换为完全本地方案(零成本) 总结 🌟 完整代码流程回顾 效果评估指标 进阶方向 🔮 💬 互动区 📎 参考资料)
- [8.2 重排序(Reranking)](#🧠 手把手搭建本地 RAG 知识库问答系统:Python + DeepSeek + ChromaDB 全栈实战 @TOC 📌 前言 一、RAG 原理深度解析 🔍 1.1 为什么需要 RAG? 1.2 RAG 工作流程 1.3 关键指标 二、技术选型与架构设计 🏗️ 2.1 技术栈选择 2.2 项目结构 三、环境搭建 🛠️ 3.1 安装依赖 3.2 配置文件 四、文档加载与分割 📂 五、向量化与入库 🗄️ 六、检索与问答核心实现 💬 七、多格式文档支持 📎 7.1 完整的文档处理管道 八、优化策略:提升检索质量 🎯 8.1 混合检索(Hybrid Search) 8.2 重排序(Reranking) 8.3 查询扩展(Query Expansion) 九、WebUI 界面(Gradio)🖥️ 十、部署与进阶 🚀 10.1 性能优化对比 10.2 替换为完全本地方案(零成本) 总结 🌟 完整代码流程回顾 效果评估指标 进阶方向 🔮 💬 互动区 📎 参考资料)
- [8.3 查询扩展(Query Expansion)](#🧠 手把手搭建本地 RAG 知识库问答系统:Python + DeepSeek + ChromaDB 全栈实战 @TOC 📌 前言 一、RAG 原理深度解析 🔍 1.1 为什么需要 RAG? 1.2 RAG 工作流程 1.3 关键指标 二、技术选型与架构设计 🏗️ 2.1 技术栈选择 2.2 项目结构 三、环境搭建 🛠️ 3.1 安装依赖 3.2 配置文件 四、文档加载与分割 📂 五、向量化与入库 🗄️ 六、检索与问答核心实现 💬 七、多格式文档支持 📎 7.1 完整的文档处理管道 八、优化策略:提升检索质量 🎯 8.1 混合检索(Hybrid Search) 8.2 重排序(Reranking) 8.3 查询扩展(Query Expansion) 九、WebUI 界面(Gradio)🖥️ 十、部署与进阶 🚀 10.1 性能优化对比 10.2 替换为完全本地方案(零成本) 总结 🌟 完整代码流程回顾 效果评估指标 进阶方向 🔮 💬 互动区 📎 参考资料)
- [九、WebUI 界面(Gradio)🖥️](#🧠 手把手搭建本地 RAG 知识库问答系统:Python + DeepSeek + ChromaDB 全栈实战 @TOC 📌 前言 一、RAG 原理深度解析 🔍 1.1 为什么需要 RAG? 1.2 RAG 工作流程 1.3 关键指标 二、技术选型与架构设计 🏗️ 2.1 技术栈选择 2.2 项目结构 三、环境搭建 🛠️ 3.1 安装依赖 3.2 配置文件 四、文档加载与分割 📂 五、向量化与入库 🗄️ 六、检索与问答核心实现 💬 七、多格式文档支持 📎 7.1 完整的文档处理管道 八、优化策略:提升检索质量 🎯 8.1 混合检索(Hybrid Search) 8.2 重排序(Reranking) 8.3 查询扩展(Query Expansion) 九、WebUI 界面(Gradio)🖥️ 十、部署与进阶 🚀 10.1 性能优化对比 10.2 替换为完全本地方案(零成本) 总结 🌟 完整代码流程回顾 效果评估指标 进阶方向 🔮 💬 互动区 📎 参考资料)
- [十、部署与进阶 🚀](#🧠 手把手搭建本地 RAG 知识库问答系统:Python + DeepSeek + ChromaDB 全栈实战 @TOC 📌 前言 一、RAG 原理深度解析 🔍 1.1 为什么需要 RAG? 1.2 RAG 工作流程 1.3 关键指标 二、技术选型与架构设计 🏗️ 2.1 技术栈选择 2.2 项目结构 三、环境搭建 🛠️ 3.1 安装依赖 3.2 配置文件 四、文档加载与分割 📂 五、向量化与入库 🗄️ 六、检索与问答核心实现 💬 七、多格式文档支持 📎 7.1 完整的文档处理管道 八、优化策略:提升检索质量 🎯 8.1 混合检索(Hybrid Search) 8.2 重排序(Reranking) 8.3 查询扩展(Query Expansion) 九、WebUI 界面(Gradio)🖥️ 十、部署与进阶 🚀 10.1 性能优化对比 10.2 替换为完全本地方案(零成本) 总结 🌟 完整代码流程回顾 效果评估指标 进阶方向 🔮 💬 互动区 📎 参考资料)
- [10.1 性能优化对比](#🧠 手把手搭建本地 RAG 知识库问答系统:Python + DeepSeek + ChromaDB 全栈实战 @TOC 📌 前言 一、RAG 原理深度解析 🔍 1.1 为什么需要 RAG? 1.2 RAG 工作流程 1.3 关键指标 二、技术选型与架构设计 🏗️ 2.1 技术栈选择 2.2 项目结构 三、环境搭建 🛠️ 3.1 安装依赖 3.2 配置文件 四、文档加载与分割 📂 五、向量化与入库 🗄️ 六、检索与问答核心实现 💬 七、多格式文档支持 📎 7.1 完整的文档处理管道 八、优化策略:提升检索质量 🎯 8.1 混合检索(Hybrid Search) 8.2 重排序(Reranking) 8.3 查询扩展(Query Expansion) 九、WebUI 界面(Gradio)🖥️ 十、部署与进阶 🚀 10.1 性能优化对比 10.2 替换为完全本地方案(零成本) 总结 🌟 完整代码流程回顾 效果评估指标 进阶方向 🔮 💬 互动区 📎 参考资料)
- [10.2 替换为完全本地方案(零成本)](#🧠 手把手搭建本地 RAG 知识库问答系统:Python + DeepSeek + ChromaDB 全栈实战 @TOC 📌 前言 一、RAG 原理深度解析 🔍 1.1 为什么需要 RAG? 1.2 RAG 工作流程 1.3 关键指标 二、技术选型与架构设计 🏗️ 2.1 技术栈选择 2.2 项目结构 三、环境搭建 🛠️ 3.1 安装依赖 3.2 配置文件 四、文档加载与分割 📂 五、向量化与入库 🗄️ 六、检索与问答核心实现 💬 七、多格式文档支持 📎 7.1 完整的文档处理管道 八、优化策略:提升检索质量 🎯 8.1 混合检索(Hybrid Search) 8.2 重排序(Reranking) 8.3 查询扩展(Query Expansion) 九、WebUI 界面(Gradio)🖥️ 十、部署与进阶 🚀 10.1 性能优化对比 10.2 替换为完全本地方案(零成本) 总结 🌟 完整代码流程回顾 效果评估指标 进阶方向 🔮 💬 互动区 📎 参考资料)
- [总结 🌟](#🧠 手把手搭建本地 RAG 知识库问答系统:Python + DeepSeek + ChromaDB 全栈实战 @TOC 📌 前言 一、RAG 原理深度解析 🔍 1.1 为什么需要 RAG? 1.2 RAG 工作流程 1.3 关键指标 二、技术选型与架构设计 🏗️ 2.1 技术栈选择 2.2 项目结构 三、环境搭建 🛠️ 3.1 安装依赖 3.2 配置文件 四、文档加载与分割 📂 五、向量化与入库 🗄️ 六、检索与问答核心实现 💬 七、多格式文档支持 📎 7.1 完整的文档处理管道 八、优化策略:提升检索质量 🎯 8.1 混合检索(Hybrid Search) 8.2 重排序(Reranking) 8.3 查询扩展(Query Expansion) 九、WebUI 界面(Gradio)🖥️ 十、部署与进阶 🚀 10.1 性能优化对比 10.2 替换为完全本地方案(零成本) 总结 🌟 完整代码流程回顾 效果评估指标 进阶方向 🔮 💬 互动区 📎 参考资料)
- [完整代码流程回顾](#🧠 手把手搭建本地 RAG 知识库问答系统:Python + DeepSeek + ChromaDB 全栈实战 @TOC 📌 前言 一、RAG 原理深度解析 🔍 1.1 为什么需要 RAG? 1.2 RAG 工作流程 1.3 关键指标 二、技术选型与架构设计 🏗️ 2.1 技术栈选择 2.2 项目结构 三、环境搭建 🛠️ 3.1 安装依赖 3.2 配置文件 四、文档加载与分割 📂 五、向量化与入库 🗄️ 六、检索与问答核心实现 💬 七、多格式文档支持 📎 7.1 完整的文档处理管道 八、优化策略:提升检索质量 🎯 8.1 混合检索(Hybrid Search) 8.2 重排序(Reranking) 8.3 查询扩展(Query Expansion) 九、WebUI 界面(Gradio)🖥️ 十、部署与进阶 🚀 10.1 性能优化对比 10.2 替换为完全本地方案(零成本) 总结 🌟 完整代码流程回顾 效果评估指标 进阶方向 🔮 💬 互动区 📎 参考资料)
- [效果评估指标](#🧠 手把手搭建本地 RAG 知识库问答系统:Python + DeepSeek + ChromaDB 全栈实战 @TOC 📌 前言 一、RAG 原理深度解析 🔍 1.1 为什么需要 RAG? 1.2 RAG 工作流程 1.3 关键指标 二、技术选型与架构设计 🏗️ 2.1 技术栈选择 2.2 项目结构 三、环境搭建 🛠️ 3.1 安装依赖 3.2 配置文件 四、文档加载与分割 📂 五、向量化与入库 🗄️ 六、检索与问答核心实现 💬 七、多格式文档支持 📎 7.1 完整的文档处理管道 八、优化策略:提升检索质量 🎯 8.1 混合检索(Hybrid Search) 8.2 重排序(Reranking) 8.3 查询扩展(Query Expansion) 九、WebUI 界面(Gradio)🖥️ 十、部署与进阶 🚀 10.1 性能优化对比 10.2 替换为完全本地方案(零成本) 总结 🌟 完整代码流程回顾 效果评估指标 进阶方向 🔮 💬 互动区 📎 参考资料)
- [进阶方向 🔮](#🧠 手把手搭建本地 RAG 知识库问答系统:Python + DeepSeek + ChromaDB 全栈实战 @TOC 📌 前言 一、RAG 原理深度解析 🔍 1.1 为什么需要 RAG? 1.2 RAG 工作流程 1.3 关键指标 二、技术选型与架构设计 🏗️ 2.1 技术栈选择 2.2 项目结构 三、环境搭建 🛠️ 3.1 安装依赖 3.2 配置文件 四、文档加载与分割 📂 五、向量化与入库 🗄️ 六、检索与问答核心实现 💬 七、多格式文档支持 📎 7.1 完整的文档处理管道 八、优化策略:提升检索质量 🎯 8.1 混合检索(Hybrid Search) 8.2 重排序(Reranking) 8.3 查询扩展(Query Expansion) 九、WebUI 界面(Gradio)🖥️ 十、部署与进阶 🚀 10.1 性能优化对比 10.2 替换为完全本地方案(零成本) 总结 🌟 完整代码流程回顾 效果评估指标 进阶方向 🔮 💬 互动区 📎 参考资料)
- [💬 互动区](#🧠 手把手搭建本地 RAG 知识库问答系统:Python + DeepSeek + ChromaDB 全栈实战 @TOC 📌 前言 一、RAG 原理深度解析 🔍 1.1 为什么需要 RAG? 1.2 RAG 工作流程 1.3 关键指标 二、技术选型与架构设计 🏗️ 2.1 技术栈选择 2.2 项目结构 三、环境搭建 🛠️ 3.1 安装依赖 3.2 配置文件 四、文档加载与分割 📂 五、向量化与入库 🗄️ 六、检索与问答核心实现 💬 七、多格式文档支持 📎 7.1 完整的文档处理管道 八、优化策略:提升检索质量 🎯 8.1 混合检索(Hybrid Search) 8.2 重排序(Reranking) 8.3 查询扩展(Query Expansion) 九、WebUI 界面(Gradio)🖥️ 十、部署与进阶 🚀 10.1 性能优化对比 10.2 替换为完全本地方案(零成本) 总结 🌟 完整代码流程回顾 效果评估指标 进阶方向 🔮 💬 互动区 📎 参考资料)
- [📎 参考资料](#🧠 手把手搭建本地 RAG 知识库问答系统:Python + DeepSeek + ChromaDB 全栈实战 @TOC 📌 前言 一、RAG 原理深度解析 🔍 1.1 为什么需要 RAG? 1.2 RAG 工作流程 1.3 关键指标 二、技术选型与架构设计 🏗️ 2.1 技术栈选择 2.2 项目结构 三、环境搭建 🛠️ 3.1 安装依赖 3.2 配置文件 四、文档加载与分割 📂 五、向量化与入库 🗄️ 六、检索与问答核心实现 💬 七、多格式文档支持 📎 7.1 完整的文档处理管道 八、优化策略:提升检索质量 🎯 8.1 混合检索(Hybrid Search) 8.2 重排序(Reranking) 8.3 查询扩展(Query Expansion) 九、WebUI 界面(Gradio)🖥️ 十、部署与进阶 🚀 10.1 性能优化对比 10.2 替换为完全本地方案(零成本) 总结 🌟 完整代码流程回顾 效果评估指标 进阶方向 🔮 💬 互动区 📎 参考资料)
📌 前言
你是否遇到过这样的场景?
- 📄 公司有几百份 PDF 文档,想直接用自然语言提问
- 📚 个人笔记库很大,找不到某个知识点在哪
- 🏢 企业私有数据不能上传到 ChatGPT,想在本地部署一套智能问答
RAG(检索增强生成) 正是解决这些问题的核心技术。
本文将带你从零开始,用 Python + DeepSeek + ChromaDB 构建一个完整的本地知识库问答系统,支持上传 PDF / TXT / Word 文档,实现秒级智能检索。
💡 RAG = Retrieval-Augmented Generation(检索增强生成)
一、RAG 原理深度解析 🔍
1.1 为什么需要 RAG?
大语言模型(LLM)有两个天然缺陷:
| 问题 | 描述 | RAG 解法 |
|---|---|---|
| 知识截止 | 训练数据有时效性,不知道最新信息 | 实时检索最新文档 |
| 幻觉问题 | 会编造不存在的"知识" | 基于真实文档生成答案 |
| 私有数据 | 无法访问企业内部文档 | 本地构建专属知识库 |
| 上下文限制 | Token 窗口有限,无法输入整本书 | 检索最相关片段后输入 |
1.2 RAG 工作流程
┌─────────────────────────────────┐
│ 离线构建阶段 │
│ │
原始文档 ──→ 文本分割 ──→ Embedding 向量化 ──→ 存入向量数据库
(PDF/Word/TXT) (Chunks) (模型编码) (ChromaDB)
└─────────────────────────────────┘
┌─────────────────────────────────┐
│ 在线问答阶段 │
│ │
用户提问 ──→ 问题向量化 ──→ 相似度检索 ──→ 召回 Top-K 文档
↓
最终答案 ←── LLM 生成 ←── 构造 Prompt(问题 + 相关文档)
└─────────────────────────────────┘
1.3 关键指标
- 召回率:相关文档是否被检索到(宁可多,不能漏)
- 精确率:检索到的文档是否真的相关
- 生成质量:LLM 基于文档回答是否准确
二、技术选型与架构设计 🏗️
2.1 技术栈选择
| 模块 | 选型 | 理由 |
|---|---|---|
| LLM | DeepSeek-V3 / DeepSeek-R1 | 中文能力强,性价比极高 |
| Embedding | BGE-M3(本地)/ text-embedding-3-small | 中文语义理解最佳 |
| 向量数据库 | ChromaDB | 轻量,零配置,适合本地 |
| 文档处理 | LangChain Document Loaders | 支持格式最全 |
| 文本分割 | RecursiveCharacterTextSplitter | 语义保留最好 |
| WebUI | Gradio | 5 分钟搭建界面 |
2.2 项目结构
rag_system/
├── 📁 data/ # 原始文档目录
│ ├── pdfs/
│ ├── docs/
│ └── txts/
├── 📁 vector_store/ # 向量数据库持久化
├── 📁 src/
│ ├── document_loader.py # 文档加载与分割
│ ├── embeddings.py # 向量化模块
│ ├── retriever.py # 检索模块
│ ├── qa_chain.py # 问答链
│ └── config.py # 配置文件
├── app.py # Gradio WebUI
├── main.py # 命令行入口
└── requirements.txt
三、环境搭建 🛠️
3.1 安装依赖
bash
# Python 3.11+ 推荐
pip install langchain langchain-community langchain-openai
pip install chromadb
pip install sentence-transformers # 本地 Embedding
pip install pypdf python-docx # 文档解析
pip install gradio # WebUI
pip install python-dotenv rich tiktoken
3.2 配置文件
python
# src/config.py
import os
from dotenv import load_dotenv
load_dotenv()
# ===== LLM 配置 =====
# DeepSeek(推荐,国内稳定,价格极低)
LLM_API_KEY = os.getenv("DEEPSEEK_API_KEY")
LLM_BASE_URL = "https://api.deepseek.com/v1"
LLM_MODEL = "deepseek-chat"
# ===== Embedding 配置 =====
EMBEDDING_MODEL = "BAAI/bge-m3" # 本地模型(免费,中文最强)
# 或使用 OpenAI: "text-embedding-3-small"
# ===== 文本分割配置 =====
CHUNK_SIZE = 500 # 每段文本长度
CHUNK_OVERLAP = 50 # 段落重叠长度(保留上下文)
# ===== 检索配置 =====
RETRIEVAL_TOP_K = 5 # 召回文档数量
SIMILARITY_THRESHOLD = 0.3 # 相似度阈值
# ===== 向量库路径 =====
VECTOR_STORE_PATH = "./vector_store"
bash
# .env 文件
DEEPSEEK_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxx
四、文档加载与分割 📂
这是 RAG 系统质量的第一道关卡,分割策略直接影响检索效果。
python
# src/document_loader.py
from langchain_community.document_loaders import (
PyPDFLoader,
TextLoader,
Docx2txtLoader,
DirectoryLoader,
UnstructuredMarkdownLoader,
)
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.schema import Document
from pathlib import Path
from typing import List
from rich.console import Console
console = Console()
class DocumentProcessor:
"""文档处理器:加载 + 清洗 + 分割"""
def __init__(self, chunk_size: int = 500, chunk_overlap: int = 50):
self.chunk_size = chunk_size
self.chunk_overlap = chunk_overlap
# 递归字符分割器(最适合中文文本)
self.text_splitter = RecursiveCharacterTextSplitter(
chunk_size=chunk_size,
chunk_overlap=chunk_overlap,
separators=["\n\n", "\n", "。", "!", "?", ";", ",", " ", ""],
length_function=len,
)
def load_single_file(self, file_path: str) -> List[Document]:
"""根据文件类型自动选择加载器"""
path = Path(file_path)
suffix = path.suffix.lower()
loaders = {
".pdf": PyPDFLoader,
".txt": lambda f: TextLoader(f, encoding="utf-8"),
".docx": Docx2txtLoader,
".md": UnstructuredMarkdownLoader,
}
if suffix not in loaders:
console.print(f"[yellow]⚠️ 不支持的文件格式:{suffix}[/yellow]")
return []
try:
loader = loaders[suffix](file_path)
docs = loader.load()
console.print(f"[green]✅ 已加载:{path.name}({len(docs)} 页)[/green]")
return docs
except Exception as e:
console.print(f"[red]❌ 加载失败 {path.name}:{e}[/red]")
return []
def load_directory(self, dir_path: str) -> List[Document]:
"""批量加载目录下所有支持的文档"""
all_docs = []
path = Path(dir_path)
supported_extensions = [".pdf", ".txt", ".docx", ".md"]
files = [f for f in path.rglob("*") if f.suffix.lower() in supported_extensions]
console.print(f"\n📂 扫描到 {len(files)} 个文档...")
for file in files:
docs = self.load_single_file(str(file))
all_docs.extend(docs)
console.print(f"\n📊 共加载 {len(all_docs)} 个文档片段")
return all_docs
def split_documents(self, documents: List[Document]) -> List[Document]:
"""文本分割"""
chunks = self.text_splitter.split_documents(documents)
# 过滤太短的片段(噪音)
chunks = [c for c in chunks if len(c.page_content.strip()) > 20]
console.print(f"✂️ 分割完成:{len(documents)} 篇 → {len(chunks)} 个片段")
console.print(f" 平均片段长度:{sum(len(c.page_content) for c in chunks) // len(chunks)} 字")
return chunks
def process(self, source: str) -> List[Document]:
"""一键处理:加载 + 分割"""
path = Path(source)
if path.is_dir():
docs = self.load_directory(source)
elif path.is_file():
docs = self.load_single_file(source)
else:
raise ValueError(f"路径不存在:{source}")
if not docs:
raise ValueError("未能加载任何文档,请检查文件格式")
return self.split_documents(docs)
五、向量化与入库 🗄️
python
# src/embeddings.py
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_community.vectorstores import Chroma
from langchain.schema import Document
from typing import List, Optional
from rich.console import Console
import os
console = Console()
class VectorStoreManager:
"""向量数据库管理器"""
def __init__(
self,
persist_dir: str = "./vector_store",
embedding_model: str = "BAAI/bge-m3"
):
self.persist_dir = persist_dir
console.print(f"🔄 加载 Embedding 模型:{embedding_model}")
# BGE-M3:中文语义理解最强的开源模型
self.embeddings = HuggingFaceEmbeddings(
model_name=embedding_model,
model_kwargs={"device": "cpu"}, # 改为 "cuda" 可使用 GPU
encode_kwargs={
"normalize_embeddings": True, # 归一化,提升余弦相似度效果
"batch_size": 32,
}
)
self.vectorstore: Optional[Chroma] = None
def build_from_documents(self, documents: List[Document]) -> Chroma:
"""从文档列表构建向量库"""
console.print(f"\n⚡ 开始向量化 {len(documents)} 个文档片段...")
# 批量向量化并存入 ChromaDB
self.vectorstore = Chroma.from_documents(
documents=documents,
embedding=self.embeddings,
persist_directory=self.persist_dir,
collection_metadata={"hnsw:space": "cosine"}, # 使用余弦相似度
)
console.print(f"[green]✅ 向量库构建完成!共 {self.vectorstore._collection.count()} 条记录[/green]")
console.print(f"💾 已持久化到:{self.persist_dir}")
return self.vectorstore
def load_existing(self) -> Optional[Chroma]:
"""加载已存在的向量库"""
if not os.path.exists(self.persist_dir):
console.print(f"[yellow]⚠️ 向量库不存在:{self.persist_dir}[/yellow]")
return None
self.vectorstore = Chroma(
persist_directory=self.persist_dir,
embedding_function=self.embeddings,
)
count = self.vectorstore._collection.count()
console.print(f"[green]📂 已加载向量库:{count} 条记录[/green]")
return self.vectorstore
def add_documents(self, documents: List[Document]):
"""增量添加文档"""
if self.vectorstore is None:
raise RuntimeError("请先加载或构建向量库")
self.vectorstore.add_documents(documents)
console.print(f"[green]➕ 已添加 {len(documents)} 个新文档片段[/green]")
def get_retriever(self, top_k: int = 5, score_threshold: float = 0.3):
"""获取检索器"""
return self.vectorstore.as_retriever(
search_type="similarity_score_threshold",
search_kwargs={
"k": top_k,
"score_threshold": score_threshold,
}
)
六、检索与问答核心实现 💬
python
# src/qa_chain.py
from langchain_openai import ChatOpenAI
from langchain.chains import RetrievalQA
from langchain.prompts import PromptTemplate
from langchain.schema import BaseRetriever
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
from typing import Generator
# ===== 高质量中文问答 Prompt =====
QA_PROMPT_TEMPLATE = """你是一个专业的知识库问答助手。请根据以下检索到的相关文档内容回答用户的问题。
【相关文档】
{context}
【用户问题】
{question}
【回答要求】
1. 只根据上述文档内容回答,不要编造信息
2. 如果文档中没有相关信息,请明确说"根据现有文档,无法回答此问题"
3. 回答要简洁准确,必要时可以引用原文
4. 使用中文回答
【回答】"""
QA_PROMPT = PromptTemplate(
template=QA_PROMPT_TEMPLATE,
input_variables=["context", "question"]
)
class RAGQASystem:
"""RAG 问答系统核心"""
def __init__(self, retriever: BaseRetriever, api_key: str, base_url: str, model: str):
self.retriever = retriever
# 初始化 LLM(DeepSeek)
self.llm = ChatOpenAI(
model=model,
api_key=api_key,
base_url=base_url,
temperature=0.1, # 低温度:更准确,减少幻觉
max_tokens=2048,
streaming=True, # 支持流式输出
)
# 构建 RAG 链(LCEL 写法,推荐)
self.chain = self._build_chain()
def _format_docs(self, docs) -> str:
"""格式化检索到的文档"""
formatted = []
for i, doc in enumerate(docs, 1):
source = doc.metadata.get("source", "未知来源")
page = doc.metadata.get("page", "")
source_info = f"[来源:{source}" + (f" 第{page+1}页" if page != "" else "") + "]"
formatted.append(f"--- 文档 {i} {source_info} ---\n{doc.page_content}")
return "\n\n".join(formatted)
def _build_chain(self):
"""使用 LCEL 构建 RAG 链"""
return (
{
"context": self.retriever | self._format_docs,
"question": RunnablePassthrough()
}
| QA_PROMPT
| self.llm
| StrOutputParser()
)
def ask(self, question: str) -> str:
"""同步问答"""
return self.chain.invoke(question)
def ask_stream(self, question: str) -> Generator[str, None, None]:
"""流式问答(逐字输出)"""
for chunk in self.chain.stream(question):
yield chunk
def ask_with_sources(self, question: str) -> dict:
"""问答 + 返回来源文档"""
docs = self.retriever.invoke(question)
answer = self.ask(question)
sources = []
for doc in docs:
sources.append({
"content": doc.page_content[:200] + "...",
"source": doc.metadata.get("source", "未知"),
"page": doc.metadata.get("page", ""),
})
return {
"answer": answer,
"sources": sources,
"docs_count": len(docs)
}
七、多格式文档支持 📎
7.1 完整的文档处理管道
python
# main.py
from src.config import *
from src.document_loader import DocumentProcessor
from src.embeddings import VectorStoreManager
from src.qa_chain import RAGQASystem
from rich.console import Console
from rich.panel import Panel
from rich.table import Table
import os
console = Console()
def build_knowledge_base(data_dir: str = "./data"):
"""构建知识库"""
console.print(Panel.fit("🔨 开始构建知识库", style="bold blue"))
# 1. 加载并分割文档
processor = DocumentProcessor(
chunk_size=CHUNK_SIZE,
chunk_overlap=CHUNK_OVERLAP
)
chunks = processor.process(data_dir)
# 2. 向量化并存储
manager = VectorStoreManager(
persist_dir=VECTOR_STORE_PATH,
embedding_model=EMBEDDING_MODEL
)
manager.build_from_documents(chunks)
console.print(Panel.fit("✅ 知识库构建完成!", style="bold green"))
return manager
def load_knowledge_base():
"""加载已有知识库"""
manager = VectorStoreManager(
persist_dir=VECTOR_STORE_PATH,
embedding_model=EMBEDDING_MODEL
)
vectorstore = manager.load_existing()
if vectorstore is None:
raise RuntimeError("知识库不存在,请先运行 build_knowledge_base()")
return manager
def interactive_qa(manager: VectorStoreManager):
"""命令行交互问答"""
retriever = manager.get_retriever(
top_k=RETRIEVAL_TOP_K,
score_threshold=SIMILARITY_THRESHOLD
)
qa_system = RAGQASystem(
retriever=retriever,
api_key=LLM_API_KEY,
base_url=LLM_BASE_URL,
model=LLM_MODEL
)
console.print(Panel.fit(
"💬 知识库问答系统已就绪!输入 'quit' 退出",
style="bold cyan"
))
while True:
question = input("\n❓ 请输入问题:").strip()
if question.lower() in ["quit", "exit", "q"]:
console.print("[yellow]👋 再见![/yellow]")
break
if not question:
continue
console.print("\n🤔 正在检索和生成回答...")
# 流式输出答案
console.print("\n[bold green]💡 答案:[/bold green]")
result = qa_system.ask_with_sources(question)
console.print(result["answer"])
# 显示来源
if result["sources"]:
table = Table(title=f"\n📎 参考来源(共 {result['docs_count']} 段)")
table.add_column("序号", style="cyan", width=5)
table.add_column("来源文件", style="green")
table.add_column("相关内容片段", style="white")
for i, src in enumerate(result["sources"][:3], 1):
table.add_row(
str(i),
os.path.basename(src["source"]),
src["content"][:80] + "..."
)
console.print(table)
if __name__ == "__main__":
import sys
if len(sys.argv) > 1 and sys.argv[1] == "build":
# python main.py build
manager = build_knowledge_base("./data")
else:
# python main.py
manager = load_knowledge_base()
interactive_qa(manager)
八、优化策略:提升检索质量 🎯
8.1 混合检索(Hybrid Search)
python
from langchain_community.retrievers import BM25Retriever
from langchain.retrievers import EnsembleRetriever
# BM25:关键词检索(擅长精确匹配)
bm25_retriever = BM25Retriever.from_documents(chunks)
bm25_retriever.k = 5
# 向量检索:语义相似度(擅长语义理解)
vector_retriever = vectorstore.as_retriever(search_kwargs={"k": 5})
# 混合检索:两者取长补短
ensemble_retriever = EnsembleRetriever(
retrievers=[bm25_retriever, vector_retriever],
weights=[0.4, 0.6] # BM25 权重 40%,向量 60%
)
8.2 重排序(Reranking)
python
from langchain.retrievers import ContextualCompressionRetriever
from langchain.retrievers.document_compressors import CrossEncoderReranker
from langchain_community.cross_encoders import HuggingFaceCrossEncoder
# Cross-Encoder 重排序模型(更精准但更慢)
cross_encoder = HuggingFaceCrossEncoder(
model_name="BAAI/bge-reranker-v2-m3"
)
reranker = CrossEncoderReranker(
model=cross_encoder,
top_n=3 # 从 10 个候选中选出最相关的 3 个
)
# 先召回 10 个,再精排 Top 3
base_retriever = vectorstore.as_retriever(search_kwargs={"k": 10})
compression_retriever = ContextualCompressionRetriever(
base_compressor=reranker,
base_retriever=base_retriever
)
8.3 查询扩展(Query Expansion)
python
from langchain.chains import HypotheticalDocumentEmbedder
def expand_query(question: str, llm) -> List[str]:
"""
用 LLM 生成多个变体问题,提升召回率
例:'苹果营养价值' → ['苹果有哪些维生素', '吃苹果的好处', '苹果的营养成分']
"""
prompt = f"""请将以下问题改写为3个不同表达方式的问题,用于检索文档。
原始问题:{question}
直接输出3个问题,每行一个,不要编号:"""
response = llm.invoke(prompt).content
variants = [q.strip() for q in response.strip().split("\n") if q.strip()]
return [question] + variants[:3] # 原始问题 + 3个变体
def multi_query_retrieve(question: str, retriever, llm) -> List:
"""多查询检索"""
queries = expand_query(question, llm)
all_docs = []
seen_ids = set()
for query in queries:
docs = retriever.invoke(query)
for doc in docs:
doc_id = hash(doc.page_content)
if doc_id not in seen_ids:
all_docs.append(doc)
seen_ids.add(doc_id)
return all_docs
九、WebUI 界面(Gradio)🖥️
用 Gradio 5 分钟搭建一个好看的问答界面:
python
# app.py
import gradio as gr
from main import load_knowledge_base
from src.config import *
from src.qa_chain import RAGQASystem
# 加载知识库
manager = load_knowledge_base()
retriever = manager.get_retriever(top_k=RETRIEVAL_TOP_K)
qa_system = RAGQASystem(
retriever=retriever,
api_key=LLM_API_KEY,
base_url=LLM_BASE_URL,
model=LLM_MODEL
)
def chat(message: str, history: list):
"""流式对话函数"""
response = ""
for chunk in qa_system.ask_stream(message):
response += chunk
yield response
def upload_and_index(files):
"""上传文档并实时建索引"""
from src.document_loader import DocumentProcessor
processor = DocumentProcessor()
all_chunks = []
for file in files:
chunks = processor.process(file.name)
all_chunks.extend(chunks)
manager.add_documents(all_chunks)
return f"✅ 已成功索引 {len(files)} 个文件,共 {len(all_chunks)} 个片段"
# 构建界面
with gr.Blocks(
title="🧠 本地知识库问答系统",
theme=gr.themes.Soft(),
css=".gradio-container { max-width: 900px !important; margin: auto; }"
) as demo:
gr.Markdown("""
# 🧠 本地知识库问答系统
> **基于 RAG 技术** | Python + DeepSeek + ChromaDB
""")
with gr.Row():
with gr.Column(scale=3):
# 聊天界面
chatbot = gr.Chatbot(
height=500,
show_label=False,
avatar_images=("👤", "🤖"),
bubble_full_width=False,
)
with gr.Row():
msg = gr.Textbox(
placeholder="请输入你的问题...",
scale=4,
show_label=False,
)
send_btn = gr.Button("发送 🚀", variant="primary", scale=1)
gr.Examples(
examples=[
"这个知识库主要包含哪些内容?",
"请总结一下最重要的知识点",
"有没有关于...的介绍?",
],
inputs=msg
)
with gr.Column(scale=1):
gr.Markdown("### 📁 上传文档")
upload = gr.File(
label="支持 PDF / Word / TXT / MD",
file_count="multiple",
file_types=[".pdf", ".docx", ".txt", ".md"]
)
upload_btn = gr.Button("开始索引 ⚡", variant="secondary")
upload_status = gr.Textbox(
label="索引状态",
interactive=False,
lines=3
)
gr.Markdown("### ℹ️ 系统信息")
gr.Markdown(f"""
- **LLM**:{LLM_MODEL}
- **Embedding**:BGE-M3
- **向量库**:ChromaDB
- **Top-K**:{RETRIEVAL_TOP_K}
""")
# 事件绑定
msg.submit(chat, [msg, chatbot], [chatbot])
send_btn.click(chat, [msg, chatbot], [chatbot])
upload_btn.click(upload_and_index, [upload], [upload_status])
if __name__ == "__main__":
demo.launch(
server_name="0.0.0.0",
server_port=7860,
share=False, # 改为 True 可生成公网链接
inbrowser=True, # 自动打开浏览器
)
启动命令:
bash
# 先构建知识库
python main.py build
# 启动 WebUI
python app.py
# 访问 http://localhost:7860
十、部署与进阶 🚀
10.1 性能优化对比
| 优化方向 | 方案 | 效果 |
|---|---|---|
| 召回质量 | 混合检索 + Reranking | 准确率 +30% |
| 响应速度 | 向量缓存 + 异步处理 | 速度 +50% |
| 支持规模 | 换用 Milvus / Qdrant | 支持亿级向量 |
| 中文效果 | BGE-M3 Embedding | 优于 OpenAI |
| 成本控制 | 本地 Ollama + Qwen | 零 API 费用 |
10.2 替换为完全本地方案(零成本)
python
# 完全本地:Ollama + DeepSeek-R1:7B
from langchain_ollama import ChatOllama, OllamaEmbeddings
# 需先安装 Ollama 并拉取模型:ollama pull deepseek-r1:7b
llm = ChatOllama(
model="deepseek-r1:7b",
temperature=0.1
)
# 本地 Embedding
embeddings = OllamaEmbeddings(model="nomic-embed-text")
bash
# 安装 Ollama(一行命令)
curl -fsSL https://ollama.com/install.sh | sh
# 拉取模型
ollama pull deepseek-r1:7b
ollama pull nomic-embed-text
# 启动 Ollama 服务
ollama serve
总结 🌟
完整代码流程回顾
python
# 5 步搭建 RAG 系统
# ① 加载文档
processor = DocumentProcessor()
chunks = processor.process("./data")
# ② 向量化存储
manager = VectorStoreManager()
manager.build_from_documents(chunks)
# ③ 创建检索器
retriever = manager.get_retriever(top_k=5)
# ④ 构建问答链
qa = RAGQASystem(retriever=retriever, ...)
# ⑤ 提问!
answer = qa.ask("你的问题")
效果评估指标
| 指标 | 评估方法 | 目标值 |
|---|---|---|
| 召回率 | 相关文档被检索到的比例 | > 90% |
| 精确率 | 检索文档的相关性 | > 80% |
| 答案准确率 | 与标准答案的一致性 | > 85% |
| 响应时间 | 端到端延迟 | < 3s |
进阶方向 🔮
- 🕸️ Graph RAG:知识图谱 + 向量检索,处理复杂关联关系
- 🖼️ 多模态 RAG:支持图片、表格、PPT 理解
- 🔁 自适应 RAG:根据问题动态调整检索策略
- 📊 RAG 评估框架:RAGAS、TruLens 自动化评估
💬 互动区
你的 RAG 系统是用于哪个场景的?遇到过哪些坑?
点赞 👍 + 收藏 ⭐ + 关注 获取更多 Python × AI 实战教程!
📎 参考资料
📕个人领域 :Linux/C++/java/AI
🚀 个人主页 :有点流鼻涕 · CSDN
💬 座右铭 : "向光而行,沐光而生。"
*