Files
label_backend/README.md

402 lines
12 KiB
Markdown
Raw Normal View History

2026-04-14 20:00:37 +08:00
# label-backend
## 项目简介
`label-backend` 是知识图谱智能标注平台的后端服务,负责资料上传、任务分发、提取标注、问答生成、训练样本导出、系统配置和视频预处理等核心流程。
系统采用 Spring Boot 3 + MyBatis-Plus + PostgreSQL + Redis 的技术组合,面向多租户标注场景设计,支持:
- 公司级数据隔离
- 基于 Redis Token 的认证鉴权
- 提取与问答两阶段标注流程
- 导出训练数据并对接微调任务
- 视频预处理与异步回调
- 审计日志与任务状态追踪
代码结构已按扁平标准目录整理,主包位于 `src/main/java/com/label`
## 功能特性
- 认证鉴权
- 使用 UUID Bearer Token + Redis 会话存储
- 自定义 `@RequireAuth``@RequireRole`
- 角色分级:`ADMIN > REVIEWER > ANNOTATOR > UPLOADER`
- 多租户隔离
- 基于 `CompanyContext` + `TenantLineInnerInterceptor`
- 对租户表自动追加 `company_id` 条件
- 特殊表通过显式 `companyId` 参数校验
- 公司与用户管理
- 公司 CRUD
- 公司内用户创建、状态变更、角色变更
- 角色变更和禁用后即时刷新或失效 Redis Token
- 资料管理
- 支持文本、图片、视频三类原始资料
- 上传到 RustFS数据库保存元数据
- 支持按角色查看、查询详情、删除
- 任务管理
- 任务池、我的任务、待审批队列、管理员全量视图
- Redis 分布式锁 + 数据库原子更新保证任务领取并发安全
- 提取标注
- AI 预标注
- 标注结果整体覆盖更新
- 提交、审批通过、驳回
- 问答生成
- 基于提取审批通过事件生成候选问答对
- 支持编辑、提交、审批、驳回
- 训练数据导出
- 查询已审批样本
- 创建导出批次
- 触发微调任务并查询状态
- 系统配置
- 支持公司专属配置覆盖全局默认配置
- 配置项存储于 `sys_config`
- 视频处理
- 支持触发视频预处理任务
- 支持异步回调、失败重试、管理员重置
## 技术栈
- Java 21
- Spring Boot 3.1.5
- Spring MVC
- MyBatis-Plus 3.5.3.1
- PostgreSQL
- Redis
- Spring AOP
- springdoc-openapi
- Testcontainers
- RustFS / S3 兼容对象存储
## 项目结构
项目根目录结构:
```text
label_backend/
├── assembly/ # 分发包描述与占位目录
├── docs/ # 设计、计划、规范文档
├── scripts/ # 启动脚本
├── src/
│ ├── main/
│ │ ├── java/com/label/ # 主代码
│ │ └── resources/
│ │ ├── application.yml
│ │ ├── logback.xml
│ │ └── sql/ # 初始化 SQL不打入构建产物
│ └── test/
│ ├── java/ # 单元测试与集成测试
│ └── resources/db/init.sql # Testcontainers 测试初始化 SQL
├── docker-compose.yml
├── Dockerfile
├── pom.xml
└── README.md
```
Java 包结构:
```text
com.label
├── annotation # 自定义注解,如 RequireAuth / RequireRole / OperationLog
├── aspect # AOP 审计切面
├── common # 通用能力auth、context、exception、result、storage、ai、statemachine
├── config # Spring 配置、MyBatis-Plus 配置、认证拦截器注册
├── controller # 所有 REST 接口
├── dto # DTO
├── entity # 实体
├── event # 领域事件
├── interceptor # 认证拦截器
├── listener # 事件监听器
├── mapper # MyBatis Mapper
├── service # 业务服务
└── util # 工具类
```
## 数据库表结构
初始化脚本位于 [init.sql](d:/workspace/label/label_backend/src/main/resources/sql/init.sql),包含 11 张核心表:
- `sys_company`
- 租户公司表
- `sys_user`
- 公司用户表,包含角色与状态
- `source_data`
- 原始资料元数据,支持 `TEXT` / `IMAGE` / `VIDEO`
- `annotation_task`
- 标注任务表,支持 `EXTRACTION` / `QA_GENERATION`
- `annotation_result`
- 提取阶段 JSON 结果
- `training_dataset`
- 训练样本数据,存储 GLM 格式 JSON
- `export_batch`
- 导出批次与微调任务状态
- `sys_config`
- 全局与公司级配置
- `sys_operation_log`
- 审计日志,只追加不更新
- `annotation_task_history`
- 任务状态变更历史
- `video_process_job`
- 视频预处理任务与回调状态
当前主要状态机:
- `source_data.status`
- `PENDING` / `PREPROCESSING` / `EXTRACTING` / `QA_REVIEW` / `APPROVED`
- `annotation_task.status`
- `UNCLAIMED` / `IN_PROGRESS` / `SUBMITTED` / `APPROVED` / `REJECTED`
- `training_dataset.status`
- `PENDING_REVIEW` / `APPROVED` / `REJECTED`
- `video_process_job.status`
- `PENDING` / `RETRYING` / `SUCCESS` / `FAILED`
## 配置说明
主配置文件位于 [application.yml](d:/workspace/label/label_backend/src/main/resources/application.yml)。
### 环境变量
| 变量名 | 说明 |
|---|---|
| `SPRING_DATASOURCE_URL` | PostgreSQL JDBC 地址 |
| `SPRING_DATASOURCE_USERNAME` | PostgreSQL 用户名 |
| `SPRING_DATASOURCE_PASSWORD` | PostgreSQL 密码 |
| `SPRING_DATA_REDIS_HOST` | Redis 主机 |
| `SPRING_DATA_REDIS_PORT` | Redis 端口 |
| `SPRING_DATA_REDIS_PASSWORD` | Redis 密码 |
| `RUSTFS_ENDPOINT` | RustFS / S3 兼容服务地址 |
| `RUSTFS_ACCESS_KEY` | RustFS Access Key |
| `RUSTFS_SECRET_KEY` | RustFS Secret Key |
| `AI_SERVICE_BASE_URL` | AI 服务地址 |
| `VIDEO_CALLBACK_SECRET` | 视频处理回调共享密钥 |
### 关键配置项
- `auth.enabled`
- `true` 时启用真实 Token 鉴权
- `false` 时使用 mock 身份,便于本地开发
- `auth.mock-company-id`
- 开发模式下的模拟公司 ID
- `auth.mock-user-id`
- 开发模式下的模拟用户 ID
- `auth.mock-role`
- 开发模式下的模拟角色
- `token.ttl-seconds`
- Token 有效期,默认 7200 秒
- `springdoc.api-docs.path`
- OpenAPI 文档路径,默认 `/v3/api-docs`
- `springdoc.swagger-ui.path`
- Swagger UI 路径,默认 `/swagger-ui.html`
## API接口
以下为当前主要接口分组。
### 1. 认证接口
- `POST /api/auth/login`
- 登录并返回 Bearer Token
- `POST /api/auth/logout`
- 登出并立即失效当前 Token
- `GET /api/auth/me`
- 获取当前登录用户信息
### 2. 公司管理
- `GET /api/companies`
- `POST /api/companies`
- `PUT /api/companies/{id}`
- `PUT /api/companies/{id}/status`
- `DELETE /api/companies/{id}`
### 3. 用户管理
- `GET /api/users`
- `POST /api/users`
- `PUT /api/users/{id}`
- `PUT /api/users/{id}/status`
- `PUT /api/users/{id}/role`
### 4. 资料管理
- `POST /api/source/upload`
- `GET /api/source/list`
- `GET /api/source/{id}`
- `DELETE /api/source/{id}`
### 5. 任务管理
- `GET /api/tasks/pool`
- `GET /api/tasks/mine`
- `GET /api/tasks/pending-review`
- `GET /api/tasks`
- `POST /api/tasks`
- `GET /api/tasks/{id}`
- `POST /api/tasks/{id}/claim`
- `POST /api/tasks/{id}/unclaim`
- `POST /api/tasks/{id}/reclaim`
- `PUT /api/tasks/{id}/reassign`
### 6. 提取标注
- `GET /api/extraction/{taskId}`
- `PUT /api/extraction/{taskId}`
- `POST /api/extraction/{taskId}/submit`
- `POST /api/extraction/{taskId}/approve`
- `POST /api/extraction/{taskId}/reject`
### 7. 问答生成
- `GET /api/qa/{taskId}`
- `PUT /api/qa/{taskId}`
- `POST /api/qa/{taskId}/submit`
- `POST /api/qa/{taskId}/approve`
- `POST /api/qa/{taskId}/reject`
### 8. 导出与微调
- `GET /api/training/samples`
- `POST /api/export/batch`
- `POST /api/export/{batchId}/finetune`
- `GET /api/export/{batchId}/status`
- `GET /api/export/list`
### 9. 系统配置
- `GET /api/config`
- `PUT /api/config/{key}`
### 10. 视频处理
- `POST /api/video/process`
- `GET /api/video/jobs/{jobId}`
- `POST /api/video/jobs/{jobId}/reset`
- `POST /api/video/callback`
## 定时任务
当前项目中**没有启用 Spring `@Scheduled` 定时同步任务**。
现有异步能力主要通过以下方式完成:
- 事务提交后事件监听
- 提取审批通过后触发问答生成
- 外部 AI 服务异步回调
- 视频处理完成后回调 `/api/video/callback`
- Redis 分布式锁
- 用于任务领取并发控制
如果后续需要周期性任务,建议单独引入明确的调度场景,不要复用当前业务链路中的事件机制。
## 部署说明
### 1. 数据库初始化
初始化 SQL 位于:
- 开发/部署初始化脚本
- [src/main/resources/sql/init.sql](d:/workspace/label/label_backend/src/main/resources/sql/init.sql)
说明:
- `src/main/resources/sql/init.sql` 会随源码保存,但**不会被打入 jar、target/classes 或分发包**
- `docker-compose.yml` 通过挂载该文件完成 PostgreSQL 初始化
### 2. 本地构建
```bash
mvn clean package -DskipTests
```
构建产物:
2026-04-15 00:24:27 +08:00
...
2026-04-14 20:00:37 +08:00
- `target/label-backend-1.0.0-SNAPSHOT.zip`
- `target/label-backend-1.0.0-SNAPSHOT.tar.gz`
### 3. 分发包结构
分发包由 [distribution.xml](d:/workspace/label/label_backend/assembly/distribution.xml) 组装,解压后结构如下:
```text
label-backend-<version>/
├── bin/
│ └── start.sh
├── etc/
│ ├── application.yml
│ └── logback.xml
├── libs/
│ ├── label-backend-<version>.jar
│ └── *.jar
└── logs/
```
### 4. 启动脚本
启动脚本位于 [start.sh](d:/workspace/label/label_backend/scripts/start.sh)。
行为说明:
- 在 Docker 容器中检测到 `/.dockerenv` 时,前台 `exec java ...`
- 在宿主机环境中使用 `nohup` 后台启动
- 日志默认写入 `logs/startup.log`
### 5. Docker Compose 启动
```bash
docker compose up -d
```
当前 `docker-compose.yml` 会启动:
- PostgreSQL
- Redis
- RustFS当前使用 MinIO 作为 S3 兼容替代)
- backend
- ai-service 占位服务
- frontend 占位服务
### 6. Docker 镜像构建
```bash
docker build -t label-backend:latest .
```
`Dockerfile` 使用多阶段构建,并从项目根目录的 `scripts/start.sh` 复制启动脚本。
## 注意事项
1. 开发模式下 `auth.enabled=false`
- 此时会使用 mock 用户身份,不适合生产环境
- 生产部署前必须显式启用真实鉴权
2. 多租户隔离仍依赖 `CompanyContext` + `TenantLineInnerInterceptor`
- 租户表查询默认依赖租户拦截器
- 个别特殊场景通过显式 `companyId` 参数校验
3. `sys_config``sys_company``video_process_job` 属于特殊表
- 其中部分表被排除出自动租户注入,需在服务层显式控制
4. SQL 已迁移到 `src/main/resources/sql`
- 仅作为源码级初始化文件保留
- 不会打进构建产物
5. 集成测试依赖 Testcontainers
- 运行完整集成测试需要本机可用 Docker 环境
6. 认证实现已移除 Shiro
- 当前使用自定义拦截器、注解与 Redis Token
7. 用户上下文 ThreadLocal 已移除
- 当前只保留 `CompanyContext`
- 用户主体通过请求属性中的 `TokenPrincipal` 传递
## 开发规范
当前约束摘要:
- 统一扁平目录结构,避免再次引入按业务域分层的旧目录
- DTO 统一放在 `dto/`,不再拆分 `request/response`
- Service 统一放在 `service/`,不拆 `service/impl`
- 业务规则优先放在 ServiceController 只负责 HTTP 协议层
- 新增接口需同步补齐 Swagger 注解与测试
- 所有对外接口参数必须在 Swagger 中明确体现名称、类型和含义
- 固定结构请求体禁止继续使用匿名 `Map<String, Object>``Map<String, String>`,必须定义 DTO 并补齐 `@Schema` 字段说明
- 固定结构响应应优先使用明确 DTO或至少为 Swagger 暴露对象补齐字段级 `@Schema` 注解
- 路径参数、查询参数、请求体、分页包装和通用返回体都必须维护可读的 OpenAPI 文档说明
2026-04-15 15:28:11 +08:00
- 需要保持历史兼容的原始 JSON 字符串请求体可以继续使用 `String`,但必须在 Swagger `@RequestBody` 中说明完整 JSON body 的提交方式和兼容原因
- 修改 Controller 参数、请求 DTO、响应 DTO 或对外实体后,必须运行 `mvn -Dtest=OpenApiAnnotationTest test`,确保 Swagger 参数名称、类型和含义没有回退
2026-04-14 20:00:37 +08:00
- 目录、配置、打包方式变化后README、设计文档和部署说明必须同步更新