Files
yingqing/core/backend/ARCHITECTURE.md
T

452 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# AirShelf 后端架构
> 适用目录:`core/backend`。
> 最后核对:2026-07-21。
<!-- architecture-sync-commit: 9429133d04e695e53ba5c485e3e13a379fb3a03a -->
> 本文描述当前代码结构;系统级拓扑见 [core/ARCHITECTURE.md](../ARCHITECTURE.md)。
## 1. 定位
后端是 AirShelf 的业务与数据中枢,负责:
- 用户、团队、成员、邀请码和权限。
- 商品、项目、资产和五阶段生产状态。
- AI Provider、模型配置和生成任务编排。
- 积分预留、结算、释放和额度限制。
- TOS 文件、素材审核、资产引用和垃圾桶生命周期。
- Celery 异步任务、脚本 SSE、视频轮询和 FFmpeg 导出。
- 通知中心和平台超管治理接口。
## 2. 目录结构
```text
core/backend/
├─ airshelf/
│ ├─ settings/
│ │ ├─ base.py 公共配置、数据库、Redis、Provider 环境变量
│ │ ├─ development.py 本地开发配置
│ │ ├─ production.py 生产安全和 WhiteNoise 配置
│ │ └─ test.py 测试配置
│ ├─ urls.py API 总路由
│ ├─ celery.py Celery 应用入口
│ ├─ wsgi.py
│ └─ asgi.py
├─ apps/
│ ├─ common/
│ ├─ accounts/
│ ├─ products/
│ ├─ assets/
│ ├─ projects/
│ ├─ ai/
│ ├─ billing/
│ ├─ ops/
│ └─ adminpanel/
├─ skills/ 脚本生成、实体提取等 AI Skill 资料
├─ manage.py
├─ requirements.txt
├─ Dockerfile
├─ docker-entrypoint.sh
└─ README.md 本地启动与常用命令
```
## 3. Django 工程入口
### 3.1 Settings
`airshelf/settings/base.py` 统一声明:
- Django apps 和中间件。
- DRF 鉴权、权限、分页和过滤。
- SQLite/MySQL 数据库切换。
- Redis cache、Celery broker/result 和业务锁。
- TOS、火山 ARK、火山 TTS、YunQi、TokenSSR 配置。
- `MODEL_ROUTING_POLICY` 集中声明文本、图片、配音和视频的重试、单次超时、总时限、最多候选模型数、最多真实调用数及后处理退避。
- 模型路由策略允许由环境变量覆盖;修改后需要同步重启 API 与 Celery Worker,保证两端使用相同策略。
- AI 功能开关和灰度团队配置。
- 积分赠送等平台参数。
敏感凭证只从环境变量或部署 Secret 读取,不应写入架构文档和仓库代码。
### 3.2 路由
API 总入口:
```text
/api/health/ 健康检查
/api/auth/ 用户、团队、登录、邀请码
/api/products/ 商品
/api/assets/ 资产
/api/models/ 模特库
/api/projects/ 项目和五阶段流水线
/api/billing/ 账户、额度和流水
/api/ai/ AI 任务、生成、模型配置
/api/ops/ 通知
/api/admin/ 平台超管 API
/django-admin/ Django Admin
```
`/admin/*` 留给前端平台后台,Django 自带后台使用 `/django-admin/`
### 3.3 鉴权
当前 DRF 支持:
- Token Authentication:前端主流程使用 `Authorization: Token ...`
- Session AuthenticationDjango Admin 和部分浏览器会话。
- Basic Authentication:保留的 DRF 兼容入口。
当前不是 JWT 架构,不存在 refresh token 轮换链路。
## 4. 应用模块
### 4.1 `common`
提供基础设施型公共代码:
- `UUIDModel`
- `TimeStampedModel`
- `TeamOwnedModel`
- `TeamScopedViewSetMixin`
- 默认分页
- 健康检查
业务 app 应复用这些基类,避免自行实现团队过滤和通用字段。
### 4.2 `accounts`
负责身份和租户:
- 自定义 `User`
- `Team`
- `TeamMember`
- `Invitation`
- `UserPreference`
- `LoginSession`
- `AdminAuditLog`
团队角色主要包括 owner、admin、member;平台超管通过用户字段识别,与团队角色是两个维度。
成员可配置日、月、累计总积分限制;团队可配置月积分限制。
### 4.3 `products`
负责生产链输入:
- `Product`
- `ProductImage`
- `ProductSellingPoint`
商品包含标题、品牌、类目、目标人群、规格、描述、图片和卖点,为脚本及后续资产生成提供上下文。
### 4.4 `assets`
负责业务资产和文件元数据:
- `Asset`
- `AssetFile`
- `Model`
- `AssetReviewGroup`
- `AssetTag` / `AssetTagging`
- `AssetUsage`
- `FreeAssetGroup` / `FreeAsset`
`Asset` 表达业务语义、归属、分类、状态和审核信息;`AssetFile` 保存 TOS 对象键、bucket、content type、文件大小、checksum、宽高、时长、预览地址等。
资产模块还负责:
- 模特立绘和三视图。
- 人像素材审核提交与状态查询。
- 项目资产使用关系。
- 图片/视频资产库展示。
- 自由创作资产归组。
- 软删除、垃圾桶和恢复相关数据。
### 4.5 `projects`
负责视频项目和五阶段数据结构:
- `Project`
- `ProjectStage`
- `ScriptVersion` / `ScriptSegment`
- `BaseAssetGroup`
- `StoryboardVersion` / `StoryboardFrame`
- `StoryboardShot` / `StoryboardShotVersion`
- `VideoSegment` / `VideoSegmentVersion`
- `Timeline` / `TimelineClip`
- `SubtitleTrack`
- `BgmTrack`
- `ExportJob`
`projects` 负责业务状态和资源关系;具体 AI 外部请求应委托 `ai` 模块,积分动作应委托 `billing` 模块。
### 4.6 `ai`
负责所有模型和生成编排:
- `ModelProvider`
- `ModelConfig`
- `AITask`
- `AIModelAttempt`
- `ImageConversation`
- `QualityWord`
- `PromptTemplate`
- Provider 适配器
- 脚本 Agent 与 Skill 装配
- 实体提取、基础资产、三视图、生图、生视频和 TTS
- 用户错误转换和生成通知
`AITask` 表示一次用户逻辑任务及其唯一计费生命周期;它与 `AIModelAttempt` 是一对多关系。每条 `AIModelAttempt` 对应一次真实模型请求,按顺序保存供应商/模型快照、重试或 Fallback 标记、状态、耗时、错误、用量、平台成本及脱敏请求/响应摘要,不独立参与积分预留、扣费或任务状态推进。
主要目录和文件:
```text
apps/ai/
├─ providers/ Provider 适配层
├─ services.py 多生成场景编排
├─ tasks.py Celery 任务入口
├─ script_agent.py 脚本 Agent 和 SSE 编排
├─ free_video.py 自由视频任务
├─ generation_errors.py 对外错误语义
├─ pricing.py 通用模型计价
├─ video_pricing.py 视频计价
└─ model_library.py 模型/模特相关生成能力
```
`services.py` 是当前复杂度中心。新增场景应优先复用 Provider、任务、计费、错误转换和资产落库逻辑,避免继续堆叠重复流程。
### 4.7 `billing`
负责积分和额度:
- `CreditAccount`:团队余额与预留余额。
- `CreditLedger`:充值、预留、释放、扣费、调整、退款流水。
- `CreditReservation`:与计费型 `AITask` 关联的预留记录。
- `BillingConfig`:积分换算、视频毛利和预留 buffer。
- `QuotaPolicy`:团队、项目和单任务策略。
核心服务函数:
```text
reserve_credit
charge_reserved_credit
release_credit
```
这些函数负责事务、行锁、幂等、额度检查和流水。其他模块禁止直接改余额来模拟扣费。
### 4.8 `ops`
当前主要负责 `Notification`、消息列表和通知补齐任务。生成失败、额度变化和重要任务状态可以通过该模块形成用户消息。
### 4.9 `adminpanel`
为 React 平台超管后台提供跨团队治理 API,包括:
- 邀请码、团队和用户。
- 提示词、质量词和模型配置。
- 资产审核。
- AI 任务查询、重试和回收。
- 积分流水、计费配置和额度策略。
- 项目和平台完整性检查。
跨团队查询必须限制为平台超管,并保留必要审计信息。
## 5. 核心业务链
### 5.1 注册与团队
```text
校验邀请码
→ 注册或加入团队
→ 创建 TeamMember
→ 初始化团队积分账户
→ 返回 Token、User、Team、Role
```
### 5.2 商品到项目
```text
Product
→ 创建 Project
→ 初始化 ProjectStage
→ 进入 script 阶段
```
### 5.3 五阶段
```text
script
ScriptVersion → ScriptSegment
base_assets
生成/上传商品、人物、场景 → Asset / BaseAssetGroup
storyboard
StoryboardShot → 多个 ShotVersion → 采用版本
video
VideoSegment → 外部视频任务 → VideoSegmentVersion
export
Timeline + 字幕 + BGM + 配音 → ExportJob → 最终 Asset
```
## 6. AI Provider 架构
### 6.1 数据配置
`ModelProvider` 保存供应商名称、地址、状态和元数据;`ModelConfig` 保存模型名称、能力、价格、默认状态和模型参数。
Provider 地址和密钥的解析顺序由服务层控制:数据库配置优先,缺失时回退到环境变量。密钥不应写入数据迁移和普通日志。
### 6.2 适配层
```text
AIProvider Protocol
├─ VolcanoArkProvider
├─ OpenAICompatibleProvider
├─ YunqiProvider
└─ VolcanoTtsProvider
```
通用 OpenAI-compatible 适配器承担 YunQi、TokenSSR 及类似网关的共性协议;Provider 特殊差异通过元数据和适配器处理。
### 6.3 默认模型
默认模型可能由数据迁移、后台配置和 Provider 状态共同决定。业务代码不应长期硬编码某个供应商为唯一默认模型;架构文档也不复制易变化的默认模型名单。
## 7. 任务执行模型
### 7.1 Celery
当前 Celery 任务包括:
- AI 任务提交与轮询。
- 独立生图。
- 实体提取。
- 基础资产生成。
- 商品、人物三视图生成。
- 自由视频轮询。
- 项目视频片段轮询。
- FFmpeg 导出。
- 通知补齐。
任务必须使用数据库状态作为事实来源,不能只依赖 Celery result backend。
### 7.2 SSE
脚本 Agent 使用 SSE 在单个 HTTP 流中发送分析、生成、自检、草稿、保存和完成事件。断连、异常和计费释放由脚本 Agent 编排层兜底。
### 7.3 审核轮询
素材审核提交可在 AI 资产落库后触发。目前审核状态轮询主要由项目 API 和超管 API 请求调用,不是独立 Celery 周期任务。
### 7.4 前端轮询
前端通过任务和项目 API 获取进度。前端展示进度不是最终事实,后端任务状态、外部任务标识和数据库资产才是恢复依据。
## 8. 计费生命周期
计费型任务的标准流程:
```text
创建 AITask
→ 计算报价
→ 检查团队、成员、项目、单任务额度
→ reserve_credit
→ 提交任务
→ 执行/轮询
├─ 成功:写资产和业务版本 → charge_reserved_credit
└─ 失败:记录错误 → release_credit
```
额度层级:
- `Team.monthly_credit_limit`
- `TeamMember.daily_credit_limit`
- `TeamMember.monthly_credit_limit`
- `TeamMember.total_credit_limit`
- `QuotaPolicy.monthly_limit`
- `QuotaPolicy.project_limit`
- `QuotaPolicy.per_task_limit`
预留、结算和释放均需要幂等。删除仍处于 ACTIVE 的任务时,信号会尝试释放预留,避免余额永久冻结。
## 9. 资产与审核
### 9.1 文件存储
文件上传 TOS 后,数据库保存对象定位和元数据。对外访问使用后端生成或保存的可访问 URL,不把云存储密钥交给前端。
### 9.2 人像审核
需要审核的资产保存:
- `review_status`
- `review_remote_id`
- `review_error`
审核提交失败必须如实返回,不能把未提交成功的资产误标成 processing。轮询只更新发生变化的状态,避免刷新时间导致超时判断失效。
### 9.3 删除
删除需要区分:
- 业务记录软删除。
- 垃圾桶展示与恢复。
- 项目或会话引用解绑。
- TOS 对象最终删除。
- 任务和计费审计保留。
物理清理前必须检查资产引用,避免删除仍被商品、项目、模特或生成任务使用的文件。
## 10. 部署
### 10.1 API
后端镜像默认以 Gunicorn 启动。当前配置使用多个 worker 和线程,避免慢 AI/TOS 请求占满全部请求槽并饿死健康检查。
### 10.2 Worker
Celery Worker 复用 API 镜像,通过启动参数切换进程。当前 K8s 使用一个 Worker Deployment、并发 4,AI 和媒体任务尚未拆分独立队列。
### 10.3 Migration
`docker-entrypoint.sh` 只在 Gunicorn 启动时执行 migration 和 collectstatic。MySQL 使用 `GET_LOCK` 串行化迁移,Worker 明确跳过数据库结构变更。
### 10.4 FFmpeg
后端镜像安装 FFmpeg 和 Noto CJK 字体,用于视频拼接、字幕、BGM 和配音混合。
## 11. 测试与验证
常用验证:
```bash
python manage.py check
python manage.py makemigrations --check --dry-run
python manage.py test
```
测试环境使用独立 settings,并可让 Celery eager 执行。涉及计费、删除、任务重试和数据迁移的改动必须补回归测试。
## 12. 当前风险与维护边界
- `apps/ai/services.py` 体积较大,场景边界需要渐进拆分。
- AI 默认模型会通过迁移和后台配置变化,文档不能写死。
- 同步请求、SSE、Celery 和 API 轮询并存,新增流程必须明确执行模型。
- 单 Worker Deployment 可能导致 AI 和导出资源争用。
- 资产删除与任务删除涉及引用、计费和 TOS,不能只删除单表记录。
- 数据迁移可能包含业务数据变换,必须保证幂等或通过迁移锁串行执行。
## 13. 文档同步规则
出现以下变化时必须更新本文:
- Django app、核心模型或模块职责变化。
- API 一级路由或鉴权机制变化。
- AI Provider 适配机制变化。
- Celery/SSE/同步执行边界变化。
- 计费、额度或资产删除生命周期变化。
- 数据库、Redis、TOS、FFmpeg 或部署方式变化。