面向电力系统与国家电网业务场景的 RAG 项目。当前主线是前后端分离架构:
frontend/:React + Vite 前端,负责聊天、文件管理、用户管理、消息渲染backend/:FastAPI 后端,负责鉴权、会话、流式回答、文件服务接口tools/、config/、data/、models/:前后端共享的知识库、解析、检索和模型资源
旧的 Streamlit 入口和相关运行逻辑已经移除,当前部署主线只保留前后端分离架构。
这个项目主要解决以下问题:
- 上传 PDF / 文档并完成知识库入库
- 使用 MinerU 提取正文、图片、表格
- 使用 Qdrant 做向量检索与混合检索
- 对复杂表格做独立切块、表格摘要、证据回溯
- 在前端以聊天形式展示答案、来源、表格和附件图片
核心特点:
- 面向中文、电力行业、国网业务资料
- 支持图片与表格证据回溯
- 支持流式回答
- 支持用户鉴权与管理员文件管理
- 当前部署统一走前后端分离入口
当前主线由四类组件组成:
frontend:React + Vite 前端,负责页面、登录态、聊天 UI、文件管理 UIbackend:FastAPI 后端,负责鉴权、会话、SSE 流式问答、文件接口qdrant:向量库服务,负责持久化向量、payload 和相似度检索redis:会话索引与元数据服务,负责会话列表、标题、最近活跃时间、消息数
运行拓扑如下:
浏览器
|
v
frontend
|
| /api
v
backend
|
+--> qdrant 向量库服务
+--> redis 会话索引与元数据
+--> models/ 本地 embedding / reranker / summary 模型
+--> .user/ 用户与鉴权数据
+--> SHARED_STORAGE_ROOT/
├── stored_files/
│ └── mineru_output/
├── content_lists/
├── exported_chunks/
├── agent_memory/
└── chat_sessions/
当前项目的状态分成三层:
-
持久化服务层
qdrant:知识库向量、payload、collection 数据redis:会话索引、会话元信息
-
文件持久化层
SHARED_STORAGE_ROOT/stored_files:上传原始文件SHARED_STORAGE_ROOT/stored_files/mineru_output:图片、表格截图SHARED_STORAGE_ROOT/agent_memory:memory 快照SHARED_STORAGE_ROOT/chat_sessions:完整 transcript
-
进程内运行态
- backend 进程内
ChatAgent - backend 进程内热模型缓存
- backend 进程内 session 执行态
- backend 进程内
这也是当前仍然保持 BACKEND_WORKERS=1 的原因:会话索引已经外置,但 ChatAgent 执行态还没有完全无状态化。
当前代码支持三种模式:
-
本地最小模式
QDRANT_MODE=localREDIS_URL=为空- 用于先验证前后端主流程
-
本地完整链路模式
- backend / frontend 本地启动
qdrant和redis作为独立服务运行- 用于验证完整服务链
-
Docker 部署模式
web + backend + qdrant + redis- 用于标准化部署
rag/
├── frontend/ # React + Vite 前端
│ ├── src/
│ │ ├── api/
│ │ ├── components/
│ │ ├── pages/
│ │ ├── stores/
│ │ └── types/
│ ├── package.json
│ └── vite.config.ts
│
├── backend/ # FastAPI 后端
│ ├── app/
│ │ ├── api/v1/ # 路由层
│ │ ├── core/ # 安全、中间件、Redis 客户端
│ │ ├── schemas/ # Pydantic schema
│ │ ├── services/ # chat / file / user / auth
│ │ ├── config.py # 后端配置入口
│ │ ├── dependencies.py # 依赖注入与资源缓存
│ │ └── main.py # FastAPI 应用入口
│ ├── run.py
│ └── requirements.txt
│
├── tools/ # MinerU、入库、检索、Qdrant 工具链
├── config/ # MinerU 等公共配置
├── deploy/nginx/ # Docker Nginx 反向代理配置
├── scripts/ # 迁移、调试、smoke、评测脚本
├── storage_paths.py # 共享存储路径统一入口
├── requirements.txt # 根目录主依赖清单(含 camel-ai、mineru 等)
├── backend/requirements.txt # 后端附加依赖清单
├── Dockerfile.backend
├── Dockerfile.frontend
├── docker-compose.yml # 唯一启动入口
├── docker-compose.deploy.yml # 部署版(使用预构建镜像标签)
├── deploy.sh # 一键部署脚本
├── update.sh # 一键更新脚本
├── README.md
└── .gitignore
默认 SHARED_STORAGE_ROOT=data,因此当前运行数据目录如下:
data/
├── qdrant/ # Qdrant Server 数据目录
├── redis/ # Redis AOF / RDB 数据目录
├── lex_index/ # 后端词汇索引缓存
├── stored_files/ # 上传的原始文件
│ └── mineru_output/ # 图片、表格截图、方程截图
├── content_lists/ # 文档解析中间结果
├── exported_chunks/ # 调试导出的 chunk
├── agent_memory/ # memory 快照
├── chat_sessions/ # transcript 文件
└── storages/ # 历史 local Qdrant 数据目录(兼容旧库)
前端负责:
- 登录与用户态维护
- 聊天页面与历史会话列表
- 文件管理、导入、删除
- SSE 流式渲染
- Markdown / 表格 / 数学公式 / 附件图片区渲染
关键模块:
frontend/src/pages/ChatPage.tsxfrontend/src/components/chat/frontend/src/stores/frontend/src/api/
后端负责:
- JWT 鉴权
- Chat SSE 流式响应
- ChatAgent 会话生命周期管理
- transcript / memory 持久化
- 文件上传、入库、删除、预览
- 调用
backend/app/core/与tools/
关键模块:
backend/app/services/chat_service.pybackend/app/services/file_service.pybackend/app/services/user_service.pybackend/app/core/redis_client.pybackend/app/dependencies.py
共享核心能力:
-
tools/mineru_toolkit.py- PDF 解析
- 图片、表格、方程输出
-
tools/load_files.py- 内容预处理
- chunk 切分
- 表格摘要
- Qdrant 写入
-
tools/qdrant.py- 支持
local/server双模式 - 向量检索
- 词汇索引缓存
- hybrid 检索
- 支持
-
tools/database_toolkit.py- 对 Agent 暴露
search_database - rerank
- 动态裁剪和去重
- 对 Agent 暴露
-
backend/app/core/model_runtime.py- LLM
- embedding
- reranker
- table summary model
-
backend/app/core/agent_factory.py- 问答 Agent 工厂
- 系统提示词与行为约束
- Python 3.10+
- Node.js 20.19+ 或 22.12+
- 推荐 Linux 环境
- 推荐使用虚拟环境
python3 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip setuptools wheel
pip install -r requirements.txt
pip install -r backend/requirements.txt说明:
- 根目录
requirements.txt已包含主工程依赖和后端运行时依赖 backend/requirements.txt用于和 Docker 镜像安装链路保持一致,建议继续安装
cd frontend
npm install
cd ..如果要跑完整服务链,需要额外准备:
qdrant服务redis服务
你可以:
- 用 Docker 起这两个服务
- 或者在系统里单独安装它们并本地启动
在项目根目录创建 .env。推荐直接复制 .env.example 后按实际环境修改。
示例:
# ------------------------------
# 基础运行配置
# ------------------------------
DEBUG=false
SECRET_KEY=change-me
# ------------------------------
# OpenAI 兼容模型服务
# ------------------------------
OPENAI_API_KEY=your-api-key
url=https://your-openai-compatible-endpoint/v1
MODEL_NAME=qwq32b
# ------------------------------
# 主回答 Agent 参数
# ------------------------------
MAIN_AGENT_MODEL_NAME=qwq32b
MAIN_AGENT_TEMPERATURE=0.2
MAIN_AGENT_TOP_P=0.9
MAIN_AGENT_MAX_TOKENS=4000
MAIN_AGENT_MESSAGE_WINDOW_SIZE=12
MAIN_AGENT_SUMMARIZE_THRESHOLD=20
MAIN_AGENT_PRUNE_TOOL_CALLS=true
MAIN_AGENT_STREAM_ACCUMULATE=false
MAIN_AGENT_SYSTEM_PROMPT_PATH=config/prompts/main_agent_system.txt
# ------------------------------
# 辅助 Agent 参数
# ------------------------------
INTENT_ROUTER_MODEL_NAME=qwq32b
INTENT_ROUTER_TEMPERATURE=0.0
INTENT_ROUTER_TOP_P=1.0
INTENT_ROUTER_MAX_TOKENS=800
SEARCH_REWRITER_MODEL_NAME=qwq32b
SEARCH_REWRITER_TEMPERATURE=0.1
SEARCH_REWRITER_TOP_P=1.0
SEARCH_REWRITER_MAX_TOKENS=1200
# ------------------------------
# 本地模型路径
# ------------------------------
conan_path=models/bge-base-zh-v1.5
reranker_path=models/bge-reranker-base
TABLE_SUMMARY_MODEL_PATH=models/Qwen2.5-1.5B-Instruct
EMBEDDING_DEVICE=
RERANKER_DEVICE=
TABLE_SUMMARY_DEVICE=
# ------------------------------
# Agent Memory
# ------------------------------
AGENT_MEMORY_ENABLED=true
AGENT_MEMORY_TOKEN_LIMIT=12000
AGENT_MEMORY_RETRIEVE_LIMIT=6
AGENT_MEMORY_KEEP_RATE=0.9
MEMORY_TOKEN_COUNTER_MODEL=GPT_4O_MINI
CHAT_CONTEXT_BUDGET_LOG_ENABLED=false
AGENT_COMPACT_ENABLED=true
AGENT_COMPACT_TRIGGER_MESSAGES=12
AGENT_COMPACT_TRIGGER_CHARS=24000
AGENT_COMPACT_KEEP_RECENT_MESSAGES=4
FACTUAL_EVIDENCE_MAX_CHARS=6000
# ------------------------------
# Qdrant / Redis / 共享存储
# ------------------------------
SHARED_STORAGE_ROOT=data
QDRANT_MODE=server
QDRANT_URL=http://127.0.0.1:6333
QDRANT_API_KEY=
QDRANT_LOCAL_PATH=data/storages
QDRANT_LEXICAL_INDEX_DIR=data/lex_index
REDIS_URL=redis://127.0.0.1:6379/0
REDIS_PREFIX=rag
REDIS_SOCKET_TIMEOUT_SEC=5
REDIS_SOCKET_CONNECT_TIMEOUT_SEC=5| 变量 | 作用 |
|---|---|
OPENAI_API_KEY |
主对话模型 API Key |
url |
OpenAI 兼容接口地址 |
MODEL_NAME |
默认模型名称;未给子 agent 单独指定时会回退到这里 |
MAIN_AGENT_MODEL_NAME |
主回答 agent 使用的模型名 |
MAIN_AGENT_TEMPERATURE |
主回答 agent 采样温度 |
MAIN_AGENT_TOP_P |
主回答 agent 的 top_p |
MAIN_AGENT_MAX_TOKENS |
主回答 agent 最大生成 token 数 |
MAIN_AGENT_MESSAGE_WINDOW_SIZE |
主回答 agent 的短窗口消息数 |
MAIN_AGENT_SUMMARIZE_THRESHOLD |
主回答 agent 的摘要触发阈值 |
MAIN_AGENT_PRUNE_TOOL_CALLS |
是否裁掉工具调用痕迹 |
MAIN_AGENT_STREAM_ACCUMULATE |
流式输出时是否累积完整内容 |
MAIN_AGENT_SYSTEM_PROMPT_PATH |
主回答 agent 系统提示词文件路径 |
INTENT_ROUTER_MODEL_NAME |
意图路由器模型名 |
INTENT_ROUTER_TEMPERATURE |
意图路由器温度 |
SEARCH_REWRITER_MODEL_NAME |
检索改写器模型名 |
SEARCH_REWRITER_TEMPERATURE |
检索改写器温度 |
conan_path |
embedding 模型路径 |
reranker_path |
reranker 模型路径 |
TABLE_SUMMARY_MODEL_PATH |
表格摘要模型路径 |
EMBEDDING_DEVICE |
embedding 模型设备,留空为自动检测 |
RERANKER_DEVICE |
reranker 模型设备,留空为自动检测 |
TABLE_SUMMARY_DEVICE |
表格摘要模型设备,留空为自动检测 |
SECRET_KEY |
后端 JWT 密钥 |
DEBUG |
后端调试模式 |
AGENT_MEMORY_ENABLED |
是否启用 CAMEL 长期记忆 |
AGENT_MEMORY_TOKEN_LIMIT |
长期记忆 token 上限 |
AGENT_MEMORY_RETRIEVE_LIMIT |
长期记忆召回条数 |
AGENT_MEMORY_KEEP_RATE |
历史消息保留系数 |
QDRANT_MODE |
Qdrant 运行模式,local 或 server |
QDRANT_URL |
Qdrant 服务地址,服务模式必填 |
QDRANT_LEXICAL_INDEX_DIR |
BM25 词汇索引缓存目录 |
REDIS_URL |
Redis 地址,用于会话索引和元数据共享 |
REDIS_PREFIX |
Redis key 前缀 |
SHARED_STORAGE_ROOT |
共享文件根目录,默认 data |
用于先跑通前后端主流程:
QDRANT_MODE=local
QDRANT_URL=
REDIS_URL=
SHARED_STORAGE_ROOT=data用于验证独立服务链:
QDRANT_MODE=server
QDRANT_URL=http://127.0.0.1:6333
REDIS_URL=redis://127.0.0.1:6379/0
SHARED_STORAGE_ROOT=dataDocker Compose 会覆盖为:
QDRANT_MODE=server
QDRANT_URL=http://qdrant:6333
REDIS_URL=redis://redis:6379/0
SHARED_STORAGE_ROOT=data以下目录默认不提交远程仓库:
models/data/qdrant/data/redis/data/lex_index/data/stored_files/data/content_lists/data/exported_chunks/data/agent_memory/data/chat_sessions/.user/
这些目录分别存放:
- 本地模型
- Qdrant Server 持久化数据
- Redis 持久化数据
- 本地词汇索引缓存
- 上传原始文件
- MinerU 输出图片/表格截图
- 文档解析缓存
- 会话与 agent memory 持久化数据
- 用户数据
适用于先验证:
- 后端可启动
- 前端可启动
- 本地 local Qdrant 可工作
- 上传、入库、问答链路可跑通
后端:
cd rag
source .venv/bin/activate
python backend/run.py --host 0.0.0.0 --port 8000前端:
cd rag/frontend
npm run dev -- --host 0.0.0.0 --port 3000访问:
- 前端:
http://127.0.0.1:3000 - 后端:
http://127.0.0.1:8000/docs
适用于验证:
- backend
- frontend
- qdrant server
- redis
- 完整服务链
典型启动顺序:
- 启动
redis - 启动
qdrant - 启动
backend - 启动
frontend
推荐先把 .env 切到服务模式:
QDRANT_MODE=server
QDRANT_URL=http://127.0.0.1:6333
REDIS_URL=redis://127.0.0.1:6379/0
SHARED_STORAGE_ROOT=data四个终端分别执行:
终端 1,启动 redis:
mkdir -p rag/data/redis
redis-server --port 6379 --appendonly yes --dir rag/data/redis终端 2,启动 qdrant:
unset http_proxy https_proxy HTTP_PROXY HTTPS_PROXY ALL_PROXY
export NO_PROXY=127.0.0.1,localhost
export no_proxy=127.0.0.1,localhost
mkdir -p rag/data/qdrant
QDRANT__STORAGE__STORAGE_PATH=rag/data/qdrant qdrant终端 3,启动 backend:
cd rag
source .venv/bin/activate
python backend/run.py --host 0.0.0.0 --port 8000终端 4,启动 frontend:
cd rag/frontend
npm install
npm run dev -- --host 0.0.0.0 --port 3000验证命令:
curl http://127.0.0.1:6333/collections
redis-cli -p 6379 ping
curl http://127.0.0.1:8000/health如果你之前使用的是:
QDRANT_MODE=local- 旧库位于
data/storages
而现在切到:
QDRANT_MODE=server
那么需要把旧数据迁移到 Qdrant Server。
项目已提供迁移脚本:
推荐命令:
cd rag
source .venv/bin/activate
python scripts/migrate_qdrant_local_to_server.py \
--local-path data/storages \
--server-url http://127.0.0.1:6333 \
--collection database \
--recreate说明:
- 迁移直接复制
id + vector + payload - 不需要重新 embedding
- 不需要重新导入 PDF
迁移后验证:
curl http://127.0.0.1:6333/collections/database当前只推荐一种启动方式:使用根目录 docker-compose.yml 统一启动 web + backend + qdrant + redis。
架构如下:
浏览器
|
v
nginx + frontend 静态资源 (:APP_PORT,默认 8080)
|
v
backend (FastAPI, 容器内 :8000)
|
+--> qdrant (容器内 :6333)
+--> redis (容器内 :6379)
|
+--> data/ 持久化文档、词汇索引、截图、transcript、memory
+--> models/ 本地模型目录
+--> .user/ 用户数据
部署相关文件现在只保留这一组:
rag/
├── docker-compose.yml # 唯一启动入口
├── Dockerfile.backend # 后端镜像
├── Dockerfile.frontend # 前端静态构建 + Nginx 镜像
└── deploy/nginx/default.conf # 统一反向代理配置
旧的 Dockerfile、Dockerfile.cuda、docker-compose.gpu.yml 不再保留,避免入口分叉。
确认以下目录和文件存在:
- 根目录
.env - 根目录
data/ - 根目录
models/ - 根目录
.user/
最少需要在 .env 中提供:
OPENAI_API_KEY=your-api-key
url=https://your-openai-compatible-endpoint/v1
MODEL_NAME=qwq32b
SECRET_KEY=change-me
MAIN_AGENT_MODEL_NAME=qwq32b
MAIN_AGENT_TEMPERATURE=0.2
MAIN_AGENT_TOP_P=0.9
MAIN_AGENT_MAX_TOKENS=4000
MAIN_AGENT_SYSTEM_PROMPT_PATH=config/prompts/main_agent_system.txt
conan_path=models/bge-base-zh-v1.5
reranker_path=models/bge-reranker-base
TABLE_SUMMARY_MODEL_PATH=models/Qwen2.5-1.5B-Instruct
MINERU_MODELS_DIR_PIPELINE=models/mineru/OpenDataLab/PDF-Extract-Kit-1___0
MINERU_MODELS_DIR_VLM=models/mineru/OpenDataLab/mineru2.5/OpenDataLab/MinerU2___5-2509-1___2B
INITIAL_ADMIN_USERNAME=admin
INITIAL_ADMIN_PASSWORD=change-this-admin-password可选覆盖项:
APP_PORT=8080
BACKEND_WORKERS=1
NVIDIA_VISIBLE_DEVICES=all
NVIDIA_DRIVER_CAPABILITIES=compute,utility说明:
APP_PORT是宿主机对外端口,默认8080BACKEND_WORKERS默认固定为1,这是为了避免本地会话状态和本地向量存储在多进程下产生不一致- 仅当
.user/users.json不存在时,INITIAL_ADMIN_USERNAME/INITIAL_ADMIN_PASSWORD才会用于初始化首个管理员 - 不再内置默认管理员口令
- MinerU 的模型目录支持通过
MINERU_MODELS_DIR_PIPELINE/MINERU_MODELS_DIR_VLM在.env中统一覆盖 NVIDIA_DRIVER_CAPABILITIES需要包含utility,这样容器内才能执行nvidia-smi
建议在首次 Docker 部署前手动创建持久化目录:
mkdir -p \
data/qdrant \
data/redis \
data/lex_index \
data/stored_files \
data/content_lists \
data/exported_chunks \
data/agent_memory \
data/chat_sessions \
models \
.user如果你此前在宿主机本地手动启动过:
redis-serverqdrantpython backend/run.pynpm run dev
建议先停掉这些本地进程,再启动 Docker。
原因是 data/ 会被容器直接挂载,本地进程和容器不要同时占用同一套数据目录。
当前只需要把下面 3 个顶层目录作为宿主机持久化挂载:
./data:/app/data./models:/app/models./.user:/app/.user
说明:
data/已经包含qdrant/、redis/、lex_index/、stored_files/、content_lists/、exported_chunks/、agent_memory/、chat_sessions/models/用于本地 embedding、reranker、表格模型以及其他下载模型.user/用于用户数据和鉴权信息.env只通过env_file注入,不需要作为 volume 挂载- 当前 Compose 默认注入
SHARED_STORAGE_ROOT=data,所有上传文件、MinerU 输出、transcript、memory 都从这个根目录派生
最简单的标准命令:
docker compose up -d --build如果你需要在容器里直接使用 GPU 并执行 nvidia-smi,启动前请确认宿主机已经安装 NVIDIA Container Toolkit;当前 backend 服务已经在 Compose 中申请 gpus: all,并默认注入:
NVIDIA_VISIBLE_DEVICES=all
NVIDIA_DRIVER_CAPABILITIES=compute,utility推荐把首次管理员初始化和 GPU 相关变量一起写入 .env:
INITIAL_ADMIN_USERNAME=admin
INITIAL_ADMIN_PASSWORD=change-this-admin-password
NVIDIA_VISIBLE_DEVICES=all
NVIDIA_DRIVER_CAPABILITIES=compute,utility推荐启动命令:
docker compose up -d --build启动后可直接验证:
docker compose exec backend nvidia-smi如果 nvidia-smi 能在 backend 容器内正常输出 GPU 信息,说明 GPU 透传已经生效。
当你修改了 Dockerfile.backend、Dockerfile.frontend、requirements.txt、backend/requirements.txt 之后,都应继续使用 --build 触发镜像重建。
如果你的环境拉取基础镜像或执行 pip install / npm ci / git clone 时网络不稳定,推荐使用本项目当前验证过的回退方式:
DOCKER_BUILDKIT=0 docker compose up -d --build如果你只想先构建镜像,再单独启动容器:
DOCKER_BUILDKIT=0 docker compose build --no-cache
docker compose up -d如果你宿主机上已经开了 HTTP 代理,例如:
export http_proxy=http://127.0.0.1:7897
export https_proxy=http://127.0.0.1:7897那么构建 Docker 镜像前,建议同时导出大小写两套变量:
export HTTP_PROXY=http://127.0.0.1:7897
export HTTPS_PROXY=http://127.0.0.1:7897
export NO_PROXY=localhost,127.0.0.1,qdrant,redis,backend,web
export http_proxy=http://127.0.0.1:7897
export https_proxy=http://127.0.0.1:7897
export no_proxy=localhost,127.0.0.1,qdrant,redis,backend,web本项目当前 Compose 已经做了两件事:
build阶段会把这些代理变量透传给apt-get、pip install、npm ci- 运行阶段不会再把代理写进
backend容器环境,避免模型请求被错误转发到127.0.0.1:7897
如果你已经构建完成,且后续不再需要 Docker 构建联网,可以在宿主机清掉这些变量:
unset HTTP_PROXY HTTPS_PROXY NO_PROXY
unset http_proxy https_proxy no_proxy如果你只改了前端代码,不需要整套重建,只重建 web 即可:
DOCKER_BUILDKIT=0 docker compose build --no-cache web
docker compose up -d web如果你只改了后端代码或后端依赖,只重建 backend:
DOCKER_BUILDKIT=0 docker compose build --no-cache backend
docker compose up -d --force-recreate backend如果你同时改了前后端:
DOCKER_BUILDKIT=0 docker compose build --no-cache backend web
docker compose up -d --force-recreate backend web查看状态:
docker compose ps
docker compose logs -f redis
docker compose logs -f qdrant
docker compose logs -f backend
docker compose logs -f web停止服务:
docker compose down如果只是想重启容器但保留数据目录:
docker compose restart- 主应用:
http://localhost:8080 - 后端健康检查:
http://localhost:8080/health - Swagger:
http://localhost:8080/docs - ReDoc:
http://localhost:8080/redoc
如果你设置了 APP_PORT,把上面的 8080 替换掉即可。
Windows 可以部署这套多容器架构,但建议区分两种方式理解:
- 推荐方式:
Windows + Docker Desktop + WSL2 - 可运行但不推荐:
Windows 原生目录 + Docker Desktop
更稳的做法是:
- 安装 Docker Desktop
- 打开 WSL2 backend
- 安装一个 Linux 发行版,例如 Ubuntu
- 在 Docker Desktop 里开启该 WSL 发行版的集成
- 把项目放在 WSL 的 Linux 文件系统中,例如:
/home/<your-user>/rag为什么推荐 WSL2:
- 当前项目依赖 Linux 风格路径和工具链
data/、models/、.user/这些目录在 Linux 文件系统下读写更稳- Qdrant、Redis、OCR、PDF 解析、模型文件加载都更适合 Linux 文件系统
- 如果项目直接放在
C:\Users\...这类 Windows 路径下,挂载性能和兼容性通常更差
WSL2 下的推荐命令流程:
进入 WSL 终端后执行:
cd /home/<your-user>/rag
mkdir -p \
data/qdrant \
data/redis \
data/lex_index \
data/stored_files \
data/content_lists \
data/exported_chunks \
data/agent_memory \
data/chat_sessions \
models \
.user确认根目录 .env 已配置好模型地址、密钥和模型路径后,执行:
DOCKER_BUILDKIT=0 docker compose up -d --build查看状态:
docker compose ps
docker compose logs -f backend
docker compose logs -f web访问地址仍然是:
http://localhost:8080
这里的 localhost 指 Windows 宿主机浏览器访问 Docker Desktop 暴露出来的端口。
WSL2 下的目录建议:
建议把以下目录长期保存在 WSL Linux 文件系统里:
data/models/.user/
尤其是 models/ 和 data/qdrant/,文件多且体积大,放在 WSL 内部磁盘通常更稳。
WSL2 下的注意事项:
- 不建议一边在 Windows 原生 Python 环境里手动跑后端,一边再用 Docker Desktop 跑同一套
data/ - 如果宿主机需要代理,优先先确认 Docker Desktop 本身能正常拉镜像
- 如果你已经在 WSL 中验证过
DOCKER_BUILDKIT=0 docker compose up -d --build能成功,就继续沿用这一条 - 如果修改了前端代码,只重建
web - 如果修改了后端代码或依赖,只重建
backend
如果你不想用 WSL2,也可以直接在 Windows 上这样做:
- 安装 Docker Desktop
- 把项目放在 Windows 路径,例如:
D:\rag
- 用 PowerShell 进入项目目录
- 准备
data/、models/、.user/ - 执行:
docker compose up -d --build这种方式可以跑,但要明确它的局限:
data/qdrant/、data/redis/、models/在 Windows 文件系统上的 IO 性能通常更差- 大量小文件、模型目录和向量库目录更容易拖慢容器
- Windows 路径、权限和换行细节更容易引入兼容性问题
- 如果后续涉及代理、镜像构建、OCR 或模型依赖排查,Windows 原生路径通常更难处理
因此:
- 临时验证功能,可以这样跑
- 长期使用、多人共用、模型较大或数据量较大时,不建议这样部署
- 前端静态资源由 Nginx 托管,启动更稳定,资源占用低
- 外部只暴露一个端口,后端不直接对公网开放
/api反向代理已关闭缓冲,兼容 SSE 流式输出- 向量库已切换为独立
qdrant服务,不再依赖 backend 容器内的本地 embedded storage - 会话索引、标题、消息数和最近活跃时间已切到独立
redis服务 - Redis 容器当前默认使用
redis:8-alpine,与现有data/redis/持久化数据格式兼容性更稳 data/、models/、.user/全部通过 bind mount 持久化- redis、backend 和 web 都带健康检查;backend 会在启动时自动等待 redis 并重试连接 qdrant
init: true和restart: unless-stopped已开启,降低僵尸进程和意外退出影响
当前后端包含:
- 进程内会话缓存
- 本地 agent memory 持久化恢复
- 本地 chat transcript 持久化文件
虽然向量库和会话索引已经切到独立服务,但 ChatAgent 实例本身、memory 快照恢复和 transcript 文件仍然是单实例语义,所以 Docker 部署默认采用单 worker。如果后续把会话执行态也进一步外置,再考虑多 backend 横向扩展。
如果后续要走多人共享和后端多副本部署,参考 docs/scalable_docker_architecture.md。
文档入库大致流程如下:
上传 PDF
-> MinerU 解析
-> 图片重命名
-> 提取文本 / 表格 / 图片内容
-> 表格独立切块
-> 可选表格摘要
-> embedding
-> 写入 Qdrant
关键实现:
tools/load_files.pytools/mineru_toolkit.pytools/qdrant.py
回答链路大致如下:
用户提问
-> Chat Agent 调用 search_database
-> Qdrant 混合检索
-> rerank
-> 动态阈值筛选
-> 返回完整原文 chunk
-> 生成最终回答
-> 前端渲染正文 / 表格 / 附件图片
当前项目对表格类问题做了额外保护:
- 表格类 query 会自动放宽证据预算
- 表格和图片证据路径要求尽量原样保留
- 前端将图片与正文分离,放到附件图片区
会话索引和元数据目前保存在 Redis 中,包括:
session_idusernametitlecreated_atupdated_atlast_activitymessage_countmemory_enabled
会话全文和 memory 快照目前仍然通过文件持久化:
data/chat_sessions/<username>/data/agent_memory/<username>/
这意味着:
- 会话列表可以跨 backend 共享
- 但具体
ChatAgent执行态仍然不是完全无状态
当前所有文件类路径统一收口在:
后端、工具链、脚本都会从 SHARED_STORAGE_ROOT 派生:
stored_filesmineru_outputcontent_listsexported_chunksagent_memorychat_sessions
POST /api/v1/auth/loginGET /api/v1/auth/mePOST /api/v1/auth/logout
POST /api/v1/chat/streamDELETE /api/v1/chat/session/{session_id}GET /api/v1/chat/sessionsGET /api/v1/chat/session/{session_id}
GET /api/v1/filesPOST /api/v1/files/uploadPOST /api/v1/files/importGET /api/v1/files/content/{file_tag}DELETE /api/v1/files
GET /api/v1/usersPOST /api/v1/usersPOST /api/v1/users/change-passwordPOST /api/v1/users/reset-password
更多细节见:
backend/README.mdhttp://localhost:8000/docs
scripts/ 目录下收录了所有日常运维、测试和调试用的命令行工具。激活虚拟环境后在项目根目录执行。
| 脚本 | 用途 | 典型触发场景 |
|---|---|---|
| chat_model_interactive.py | 裸模型对话 | 刚改完 .env 想确认模型 API 通了 |
| chat_agent_interactive.py | 完整 RAG Agent 对话 | 想端到端验证检索+回答链路 |
| import_file.py | 单文件入库 | 手动补录某个 PDF |
| search_qdrant.py | 检索验证 | 入库后确认某个词能不能被检出 |
| migrate_qdrant_local_to_server.py | 数据迁移 | 从 local 模式切换到 server 模式 |
| download_table_summary_model.py | 下载模型 | 首次部署,Qwen 模型还没下载 |
| eval_retrieval.py | 策略评测 | 调参时对比四种检索策略优劣 |
| smoke_hybrid_retrieval.py | 检索接口 smoke | 改了 qdrant.py 后快速回归 |
| smoke_mineru_ingest_retrieve.py | 入库链路 smoke | 改了 load_files.py 后验证 |
| smoke_e2e_pdf_hybrid_rerank.py | E2E smoke | 改了 rerank 逻辑后跑真实 PDF |
| smoke_mineru_embedding_qdrant.py | 三合一 smoke | 换了 embedding 模型后验证 |
| smoke_pdf_ingest_query.py | 业务 query smoke | 回归四类核心业务 PDF 的问答 |
| test_mineru_modes.py | MinerU 模式对比 | 评估 pipeline vs VLM 提取质量 |
| inspect_agent_response.py | Agent 响应诊断 | 升级 CAMEL 版本后排查响应结构 |
| patch_camel_chat_agent_reasoning.py | CAMEL 推理字段兼容补丁 | Dockerfile.backend 构建时自动执行 |
| inspect_api_reasoning_field.py | API reasoning 字段诊断 | 排查流式 delta.reasoning 透传问题 |
| example_rag_api_client.py | RAG API 示例客户端 | 验证 /api/v1/rag 外部调用接口 |
直接使用 stream_model() 构建 ChatAgent,不加载任何 RAG 工具。用途:验证模型 API 连通性与流式输出。
python scripts/chat_model_interactive.py使用 chat_agent_factory() 创建带完整 RAG 工具链的 ChatAgent。用途:端到端验证 Agent + DatabaseToolkit + 向量检索。
python scripts/chat_agent_interactive.py将指定 PDF 解析并写入 Qdrant 知识库,支持指定 collection 和 DPI。
python scripts/import_file.py data/stored_files/example.pdf
python scripts/import_file.py data/stored_files/example.pdf --collection database --dpi 200对指定 collection 执行向量检索并打印结果,验证入库是否成功。
python scripts/search_qdrant.py 供电营业规则
python scripts/search_qdrant.py 供电营业规则 --collection database --top-k 5将本地 Qdrant 数据迁移到远端 Qdrant Server,直接复制 id + vector + payload,无需重新 embedding。
python scripts/migrate_qdrant_local_to_server.py \
--local-path data/storages \
--server-url http://127.0.0.1:6333 \
--collection database \
--recreate下载 Qwen2.5-1.5B-Instruct(约 3GB),支持 ModelScope、HuggingFace、HF 镜像三种来源。
python scripts/download_table_summary_model.py
python scripts/download_table_summary_model.py --source modelscope
python scripts/download_table_summary_model.py --test-only
python scripts/download_table_summary_model.py --source hf-mirror用可控文本验证 keyword_search、hybrid_search、dynamic topk、rerank 接口正确性。写入临时 collection,测试后自动清理。
python scripts/smoke_hybrid_retrieval.py验证:MinerU 解析取证 -> 真实入库 -> 检索断言。
python scripts/smoke_mineru_ingest_retrieve.py data/stored_files/example.pdf真实 PDF 入库 -> MinerU 提取锚点 -> hybrid 检索断言 -> rerank 验证(需配置 reranker_path)。
python scripts/smoke_e2e_pdf_hybrid_rerank.py data/stored_files/example.pdf依次验证:MinerU 解析 -> embedding 模型加载与向量检查 -> Qdrant 入库与检索。支持 SMOKE_PDF 环境变量。
python scripts/smoke_mineru_embedding_qdrant.py
SMOKE_PDF=data/stored_files/your.pdf python scripts/smoke_mineru_embedding_qdrant.py针对四类业务 PDF 设计精确原文短语断言,根据文件名自动匹配测试计划,使用临时 collection。
python scripts/smoke_pdf_ingest_query.py data/stored_files/电网运行规则.pdf对比 vector_only / hybrid / hybrid_dynamic / hybrid_rerank_dynamic 四种策略的命中率、MRR 和延迟。可在 DEFAULT_CASES 中添加业务真实 query。
python scripts/eval_retrieval.py
EVAL_TOP_K=10 EVAL_ALPHA=0.75 python scripts/eval_retrieval.py测试 pipeline / VLM 两种解析模式,分析元素类型分布,可对比两种模式差异。
python scripts/test_mineru_modes.py data/stored_files/example.pdf
python scripts/test_mineru_modes.py data/stored_files/example.pdf --compare检查 CAMEL 框架流式模式下 response 对象结构,确认 reasoning_content 等字段传递情况。结果同时输出到终端和 logs/ 目录。
python scripts/inspect_agent_response.py
python scripts/inspect_agent_response.py --query "你好"修补 CAMEL 对 OpenAI-compatible reasoning 字段的兼容性,确保流式 delta.reasoning 能透传到后端 SSE。Dockerfile.backend 构建时自动执行此脚本。
python scripts/patch_camel_chat_agent_reasoning.py检查后端 API 流式响应中 reasoning_content 字段的传递情况,用于排查 SSE 输出中推理内容是否正确透传。
python scripts/inspect_api_reasoning_field.py演示如何通过外部 HTTP 请求调用 /api/v1/rag 接口,用于验证 RAG API 的独立可用性。
python scripts/example_rag_api_client.pysource .venv/bin/activate
python -m py_compile backend/app/config.py
python -m py_compile backend/app/services/chat_service.py
python -m py_compile tools/qdrant.pysource .venv/bin/activate
python3 -m pytest backend/tests -vcd frontend
npm run buildcd backend
python3 run.py推荐按这个顺序检查:
qdrant是否可访问redis是否可访问- 后端
/health是否正常 - 前端能否登录
- 文件列表是否正常显示
- 文件入库后
databasecollection 点数是否增加 - 聊天是否返回检索结果
优先检查:
- 前端是否跑在
3000 - 后端是否跑在
8000 - 浏览器是否拿到旧 bundle
/api/v1/auth/me是否异常
优先检查:
- 是否直接使用了
DOCKER_BUILDKIT=0 docker compose up -d --build - 宿主机是否已经配置代理
HTTP_PROXY/HTTPS_PROXY/http_proxy/https_proxy是否已导出- Docker 构建日志里失败的是哪一层:
FROM python/node/nginx:通常是镜像源或 Docker daemon 网络问题apt-get / pip install / npm ci / git clone:通常是构建阶段代理问题
推荐命令:
DOCKER_BUILDKIT=0 docker compose build --no-cache如果后端日志里出现:
httpx.ConnectErroropenai.APIConnectionError- 或者显式显示正在连接
127.0.0.1:7897
优先检查:
docker compose exec backend env | grep -i proxybackend运行时是否还带着宿主机代理变量.env中的url=是否是可从容器访问的模型地址
当前项目的正确行为是:
- 代理只用于 Docker
build backend运行时不再注入HTTP_PROXY/http_proxy
如果你刚改过 Dockerfile 或 Compose,记得重建 backend:
DOCKER_BUILDKIT=0 docker compose build --no-cache backend
docker compose up -d --force-recreate backend优先检查:
- 当前后端使用的是
QDRANT_MODE=local还是server QDRANT_MODE=server时,http://127.0.0.1:6333/collections/database的points_count是否大于 0- 旧库是否还停留在
data/storages - 是否已经执行迁移脚本
scripts/migrate_qdrant_local_to_server.py
这通常不是 Compose 配置错误,而是:
- 你挂载的
data/redis/里已有旧持久化数据 - 当前 Redis 镜像版本太低,读不了已有数据格式
当前仓库已经默认使用:
redis:8-alpine
如果你本地仍然遇到这个问题,优先检查:
- 是否已经重新
docker compose up -d docker compose logs --tail=100 redis
如果 Redis 中只是会话索引缓存,并且你接受重建,也可以清空 data/redis/ 后再启动。
优先检查:
data/stored_files/mineru_output/中是否存在对应图片- 文件服务接口
/api/v1/files/content/...是否可访问 - 回答中的图片路径是否被模型改写
- 浏览器是否仍在使用旧前端代码
这通常是前端旧 bundle 仍在运行,或者 web 容器还没重建。
优先处理:
DOCKER_BUILDKIT=0 docker compose build --no-cache web
docker compose up -d web然后浏览器强刷页面。
当前项目已对表格/议程/清单类 query 自动放宽检索预算。如果仍然截断,优先检查:
tools/database_toolkit.py中预算参数- 表格切块是否正常
- 原始文档在 MinerU 输出中是否已被截断
可以,但不建议长期作为主运行方式。因为两套入口已经分化,后续维护更推荐以前后端分离架构为主。
建议提交:
- 代码
- 配置模板
- 文档
- 轻量测试
不要提交:
.env.user/models/data/stored_files/data/qdrant/data/redis/data/lex_index/frontend/node_modules/frontend/dist/- 大日志与压缩包
推送前建议执行:
git status
git diff --cached --stat
git check-ignore -v .env models data/stored_files data/qdrant data/redis data/lex_index frontend/node_modules frontend/dist- 主线:前后端分离
- Runtime 依赖:
backend + frontend + qdrant + redis - Streamlit:旧入口已移除
- 当前状态:Qdrant 服务化、Redis 会话索引化、共享存储根目录统一化均已完成
- 仍未完成:
ChatAgent执行态彻底无状态化 - 仓库适合提交为代码仓,不适合直接提交运行数据仓