Files
model-platform/docs/architecture/A卡模型运维模块-后端架构与数据库设计-V0.2.md
T

309 lines
17 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.
# A 卡模型运维模块后端架构与数据库设计 V0.2
> 状态:设计评审稿;独立库 DDL 已生成但尚未执行,ORM、迁移和接口尚未实现
> 日期:2026-08-31
> 依据:当前 `develop` 工程、运维前端 V1.9、现有三条 API 契约及甲方提供的 `model_platform` 18 张表 DDL
## 1. 结论
采用“**同一工程、两个数据库、平台库只读、运维库自有**”的方式:
- 现有 `model_platform` 库保持不变,只读复用用户、角色、工作空间、对象存储、脚本版本和调度数据。
- 新建独立 `model_operations` 库;模型平台直接写入其中 7 张受控源表,不通过运维平台复制一份数据。
- 运维模块只读取状态为 `published` 的监控批次,未发布或失败批次对页面不可见。
- 判级、复核、报告、流程、文档、Prompt 和配置由运维模块独立维护,模型平台不得写入。
- 已发布监控数据不原地覆盖;勘误时新增修订批次,保留历史版本和审计链。
- 首期不新增微服务、Redis或消息中间件;复用现有 Nginx、React、FastAPI、对象存储和 Schedule Executor,新库自带独立 Outbox/Inbox。
这能满足“模型方直接写业务表”和“我方单独建库”的双重要求,同时避免取得现有平台库不必要的写权限。
## 2. 模块边界
### 2.1 模型平台负责
- 银行、模型实例、模型版本及生命周期数据的写入。
- 月度监控原始结果、特征指标和分箱分布数据的计算与写入。
- 写入批次的完整性校验、计数、校验和及发布。
- 仅获得 `model_operations` 7 张源表的受控写权限,以及发布事件所需的 Outbox 插入权限。
- 已发布数据发生错误时,以新修订批次更正,不修改旧记录。
### 2.2 运维模块负责
- 按已发布原始结果和已发布规则版本计算异常等级、监控结果等级和命中原因。
- 模型团队初审、业务团队终审、超时默认不处理及全程留痕。
- 监控/诊断报告生成、编辑、发送、汇总和历史修订。
- 七阶段开发评审流程、材料、知识库、规则、Prompt、报告模板和按银行配置。
- 工作台、模型大类、细分银行、监控明细和详情等查询 API。
### 2.3 明确不做
- 运维模块不重复建设账号、角色、权限表;只复用登录模块返回的用户、角色和工作空间。
- 运维模块不得读取 `model_platform.users.password_hash`,不得写现有平台任一业务表。
- 模型平台不写判级、处理、报告、流程或配置表。
- “手工同步”不再复制数据;其含义调整为“校验最新发布批次并重建派生判级”。
- 报告汇总、知识库和工作台不单独建冗余汇总表,首期由业务表查询生成。
## 3. 总体架构
现有服务拓扑保持不变。运维能力作为 FastAPI 后端内的新 bounded context 接入,但增加第二套数据库连接:
1. 浏览器继续经 Nginx 访问 React SPA 和同源 `/api/v1/*`
2. `DATABASE_URL` 继续连接 `model_platform`,只承担现有认证、工作空间、存储和调度能力。
3. 新增 `OPERATIONS_DATABASE_URL` 连接 `model_operations`,承载全部运维业务数据。
4. 模型平台模块或调度任务直接写新库的 `ops_*` 源表。
5. 批次发布后,运维服务计算并保存规则判级快照。
6. 运维 API 联查新库源数据、判级和处理结果;用户显示名等按需只读平台库。
7. 报告生成、提醒等动作写新库 `ops_outbox_events`;接入异步阶段时让 Schedule Executor 增加运维库轮询连接。
8. 报告文件、流程材料继续复用平台库 `storage_objects` 与现有对象存储服务,运维库只保存对象 ID。
配套图:
- `A卡模型运维模块-系统架构-V0.2.png/.svg`
- `A卡模型运维模块-数据域关系-V0.2.png/.svg`
修改 YAML 后运行 `python3 docs/architecture/render_diagrams.py` 可重新生成两种格式;脚本依赖 `diagrams``pyyaml` 和本机 Graphviz。
配套建库建表脚本位于 `docs/database/model_operations-V0.1/`,包含 24 张表、1 个视图、四类模型大类种子数据和静态安全校验脚本;原始平台 DDL 已只读归档到 `docs/database/reference/`
## 4. 数据设计约定
- 表名前缀统一为 `ops_`,与现有模型平台表隔离。
- 全部 `ops_*` 对象均位于独立 `model_operations` 库。
- 主键统一使用 ULID `CHAR(26)`;日期时间统一 `DATETIME(3)`
- 月份在库内用 `DATE` 且固定为当月 1 日,API 序列化为 `YYYY-MM`
- KS、PSI、IV、CSI、坏账率和降幅在数据库中统一存 **01 比率**,使用 `DECIMAL(12,8)`;API 转换为 0~100 的百分数。
- 沿用当前仓库约定:不创建物理外键,使用 `fk_*` 逻辑索引并在服务层校验完整性。
- 可修改业务状态表使用 `state_version INTEGER` 做乐观锁。
- 需要删除的配置或流程数据采用 `is_deleted``deleted_at` 软删除;监控历史不允许删除。
- 所有根业务表包含 `workspace_id`,避免未来多个项目空间数据串用。
- `workspace_id/user_id/storage_object_id/platform_versions_id` 是对 `model_platform` 的逻辑引用,不建立跨库物理外键。
## 5. 表清单与归属
### 5.1 模型平台可写源表(7 张)
| 表 | 用途 | 核心唯一性 |
|---|---|---|
| `ops_banks` | 银行主数据及无极银行标记 | `(workspace_id, bank_code)` |
| `ops_model_instances` | 银行下的模型实例、通用模型关系、当前版本 | `(workspace_id, model_id)` |
| `ops_model_versions` | 版本、开发指标和生命周期日期 | `(model_instance_id, version_label)` |
| `ops_monitor_batches` | 月度写入批次、修订号、发布状态和校验和 | `(workspace_id, source_system, monitor_month, revision_no)` |
| `ops_monitor_results` | 模型单月原始排序性、KS、PSI和样本量 | `(batch_id, model_instance_id)` |
| `ops_monitor_feature_metrics` | 单月特征级 IV、CSI及贡献变化 | `(monitor_result_id, feature_code)` |
| `ops_monitor_distributions` | 评分分箱或特征分箱的基准期/当期分布 | `(monitor_result_id, dimension_type, feature_code, bin_order)` |
`ops_model_categories` 为运维模块维护的固定字典,模型平台只有读取权限。首期种子为 `std / bai / big / afd` 四类。
### 5.2 运维模块独占业务表(15 张)
| 数据域 | 表 |
|---|---|
| 字典 | `ops_model_categories` |
| 判级与处理 | `ops_rule_versions``ops_rule_items``ops_monitor_evaluations``ops_monitor_reviews` |
| 报告治理 | `ops_reports``ops_report_revisions``ops_report_template_versions``ops_prompt_versions``ops_prompt_regression_runs``ops_bank_report_configs` |
| 流程与材料 | `ops_workflows``ops_workflow_stages``ops_documents` |
| 使用统计 | `ops_usage_events` |
不新增通知任务表;通知和后台报告任务复用新库 `ops_outbox_events`。若后续需要展示逐次送达结果,再增通知投递日志表。
### 5.3 运维库技术表(2 张)
- `ops_outbox_events`:与运维业务写入同事务提交的后台事件。
- `ops_consumer_inbox`:异步消费者幂等去重。
新库合计 **24 张表 + 1 个当前监控结果视图**。不直接写 `model_platform.outbox_events`,防止运维事件污染现有模型调度事件流。
## 6. 核心表字段初稿
### 6.1 模型与版本
`ops_model_instances`
- `model_instance_id``workspace_id``bank_id``category_id`
- `model_id``model_name``model_status`
- `current_version_id`
- `is_common_model``common_source_model_id``common_model_name`
- `source_updated_at``created_at``updated_at`
`ops_model_versions`
- `model_version_id``model_instance_id``version_label``version_status`
- `developer_user_ref``developer_display_name`
- `development_date``iteration_start_date``last_iteration_date``iteration_reason`
- `escort_start_date``escort_end_date``online_date``offline_date`
- `development_ks``development_psi``max_lift`
- `scoring_logic_storage_object_id``source_updated_at`
模型实例只保存当前版本指针,所有生命周期和开发指标按版本留存。
### 6.2 监控批次和原始结果
`ops_monitor_batches`
- `batch_id``workspace_id``source_system``source_batch_no`
- `monitor_month``revision_no`
- `batch_status``writing / published / failed / superseded`
- `expected_model_count``written_model_count``feature_row_count``distribution_row_count`
- `checksum_sha256``generated_at``published_at``failed_reason`
`ops_monitor_results`
- `monitor_result_id``batch_id``model_instance_id``model_version_id``monitor_month`
- `ranking_result``matched / unmatched / not_applicable`
- `ks_value``psi_value`
- `sample_count``good_count``bad_count`
- `source_result_json`:仅保存尚未结构化且确有追溯价值的源字段
- `calculated_at``created_at`
源表不保存 A/B/C、异常等级、处理建议或报告状态,避免两个模块同时改一行。
### 6.3 判级快照
`ops_monitor_evaluations`
- `evaluation_id``monitor_result_id``rule_version_id``rule_item_id`
- `ks_mom_drop_rate``secondary_level2_hits_6m`
- `abnormal_level``normal / level1 / level2 / level3`
- `monitor_grade``A / B / C`
- `reason_code``reason_text_snapshot``action_snapshot`
- `is_current``evaluated_at`
每次规则发布或源数据修订都新增判级记录;旧快照不覆盖。页面默认读取 `is_current=1` 的记录,历史报告仍绑定生成时的判级快照。
### 6.4 两段处理
`ops_monitor_reviews`
- `review_id``monitor_result_id``evaluation_id`
- `review_stage``model_initial / business_final`
- `review_status``pending / handled / auto_closed`
- `decision``no_action / tune_or_rebuild`
- `handling_note`(手工处理必填)
- `due_at``handled_by``handled_at``auto_closed_at`
- `state_version``created_at``updated_at`
唯一约束为 `(monitor_result_id, review_stage)`。模型团队阶段完成后才创建或激活业务团队阶段;超时任务通过 Outbox 执行默认“不处理”。
### 6.5 报告
`ops_reports` 保存报告主状态与绑定快照,`ops_report_revisions` 保存每次正文修改:
- 报告绑定 `monitor_result_id + evaluation_id + template_version_id + prompt_version_id`
- `ops_report_revisions` 使用 `(report_id, revision_no)` 唯一约束,正文和结构化快照均不可变。
- 监控报告页默认只查询最新监控月份;报告汇总页查询全部历史。数据库不删除旧月份报告。
- PDF/Excel 等文件通过 `storage_object_id` 指向现有 `storage_objects`
### 6.6 流程、材料与知识库
- `ops_workflows`:银行、模型大类、模型实例、独立开发/复用通用模型、当前阶段、状态和计划日期。
- `ops_workflow_stages`:1~7 阶段实例、负责人角色、开始/截止/完成时间、确认状态和停滞天数。
- `ops_documents`:同时支持 `storage_object_id``external_url`,可关联流程、阶段、模型和版本。
- 知识库不是新表,而是对 `ops_documents` 按银行、模型、版本、环节和通用模型标记查询。
## 7. 发布协议
模型平台每次写入必须执行以下协议:
1. 创建 `ops_monitor_batches`,状态为 `writing`,携带幂等的 `source_batch_no`
2. 幂等写入银行、模型实例和版本;插入本批次结果、特征指标和分布。
3. 校验模型数、明细行数、必填字段、指标范围和 SHA-256 校验和。
4. 在一个短事务内将批次改为 `published`;同月份上一修订改为 `superseded`
5. 写入 `monitor_batch.published` Outbox 事件,触发运维模块生成判级快照。
6. 运维查询只允许关联 `published` 批次,并按最高修订号取当前结果。
失败批次保留为 `failed` 供排查。任何已发布结果、特征和分布均不得执行 `UPDATE` 或物理删除。
## 8. 数据库权限
建议生产环境至少分四类账号:
| 账号 | 权限 |
|---|---|
| `schema_migrator` | 仅部署时使用,可对 `model_operations` 执行 DDL;不改 `model_platform` |
| `platform_reader` | 对平台库指定字段只读;禁止读取密码散列和权限内部表 |
| `model_writer` | 读取字典;对新库 7 张源表执行限定 `SELECT/INSERT/UPDATE`,并插入发布事件;无 `DELETE`,不能写运维独占表 |
| `operations_app` | 读写运维库;只读平台库必要表;服务层禁止修改已发布源结果 |
若模型任务与运维 API 暂时运行在同一 FastAPI 进程,代码层仍按平台库/运维库两个 session factory 和 repository 隔离;生产批处理脚本优先使用独立 `MODEL_WRITER_DATABASE_URL`,将权限边界落实到数据库。
## 9. API 设计
### 9.1 首条真实纵向链路
保持前端已写好的路径,不重新发明契约:
| 接口 | 主要数据来源 |
|---|---|
| `GET /api/v1/operations/models` | 模型实例 + 当前版本 + 最新已发布结果 + 当前判级 + 最近处理 |
| `GET /api/v1/operations/models/{model_id}` | 单模型完整元数据和最新状态 |
| `GET /api/v1/operations/models/{model_id}/monitor-results?month=YYYY-MM` | 指定月最新已发布修订 + 当前判级 |
所有接口返回现有 `{ data, meta? }` 包装。切换 `VITE_OPERATIONS_API_MODE=api` 前,前端 `operationsApi.ts` 需要统一附加当前 `workspace_id`,用于选择并校验数据空间。
### 9.2 后续资源接口
- 查询:`/model-categories/overview``/banks/overview``/monitor-results``/monitor-results/{id}/features``/monitor-results/{id}/distributions`
- 处理:`/monitor-results/{id}/reviews/model-initial``/reviews/business-final`
- 报告:`/reports``/reports/{id}``/reports/{id}/revisions``/reports/{id}/send`
- 流程:`/workflows``/workflows/{id}``/workflows/{id}/stages/{stage}``/documents`
- 治理:`/rule-versions``/prompt-versions``/report-template-versions``/bank-report-configs`
列表统一支持分页、排序和与 V1.9 筛选框一致的查询参数;Excel/PDF 导出走独立端点,不让普通列表接口返回超大数据集。
## 10. 登录与角色
- 不增加运维 RBAC 表,也不接管现有权限管理模块。
- API 复用登录 Cookie、`Users``Roles` 和当前工作空间,不创建新的角色或权限数据。
- 新增轻量 `operations_context`:校验用户已登录且可访问所选工作空间;业务角色取与 `/api/v1/auth/me`、前端 `AuthUser.role_code` 相同的登录角色来源,避免前后端角色口径不一致。
- 角色映射约定:`admin` → 管理员;`developer/model_team` → 模型团队;`business/business_team/biz` → 业务团队。
- 前端按角色决定页面呈现,后端仍必须按角色校验写操作,不能把前端隐藏按钮当安全边界。
- 角色代码最终值由登录/权限模块给出,运维模块只维护一处映射常量。
## 11. 代码落位建议
沿用现有 router / schema / service 分层,每个文件不超过 500 行:
```text
common/src/common/db/models/operations/
reference.py models.py monitoring.py governance.py
reviews.py reports.py workflows.py usage.py
backend/src/backend/api/operations/
__init__.py _deps.py models.py monitoring.py reviews.py
reports.py workflows.py governance.py
backend/src/backend/services/operations/
queries.py evaluation.py publishing.py reports.py workflows.py
backend/src/backend/schemas/operations/
common.py models.py monitoring.py reports.py workflows.py governance.py
```
运维 ORM 使用独立 Alembic 版本线和 `OPERATIONS_DATABASE_URL`,不能让现有 `model_platform` 基线迁移误扫新表。`backend.main` 创建第二个 engine/session factory 并只注册一个 `operations_router`;业务规则不写进路由文件。
## 12. 实施顺序
### P0:首条真实链路
1. DBA 审核并创建 `model_operations`;建模型/版本/批次/结果/特征/分布及规则判级 11 张核心表。
2. 导入一组 2026-07 样例数据并走完整 `writing → published` 协议。
3. 实现三条既有 API,前端追加 `workspace_id` 后切到 API 模式。
4. 验证列表、模型详情、单月监控详情数值一致。
### P1:业务闭环
实现两段复核、报告及修订、七阶段流程、材料和知识库。
### P2:治理与运营
实现规则版本、Prompt 回归、模板版本、使用统计、提醒和导出优化。
## 13. 开发前需共同确认的 5 项
以下均给出推荐默认值;未得到反对意见时可按推荐值实施:
1. **模型 ID 唯一性**:推荐 `model_id` 在工作空间内全局唯一,不只在银行内唯一。
2. **指标单位**:推荐数据库存 0~1 比率,API 输出百分数;禁止两种单位混写。
3. **批次粒度**:推荐一个来源系统每月一个全量批次,勘误整体升修订号。
4. **工作空间范围**:推荐全部根表带 `workspace_id` 并逻辑引用 `model_platform.workspaces`,即使首期只有一个 A 卡项目空间。
5. **模型开发材料**:推荐运维表同时支持对象存储文件和模型平台链接,避免重复上传。
这 5 项确认后即可开始 ORM、Alembic 迁移和首条真实接口实现。