多库检索与存储修复: - RRF 融合去重改用 (collection, chunk_id) 复合键,修复同名文件结果被吞 - DocStore 存储路径加 collection 前缀,修复跨库同名切片数据覆盖 - search_multiple 去重改用复合键 - chunk_id 解析改用 rsplit 兼容下划线文件名 上传与版本管理修复: - 同名文件上传改为覆盖模式,自动清理旧切片 - 修复首次上传不创建版本记录 - 修复覆盖上传版本号回退到 v1 - sync ADDED 分支改用动态版本号生成 - _generate_version_id 改为基于全部版本递增 - 废止/恢复操作同步 SQLite 版本记录 - mark_document_as_superseded 改为仅更新 SQLite 删除清理修复: - 删除文档时同步清理 SQLite 版本记录和变更日志 - 删除向量库时同步清理该库所有版本记录 - cleanup 改为清理 SQLite 记录而非 ChromaDB 测试: - test_version_management.py: 27 条版本管理单元测试 - test_edge_cases.py: 28 条边界用例测试 - test_upload_dedup.py: 5 条上传去重测试 - e2e_risk_test.py: 27 条端到端风险测试 文档: - 新增风险边界问题修复注意事项.md(面向后端的对接文档) - 新增向量库边界风险分析.md - 更新多篇现有文档
502 lines
18 KiB
Markdown
502 lines
18 KiB
Markdown
# RAG 服务架构与部署方案
|
||
|
||
## 一、系统架构概览
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||
│ 前端应用 │
|
||
│ (Vue/React Web/App) │
|
||
└─────────────────────────────────────┬───────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||
│ 后端网关 │
|
||
│ (Nginx / API Gateway / Spring Cloud) │
|
||
│ │
|
||
│ 职责: │
|
||
│ • 用户认证 (登录/Token验证) │
|
||
│ • 权限控制 (角色/部门/接口权限) │
|
||
│ • Header 注入 (X-User-ID, X-User-Role, X-User-Department) │
|
||
│ • 请求路由与负载均衡 │
|
||
└─────────────────────────────────────┬───────────────────────────────────────┘
|
||
│
|
||
┌─────────────────┴─────────────────┐
|
||
│ │
|
||
▼ ▼
|
||
┌───────────────────────────────┐ ┌───────────────────────────────────────┐
|
||
│ 后端业务服务 │ │ RAG 服务 │
|
||
│ (Java/Spring Boot/Go) │ │ (Python/Flask) │
|
||
│ │ │ │
|
||
│ 职责: │ │ 职责: │
|
||
│ • 用户账户管理 │ │ • 向量存储 (ChromaDB) │
|
||
│ • 组织架构/角色权限 │ │ • BM25 索引 │
|
||
│ • 会话管理 (对话历史) │ │ • 文档解析与分块 │
|
||
│ • 审计日志 │ │ • 知识库问答 (RAG) │
|
||
│ • 反馈记录 │ │ • 文档同步与向量化 │
|
||
│ • 业务主数据 (学生/课程等) │ │ • 出题能力 │
|
||
│ • 题库/试卷管理 │ │ │
|
||
│ │ │ │
|
||
│ 数据库: │ │ 数据存储: │
|
||
│ • MySQL/PostgreSQL │ │ • ChromaDB (向量库) │
|
||
│ │ │ • 文件系统 (documents/) │
|
||
│ │ │ • SQLite (同步状态哈希) │
|
||
└───────────────────────────────┘ └───────────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## 二、职责分工详解
|
||
|
||
### 2.1 RAG 组(本项目)负责
|
||
|
||
| 模块 | 功能 | 数据存储 |
|
||
|------|------|----------|
|
||
| **向量存储** | ChromaDB 向量库管理 | `vector_store/chroma/` |
|
||
| **BM25 索引** | 关键词检索 | 内存/文件 |
|
||
| **文档解析** | PDF/Word/Excel 解析与分块 | 临时处理 |
|
||
| **知识库问答** | Agentic RAG 问答引擎 | - |
|
||
| **文档同步** | 文件变更检测与向量化 | SQLite (哈希记录) |
|
||
| **出题能力** | 基于知识库生成题目 | 无状态 |
|
||
|
||
### 2.2 后端组负责
|
||
|
||
| 模块 | 功能 | 数据存储 |
|
||
|------|------|----------|
|
||
| **用户认证** | 登录/注册/Token 管理 | MySQL/PostgreSQL |
|
||
| **权限控制** | 角色/部门/接口权限 | MySQL/PostgreSQL |
|
||
| **会话管理** | 对话历史记录 | MySQL/PostgreSQL |
|
||
| **审计日志** | 操作日志记录 | MySQL/PostgreSQL |
|
||
| **反馈系统** | 用户反馈收集 | MySQL/PostgreSQL |
|
||
| **业务主数据** | 学生/课程/组织架构 | MySQL/PostgreSQL |
|
||
| **题库管理** | 题目存储/试卷管理 | MySQL/PostgreSQL |
|
||
| **网关路由** | 请求路由/Header 注入 | - |
|
||
|
||
### 2.3 数据归属对照表
|
||
|
||
| 数据类型 | 存储位置 | 管理方 | 说明 |
|
||
|----------|----------|--------|------|
|
||
| 向量数据 | ChromaDB | RAG 组 | 文档 embedding |
|
||
| 文档哈希 | SQLite | RAG 组 | 同步状态检测 |
|
||
| 原始文档 | 文件系统 | RAG 组 | documents/ 目录 |
|
||
| 用户账户 | MySQL/PG | 后端组 | 账号密码信息 |
|
||
| 会话历史 | MySQL/PG | 后端组 | 对话记录 |
|
||
| 审计日志 | MySQL/PG | 后端组 | 操作日志 |
|
||
| 反馈记录 | MySQL/PG | 后端组 | 用户反馈 |
|
||
| 题库数据 | MySQL/PG | 后端组 | 题目/试卷 |
|
||
|
||
---
|
||
|
||
## 三、接口协作规范
|
||
|
||
### 3.1 后端调用 RAG 服务
|
||
|
||
后端通过 HTTP 调用 RAG API,需注入 Header:
|
||
|
||
```
|
||
X-User-ID: 用户唯一标识
|
||
X-User-Name: 用户名(可选)
|
||
X-User-Role: 用户角色(可选)
|
||
X-User-Department: 部门(可选)
|
||
```
|
||
|
||
### 3.2 RAG 服务提供的接口
|
||
|
||
#### 问答接口
|
||
| 接口 | 方法 | 说明 |
|
||
|------|------|------|
|
||
| `/chat` | POST | 普通聊天 |
|
||
| `/rag` | POST | 知识库问答 |
|
||
| `/search` | POST | 混合检索 |
|
||
|
||
#### 向量库管理
|
||
| 接口 | 方法 | 说明 |
|
||
|------|------|------|
|
||
| `/collections` | GET | 向量库列表 |
|
||
| `/collections` | POST | 创建向量库 |
|
||
| `/collections/<name>` | PUT | 修改向量库 |
|
||
| `/collections/<name>` | DELETE | 删除向量库 |
|
||
|
||
#### 文档管理
|
||
| 接口 | 方法 | 说明 |
|
||
|------|------|------|
|
||
| `/documents/upload` | POST | 上传文件 |
|
||
| `/documents/batch-upload` | POST | 批量上传 |
|
||
| `/documents/list` | GET | 文档列表 |
|
||
| `/documents/<path>` | DELETE | 删除文档 |
|
||
| `/documents/<path>/status` | GET | 处理状态 |
|
||
|
||
#### 切片管理
|
||
| 接口 | 方法 | 说明 |
|
||
|------|------|------|
|
||
| `/documents/<path>/chunks` | GET | 查看切片 |
|
||
| `/chunks` | POST | 新增切片 |
|
||
| `/chunks/<id>` | PUT | 修改切片 |
|
||
| `/chunks/<id>` | DELETE | 删除切片 |
|
||
|
||
#### 同步服务
|
||
| 接口 | 方法 | 说明 |
|
||
|------|------|------|
|
||
| `/sync` | POST | 触发同步 |
|
||
| `/sync/status` | GET | 同步状态 |
|
||
|
||
#### 出题接口
|
||
| 接口 | 方法 | 说明 |
|
||
|------|------|------|
|
||
| `/exam/generate` | POST | 生成题目 |
|
||
| `/exam/grade` | POST | 批改答案 |
|
||
|
||
### 3.3 后端需要提供的接口
|
||
|
||
RAG 服务可能需要调用后端获取用户信息:
|
||
|
||
```
|
||
GET /api/users/{user_id}
|
||
|
||
响应:
|
||
{
|
||
"user_id": "xxx",
|
||
"username": "用户名",
|
||
"name": "真实姓名",
|
||
"role": "admin/manager/user",
|
||
"department": "部门名称"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 四、合并前准备工作
|
||
|
||
### 4.1 RAG 组需完成
|
||
|
||
- [x] 权限控制简化(依赖后端网关)
|
||
- [x] 移除会话管理依赖
|
||
- [x] 移除审计日志依赖
|
||
- [x] 更新 API 文档
|
||
- [ ] 清理测试数据和临时文件
|
||
- [ ] 整理依赖列表 (requirements.txt)
|
||
- [ ] 准备环境变量配置模板 (`deploy/.env.production`)
|
||
- [ ] 编写 Dockerfile.prod 和 docker-compose.prod.yml
|
||
|
||
### 4.2 后端组需完成
|
||
|
||
- [ ] 设计数据库表结构
|
||
- [ ] 实现用户认证接口
|
||
- [ ] 实现会话管理接口
|
||
- [ ] 实现审计日志接口
|
||
- [ ] 配置网关路由和 Header 注入
|
||
- [ ] 提供 RAG 服务调用的接口
|
||
|
||
### 4.3 双方需确认
|
||
|
||
- [ ] 接口协议和字段格式
|
||
- [ ] 错误码规范
|
||
- [ ] 部署环境和网络配置
|
||
- [ ] 文件存储方案(本地/NFS/OSS)
|
||
|
||
---
|
||
|
||
## 五、Linux 部署方案(Docker)
|
||
|
||
### 5.1 服务器规格
|
||
|
||
| 项目 | 配置 |
|
||
|------|------|
|
||
| 操作系统 | Ubuntu 22.04 LTS |
|
||
| CPU | 4 vCPU |
|
||
| 内存 | 8 GB |
|
||
| 部署路径 | `/opt/rag-agent` |
|
||
| 容器运行时 | Docker + Docker Compose |
|
||
|
||
### 5.2 部署架构
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ Linux 服务器 (Ubuntu 22.04) │
|
||
├─────────────────────────────────────────────────────────────────┤
|
||
│ │
|
||
│ ┌──────────────────────────────────────────────────────────┐ │
|
||
│ │ Docker (rag-service 容器) │ │
|
||
│ │ │ │
|
||
│ │ ┌──────────────────────────────────────────────────┐ │ │
|
||
│ │ │ Gunicorn (gthread worker) │ │ │
|
||
│ │ │ └── Flask App :5001 │ │ │
|
||
│ │ └──────────────────────────────────────────────────┘ │ │
|
||
│ │ │ │
|
||
│ │ 数据卷挂载: │ │
|
||
│ │ • vector_store/ → 向量库持久化 │ │
|
||
│ │ • documents/ → 原始文档 │ │
|
||
│ │ • models/ → 本地模型文件 │ │
|
||
│ │ • .data/ → 运行时缓存 │ │
|
||
│ │ • data/ → SQLite 同步状态 │ │
|
||
│ └──────────────────────────────────────────────────────────┘ │
|
||
│ ▲ │
|
||
│ │ :5001 │
|
||
│ ┌──────┴──────┐ │
|
||
│ │ 后端网关 │ (Nginx / Spring Cloud Gateway) │
|
||
│ │ :80/443 │ │
|
||
│ └─────────────┘ │
|
||
│ │
|
||
└─────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### 5.3 项目目录结构
|
||
|
||
```
|
||
/opt/rag-agent/
|
||
├── deploy/
|
||
│ ├── Dockerfile.prod # 生产镜像定义
|
||
│ ├── docker-compose.prod.yml # 编排文件
|
||
│ └── .env.production # 生产环境变量
|
||
├── app/ # 应用源码
|
||
├── vector_store/ # ChromaDB 向量库(持久化)
|
||
├── documents/ # 原始文档(持久化)
|
||
├── models/ # 本地模型文件(持久化)
|
||
├── .data/ # 运行时缓存
|
||
└── data/ # SQLite 同步状态
|
||
```
|
||
|
||
### 5.4 Dockerfile.prod
|
||
|
||
```dockerfile
|
||
# deploy/Dockerfile.prod
|
||
FROM python:3.10-slim
|
||
|
||
WORKDIR /app
|
||
|
||
# 安装系统依赖
|
||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||
build-essential \
|
||
&& rm -rf /var/lib/apt/lists/*
|
||
|
||
# 安装 CPU-only PyTorch(减小镜像体积)
|
||
RUN pip install --no-cache-dir torch --index-url https://download.pytorch.org/whl/cpu
|
||
|
||
# 安装 Python 依赖
|
||
COPY requirements.txt .
|
||
RUN pip install --no-cache-dir -r requirements.txt
|
||
|
||
# 复制应用代码
|
||
COPY . .
|
||
|
||
EXPOSE 5001
|
||
|
||
# 使用 Gunicorn gthread 模式启动
|
||
CMD ["gunicorn", \
|
||
"--bind", "0.0.0.0:5001", \
|
||
"--workers", "2", \
|
||
"--threads", "4", \
|
||
"--worker-class", "gthread", \
|
||
"--timeout", "300", \
|
||
"main:app"]
|
||
```
|
||
|
||
### 5.5 docker-compose.prod.yml
|
||
|
||
```yaml
|
||
# deploy/docker-compose.prod.yml
|
||
version: "3.8"
|
||
|
||
services:
|
||
rag-service:
|
||
build:
|
||
context: ..
|
||
dockerfile: deploy/Dockerfile.prod
|
||
container_name: rag-service
|
||
ports:
|
||
- "5001:5001"
|
||
env_file:
|
||
- .env.production
|
||
volumes:
|
||
- ../vector_store:/app/vector_store
|
||
- ../documents:/app/documents
|
||
- ../models:/app/models
|
||
- ../.data:/app/.data
|
||
- ../data:/app/data
|
||
restart: unless-stopped
|
||
deploy:
|
||
resources:
|
||
limits:
|
||
memory: 6G
|
||
```
|
||
|
||
### 5.6 环境变量配置
|
||
|
||
所有环境变量通过 `deploy/.env.production` 文件注入,不在代码中硬编码:
|
||
|
||
```bash
|
||
# deploy/.env.production
|
||
|
||
# 运行模式
|
||
DEV_MODE=false
|
||
|
||
# 路径配置
|
||
DOCUMENTS_PATH=/app/documents
|
||
VECTOR_STORE_PATH=/app/vector_store
|
||
|
||
# API 密钥
|
||
DASHSCOPE_API_KEY=your_api_key_here
|
||
|
||
# 其他配置项按需添加...
|
||
```
|
||
|
||
### 5.7 首次部署
|
||
|
||
```bash
|
||
# 1. 在服务器上创建部署目录
|
||
sudo mkdir -p /opt/rag-agent
|
||
sudo chown $USER:$USER /opt/rag-agent
|
||
|
||
# 2. 上传项目代码到 /opt/rag-agent
|
||
scp -r ./rag-agent/* server:/opt/rag-agent/
|
||
|
||
# 3. 配置环境变量
|
||
cd /opt/rag-agent/deploy
|
||
cp .env.production.example .env.production
|
||
vim .env.production # 填入实际的 API Key 等配置
|
||
|
||
# 4. 构建并启动容器
|
||
docker compose -f docker-compose.prod.yml up -d --build
|
||
|
||
# 5. 验证服务状态
|
||
docker ps
|
||
docker logs rag-service
|
||
curl -f http://localhost:5001/health
|
||
```
|
||
|
||
### 5.8 热更新流程
|
||
|
||
#### 小改动(配置文件、Prompt 模板等)
|
||
|
||
```bash
|
||
# 直接复制文件进容器并重启
|
||
docker cp ./app/config.py rag-service:/app/config.py
|
||
docker restart rag-service
|
||
```
|
||
|
||
#### 大改动(代码逻辑、依赖变更等)
|
||
|
||
```bash
|
||
# 重新构建镜像并启动(数据卷不受影响)
|
||
cd /opt/rag-agent/deploy
|
||
docker compose -f docker-compose.prod.yml up -d --build
|
||
```
|
||
|
||
### 5.9 网关 Header 注入示例
|
||
|
||
后端网关在转发请求到 RAG 服务时注入 Header:
|
||
|
||
```java
|
||
// Spring Cloud Gateway 示例
|
||
@Bean
|
||
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
|
||
return builder.routes()
|
||
.route("rag-service", r -> r.path("/rag-api/**")
|
||
.filters(f -> f
|
||
.stripPrefix(1)
|
||
.addRequestHeader("X-User-ID", "#{request.getAttribute('userId')}")
|
||
.addRequestHeader("X-User-Role", "#{request.getAttribute('userRole')}")
|
||
.addRequestHeader("X-User-Department", "#{request.getAttribute('userDept')}")
|
||
)
|
||
.uri("http://127.0.0.1:5001"))
|
||
.build();
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 六、联调测试清单
|
||
|
||
### 6.1 后端接口测试
|
||
|
||
- [ ] 用户认证接口可用
|
||
- [ ] 网关正确注入 Header
|
||
- [ ] 会话管理接口可用
|
||
|
||
### 6.2 RAG 接口测试
|
||
|
||
```bash
|
||
# 测试 RAG 服务(带 Header)
|
||
curl -X POST http://localhost:5001/rag \
|
||
-H "Content-Type: application/json" \
|
||
-H "X-User-ID: test-user" \
|
||
-H "X-User-Role: admin" \
|
||
-d '{"message": "测试问题"}'
|
||
|
||
# 测试向量库列表
|
||
curl -X GET http://localhost:5001/collections \
|
||
-H "X-User-ID: test-user"
|
||
|
||
# 测试文件上传
|
||
curl -X POST http://localhost:5001/documents/upload \
|
||
-H "X-User-ID: test-user" \
|
||
-F "file=@test.pdf" \
|
||
-F "collection=public_kb"
|
||
```
|
||
|
||
### 6.3 端到端测试
|
||
|
||
- [ ] 前端 → 后端 → RAG 请求链路通
|
||
- [ ] 用户认证正确传递
|
||
- [ ] 权限控制生效
|
||
- [ ] 文件上传下载正常
|
||
- [ ] 问答功能正常
|
||
|
||
---
|
||
|
||
## 七、运维监控
|
||
|
||
### 7.1 日志管理
|
||
|
||
```bash
|
||
# 查看容器实时日志
|
||
docker logs -f rag-service
|
||
|
||
# 查看最近 100 行日志
|
||
docker logs --tail 100 rag-service
|
||
|
||
# 导出日志到文件
|
||
docker logs rag-service > /var/log/rag-service.log 2>&1
|
||
```
|
||
|
||
### 7.2 健康检查
|
||
|
||
```bash
|
||
# 手动检查
|
||
curl -f http://localhost:5001/health || echo "RAG service down"
|
||
|
||
# 可通过 docker-compose 配置自动健康检查(添加到 docker-compose.prod.yml)
|
||
# healthcheck:
|
||
# test: ["CMD", "curl", "-f", "http://localhost:5001/health"]
|
||
# interval: 30s
|
||
# timeout: 10s
|
||
# retries: 3
|
||
```
|
||
|
||
### 7.3 备份策略
|
||
|
||
```bash
|
||
# 备份向量库
|
||
tar -czf backup_vector_$(date +%Y%m%d).tar.gz /opt/rag-agent/vector_store/
|
||
|
||
# 备份文档
|
||
rsync -av /opt/rag-agent/documents/ backup/documents/
|
||
|
||
# 备份同步状态
|
||
cp /opt/rag-agent/data/knowledge.db backup/knowledge_$(date +%Y%m%d).db
|
||
```
|
||
|
||
---
|
||
|
||
## 八、故障排查
|
||
|
||
| 问题 | 可能原因 | 解决方案 |
|
||
|------|----------|----------|
|
||
| 401 未认证 | 缺少 X-User-ID | 检查网关 Header 注入 |
|
||
| 向量检索失败 | ChromaDB 损坏 | 重建向量库 |
|
||
| 文件上传失败 | 权限/空间问题 | 检查目录权限和磁盘空间 |
|
||
| 内存不足 | 向量模型占用 | 调整 docker-compose 内存限制或增加服务器内存 |
|
||
| 服务启动慢 | 模型加载 | 预热模型或使用更小模型 |
|
||
| 容器启动失败 | 镜像构建问题 | `docker logs rag-service` 查看错误 |
|
||
| 容器 OOM Killed | 内存超限 | 增大 `deploy.resources.limits.memory` 或加 swap |
|
||
| 数据卷未挂载 | 路径配置错误 | `docker inspect rag-service` 检查 Mounts |
|