fix(boundary): 修复多库边界问题、版本管理及删除清理

多库检索与存储修复:
- 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
- 更新多篇现有文档
This commit is contained in:
lacerate551
2026-06-04 23:58:44 +08:00
parent a1a0814633
commit cb75b9b274
50 changed files with 6385 additions and 6248 deletions

View File

@@ -106,7 +106,6 @@ X-User-Department: 部门(可选)
|------|------|------|
| `/chat` | POST | 普通聊天 |
| `/rag` | POST | 知识库问答 |
| `/rag/stream` | POST | 流式问答 |
| `/search` | POST | 混合检索 |
#### 向量库管理
@@ -175,7 +174,8 @@ GET /api/users/{user_id}
- [x] 更新 API 文档
- [ ] 清理测试数据和临时文件
- [ ] 整理依赖列表 (requirements.txt)
- [ ] 准备环境变量配置模板
- [ ] 准备环境变量配置模板 (`deploy/.env.production`)
- [ ] 编写 Dockerfile.prod 和 docker-compose.prod.yml
### 4.2 后端组需完成
@@ -195,155 +195,193 @@ GET /api/users/{user_id}
---
## 五、Linux 部署方案
## 五、Linux 部署方案Docker
### 5.1 部署架构
### 5.1 服务器规格
| 项目 | 配置 |
|------|------|
| 操作系统 | Ubuntu 22.04 LTS |
| CPU | 4 vCPU |
| 内存 | 8 GB |
| 部署路径 | `/opt/rag-agent` |
| 容器运行时 | Docker + Docker Compose |
### 5.2 部署架构
```
┌─────────────────────────────────────────────────────────────────┐
│ Linux 服务器
│ Linux 服务器 (Ubuntu 22.04)
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ Nginx 后端服务 │ RAG 服务 │ │
│ │ :80/443 │───▶│ :8080 :5001 │ │
─────────────┘ └─────────────┘ └─────────────────────
│ │
│ ▼
│ ┌─────────────┐ ┌─────────────
MySQL/PG ChromaDB
└─────────────┘ └─────────────┘
┌─────────────┐
│ │ documents/ │ ◀── 文档存储目录
└─────────────┘
│ ┌──────────────────────────────────────────────────────────┐
│ │ Docker (rag-service 容器)
│ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ Gunicorn (gthread worker)
│ │ └── Flask App :5001
│ └──────────────────────────────────────────────────
数据卷挂载:
│ • vector_store/ → 向量库持久化
• documents/ → 原始文档
│ • models/ → 本地模型文件
│ │ • .data/ → 运行时缓存
│ • data/ → SQLite 同步状态
│ └──────────────────────────────────────────────────────────┘ │
│ ▲ │
│ │ :5001 │
│ ┌──────┴──────┐ │
│ │ 后端网关 │ (Nginx / Spring Cloud Gateway) │
│ │ :80/443 │ │
│ └─────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### 5.2 环境准备
### 5.3 项目目录结构
```bash
# 1. 系统依赖
sudo apt update
sudo apt install -y python3.10 python3.10-venv python3-pip
# 2. 创建部署用户
sudo useradd -m -s /bin/bash rag
sudo su - rag
# 3. 创建目录结构
mkdir -p /home/rag/rag-service/{app,documents,vector_store,logs}
```
/opt/rag-agent/
├── deploy/
│ ├── Dockerfile.prod # 生产镜像定义
│ ├── docker-compose.prod.yml # 编排文件
│ └── .env.production # 生产环境变量
├── app/ # 应用源码
├── vector_store/ # ChromaDB 向量库(持久化)
├── documents/ # 原始文档(持久化)
├── models/ # 本地模型文件(持久化)
├── .data/ # 运行时缓存
└── data/ # SQLite 同步状态
```
### 5.3 RAG 服务部署
### 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
# 1. 上传代码
cd /home/rag/rag-service
# 将项目代码上传到 app/ 目录
# deploy/.env.production
# 2. 创建虚拟环境
python3.10 -m venv venv
source venv/bin/activate
# 3. 安装依赖
pip install -r app/requirements.txt
# 4. 配置环境变量
cat > .env << EOF
# 生产环境配置
# 运行模式
DEV_MODE=false
DOCUMENTS_PATH=/home/rag/rag-service/documents
VECTOR_STORE_PATH=/home/rag/rag-service/vector_store
# API 配置(如果需要)
DASHSCOPE_API_KEY=your_api_key
EOF
# 路径配置
DOCUMENTS_PATH=/app/documents
VECTOR_STORE_PATH=/app/vector_store
# 5. 初始化向量库
python -c "from knowledge.manager import get_kb_manager; get_kb_manager()"
# API 密钥
DASHSCOPE_API_KEY=your_api_key_here
# 6. 测试启动
cd app && python main.py --port 5001
# 其他配置项按需添加...
```
### 5.4 Systemd 服务配置
### 5.7 首次部署
```bash
# 创建服务文件
sudo cat > /etc/systemd/system/rag-service.service << 'EOF'
[Unit]
Description=RAG Knowledge Service
After=network.target
# 1. 在服务器上创建部署目录
sudo mkdir -p /opt/rag-agent
sudo chown $USER:$USER /opt/rag-agent
[Service]
Type=simple
User=rag
Group=rag
WorkingDirectory=/home/rag/rag-service/app
Environment="PATH=/home/rag/rag-service/venv/bin"
EnvironmentFile=/home/rag/rag-service/.env
ExecStart=/home/rag/rag-service/venv/bin/python main.py --port 5001
Restart=always
RestartSec=5
# 2. 上传项目代码到 /opt/rag-agent
scp -r ./rag-agent/* server:/opt/rag-agent/
[Install]
WantedBy=multi-user.target
EOF
# 3. 配置环境变量
cd /opt/rag-agent/deploy
cp .env.production.example .env.production
vim .env.production # 填入实际的 API Key 等配置
# 启动服务
sudo systemctl daemon-reload
sudo systemctl enable rag-service
sudo systemctl start rag-service
# 4. 构建并启动容器
docker compose -f docker-compose.prod.yml up -d --build
# 查看状态
sudo systemctl status rag-service
# 5. 验证服务状态
docker ps
docker logs rag-service
curl -f http://localhost:5001/health
```
### 5.5 Nginx 配置
### 5.8 热更新流程
```nginx
# /etc/nginx/sites-available/rag-service
upstream rag_backend {
server 127.0.0.1:5001;
}
#### 小改动配置文件、Prompt 模板等)
server {
listen 80;
server_name your-domain.com;
# 请求体大小限制(文件上传)
client_max_body_size 50M;
# RAG API 代理
location /rag-api/ {
proxy_pass http://rag_backend/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 注入用户信息(由认证模块设置)
proxy_set_header X-User-ID $http_x_user_id;
proxy_set_header X-User-Name $http_x_user_name;
proxy_set_header X-User-Role $http_x_user_role;
proxy_set_header X-User-Department $http_x_user_department;
# SSE 支持
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 300s;
}
# 图片文件
location /images/ {
alias /home/rag/rag-service/documents/images/;
}
}
```bash
# 直接复制文件进容器并重启
docker cp ./app/config.py rag-service:/app/config.py
docker restart rag-service
```
### 5.6 网关 Header 注入示例
#### 大改动(代码逻辑、依赖变更等)
```bash
# 重新构建镜像并启动(数据卷不受影响)
cd /opt/rag-agent/deploy
docker compose -f docker-compose.prod.yml up -d --build
```
### 5.9 网关 Header 注入示例
后端网关在转发请求到 RAG 服务时注入 Header
@@ -410,31 +448,41 @@ curl -X POST http://localhost:5001/documents/upload \
### 7.1 日志管理
```bash
# RAG 服务日志
tail -f /home/rag/rag-service/logs/rag.log
# 查看容器实时日志
docker logs -f rag-service
# Systemd 日志
journalctl -u rag-service -f
# 查看最近 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 || alert "RAG service down"
# 手动检查
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_$(date +%Y%m%d).tar.gz vector_store/
tar -czf backup_vector_$(date +%Y%m%d).tar.gz /opt/rag-agent/vector_store/
# 备份文档
rsync -av documents/ backup/documents/
rsync -av /opt/rag-agent/documents/ backup/documents/
# 备份同步状态
sqlite3 data/knowledge.db ".backup backup/knowledge.db"
cp /opt/rag-agent/data/knowledge.db backup/knowledge_$(date +%Y%m%d).db
```
---
@@ -446,5 +494,8 @@ sqlite3 data/knowledge.db ".backup backup/knowledge.db"
| 401 未认证 | 缺少 X-User-ID | 检查网关 Header 注入 |
| 向量检索失败 | ChromaDB 损坏 | 重建向量库 |
| 文件上传失败 | 权限/空间问题 | 检查目录权限和磁盘空间 |
| 内存不足 | 向量模型占用 | 增加 swap 或内存 |
| 内存不足 | 向量模型占用 | 调整 docker-compose 内存限制或增加服务器内存 |
| 服务启动慢 | 模型加载 | 预热模型或使用更小模型 |
| 容器启动失败 | 镜像构建问题 | `docker logs rag-service` 查看错误 |
| 容器 OOM Killed | 内存超限 | 增大 `deploy.resources.limits.memory` 或加 swap |
| 数据卷未挂载 | 路径配置错误 | `docker inspect rag-service` 检查 Mounts |