Files
sub2api-cn-relay-manager/docs/2026-05-22-BATCH_AUTO_IMPORT_V2_ARCHITECTURE.md
phamnazage-jpg afce3da3df docs(v2): refine batch import architecture
Expand the batch auto-import V2 spec and TDD plan with stability requirements, result state persistence, and result page design. Add a dedicated architecture document for run state, APIs, pages, and UI field layout, and sync the execution board to the new V2 scope.
2026-05-22 13:18:51 +08:00

17 KiB
Raw Blame History

V2 技术架构 — Batch Auto-Import

日期2026-05-22 状态:设计中 关联文档:

  • docs/2026-05-21-BATCH_AUTO_IMPORT_SPEC.md
  • docs/2026-05-21-BATCH_AUTO_IMPORT_TDD_PLAN.md
  • docs/EXECUTION_BOARD.md

1. 文档目标

这份文档回答 4 个问题:

  1. V2 在系统里由哪些组件组成
  2. 运行状态如何持久化,如何保证导入任务更稳定
  3. 结果页到底展示什么,字段如何组织
  4. 后续实现时,后端、存储、页面应该如何分工

这份文档不重复 SPEC 的产品动机,也不替代 TDD plan 的编码顺序。它只负责把 V2 的技术结构和结果页设计讲清楚。

2. 设计目标

V2 必须同时满足这 5 个目标:

  1. 稳定导入

    • 单条 URL + key 的 probe / provision / confirm / validate 全过程可控
    • 批量导入时,单条失败不应让整批状态丢失
  2. 状态可恢复

    • 控制面重启后,历史 run 和 item 结果仍可查看
    • 对 transient 失败要有明确 retry 轨迹
  3. 模型纠错

    • 人工填写的模型名不是最终事实
    • 必须基于 key 实探结果自动归一化、匹配、推荐
  4. 兼容分流

    • 对国产模型 / 第三方 OpenAI-compatible 上游,必须记录 capability profile
    • 后续 routing、确认逻辑、warning 解释都依赖 profile
  5. 结果可视

    • 不再只靠 CLI 和日志
    • 控制面必须提供 run 列表和 run 详情页

3. 非目标

这版架构明确不做:

  • 多 key 自动负载均衡
  • 高级调度系统
  • 实时 WebSocket 推送
  • 复杂前端工作台
  • 自动价格发现与自动调价
  • 宿主数据库直连或宿主 DB 读写

4. 逻辑组件

V2 在控制面内部拆成 6 个逻辑层:

operator input
  ↓
batch import orchestrator
  ├── probe layer
  ├── capability profiler
  ├── provision adapter
  ├── confirmation engine
  ├── validation engine
  └── run state store
        ↓
    result projection
        ↓
    HTTP API / result pages / CLI output

4.1 Probe Layer

职责:

  • 调用 upstream /v1/models
  • 探测 /v1/chat/completions
  • 探测 /v1/responses
  • 探测 /v1/messages
  • 抽取原始模型列表
  • 计算模型归一化结果

输入:

  • base_url
  • api_key
  • requested_models(可选)

输出:

  • raw_models
  • normalized_models
  • resolved_smoke_model
  • capability_profile
  • probe_summary

4.2 Provision Adapter

职责:

  • 计算 provider_id
  • 查找或创建目标 channel
  • patch model_mapping
  • patch model_pricing
  • 创建或更新 account
  • 绑定 provider 资源关系

输入:

  • normalized_models
  • capability_profile
  • resolved_smoke_model

输出:

  • channel_id
  • account_id
  • provider_id
  • managed_resources

4.3 Confirmation Engine

职责:

  • 处理宿主异步探测窗口
  • 处理首次 403 probe race
  • 处理首次 503 no available accounts
  • 决定 confirmation_status

输出状态:

  • confirmed_active
  • confirmed_warning
  • confirmed_broken

4.4 Validation Engine

职责:

  • 使用托管 key 对宿主 gateway 真实发起 /v1/chat/completions
  • 决定最终 access_status
  • 将 validation 结果写入结果页投影

4.5 Run State Store

职责:

  • 持久化 run 和 item 的阶段状态
  • 持久化 retry、warning、错误阶段
  • 为结果页提供可直接读取的数据源

4.6 Result Projection

职责:

  • 将低层运行状态整理成运营和开发都能直接看的摘要
  • 生成 run 列表统计
  • 生成 item 详情视图
  • 不暴露内部实现噪音

5. 运行时状态模型

5.1 Run 级状态

ImportRun.state

  • running
  • completed
  • completed_with_warnings
  • failed
  • cancelled

ImportRun 核心字段:

字段 含义
run_id 一次批量导入任务的主键
mode strict / partial
access_mode subscription / self_service
total_items 总条目数
completed_items 已完成条目数
active_items 最终 active 条目数
degraded_items 最终 degraded 条目数
broken_items 最终 broken 条目数
state run 总状态
started_at 开始时间
updated_at 最近更新时间
finished_at 完成时间

5.2 Item 级状态

ImportRunItem.current_stage

  • probe
  • provision
  • confirm
  • validate
  • done

ImportRunItem.stage_status

  • discovered
  • provisioned
  • confirming
  • confirmed_active
  • confirmed_warning
  • confirmed_broken

ImportRunItem 核心字段:

字段 含义
item_id 单条导入记录 ID
base_url 当前导入目标 URL
provider_id 自动生成的 provider 标识
requested_models 人工请求模型名
raw_models upstream 原始模型列表
normalized_models 归一化后模型列表
resolved_smoke_model 最终用于 smoke 的模型
capability_profile_json 能力画像
channel_id 宿主 channel
account_id 宿主 account
confirmation_status 确认状态
access_status 最终访问状态
retry_count 当前总重试次数
advisory_messages warning / advisory 列表
last_error_stage 最近错误发生阶段
last_error 最近错误文本
created_at 创建时间
updated_at 更新时间

6. 状态库设计

推荐在控制面 SQLite 中新增两张表:

6.1 import_runs

id TEXT PRIMARY KEY
mode TEXT NOT NULL
access_mode TEXT NOT NULL
state TEXT NOT NULL
total_items INTEGER NOT NULL
completed_items INTEGER NOT NULL
active_items INTEGER NOT NULL
degraded_items INTEGER NOT NULL
broken_items INTEGER NOT NULL
started_at DATETIME NOT NULL
updated_at DATETIME NOT NULL
finished_at DATETIME NULL

索引:

  • idx_import_runs_started_at
  • idx_import_runs_state

6.2 import_run_items

id TEXT PRIMARY KEY
run_id TEXT NOT NULL
base_url TEXT NOT NULL
provider_id TEXT NOT NULL
current_stage TEXT NOT NULL
stage_status TEXT NOT NULL
requested_models_json TEXT NOT NULL
raw_models_json TEXT NOT NULL
normalized_models_json TEXT NOT NULL
resolved_smoke_model TEXT NOT NULL
capability_profile_json TEXT NOT NULL
channel_id INTEGER NULL
account_id INTEGER NULL
confirmation_status TEXT NOT NULL
access_status TEXT NOT NULL
retry_count INTEGER NOT NULL
advisory_messages_json TEXT NOT NULL
last_error_stage TEXT NULL
last_error TEXT NULL
created_at DATETIME NOT NULL
updated_at DATETIME NOT NULL

索引:

  • idx_import_run_items_run_id
  • idx_import_run_items_provider_id
  • idx_import_run_items_stage_status
  • idx_import_run_items_access_status

约束:

  • 所有页面和 API 只读这两张控制面表
  • 不直接读宿主数据库
  • 宿主状态变化要通过控制面自己的确认与验证结果回写

7. 稳定性机制

7.1 阶段落盘

每个 item 每完成一个阶段都立刻落盘:

  • probe 完成后写 discovered
  • provision 完成后写 provisioned
  • confirm 开始写 confirming
  • confirm/validate 结束后写 confirmed_*

这样做的价值:

  • 进程中断后不丢历史轨迹
  • 页面可以显示“卡在哪一阶段”
  • 后续如果支持 resume有阶段边界可用

7.2 Advisory 与 Blocking 分离

V2 必须显式区分:

  • blocking error
    • 真正阻止继续执行
  • advisory
    • 不阻止完成,但需要展示原因

典型 advisory

  • 第三方 upstream 首次 403 Forbidden probe race
  • 首次 503 no available accounts 但重试后恢复
  • /responses 不支持,但 /chat/completions 可用

7.3 Retry Policy

不是所有失败都重试。

建议策略:

错误类型 处理
401/403 unauthorized 不重试,直接失败
首次 403 probe race advisory等待异步确认再测
429 rate_limit 记录 warning可选限次重试
首次 503 no available accounts 短时重试
502/503 upstream unreachable 按策略有限重试

每次 retry 都必须写入:

  • retry_count
  • last_error_stage
  • last_error
  • 最近 retry 时间

7.4 Restart Safety

控制面重启后至少保证:

  • 历史 run 列表还能查看
  • 历史 item 详情还能查看
  • 若 run 在中途停止,页面能看到“最后停在什么阶段”

V2 第一阶段可以不做自动 resume但必须让“失败现场可见”。

8. 结果页设计

V2 最少提供两个页面:

  • /batch-import/runs
  • /batch-import/runs/{run_id}

8.1 批次列表页

页面目标:

  • 快速看最近有哪些导入批次
  • 快速判断哪一批成功、哪一批有 warning、哪一批失败

页面结构

页面标题Batch Import Runs

[筛选区]
- 状态筛选all / running / completed / warning / failed
- access_mode 筛选all / subscription / self_service
- 时间范围
- 关键字搜索run_id / provider_id / base_url

[列表表格]
- Run ID
- Started At
- Finished At
- Mode
- Access Mode
- Total
- Active
- Degraded
- Broken
- State
- Actions

字段布局

说明
Run ID 可点击进入详情
Started At 开始时间
Finished At 完成时间,运行中为空
Mode strict / partial
Access Mode subscription / self_service
Total item 总数
Active 绿色数值
Degraded 黄色数值
Broken 红色数值
State run 总状态 badge
Actions 查看详情

状态表现

  • running:蓝色 badge
  • completed:绿色 badge
  • completed_with_warnings:黄色 badge
  • failed:红色 badge
  • cancelled:灰色 badge

8.2 批次详情页

页面目标:

  • 快速回答“这批次具体哪条 URL 出了什么问题”
  • 能看到模型纠错、compatibility、warning 和 retry 轨迹

页面结构

页面标题Batch Import Run Detail

[头部摘要卡]
- Run ID
- State
- Started At / Finished At
- Mode / Access Mode
- Total / Active / Degraded / Broken

[Item 列表表格]
- Item ID
- Base URL
- Provider ID
- Requested Models
- Resolved Smoke Model
- Current Stage
- Confirmation Status
- Access Status
- Retry Count
- Last Error Stage
- Last Error
- Actions

[点击某个 Item 后展开侧栏/详情区]
- URL 与 provider 基础信息
- 模型纠错结果
- capability profile 摘要
- channel/account 资源绑定
- advisory messages
- retry timeline
- 原始错误与最终结论

Item 表格字段

说明
Item ID 单条记录标识
Base URL 当前 upstream
Provider ID 自动生成 provider
Requested Models 人工输入
Resolved Smoke Model 最终 smoke 模型
Current Stage probe/provision/confirm/validate/done
Confirmation Status confirmed_active/warning/broken
Access Status active/degraded/broken
Retry Count 已重试次数
Last Error Stage 最近错误阶段
Last Error 最近错误摘要

Item 详情区字段

  1. 基础信息

    • base_url
    • provider_id
    • channel_id
    • account_id
  2. 模型信息

    • requested_models
    • raw_models
    • normalized_models
    • resolved_smoke_model
    • recommended_models(如果发生纠错)
  3. 兼容能力摘要

    • supports_openai_models
    • supports_openai_chat_completions
    • supports_openai_responses
    • supports_anthropic_messages
    • model_id_style
    • known_advisories
  4. 确认与访问结果

    • confirmation_status
    • probe_ok
    • access_status
    • retry_count
    • last_error_stage
    • last_error
  5. 说明区

    • warning 为什么是 warning
    • broken 为什么是 broken
    • 这个 item 是否建议人工介入

8.3 页面交互原则

  • 默认先显示摘要,不先展示原始 JSON
  • 详情区优先显示“结论”和“原因”
  • 原始 capability profile / 模型列表可以折叠查看
  • warning 要能解释成一句人能读懂的话

示例:

  • responses_unsupported_but_chat_ok

    • 页面说明:该上游不支持 /v1/responses系统已自动回退到 /v1/chat/completions
  • initial_probe_race_expected

    • 页面说明:账号创建后宿主异步探测尚未稳定,首次 /test 结果已按 advisory 处理

9. API 设计

9.1 列表 API

GET /api/batch-import/runs

返回结构:

{
  "runs": [
    {
      "run_id": "batch-20260522-001",
      "state": "completed_with_warnings",
      "mode": "partial",
      "access_mode": "subscription",
      "total_items": 12,
      "active_items": 9,
      "degraded_items": 2,
      "broken_items": 1,
      "started_at": "2026-05-22T10:00:00+08:00",
      "finished_at": "2026-05-22T10:02:12+08:00"
    }
  ]
}

9.2 详情 API

GET /api/batch-import/runs/{run_id}

返回:

  • run summary
  • count summary
  • recent warnings

9.3 Item 列表 API

GET /api/batch-import/runs/{run_id}/items

支持筛选:

  • stage_status
  • access_status
  • provider_id
  • has_warning

9.4 Item 详情 API

GET /api/batch-import/runs/{run_id}/items/{item_id}

返回:

  • item 全量详情
  • capability profile
  • advisory
  • retry trail

10. 后端模块映射

建议模块划分:

internal/batch/run_state.go

职责:

  • run / item 状态仓储接口
  • run summary 聚合
  • 状态投影基础函数

internal/batch/status_projection.go

职责:

  • 将底层字段转换成页面友好的摘要
  • 统一 warning 文案
  • 统一 badge / state 映射

internal/app/http_batch_import.go

职责:

  • run 列表 API
  • run 详情 API
  • item 列表 API
  • item 详情 API

internal/app/http_batch_runs.go

职责:

  • 渲染最小结果页
  • 不关心 probe/provision 细节
  • 只依赖 projection 层输出

11. 页面草图

11.1 列表页草图

+----------------------------------------------------------------------------------+
| Batch Import Runs                                                               |
+----------------------------------------------------------------------------------+
| Status: [all v]  Access Mode: [all v]  Search: [__________________________]     |
+----------------------------------------------------------------------------------+
| Run ID             | State    | Total | Active | Degraded | Broken | Started At |
| batch-20260522-001 | warning  | 12    | 9      | 2        | 1      | 10:00:00   |
| batch-20260522-002 | running  | 4     | 1      | 0        | 0      | 10:05:13   |
+----------------------------------------------------------------------------------+

11.2 详情页草图

+----------------------------------------------------------------------------------+
| Batch Import Run: batch-20260522-001                                            |
+----------------------------------------------------------------------------------+
| State: completed_with_warnings   Mode: partial   Access: subscription           |
| Total: 12   Active: 9   Degraded: 2   Broken: 1                                 |
+----------------------------------------------------------------------------------+
| Items                                                                            |
+----------------------------------------------------------------------------------+
| URL                  | Provider   | Stage   | Confirm   | Access   | Retry | ... |
| api.deepseek.com     | deepseek   | done    | warning   | active   | 1     | ... |
| api.53hk.cn/v1       | minimax    | done    | active    | active   | 0     | ... |
+----------------------------------------------------------------------------------+
| Selected Item Detail                                                             |
+----------------------------------------------------------------------------------+
| Requested Models: [minimax-m27-highspeed]                                        |
| Resolved Smoke Model: MiniMax-M2.7-highspeed                                     |
| Capability: responses=false, chat=true, messages=false                           |
| Advisory: 首次 /test 403 已按异步 probe race 处理                               |
| Last Error Stage: confirm                                                        |
| Last Error: API returned 403: Forbidden                                          |
+----------------------------------------------------------------------------------+

12. 实施建议

按最小可落地顺序做:

  1. 先实现 run_state 表与 repo
  2. 再让 batch service 在每阶段写入状态
  3. 再做 API
  4. 最后做最小页面

不要先做页面再补状态库。否则页面会重新依赖日志和运行态对象,后面还得推倒重来。

13. 验收标准

这份架构落地后,至少应满足:

  1. 导入过程中可以查询到 run 和 item 状态
  2. 导入完成后可以通过页面复盘每个 item 的结果
  3. 页面可以看出模型纠错是否发生
  4. 页面可以看出 capability profile 的关键摘要
  5. warning 和 broken 有可读解释
  6. 控制面重启后,历史结果仍可查看
  7. 页面和 API 只依赖控制面状态库,不依赖宿主数据库