# ai-rag-admin **Repository Path**: yangdechao_admin/ai-rag-admin ## Basic Information - **Project Name**: ai-rag-admin - **Description**: 面向 RAG 开发者设计的前后端全栈工具:把本地文档批量解析、按可配置策略切片,并向量化后写入 Chroma 向量库 + MySQL 元数据库,开箱即得可检索、可复用的知识库。内置 8 种切片策略、文档解析(PDF / Word / TXT / MD / HTML / Excel / 图片 OCR)、Chroma 向量库 + BM25 混合检索、Celery 异步任务(SSE 实时进度)、检索调参 - **Primary Language**: Python - **License**: MulanPSL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-10-03 - **Last Updated**: 2026-10-09 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # ai-rag-admin · 面向 RAG 开发者的知识库向量化入库平台 面向 **RAG 开发者**设计的前后端全栈工具:把本地文档批量解析、按可配置策略切片,并向量化后写入 **Chroma 向量库 + MySQL 元数据库**,开箱即得可检索、可复用的知识库。内置 8 种切片策略、文档解析(PDF / Word / TXT / MD / HTML / Excel / 图片 OCR)、Chroma 向量库 + BM25 **混合检索**、Celery 异步任务(SSE 实时进度)、检索调参(含请求报文回显)、问答测试(流式 + 引用 + 五步流水线可视化)、自定义标签 / 元数据、操作与问答双日志中心。 本项目已实现**全部组件本地 Docker 容器化部署**(MySQL 也由 compose 托管,无需外部数据库)。 ## 开发背景与适用场景 构建 RAG 应用时,开发者最先要解决的是"知识库如何入库":把 PDF / Word / Markdown 等资料解析成文本、切成合适的片段、生成 embedding 写入向量库,同时保留正文与元数据供 BM25 检索与后续排查。这一过程涉及解析、切片、向量化、向量库与业务库双写、异步任务与索引维护,重复且繁琐。 **ai-rag-admin 把这条"文档 → 切片 → 向量入库"的流水线做成了可视化后台**:开发者无需手写脚本,即可通过界面上传文档、指定切分策略、监控向量化进度,并直接得到一份可被任意 RAG 应用调用的知识库(向量在 Chroma、正文与元数据在 MySQL)。 典型使用场景: - **知识库向量化入库**:批量上传企业制度、产品文档、技术手册,一键完成解析、切片、embedding 并写入向量库。 - **切片策略实验**:同一份文档可分别用 8 种策略切片对比效果,配合单切片编辑 / 拆分 / 原文定位做精细化调优。 - **检索效果验证**:通过检索调参页实时调整 Top-K、权重、Query 改写、元数据过滤,并查看完整请求报文与召回得分,验证入库质量。 - **RAG 应用数据中台**:FastAPI 提供标准化知识库 / 切片 / 检索接口,业务侧直接接入这套已入库的向量知识库,无需重复建设。 - **本地学习与二次开发**:全栈容器化、SQLAlchemy 异步模型、Celery 异步任务、统一响应与日志,可作为 RAG 基础设施的学习样板或二次开发基座。 ## 界面预览 | 仪表盘 | 知识库管理 | 异步任务中心 | |:---:|:---:|:---:| | ![仪表盘](docs/images/1.png) | ![知识库管理](docs/images/2.png) | ![异步任务中心](docs/images/3.png) | | 知识库总览 | 切片策略(8 种) | 检索调参 | 问答测试(五步流水线) | |:---:|:---:|:---:|:---:| | ![知识库总览](docs/images/4.png) | ![切片策略](docs/images/5.png) | ![检索调参](docs/images/6.png) | ![问答测试](docs/images/7.png) | ## 功能特性 - **知识库全生命周期**:创建 / 归档 / 删除(软删除、输入库名校验)、概览统计与合规率。 - **文档管理**:拖拽批量上传、三重校验、MD5 去重、异步解析进度实时刷新、预览 / 下载 / 重解析。 - **上传时指定切分策略**:上传文档时可独立选择 8 种切片策略,缺省则沿用知识库默认策略;列表行内直接展示每个文档**实际生效的切分策略**(文档级 / 知识库默认)。 - **8 种切片策略**:固定长度、递归字符、Markdown 标题、HTML 语义、语义切分、父子分块、LLM 语义分块等,参数可调。 - **单文档切片详情抽屉**:按文档查看切片列表、搜索、**编辑切片内容**(同步重算向量与 BM25)、**按字符位置拆分**、原文锚点高亮定位、删除切片。 - **自定义标签 / 元数据**:文档级标签(回车添加、可关闭),保存后行内回显;标签可参与"元数据过滤"检索。 - **混合检索调参**:Top-K、相似度阈值、Rerank、**启用 Query 改写**、**启用元数据过滤**、BM25 开关与向量 / 关键词权重滑块;保存后持久化到数据库。 - **检索测试报文回显**:执行检索测试时,在召回结果上方以 JSON 完整展示实际下发的请求(query、改写结果、config、过滤前后切片数、各阶段耗时)。 - **问答测试**:DeepSeek SSE 流式回答、引用上标可跳切片、链路耗时展示;右侧**五步执行流程面板**(问题入队 → 混合检索 → Prompt 组装 → LLM 流式生成 → 落库)实时状态,会话管理、点赞 / 点踩 BadCase。 - **双写存储**:切片正文 / 元数据存 MySQL `chunks` 表并记录 `vector_id`,向量与检索元数据存 **Chroma 向量库**;删除文档 / 切片时同步清理两路。 ## 技术栈 | 层 | 技术 | |---|---| | 前端 | Vue 3 + Vite + Pinia + Vue Router + Element-Plus + ECharts | | 后端 | Python 3.12 + FastAPI + SQLAlchemy 2.0 (async) + Pydantic v2 | | 异步 | Celery 5 + Redis(broker / SSE Pub-Sub / 幂等去重) | | 存储 | MySQL 8(业务事实源,软删除)+ Chroma 1.5(向量,持久化卷 `chroma-data`)+ BM25 文件索引(每库独立,卷 `bm25`) | | 模型 | DeepSeek `deepseek-flash`(LLM)/ `bge-large-zh-v1.5`(Embedding)/ `bge-reranker-base`(Rerank);无 Key 时自动降级内置离线引擎 | ## 目录结构 ``` ai-rag-admin/ ├── backend/ │ ├── app/ │ │ ├── api/v1/ # 路由:common/dashboard/kb/document/chunk/vector/retrieve/chat/task/log │ │ ├── core/ # 配置、统一响应、错误码、trace_id、JSON 日志、SSE 事件总线 │ │ ├── db/ # ORM 模型(11 张表)+ async/sync 会话 │ │ ├── chunker/ # 8 种切片策略(统一 BaseChunker) │ │ ├── bm25/ # BM25 索引、分词、多路召回加权融合 │ │ ├── celery_tasks/ # 异步任务(解析 / 全量重建 / 增量 / BM25 / 清孤儿) │ │ ├── services/ # 解析器、向量库封装、混合检索、审计日志 │ │ ├── embeddings/ llm/ rerank/ # 三类模型 Provider(api / ollama / builtin) │ │ └── main.py # FastAPI 入口(/health /ready /api/docs) │ └── tests/ # pytest ├── frontend/ │ ├── src/{api,components,views,router,store,styles} │ │ └── views/kb/ # 详情 6 个 Tab 组件(总览/文档/切片/向量/检索/问答) │ └── Dockerfile · nginx.conf(SSE 反代免缓冲) ├── docs/ # 原型、ER 图、部署手册、测试文档(docs/rag) ├── sql/init.sql # 建库建表 + 默认模型注册(首次容器启动自动执行) ├── docker-compose.yml # mysql / redis / chroma / backend / celery-worker / celery-beat / frontend(+ flower) ├── .env.example # 全部配置项模板 └── README.md ``` ## 容器与端口规划 全部由 `docker compose` 托管,数据落在命名卷: | 服务 | 容器名 | 宿主机端口 | 说明 | |---|---|---|---| | frontend | ai-rag-frontend | **80** | Nginx,页面入口 http://127.0.0.1 | | backend | ai-rag-backend | **7000** | FastAPI,/api/docs | | mysql | ai-rag-mysql | **3308** | root/root,库 `ai_rag_mysql`(首启自动初始化) | | redis | ai-rag-redis | 6379 | Celery broker / SSE | | chroma | ai-rag-chroma | **7001** | 向量库,持久化卷 `chroma-data` | | celery-worker | ai-rag-worker | — | 异步解析 / 切片 / 向量化 | | celery-beat | ai-rag-beat | — | 定时清理 / 孤儿回收 | | flower | ai-rag-flower | 5555 | `--profile flower` 可选启用 | > 应用容器内部通过服务名互联(`mysql:3306`、`redis:6379`、`chroma:8000`);3308 / 7001 仅为宿主机调试端口。 ## 一键部署 ```bash # 1) 准备环境变量(已内置可用值;如需更换 DeepSeek Key 再编辑) cp .env.example .env # 2) 构建并启动全部容器(首次会自动建库建表) docker compose up -d --build # 3) 等待 backend 健康后访问 # 前端: http://127.0.0.1 # API: http://127.0.0.1:7000/api/docs # 探针: http://127.0.0.1:7000/health 、/ready ``` 启动顺序由 compose 的 `depends_on` + healthcheck 保证:MySQL / Redis 就绪后再起 backend / worker / beat。 ### 修改代码后如何重新部署 ```bash # 改了后端 Python / 任务代码: docker compose build backend celery-worker && docker compose up -d backend celery-worker # 改了前端 Vue: docker compose build frontend && docker compose up -d frontend # 可选:起任务监控面板 docker compose --profile flower up -d flower ``` ## 配置说明(`.env`) - MySQL 在 compose 内已固定为 `root/root`、库 `ai_rag_mysql`(被 `environment` 覆盖,一般无需改 `.env`)。 - DeepSeek LLM: - `LLM_PROVIDER=deepseek` - `DEEPSEEK_BASE_URL=https://api.deepseek.com` - `DEEPSEEK_MODEL=deepseek-flash` - `DEEPSEEK_API_KEY=sk-xxxx` - Embedding / Rerank 默认 `builtin`(离线可跑通全链路);生产可切到 `api` / `ollama` / 本地 sentence-transformers。 - `AES_SECRET_KEY` 用于加密存储模型 API Key(32 字节 hex)。 ## 前端路由 | 路由 | 页面 | |---|---| | `/dashboard` | 仪表盘(统计卡 / 趋势 / 切片分布 / 异常任务) | | `/kb/list` | 知识库列表(搜索 / 筛选 / 归档 / 删除) | | `/kb/:id/overview` | 详情-总览 | | `/kb/:id/document` | 详情-文档管理(上传时选切分策略 / 行内策略与标签 / 单文档切片抽屉) | | `/kb/:id/chunk` | 详情-切片管理(8 策略配置 / 重切片) | | `/kb/:id/vector` | 详情-向量索引(Chroma+BM25 状态 / 全量重建 / 增量 / 清孤儿) | | `/kb/:id/retrieve` | 详情-检索调参(开关持久化 / 请求报文 / 召回结果) | | `/kb/:id/test-chat` | 详情-问答测试(流式回答 / 引用 / 五步流水线面板) | | `/task` | 异步任务中心 | | `/log` | 日志中心(操作审计 CSV 导出 / 问答 BadCase) | ## 关键 API(前缀 `/api/v1`) 统一响应 `{code, message, data, trace_id}`;写操作支持 `Idempotency-Key` 头(5 分钟去重)。 - 知识库:`GET/POST /kb/list|create` · `PUT /kb/{id}/update|archive` · `DELETE /kb/{id}`(body 需 `confirm_name`)· `GET /kb/{id}/overview` - 文件:`POST /file/upload?kb_id=`(multipart `files`,可附带 `chunk_strategy`)· `GET /file/preview/{doc_id}?chunk_id=` · `GET /file/download/{doc_id}` · `PUT /file/{doc_id}/meta`(标签 / 元数据) - 文档:`GET /kb/{id}/document/list`(返回每行 `strategy_type`/`strategy_custom`/`tags`)· `POST /kb/document/reparse/{doc_id}` · `DELETE /kb/document/{doc_id}` - 切片:`GET|PUT /kb/{id}/chunk/strategy` · `GET /kb/{id}/chunk/list?document_id=` · `PUT /kb/chunk/{cid}/edit` · `POST /kb/chunk/{cid}/split` · `DELETE /kb/chunk/{cid}` - 向量:`GET /kb/{id}/vector/status` · `POST /kb/{id}/vector/reindex-full|reindex-incr|clean-orphan` - 检索:`GET|PUT /kb/{id}/retrieve/config` · `POST /kb/{id}/retrieve/test`(返回 `request` 请求报文 + 双路得分 + 阶段耗时) - 问答:`POST /chat/send`(SSE:`stage` / `recall` / `delta` / `done` / `error`)· `GET /chat/sessions|history` · `POST /chat/session/create` · `DELETE /chat/session/{sid}` · `POST /chat/feedback/{msg_id}` - 任务:`GET /task/list` · `POST /task/{id}/retry` · `GET /tasks/stream/{id}|/global`(SSE) - 日志:`GET /log/operation?export=true`(CSV)· `GET /log/chat?bad_case=true` - 探针:`GET /health` · `GET /ready`(MySQL / Redis / Chroma) ## 数据存储说明 - **MySQL**:知识库、文档、切片正文与元数据(`chunks.vector_id` 记录对应向量主键)、会话、消息、任务、操作 / 问答日志。 - **Chroma 向量库**:embedding 向量 + 检索元数据(文档 id、标签、角色等),负责向量召回;与 BM25 索引加权融合。 - 删除文档或切片时,后端同步从 Chroma、BM25 索引、MySQL 三处清理,保证一致性。 ## 本地开发(可选,不使用 Docker) ```bash cd backend python3.12 -m venv .venv && .venv/Scripts/pip install -r requirements.txt .venv/Scripts/python -m uvicorn app.main:app --port 7000 .venv/Scripts/python -m celery -A app.celery_app:celery_app worker --pool=solo cd ../frontend && npm install && npm run dev # http://localhost:5173 ``` 本地直跑时 `.env` 中 `MYSQL_HOST=127.0.0.1`、`MYSQL_PORT=3308`、`REDIS_URL=redis://127.0.0.1:6379/0`、`CHROMA_HOST=127.0.0.1`、`CHROMA_PORT=7001`(指向已起好的容器)。 ## 问题修复记录 ### 2026-10-04 | # | 问题现象 | 根因 | 修复 | 影响文件 | |---|---|---|---|---| | 1 | 上传较大 PDF(如 3.4MB 的《系统规划与管理师示例论文.pdf》)时返回 `413 Request Entity Too Large`,文件根本到不了后端 | 前端 Nginx 反向代理默认 `client_max_body_size` 仅 1MB,超出即被 Nginx 拦截 | 在前端 `nginx.conf` 的 server 块增加 `client_max_body_size 50m;`(与后端 `UPLOAD_MAX_SIZE_MB=50` 对齐),重建前端镜像 | `frontend/nginx.conf` | | 2 | 上传纯图片型 PDF(如《大数据面试指南(含答案)_v1.pdf》,61 页、文本层字符数为 0)后文档状态为 completed 但 `chunk_count=0`,提示"文档无有效文本内容(空文档或图片无文字)" | 图片型 PDF 本应走 OCR 兜底,但运行容器内未安装 PaddleOCR(worker 日志报 `No module named 'paddleocr'`),OCR 静默失败后返回空文本 | OCR 引擎由依赖过重、安装易失败的 PaddleOCR(paddlepaddle)切换为轻量的 **RapidOCR(onnxruntime,自带中文模型)**:重写解析器 OCR 调用并统一适配其返回格式 `[box, text, score]`,requirements 锁定 `rapidocr_onnxruntime==1.4.4`,重建 backend / celery-worker 镜像使依赖持久化 | `backend/app/services/parser.py`、`backend/requirements.txt` | | 3 | 系统打开后频繁"卡死",页面长时间无响应 | 后端全局任务 SSE 订阅循环在没有消息时立即空转 `continue`(无任何休眠),每个挂着的 SSE 长连接都在事件循环里忙等,实测后端 CPU 被打到约 **598%**(近 6 核满载),拖慢所有接口 | SSE 循环改为 `timeout=1.0s` + 无消息时 `await asyncio.sleep(1.0)`,keepalive 心跳降频到约 20s 一次,彻底消除空转;后端 CPU 降至约 0.14% | `backend/app/core/events.py` | | 4 | 文档管理页空闲时仍每 4 秒全量拉取文档列表,叠加增加后端与网络压力 | 文档列表定时器无条件轮询 | 改为仅当存在解析中/排队中文档时才轮询,空闲页面零请求 | `frontend/src/views/kb/DocumentTab.vue` | | 5 | 知识库列表只能新建 / 归档 / 删除,无法修改已有知识库的名称、描述、BM25 配置 | 后端 `PUT /kb/{id}/update` 已存在,但前端缺少"编辑"入口与弹窗 | 卡片 / 表格视图均新增"编辑"按钮,复用新建弹窗(模式切换为"编辑知识库 / 保存");已有文档时禁用 Embedding 模型选择(更换模型需重新向量化) | `frontend/src/views/KbList.vue` | | 6 | 检索调参页点击"执行检索测试"后结果区被清空、只显示初始提示文字,看起来像卡死 | 请求期间 `result=null` 且无任何加载态 | 结果区新增"检索中…"旋转加载中间态,按钮同时置灰并显示"检索中…" | `frontend/src/views/kb/RetrieveTab.vue` | **本次验证结果**: - 问题 1:重新上传 3.4MB PDF 不再 413,后端返回 200,文档正常解析并切出 16 个切片。 - 问题 2:对该图片型 PDF 触发重解析,`parse_status=completed`、`chunk_count=29`、`is_ocr=1`、OCR 平均置信度约 0.98;重建后的新容器内 `from rapidocr_onnxruntime import RapidOCR` 可正常导入,`/health` 返回 200。 - 问题 3:修复后后端 idle CPU 由约 598% 降至约 0.14%,内存约 70MB,页面不再卡顿。 - 问题 5:实测 `PUT /kb/{id}/update` 读写正常(名称唯一校验、描述、BM25 参数均可更新)。 > 说明:图片型 PDF / 图片的 OCR 解析在 CPU 上耗时较长(如 61 页约 5 分钟),属正常现象,前端任务进度与 SSE 会实时反馈。 ## 开发者 - 开发人:杨得朝 - 邮箱:18221638482@qq.com ## License MIT,见 `LICENSE`。