17 KiB
A 卡模型运维模块后端架构与数据库设计 V0.2
状态:设计评审稿;独立库 DDL 已生成但尚未执行,ORM、迁移和接口尚未实现
日期:2026-08-31
依据:当前develop工程、运维前端 V1.9、现有三条 API 契约及甲方提供的model_platform18 张表 DDL
1. 结论
采用“同一工程、两个数据库、平台库只读、运维库自有”的方式:
- 现有
model_platform库保持不变,只读复用用户、角色、工作空间、对象存储、脚本版本和调度数据。 - 新建独立
model_operations库;模型平台直接写入其中 7 张受控源表,不通过运维平台复制一份数据。 - 运维模块只读取状态为
published的监控批次,未发布或失败批次对页面不可见。 - 判级、复核、报告、流程、文档、Prompt 和配置由运维模块独立维护,模型平台不得写入。
- 已发布监控数据不原地覆盖;勘误时新增修订批次,保留历史版本和审计链。
- 首期不新增微服务、Redis或消息中间件;复用现有 Nginx、React、FastAPI、对象存储和 Schedule Executor,新库自带独立 Outbox/Inbox。
这能满足“模型方直接写业务表”和“我方单独建库”的双重要求,同时避免取得现有平台库不必要的写权限。
2. 模块边界
2.1 模型平台负责
- 银行、模型实例、模型版本及生命周期数据的写入。
- 月度监控原始结果、特征指标和分箱分布数据的计算与写入。
- 写入批次的完整性校验、计数、校验和及发布。
- 仅获得
model_operations7 张源表的受控写权限,以及发布事件所需的 Outbox 插入权限。 - 已发布数据发生错误时,以新修订批次更正,不修改旧记录。
2.2 运维模块负责
- 按已发布原始结果和已发布规则版本计算异常等级、监控结果等级和命中原因。
- 模型团队初审、业务团队终审、超时默认不处理及全程留痕。
- 监控/诊断报告生成、编辑、发送、汇总和历史修订。
- 七阶段开发评审流程、材料、知识库、规则、Prompt、报告模板和按银行配置。
- 工作台、模型大类、细分银行、监控明细和详情等查询 API。
2.3 明确不做
- 运维模块不重复建设账号、角色、权限表;只复用登录模块返回的用户、角色和工作空间。
- 运维模块不得读取
model_platform.users.password_hash,不得写现有平台任一业务表。 - 模型平台不写判级、处理、报告、流程或配置表。
- “手工同步”不再复制数据;其含义调整为“校验最新发布批次并重建派生判级”。
- 报告汇总、知识库和工作台不单独建冗余汇总表,首期由业务表查询生成。
3. 总体架构
现有服务拓扑保持不变。运维能力作为 FastAPI 后端内的新 bounded context 接入,但增加第二套数据库连接:
- 浏览器继续经 Nginx 访问 React SPA 和同源
/api/v1/*。 DATABASE_URL继续连接model_platform,只承担现有认证、工作空间、存储和调度能力。- 新增
OPERATIONS_DATABASE_URL连接model_operations,承载全部运维业务数据。 - 模型平台模块或调度任务直接写新库的
ops_*源表。 - 批次发布后,运维服务计算并保存规则判级快照。
- 运维 API 联查新库源数据、判级和处理结果;用户显示名等按需只读平台库。
- 报告生成、提醒等动作写新库
ops_outbox_events;接入异步阶段时让 Schedule Executor 增加运维库轮询连接。 - 报告文件、流程材料继续复用平台库
storage_objects与现有对象存储服务,运维库只保存对象 ID。
配套图:
A卡模型运维模块-系统架构-V0.2.png/.svgA卡模型运维模块-数据域关系-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、坏账率和降幅在数据库中统一存 0~1 比率,使用
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_idmodel_id、model_name、model_statuscurrent_version_idis_common_model、common_source_model_id、common_model_namesource_updated_at、created_at、updated_at
ops_model_versions
model_version_id、model_instance_id、version_label、version_statusdeveloper_user_ref、developer_display_namedevelopment_date、iteration_start_date、last_iteration_date、iteration_reasonescort_start_date、escort_end_date、online_date、offline_datedevelopment_ks、development_psi、max_liftscoring_logic_storage_object_id、source_updated_at
模型实例只保存当前版本指针,所有生命周期和开发指标按版本留存。
6.2 监控批次和原始结果
ops_monitor_batches
batch_id、workspace_id、source_system、source_batch_nomonitor_month、revision_nobatch_status:writing / published / failed / supersededexpected_model_count、written_model_count、feature_row_count、distribution_row_countchecksum_sha256、generated_at、published_at、failed_reason
ops_monitor_results
monitor_result_id、batch_id、model_instance_id、model_version_id、monitor_monthranking_result:matched / unmatched / not_applicableks_value、psi_valuesample_count、good_count、bad_countsource_result_json:仅保存尚未结构化且确有追溯价值的源字段calculated_at、created_at
源表不保存 A/B/C、异常等级、处理建议或报告状态,避免两个模块同时改一行。
6.3 判级快照
ops_monitor_evaluations
evaluation_id、monitor_result_id、rule_version_id、rule_item_idks_mom_drop_rate、secondary_level2_hits_6mabnormal_level:normal / level1 / level2 / level3monitor_grade:A / B / Creason_code、reason_text_snapshot、action_snapshotis_current、evaluated_at
每次规则发布或源数据修订都新增判级记录;旧快照不覆盖。页面默认读取 is_current=1 的记录,历史报告仍绑定生成时的判级快照。
6.4 两段处理
ops_monitor_reviews
review_id、monitor_result_id、evaluation_idreview_stage:model_initial / business_finalreview_status:pending / handled / auto_closeddecision:no_action / tune_or_rebuildhandling_note(手工处理必填)due_at、handled_by、handled_at、auto_closed_atstate_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. 发布协议
模型平台每次写入必须执行以下协议:
- 创建
ops_monitor_batches,状态为writing,携带幂等的source_batch_no。 - 幂等写入银行、模型实例和版本;插入本批次结果、特征指标和分布。
- 校验模型数、明细行数、必填字段、指标范围和 SHA-256 校验和。
- 在一个短事务内将批次改为
published;同月份上一修订改为superseded。 - 写入
monitor_batch.publishedOutbox 事件,触发运维模块生成判级快照。 - 运维查询只允许关联
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 行:
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:首条真实链路
- DBA 审核并创建
model_operations;建模型/版本/批次/结果/特征/分布及规则判级 11 张核心表。 - 导入一组 2026-07 样例数据并走完整
writing → published协议。 - 实现三条既有 API,前端追加
workspace_id后切到 API 模式。 - 验证列表、模型详情、单月监控详情数值一致。
P1:业务闭环
实现两段复核、报告及修订、七阶段流程、材料和知识库。
P2:治理与运营
实现规则版本、Prompt 回归、模板版本、使用统计、提醒和导出优化。
13. 开发前需共同确认的 5 项
以下均给出推荐默认值;未得到反对意见时可按推荐值实施:
- 模型 ID 唯一性:推荐
model_id在工作空间内全局唯一,不只在银行内唯一。 - 指标单位:推荐数据库存 0~1 比率,API 输出百分数;禁止两种单位混写。
- 批次粒度:推荐一个来源系统每月一个全量批次,勘误整体升修订号。
- 工作空间范围:推荐全部根表带
workspace_id并逻辑引用model_platform.workspaces,即使首期只有一个 A 卡项目空间。 - 模型开发材料:推荐运维表同时支持对象存储文件和模型平台链接,避免重复上传。
这 5 项确认后即可开始 ORM、Alembic 迁移和首条真实接口实现。