本地私有化智能文档问答系统 · Local Private Document Q&A System
LLM / Embedding / Rerank 全部跑在本机,文档与对话数据绝不上传外部 API。
LocalSmartRAG 是一个面向学生、科研人员、隐私敏感个人用户的本地文档问答系统。上传 PDF / Word / Markdown / TXT 文档后,即可对文档内容进行自然语言提问,回答自带引用溯源(文档名 + 页码 + 原文片段)。
与传统云端 RAG 方案不同,本项目的 LLM、Embedding、Rerank 全部在本地运行:
- 对话与向量化走 Ollama(本地推理)
- 重排走 sentence-transformers(本地权重)
- 文档与对话记录零外传,适合处理敏感资料
💡 为什么做这个项目? 云端的文档问答(如 ChatGPT 上传文件)意味着把资料交给第三方;企业内部方案又重又贵。本项目用一个
pip install+ 两个模型,就能在个人电脑上搭起一套完全私有的知识库问答,是理解 RAG 工程化的绝佳练手项目,也可直接作为简历 / 毕设 / 课程设计背书。
| 亮点 | 说明 |
|---|---|
| 🔒 完全本地 · 隐私安全 | LLM / Embedding / Rerank 全本地,代码审计只允许访问 OLLAMA_BASE_URL,数据零上传 |
| 🔀 混合检索(核心) | BM25 关键词 + 向量语义检索加权融合,再经本地 Rerank 重排,召回精度显著优于单路检索 |
| 🧰 工程化完备 | 多知识库隔离、多轮会话、引用溯源、日志/异常/缓存、上传去重,非玩具 demo |
文档处理
- ✅ 多格式解析:PDF(逐页保留页码)/ docx / Markdown / TXT
- ✅ 自适应语义分块:标题结构感知 + 代码/公式块保护 + 段落边界优先
- ✅ 文本清洗:乱码过滤、页眉页脚检测、空行压缩、全半角规范化
- ✅ 上传去重(内容 SHA-256 哈希)+ 批量向量化进度条
检索问答
- ✅ 混合检索:向量路 + BM25 路 → 归一化加权融合(或 RRF)→ 本地 Rerank 重排
- ✅ 引用溯源:回答用
[n]标注,可展开查看「文档名 + 页码 + 原文片段」 - ✅ 幻觉约束:严格限定「仅基于资料回答,无相关信息则明说」,禁止编造
- ✅ 流式输出,打字机效果
工程能力
- ✅ 多知识库隔离:每库独立 Chroma collection,embedding 模型一致性校验
- ✅ 多轮会话:滑动窗口记忆 + JSON 持久化,跨重启恢复
- ✅ 模型可配置:侧边栏切换 LLM / temperature / top_k / 融合权重
- ✅ 会话导出 Markdown、日志轮转、TTL 检索缓存
效果预览
flowchart LR
A[文档<br/>PDF/docx/md/txt] --> B[document_loader<br/>解析]
B --> C[text_cleaner<br/>清洗]
C --> D[smart_splitter<br/>分块]
D --> E[embedding_engine<br/>向量化]
E --> F[(Chroma<br/>向量库)]
Q[用户问题] --> G[retriever_hybrid<br/>混合检索]
F --> G
G --> H[reranker<br/>重排]
H --> I[rag_chain<br/>LLM 生成]
I --> J[带引用回答]
subgraph 支撑模块
K[config<br/>配置]
L[kb_service<br/>知识库]
M[session_service<br/>会话]
N[export_service<br/>导出]
end
数据流:文档 → 解析 → 清洗 → 分块 → 向量化 → Chroma → 混合检索(向量 + BM25 融合)→ 重排 → LLM → 带引用回答。
前置要求:Python 3.11+,可联网(首次需下载模型与 rerank 权重)。
Ollama 是本项目的推理引擎,负责本地跑 LLM 与 Embedding 模型。
Windows
- 方式一(推荐):打开 ollama.com/download → 下载 Windows 安装包 → 双击安装 → 启动 Ollama 应用(出现在系统托盘)。
- 方式二(命令行):
winget install Ollama.Ollama
⚠️ 安装后务必重开终端(让 PATH 生效),否则会报ollama 不是内部或外部命令。
macOS
brew install ollama
brew services start ollamaLinux
curl -fsSL https://ollama.com/install.sh | sh需要两个模型:对话模型 + 向量模型。
ollama pull qwen2.5:7b # 对话模型(约 4.7GB)
ollama pull nomic-embed-text # 向量模型(约 274MB)💡 对话模型可换成任意 Ollama 支持的模型(如
llama3.1:8b、deepseek-r1:7b),改.env里的LLM_MODEL即可。
验证:
ollama list
# 应看到 qwen2.5:7b 和 nomic-embed-text 两行方式 A:conda(推荐)
conda create -n LocalSmartRAG python=3.11 -y
conda activate LocalSmartRAG方式 B:venv
python -m venv .venv
# Windows:
.venv\Scripts\activate
# macOS / Linux:
source .venv/bin/activatepip install -r requirements.txt依赖较多(含 PyTorch 生态),首次安装需要几分钟。如遇网络慢,可先
pip install -U pip,或配置国内镜像源。
# Windows:
copy .env.example .env
# macOS / Linux:
cp .env.example .env不配置也能跑(有默认值),.env 用于自定义模型名、地址、分块/检索参数等,详见配置说明。
streamlit run app.py
# 或(含启动前健康检查):
python main.py浏览器访问 **http://localhost:8501**,开始使用 🎉
docker build -t localsmartrag .
# Linux 下用 host.docker.internal 访问宿主机 Ollama
docker run -p 8501:8501 -e OLLAMA_BASE_URL=http://host.docker.internal:11434 localsmartrag打开页面后,在左侧「知识库」面板点击展开 新建知识库,输入名称(如「高等数学资料」)和描述,点击「创建知识库」。
在「上传文档」区域点击 Browse files(可多选),支持 .pdf / .docx / .md / .txt,然后点击 上传并建库。上传过程有进度条,完成后会显示「上传成功 X 个,新增 N 块」。
⚠️ 扫描件/图片型 PDF 暂不支持(没有文字层,需 OCR,见 FAQ)。请使用有文字层的电子版 PDF。
在页面底部输入框输入问题(如「这篇文档讲了什么?」),回车发送。回答以流式输出,句末带 [n] 引用标记。
点击回答下方的 [n] 文档名 第X页 可展开查看对应原文片段,验证答案出处。
左侧「模型与参数」面板可实时调整:
- LLM 模型:下拉切换已安装的模型
- temperature:0 偏保守、1 偏发散
- 单路检索 top_k:每路召回条数
- 融合权重 alpha:越大越偏向量语义,越小越偏关键词
- 滑动窗口:多轮对话携带的历史轮数
- 点击「+ 新建会话」开新对话
- 点击「导出」把当前会话存为 Markdown 文件(含问答与引用来源)
.env 全参数(缺省均用默认值):
| 参数 | 默认值 | 说明 |
|---|---|---|
OLLAMA_BASE_URL |
http://localhost:11434 |
Ollama 服务地址(唯一允许的网络访问目标) |
LLM_MODEL |
qwen2.5:7b |
对话模型 |
EMBEDDING_MODEL |
nomic-embed-text |
向量模型(换模型需重建索引) |
RERANK_MODEL |
BAAI/bge-reranker-base |
本地重排模型(sentence-transformers) |
CHUNK_SIZE |
800 |
分块字符数 |
CHUNK_OVERLAP |
150 |
相邻块重叠字符数 |
TOP_K |
8 |
单路检索数量 |
TOP_N |
10 |
融合后合并数量 |
TOP_N_RERANK |
5 |
重排后送入 LLM 的数量 |
RETRIEVAL_ALPHA |
0.6 |
向量/BM25 融合权重(0~1) |
TEMPERATURE |
0.1 |
生成温度 |
SESSION_WINDOW |
6 |
滑动窗口轮数 |
LOG_LEVEL |
INFO |
日志级别 |
DATA_DIR |
./data |
数据目录 |
Ollama 默认把模型存在 C:\Users\<你>\.ollama\models,想改到 D 盘:
[Environment]::SetEnvironmentVariable("OLLAMA_MODELS", "D:\ollama\models", "User")然后重启 Ollama(托盘右键 → Quit → 重新打开)才生效。
先按 Markdown 标题(#/##/###)切主块;检测代码围栏与 $$、\( \) 公式块并整体保留不截断;优先段落边界(\n\n)、其次句末标点;超长块递归字符切分降级。每个块携带 source / page / chunk_index 元数据。
- 向量路:Chroma 按 query 向量取 top_k,语义匹配(能懂同义词)
- 关键词路:jieba 分词 + BM25Okapi 取 top_k,精确匹配(能命中专有名词/编号)
- 融合:两路分数各自 min-max 归一化后加权
score = alpha × minmax(向量分) + (1 - alpha) × minmax(BM25分)
- 备选:RRF 倒数排名融合(无需归一化、更鲁棒)
Ollama 无原生 rerank 端点,采用本地 BAAI/bge-reranker-base 交叉编码器对融合结果精排,取 top_n_rerank 送入 LLM。
仅携带最近 N 轮对话(默认 6 轮)作为上下文,超出丢弃最旧,防止上下文过长、成本失控。
Prompt 明确「仅基于资料回答、无相关信息则回答『资料中未找到相关信息』、回答需用 [n] 标注引用」,回答后处理将 [n] 映射为来源清单。
LocalSmartRAG/
├── main.py # 入口:健康检查 + 启动 Streamlit
├── app.py # Streamlit 界面
├── config/
│ ├── settings.py # 全局配置类(读 .env)
│ └── constants.py # 常量(路径/默认参数/停用词)
├── core/ # RAG 核心引擎
│ ├── document_loader.py # 多格式解析(工厂模式)
│ ├── text_cleaner.py # 清洗 + 页眉页脚检测
│ ├── smart_splitter.py # 自适应分块
│ ├── embedding_engine.py # Ollama 向量化封装
│ ├── retriever_hybrid.py # 混合检索 + 融合
│ ├── reranker.py # 重排(抽象 + bge + 降级)
│ └── rag_chain.py # 问答链路 + 引用后处理
├── service/
│ ├── kb_service.py # 知识库 CRUD + 上传编排
│ ├── session_service.py # 会话 + 滑动窗口
│ └── export_service.py # 导出 Markdown
├── utils/
│ ├── logger.py # 日志(RotatingFileHandler)
│ ├── file_utils.py # 文件工具(校验/哈希/安全名)
│ └── cache.py # TTL 缓存
├── data/ # 运行时生成(uploads/chroma_db/sessions)
├── requirements.txt
├── Dockerfile
└── .env.example
没安装,或安装后没重开终端。确认已安装 Ollama,并新开一个终端窗口。
只拉了对话模型,没拉向量模型。执行 ollama pull nomic-embed-text。
你的 PDF 是扫描件/图片型 PDF(没有文字层)。PyMuPDF 只能提取内嵌文字,图片里的字需 OCR。请换用电子版 PDF,或关注 Roadmap 中的 OCR 支持。
Ollama 没在运行。Windows 打开 Ollama 应用,或命令行执行 ollama serve。
设置 OLLAMA_MODELS 环境变量改到其他盘,见配置说明。
首次会从 HuggingFace 下载 BAAI/bge-reranker-base(约 1GB),属正常,之后走本地缓存离线可用。
换模型需重建知识库索引(向量维度/语义空间不同)。删除旧知识库重新上传即可。
- 本地小模型回答质量有上限,复杂推理/长链问答不如云端大模型;
- 首次启动需下载模型与 rerank 权重,耗时较长;
- 单机单用户,无分布式 / 多用户并发能力;
- 长文档、复杂表格精度有限;图片型 PDF 暂不支持 OCR;
- 深度依赖 Ollama 生态,能力受限于本地硬件。
- 增量索引(新文档追加,不重建整个库)
- 单文档删除
- OCR 支持(扫描件/图片型 PDF 文字提取)
- URL 抓取入库
- 多模态(图片 / 图文混合问答)
- 检索评估脚本(Recall@k / MRR)
- WebUI 美化
- docker-compose 一键编排 Ollama + App
欢迎 Star、Fork、提 Issue 与 PR!
- Fork 本仓库
- 新建特性分支:
git checkout -b feature/xxx - 提交改动:
git commit -m 'feat: xxx' - 推送分支:
git push origin feature/xxx - 发起 Pull Request,并描述改动动机
提交前请确保:代码风格与现有保持一致、中文注释充分、无新增未声明依赖。
本项目基于 MIT 协议开源,欢迎用于学习与二次开发。
⭐ 如果这个项目对你有帮助,欢迎点个 Star 支持一下!


