HydroPilot

架构

架构

这一页从当前实现视角介绍 HydroPilot 的架构。

两条主链路

HydroPilot 有两条彼此关联但职责不同的链路:

  • 配置链路:YAML 配置 -> 校验与模板展开 -> RunConfig
  • 运行链路:SimModel -> Session -> Workspace -> Executor -> 执行服务 -> 结果汇报

配置链路负责把用户输入转换成可执行的运行配置。运行链路负责利用这份配置完成模型执行、结果提取、指标评估和归档保存。

配置链路

从整体上看,配置准备过程大致是这样:

text
YAML
  -> prepare_config()
  -> 可选的模板展开
  -> 通用配置校验
  -> RunConfig.from_raw()
  -> load_config()

这里有几个关键点:

  • version: general 表示 YAML 已经直接描述了运行时配置。
  • version: swatversion: swatplusversion: xaj 这类模板模式,会先展开为通用运行配置再执行。
  • 校验是在展开后的配置上完成的,所以模型模板层面的错误可以尽早暴露。
  • 运行时加载成功后,HydroPilot 可以把解析后的 _general.yaml 输出到源配置旁边,便于检查。

这条链路同时服务命令行校验和 Python 运行时。区别只在于:命令行会把失败转换成用户可读的诊断信息,而 Python 接口会直接抛异常。

主要模块

面向运行时的核心模块可以概括为:

  • api:公开入口,例如 SimModel
  • cli:命令行接口
  • config:配置加载、路径解析和 schema 转换
  • evaluation:目标、约束、诊断项和派生值计算
  • io:运行器、reader 和 writer
  • models:模板注册和模型专属逻辑
  • params:参数空间和参数写入
  • reporting:归档输出和运行产物
  • runtime:session 与 workspace 生命周期
  • series:模拟值和观测值的提取规划
  • validation:面向用户的配置诊断

运行链路

运行时路径从 SimModel 开始,然后委托给一组编排组件:

text
SimModel
  -> Session
  -> Workspace
  -> Executor
     -> ExecutionServices
        -> ParamSpace
        -> ParamWritePlan
        -> ParamApplier
        -> SeriesPlan
        -> ObsStore
        -> SubprocessRunner
        -> SeriesExtractor
        -> Evaluator
  -> RunReporter

各层职责比较清晰:

  • SimModel:面向 Python 用户的公开入口
  • Session:负责一次运行时实例的生命周期和清理
  • Workspace:负责创建隔离工作目录并管理可复用的模型副本
  • Executor:负责顺序或并行执行评估任务
  • ExecutionServices:从 RunConfig 组装实际运行所需的依赖
  • RunReporter:负责归档结果、摘要和运行产物

Workspace 与执行过程

HydroPilot 会在 basic.workPath 下创建隔离的工作目录。对于每次评估,它大致会按下面的顺序工作:

  1. 创建或获取一个准备好的工程副本
  2. 将设计变量转换成物理参数
  3. 把参数写入模型输入文件
  4. 执行配置中的模型命令
  5. 提取模拟输出和观测切片
  6. 计算目标、约束和诊断项
  7. 归档结果并释放实例

默认情况下,instance_* 这类临时目录会在 session 关闭时清理掉。如果打开 basic.keepInstances: true,这些目录会被保留下来,方便调试。

为什么模板很重要

模板是 HydroPilot 架构里的关键优势之一。它让用户可以直接使用 SWAT 参数、XAJ CSV 映射这类模型层概念,而不必手写所有底层 reader 和 writer。

从工程上看,这意味着:

  • 模型专属知识被收敛在模板层
  • 运行时始终执行统一的通用配置
  • 命令行、Python 接口和 UQPyL 集成都共用同一套执行基础

这套拆分的意义

正是这种拆分,使 HydroPilot 能作为稳定的工程执行层:

  • 配置保持声明式
  • 模型专属细节收敛在模板与 I/O 处理层
  • 运行编排可以同时服务命令行、Python 接口和 UQPyL 集成

建议继续阅读