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

17 KiB
Raw Permalink Blame History

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 可重新生成两种格式;脚本依赖 diagramspyyaml 和本机 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_deleteddeleted_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_versionsops_rule_itemsops_monitor_evaluationsops_monitor_reviews
报告治理 ops_reportsops_report_revisionsops_report_template_versionsops_prompt_versionsops_prompt_regression_runsops_bank_report_configs
流程与材料 ops_workflowsops_workflow_stagesops_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_idworkspace_idbank_idcategory_id
  • model_idmodel_namemodel_status
  • current_version_id
  • is_common_modelcommon_source_model_idcommon_model_name
  • source_updated_atcreated_atupdated_at

ops_model_versions

  • model_version_idmodel_instance_idversion_labelversion_status
  • developer_user_refdeveloper_display_name
  • development_dateiteration_start_datelast_iteration_dateiteration_reason
  • escort_start_dateescort_end_dateonline_dateoffline_date
  • development_ksdevelopment_psimax_lift
  • scoring_logic_storage_object_idsource_updated_at

模型实例只保存当前版本指针,所有生命周期和开发指标按版本留存。

6.2 监控批次和原始结果

ops_monitor_batches

  • batch_idworkspace_idsource_systemsource_batch_no
  • monitor_monthrevision_no
  • batch_statuswriting / published / failed / superseded
  • expected_model_countwritten_model_countfeature_row_countdistribution_row_count
  • checksum_sha256generated_atpublished_atfailed_reason

ops_monitor_results

  • monitor_result_idbatch_idmodel_instance_idmodel_version_idmonitor_month
  • ranking_resultmatched / unmatched / not_applicable
  • ks_valuepsi_value
  • sample_countgood_countbad_count
  • source_result_json:仅保存尚未结构化且确有追溯价值的源字段
  • calculated_atcreated_at

源表不保存 A/B/C、异常等级、处理建议或报告状态,避免两个模块同时改一行。

6.3 判级快照

ops_monitor_evaluations

  • evaluation_idmonitor_result_idrule_version_idrule_item_id
  • ks_mom_drop_ratesecondary_level2_hits_6m
  • abnormal_levelnormal / level1 / level2 / level3
  • monitor_gradeA / B / C
  • reason_codereason_text_snapshotaction_snapshot
  • is_currentevaluated_at

每次规则发布或源数据修订都新增判级记录;旧快照不覆盖。页面默认读取 is_current=1 的记录,历史报告仍绑定生成时的判级快照。

6.4 两段处理

ops_monitor_reviews

  • review_idmonitor_result_idevaluation_id
  • review_stagemodel_initial / business_final
  • review_statuspending / handled / auto_closed
  • decisionno_action / tune_or_rebuild
  • handling_note(手工处理必填)
  • due_athandled_byhandled_atauto_closed_at
  • state_versioncreated_atupdated_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_idexternal_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、UsersRoles 和当前工作空间,不创建新的角色或权限数据。
  • 新增轻量 operations_context:校验用户已登录且可访问所选工作空间;业务角色取与 /api/v1/auth/me、前端 AuthUser.role_code 相同的登录角色来源,避免前后端角色口径不一致。
  • 角色映射约定:admin → 管理员;developer/model_team → 模型团队;business/business_team/biz → 业务团队。
  • 前端按角色决定页面呈现,后端仍必须按角色校验写操作,不能把前端隐藏按钮当安全边界。
  • 角色代码最终值由登录/权限模块给出,运维模块只维护一处映射常量。

11. 代码落位建议

沿用现有 router / schema / service 分层,每个文件不超过 500 行:

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 迁移和首条真实接口实现。