---
title: Document
status: active
audience: Developers
last-updated: 2026-10-22
owner: Docs Owner
---

# 配置编写指南（Configuration）

- Status: active
- Audience: Users / Developers
- Last-Updated: 2026-10-12

## 1. 目的与范围

本页说明“如何写配置、如何组织路径、如何最小化配置”。全量字段字典与校验规则请以 Reference 为准：

- `API Reference`（Sphinx 生成的配置字段文档）
- `../reference/validation.md`

## 2. 相关方

- 使用者：编写配置并运行工作流
- 开发者：维护配置模型、路径解析与默认值
- 平台维护：提供 Slurm 队列/环境初始化建议

## 3. 路径解析规则（强烈建议使用相对路径）

### 3.0 数据集格式边界

- 受支持的数据集输入：`deepmd/npy`、`deepmd/npy/mixed`、`deepmd/lmdb`（需要 `dpdata>=1.1`）。
- LMDB 输入由 dpdata 按**组成分组**读回；`frame_nlocs`/`frame_system_ids` 可用于
  `infer`/`analysis` 的逐帧明细归属。Clean 在这些元数据存在时按
  `frame_system_ids` 恢复原始 system 并导出；若元数据不足则 fail-loud，
  不使用 composition group 冒充原始 system。
- Feature 工作流的 `feature_exporter="eval_desc"`/`"embed"` 上游不支持 LMDB，DP-EVA 在
  提交作业前拒绝；请提供 npy/mixed 副本或使用进程内描述符生成。
- 完整支持矩阵与实测依据见 `docs/reference/upstream-software.md` §2.1。

### 3.1 规则

- 配置文件中推荐写相对路径，便于迁移与复现。
- CLI 会把显式路径字段按“配置文件所在目录”解析为绝对路径，包括 Collect 的 `project`。
- 例如 `configs/collect.json` 内的 `"project": "../work"` 指向与 `configs/` 同级的 `work/`，不受执行命令时的目录影响。
- 迁移说明：v0.8.2 中显式 `project` 曾遗漏路径解析而依赖 shell 当前目录。升级后，若旧配置依赖该行为，请把 `project` 改为相对于配置文件的路径，或使用绝对路径。省略该字段的默认值、直接传入 Python 配置对象的行为不变。

参考实现：`src/dpeva/utils/config.py` 的 `resolve_config_paths`。

### 3.2 常见路径字段

- `work_dir`：Train/Infer/Feature/Analysis 常用的工作目录
- `project`：Collect 常用的项目目录
- `data_path`：Feature/Infer 常用输入数据目录
- `savedir`：Feature 描述符输出目录
- `root_savedir`：Collect 输出目录

## 4. Submission 配置（Local / Slurm）

从文件读取配置时，CLI 先执行一次显式兼容迁移，再进行严格配置校验。新配置应始终使用嵌套的 `submission` 对象；旧版顶层 `backend`、`env_setup`、`slurm_config`、`slurm_array` 和 `slurm_array_task_limit` 会被移动到该对象，并输出包含替代字段和退役目标版本的 warning。若新旧写法同时出现且值不同，迁移会直接失败。

迁移在内存副本上进行，用户提供的源 JSON 不会被覆盖。规范化配置会在后续 run manifest 中单独记录。所有公开配置模型均拒绝未知字段，因此拼写错误必须在提交前修正；迁移只接受有明确映射的旧字段，不会吞掉任意扩展字段。

Python API 同样在 `BaseWorkflowConfig` 的公开模型边界执行这次迁移，因此直接调用
`InferenceConfig.model_validate(...)`、`FeatureConfig.model_validate(...)` 或其他工作流模型时，
仍可读取上述旧字段；输入 mapping 不会被修改。`AnalysisConfig` 也支持该兼容边界。
`ExplorationConfig.backend` 是探索后端自己的原生字段（例如 `atst-tools`），不会被解释为
submission backend。未知字段与新旧字段冲突仍然严格失败。

### 4.1 Local 最小配置

```json
{
  "submission": {
    "backend": "local"
  }
}
```

### 4.2 Slurm 最小配置

```json
{
  "submission": {
    "backend": "slurm",
    "env_setup": [
      "source /path/to/env.sh"
    ],
    "slurm_array": false,
    "slurm_config": {
      "nodes": 1,
      "ntasks": 1,
      "walltime": "00:30:00"
    }
  }
}
```

常用扩展字段：`partition/qos/gpus_per_node/cpus_per_task/account`。

### 4.0 运行身份与证据

`feature` 与 `infer` 的 CLI 运行会在工作目录生成
`.dpeva/runs/<run-id>/run.json`，并保存单次读取的原始配置与规范化配置快照。
每个新建的 schema `1.0` 运行都会写入 `config.metadata.json`，记录输入 schema `1.0`
与迁移 warning（无 warning 时为空列表），并由清单的 `config.metadata` 相对引用指向它；
迁移前的 legacy 清单可能没有该引用，resume 时仅接受隐含的默认 metadata。使用 `--run-id` 可固定身份；已有
身份默认拒绝覆盖。`--resume` 要求原配置、输入与运行代码证据一致，且原运行未终结、
未处于 `submitted` 状态；`failed`、`finished`、`submitted` 均拒绝 resume。
需要创建新尝试时使用 `--run-id ID --force --reason "说明"`，先确保旧进程或作业不再运行。
这些选项仅适用于 Feature/Infer，不表示训练 checkpoint 续训或自动跳过成功子任务。
运行清单中的 `finished`
只表示本地命令成功，且输出文件非空、属于当前 attempt 的新建或可观察重写并已校验；
目录中未被本次执行改写的历史文件不能让 no-op 命令成功，也不会作为本 attempt 的新产物登记。
该 freshness 判定使用 device/inode/size/mtime_ns/ctime_ns 元数据，不会在执行前读取或散列全部历史大型数组；
相同字节只要在本 attempt 中被正常重写仍是有效产物。Slurm 仅记录 `submitted`。
多 pool feature 输出会逐 pool 校验：`eval-desc` 要求每个 pool 至少有一个非空
`.npy`，`embed` 要求每个 pool 有非空 `embedding.hdf5`。
Slurm 多模型 infer 若仅部分 JobID 提交成功，父清单保持 `submitted` 并保留失败子记录，
但命令以退出码 `1` 返回；全部提交失败才记为 `failed`。
清单 `source` 记录 DP-EVA 包版本，并在 git 信息可观察时记录 commit、dirty 状态与稳定
dirty fingerprint（dirty 元数据也限定 runtime scope，并复用 runtime 内容摘要）。
Git 查询在枚举前排除 scope 外路径及任意深度的 `.dpeva`，不读取无关文档、数据集或日志内容。
新清单还记录版本化的
`runtime_fingerprint` 及其 scope：`src/dpeva` 与 `pyproject.toml` 的 tracked 内容、删除和
symlink，以及 `src/dpeva` 下未追踪的 Python runtime 文件；文档、数据集、日志和任意
`.dpeva` 内容不在 scope 内。resume 使用该 scoped fingerprint：只改文档的 commit 不会
改变 runtime identity，已提交或未提交的 runtime 修改会拒绝 resume；没有 scoped fingerprint
的 legacy 清单不会被重新解释为匹配。模型输入使用流式 SHA-256，数据集目录使用明确标注的有界 structural identity，路径只
使用相对/逻辑引用。实际生成的日志文件存在且非空时才会登记为 `log` artifact，不会
凭空创建日志记录。

Inference 在没有 `model_ref_paths` 时兼容旧的数字目录布局，但默认每个目录只选择
`model.ckpt.pt` regular checkpoint，不会隐式把 `model_ema.ckpt.pt` 加入 ensemble。需要
执行 EMA 时，为该文件提供显式 model-reference JSON，并设置 `"role": "ema"`；显式
references 可以在同一个 ensemble 中同时列出 regular 与 EMA。工作目录外的模型引用使用
basename 加内容 SHA-256 组成逻辑 ref，不把绝对路径写入 run identity。

训练脚本的完成 guard 按 backend 校验可证明的实际产物：`pt` 使用稳定 regular checkpoint
（默认 `model.ckpt.pt`，避免猜测依模型而变的 `.pth`/`.pt2` freeze 后缀），`tf` 使用
`frozen_model.pb`，`pt-expt` 使用 `frozen_model.pte`，`jax` 使用 `frozen_model.hlo`，`pd`
同时要求 `frozen_model.json` 与 `frozen_model.pdiparams`。`training.save_ckpt` 和
`training.disp_file` 的自定义路径会进入对应 guard；当 `disp_training=false` 时上游不会保证
曲线文件非空，因此完成 guard 只要求 backend 产物。原有输出布局保持不变。

支持 Slurm array 的 workflow 可设置：

- `slurm_array=true`：将同质任务合并为 Slurm array，而不是逐个 `sbatch`。
- `slurm_array_task_limit`：可选 array 并发上限，渲染为 `--array=0-N%limit`；必须为正整数。

Labeling 启用 `labeling_task_classes` 时，array 会按 task class 分组提交，每个 class 一个 array job。class 名会经过 Slurm job name 规范化，用于 `#SBATCH -J` 与 `<work_dir>/array_jobs/<class>_<attempt>/`。

## 5. 各 Workflow 最小配置示例

以下示例用于“快速跑通”，完整字段见 Reference。

### 5.1 Feature

```json
{
  "work_dir": "./",
  "data_path": "./other_dpdata_all",
  "model_path": "./DPA-3.1-3M.pt",
  "savedir": "./desc_pool",
  "mode": "cli",
  "submission": { "backend": "slurm" }
}
```

DPA4C 模型使用 DeepMD 的 exportable PyTorch backend。用于 DIRECT 采样的
descriptor 可通过 `dp --pt-expt eval-desc` 提取，单任务模型无需设置 head：

```json
{
  "work_dir": "./",
  "data_path": "./candidate_dpdata",
  "model_path": "./dpa4c_model.pt",
  "savedir": "./dpa4c_descriptors",
  "model_head": null,
  "dp_backend": "pt-expt",
  "mode": "cli",
  "feature_exporter": "eval_desc",
  "feature_kind": "descriptor",
  "submission": { "backend": "local" }
}
```

正式的 DPA4C 支持走 DeepMD-kit 3.2 兼容性通道。用户运行时可安装
`dpeva[deepmd]`，其依赖范围为 `deepmd-kit>=3.2,<3.3`；该范围内的版本不应被
视为行为完全等价。研究生产环境必须单独锁定 `deepmd-kit==3.2.0`，并记录
`dp --version`，不能用范围依赖代替精确锁定。当前 `pt-expt`
backend 提供 descriptor 提取，但尚未提供 `dp embed` 所需的组合
`eval_embedding` 接口，因此这一路径应使用 `eval_desc`。

当前 DeepMD 3.2 兼容性通道已有 4 条 `supported` 能力：DPA4
pt test/eval-desc/embed，以及 `test + deepmd/lmdb`。三条 npy 声明同时
绑定 CPU contract JobID `1128442` 和完成的 SAI V100 qualification JobID
`1128260`；脱敏 SAI promotion aggregate 与三个 CPU attestation 位于
`docs/reports/evidence/deepmd-3.2/`。LMDB `test` 另绑定 CPU JobID `1893534`
和 SAI npy↔lmdb A/B JobID `1893546`；LMDB `train` 另有 CPU contract 与
SAI 200-step execution A/B JobID `1893783`，但训练曲线随机性不足以作格式
等价声明，因此仍为 experimental。证据只证明选定 regular 模型、regular+EMA
V100 命令链完成，不构成科学精度或所有下游 head 的支持声明。一次
`pt-expt eval-desc` 虽然执行成功，但事后 descriptor inspection 证明所用 artifact
实际为 DPA4 而非 DPA4C；因此周期性 DPA4C 路线仍为 experimental，不能因命令
成功而晋级。其余能力状态以 capability manifest 和报告为准。

V100 aggregate 中六条 retained attestation 分别覆盖 DPA4 regular/EMA 的
`pt test`、`pt eval-desc` 和 `pt embed`；它们是历史资格证据，不会因 v0.8.2
打包而重新执行或扩大声明。

DeepMD PyTorch 模型可使用 `dp embed` 导出 HDF5 embedding。该路线会在 `savedir/embedding.hdf5` 中保留 `descriptor`、`atomic_feature`、`structural_feature` 和 `atom_types`；HDF5 dataset 由 DeepMD 使用 gzip + shuffle 压缩。`feature_kind="descriptor"` 读取 `descriptor`，`feature_kind="fitting_last_layer"` 对应 `atomic_feature`。

```json
{
  "work_dir": "./",
  "data_path": "./other_dpdata_all",
  "model_path": "./DPA4-Plus-OMat24-16M.pt",
  "savedir": "./desc_pool_embed",
  "model_head": "OC22",
  "mode": "cli",
  "feature_exporter": "embed",
  "feature_kind": "fitting_last_layer",
  "embedding_dtype": "fp32",
  "submission": { "backend": "slurm" }
}
```

兼容规则：

- 默认 `feature_exporter="eval_desc"`，仍调用 `dp eval-desc` 并生成旧 `.npy` descriptor。
- `feature_exporter="embed"` 支持 `feature_kind="descriptor"` 和 `feature_kind="fitting_last_layer"`。
- Collect 的 `desc_dir`、`training_desc_dir`、LLPR feature 目录既可以指向旧 `.npy` 目录，也可以指向 `embedding.hdf5` 文件或包含该文件的目录。
- Collect 默认把 `desc_dir` 与 `training_desc_dir` 当作 descriptor 读取；若这些目录来自 `feature_kind="fitting_last_layer"` 的 HDF5 embed 输出，需设置 `desc_feature_kind="fitting_last_layer"`，此时读取 HDF5 `atomic_feature`。

### 5.2 Train

```json
{
  "work_dir": "./",
  "input_json_path": "input.json",
  "training_data_path": "./sampled_dpdata",
  "base_model_path": "DPA-3.1-3M.pt",
  "num_models": 3,
  "training_mode": "init",
  "allow_experimental": false,
  "submission": { "backend": "slurm" }
}
```

`allow_experimental=true` 是显式实验能力开关。当前它用于允许
`deepmd/lmdb` 训练/fine-tune 输入；默认 `false` 时，LMDB 训练会在生成任务前
按 capability matrix 失败。preflight 使用与训练 manager 相同的路径解析
（相对路径按 input JSON 所在目录解析），且对 manifest 中未注册的
backend/模型族保持 fail-closed，不会因为查不到记录而放行。capability key 中的
`environment` 是契约测试环境（训练记录统一为 `cpu`），不是硬件资格；LMDB
fine-tune 仍是 experimental，Slurm/GPU 执行同样需要该显式开关。
该开关不放宽 `eval-desc`/`embed` 的上游限制。

### 5.3 Infer

```json
{
  "work_dir": "./",
  "data_path": "./other_dpdata_all",
  "task_name": "test_val",
  "results_prefix": "results",
  "auto_analysis": false,
  "submission": { "backend": "slurm" }
}
```

### 5.4 Collect

```json
{
  "project": "./",
  "desc_dir": "./desc_pool",
  "desc_feature_kind": "descriptor",
  "testdata_dir": "./other_dpdata_all",
  "testing_dir": "test_val",
  "results_prefix": "results",
  "root_savedir": "dpeva_uq_result",
  "sampler_type": "direct",
  "direct_n_clusters": 20,
  "direct_k": 1,
  "submission": { "backend": "slurm" }
}
```

当候选描述符来自 `dpeva feature` 的 `feature_exporter="embed"` 且 `feature_kind="fitting_last_layer"` 时，将 `desc_dir` 指向 HDF5 输出目录并设置：

```json
{
  "desc_dir": "./desc_pool_embed",
  "desc_feature_kind": "fitting_last_layer"
}
```

LLPR / energy DPOSE 可作为 Collect UQ backend 使用。最小 energy LLPR 只需要训练集与候选集 last-layer feature 目录；请求 shallow ensemble 时必须提供真实最后一层权重和候选 base energy，默认 strict parity 不会用 synthetic weights 冒充 DPOSE：

```json
{
  "uq_backend": "llpr",
  "llpr_train_feature_dir": "./train_last_layer",
  "llpr_candidate_feature_dir": "./candidate_last_layer",
  "llpr_feature_normalization": "mean",
  "llpr_num_ensemble_members": 8,
  "llpr_last_layer_weights_path": "./last_layer_weights.npy",
  "llpr_candidate_energy_path": "./candidate_energy.npy",
  "llpr_collect_score": "energy_ensemble_std_per_atom"
}
```

可选字段：

- `llpr_model_path` / `llpr_model_head`：未显式提供 `llpr_last_layer_weights_path` 时，从 PyTorch checkpoint/state_dict 按 feature dimension 解析 energy fitting last linear weight。
- `llpr_state_path` / `llpr_save_state_path`：复用或保存 LLPR covariance/Cholesky/alpha 状态。
- `llpr_ensemble_output_path`：自定义 `energy_ensemble.npy` 输出路径；未设置时写到 Collect 输出根目录下。
- `llpr_collect_score`：支持 `energy_uncertainty_per_atom`（默认）、`energy_ensemble_std_per_atom`、`force_uncertainty_max`。当前 detached feature workflow 只支持 energy；force DPOSE 仍需要可微 DeepMD PyTorch graph adapter。

### 5.5 Label integration

标注工作流启用数据整合时，可使用以下字段控制合并输出：

```json
{
  "integration_enabled": true,
  "integration_deduplicate": true,
  "integration_output_format": "deepmd/npy/mixed"
}
```

`output_format`（cleaned/anomalies）和 `integration_output_format`（merged）均支持
`deepmd/npy`、`deepmd/npy/mixed`、`deepmd/lmdb`；默认值不变。选择
`deepmd/lmdb` 时，数据写入对应输出目录下的 `dataset.lmdb`，manifest/summary
仍保留在同一目录。该写出使用 WP-4A 的显式 writer，并在发布前校验 frame/system
身份；不会把 LMDB 自动设为默认格式。

整合成功后，在 `merged_training_data_path` 下同时生成
`integration_summary.json`、当前代兼容指针 `dataset-manifest.json` 和不可变的
`dataset-manifest-<generation>.json`。summary 的 `dataset_manifest_path` 是相对于
输出目录的不可变清单引用，并同时记录 generation 与 SHA-256。清单只记录
`existing-training`、`new-labeled` 等逻辑来源，不固化机器绝对路径，并记录父集合帧数、
去重移除帧数、最终帧/体系数、canonical type map 以及导出文件 SHA-256 的证据强度。
当前整合仅保留 `existing-training` / `new-labeled` 逻辑来源标签，不生成无法解析的
parent manifest ref；待父清单随 bundle 一并固化后再扩展该引用。
未声明来源、未解释的重复/交集或 type map 冲突会在导出和下游交接前失败；显式去重会在清单中保存 overlap/removal evidence 与 `validation_result`（含 rule version）。`intersection_summary.method` 使用 `frame-identity-v1` 表示逐帧交集（必须 overlap=removed），使用 `filter-v1` 表示无交集的一般过滤；零移除使用 `not-run`。
发布目标使用进程可见的不覆盖语义：同文件系统的 sibling staging 目录通过
`renameat2(RENAME_NOREPLACE)` 原子发布，竞争目标不会被覆盖；不支持该原语的平台直接
fail-closed，不使用普通 rename 回退。该契约不声称 crash 后的目录持久化或递归 fsync
dpdata 树；JSON 文件写入可能进行文件级 flush，不能外推为整个 bundle 的 durability 保证。

### 5.6 Analysis

```json
{
  "mode": "model_test",
  "result_dir": "0/test_val",
  "results_prefix": "results",
  "data_path": "sampled_dpdata",
  "output_dir": "analysis",
  "type_map": ["Fe", "C", "O", "H"],
  "enable_cohesive_energy": true,
  "allow_ref_energy_lstsq_completion": false,
  "enhanced_parity_renderer": "auto"
}
```

Analysis 相关建议：

- Inference 若自定义了 `results_prefix`，Analysis 的 `results_prefix` 必须保持一致。
- `model_test` 模式下若需要 Cohesive Energy，请优先提供 `data_path` 指向与 `result_dir` 对应的原始数据集，以避免仅靠文件名推断组分失败。
- `enable_cohesive_energy` 控制是否启用 Cohesive Energy 统计与作图。
- `allow_ref_energy_lstsq_completion` 控制当 `ref_energies` 不完整时是否允许最小二乘补全缺失元素参考能。
- `enhanced_parity_renderer` 控制 enhanced parity 主图区渲染入口：
  - `auto`：沿用 quantity-aware 默认策略，energy/cohesive 使用 scatter，force/virial 使用 hexbin。
  - `scatter`：强制 enhanced parity 主图区全部使用 scatter。
  - `hexbin`：强制 enhanced parity 主图区全部使用 hexbin。
- `dataset` 模式若希望输出 Cohesive Energy 图，可将 `"enable_cohesive_energy": true` 并提供合理 `ref_energies`（或开启 `allow_ref_energy_lstsq_completion`）。
- 新增图谱会额外输出：
  - `dist_<quantity>_overlay.png`（Pred/True 叠加分布）
  - `dist_<quantity>_with_error.png`（主分布 + 小幅 error 分布）
  - `parity_<quantity>_enhanced.png`（含边缘分布的增强 parity）
- 图中统计信息默认仅显示 `count/mean/std/min/max`，不再显示分位数。
- `Error Distribution` 与 `parity_*_enhanced.png` 默认不显示统计信息框。
- 单变量分布图默认不显示 `All Data` 图例；dataset 元素占比/存在性使用多色饼图。
- quantity-aware 默认下，Force / Virial 的 hexbin enhanced parity 会在右侧信息栏同时展示 Error Density 与 colorbar，colorbar 表示每个 hexbin 中样本数量。

### 5.7 Labeling

```json
{
  "input_data_path": "./candidate_dpdata",
  "work_dir": "./labeling_work",
  "pp_dir": "./abacus_pp",
  "orb_dir": "./abacus_orb",
  "pp_map": { "Fe": "Fe.upf", "C": "C.upf", "O": "O.upf", "H": "H.upf" },
  "orb_map": { "Fe": "Fe.orb", "C": "C.orb", "O": "O.orb", "H": "H.orb" },
  "submission": { "backend": "slurm" }
}
```

SAI 上的 ABACUS labeling 如需同时处理普通单卡任务与 highmem/multicard 任务，应使用 `labeling_task_classes` 显式拆分 launcher/resource mode：

```json
{
  "submission": {
    "backend": "slurm",
    "env_setup": ["module load abacus/LTSv3.10.1-sm70-auto"],
    "slurm_array": true,
    "slurm_array_task_limit": 64,
    "slurm_config": {
      "partition": "4V100",
      "qos": "flood-1o2gpu",
      "walltime": "02:00:00"
    }
  },
  "tasks_per_job": 1,
  "labeling_task_classes": [
    {
      "name": "normal",
      "selector": { "max_atoms": 180 },
      "tasks_per_job": 1,
      "launcher_mode": "abacus",
      "resource_mode": "single_gpu",
      "slurm_config": {
        "ntasks": 1,
        "gpus_per_node": 1,
        "qos": "flood-1o2gpu"
      }
    },
    {
      "name": "highmem",
      "selector": { "min_atoms": 181 },
      "tasks_per_job": 1,
      "launcher_mode": "mpi_abacus",
      "resource_mode": "multi_gpu_mpi",
      "slurm_config": {
        "ntasks": 4,
        "gpus_per_node": 4,
        "qos": "flood-gpu"
      }
    }
  ]
}
```

- `launcher_mode="abacus"`：runner 直接执行 `abacus`，并强制该 class 的 Slurm resources 为 `ntasks=1,gpus_per_node=1`；不会 source SAI rank-map。
- `launcher_mode="mpi_abacus"`：runner 执行 `mpirun -np $SLURM_NTASKS --map-by $MAP_OPT -mca coll_hcoll_enable 0 abacus`，并自动补充 SAI rank-map source。
- 没有配置 `labeling_task_classes` 时，DP-EVA 保持旧的单一 `submission` 行为，兼容既有配置。
- SAI-1344 `16V100` 实测不接受 `flood-gpu`/`rush-gpu` 的 1GPU 请求（`QOSMinGRES`）。FP11 类似批量任务应使用 4GPU MPI fallback；若 `rush-gpu` array 命中 `QOSMaxSubmitJobPerUserLimit`，应改用 `flood-gpu` 完成批量提交。

### 5.8 Exploration

```json
{
  "work_dir": "./explore_work",
  "backend": "atst-tools",
  "workflow_type": "md",
  "backend_config_path": "./atst_md.yaml",
  "result_structure_paths": ["./explore_work/result.extxyz"]
}
```

Exploration 是可选能力。使用 `backend: "atst-tools"` 前需安装 `dpeva[explore]`，首版仅支持 `workflow_type` 为 `md` 或 `relax`。`backend_config_path` 保持后端原生格式，DPEVA 不重写 ATST YAML。

运行完成后，DPEVA 会在 `work_dir/dpeva_exploration_result.json` 写入标准 manifest。若配置了 `input_structure_paths`，这些结构会作为可追溯输入快照写入 `work_dir/dpeva_inputs/`；若配置了 `result_structure_paths`，这些路径必须在 backend 成功后存在并可由 ASE 读取。

## 6. 异常处理

- 配置校验失败：对照 `/docs/reference/validation.md` 的跨字段依赖与范围约束
- 输入路径不存在：检查相对路径是否以 config 所在目录为基准
- 历史字段不兼容：优先以 `sampler_type + direct_* / step*_*` 的新参数体系为准

## 7. 变更记录

- 2026-07-05：补充 `slurm_array` / `slurm_array_task_limit` 与 SAI-1344 FP11 4GPU MPI fallback 实测建议。
- 2026-07-04：补充 Labeling `labeling_task_classes`，明确 SAI ABACUS 单卡与 MPI 多卡 launcher/resource mode。
- 2026-06-12：补充 Collect LLPR / energy DPOSE ensemble 配置字段、状态复用和 strict parity 约束。
- 2026-06-11：补充 Exploration manifest、输入结构快照与结果结构校验契约。
- 2026-06-10：新增 Exploration 最小配置示例，明确 `atst-tools` 为可选 backend。
- 2026-03-30：Analysis 配置新增 `enhanced_parity_renderer`，并补充 quantity-aware parity 渲染策略说明。
- 2026-03-16：Analysis 最小配置增加 `data_path`、`enable_cohesive_energy`、`allow_ref_energy_lstsq_completion`，并补充 Cohesive Energy 配置建议。
- 2026-03-11：配置字段权威入口改为 API Reference，并补充 Labeling 最小配置示例。
- 2026-02-18：补齐路径解析、Submission 结构与最小配置示例。


## 替换入门示例中的模型与数据

入门 recipe 的用途是演示阶段连接。迁移到自己的体系时，按下表核对输入；字段的
完整定义仍以 Reference 为准。

| 变更 | 需要同步核对的配置 |
| --- | --- |
| 替换训练数据 | `training_data_path`、DeepMD 输入中的训练/验证数据设置、标签可用性与元素映射；重新选择训练步数、批量大小和损失参数 |
| 替换候选池 | Feature 的 `data_path`、Infer 的 `data_path`、Collect 的 `testdata_dir` 指向同一批数据；新描述符和推理结果必须来自这批数据 |
| 替换预训练模型 | Train 的 `base_model_path` 与配套 `input_json_path`；Feature 的 `model_path`；各阶段实际需要的 `model_head` 和 `dp_backend` |
| 更换模型家族或后端 | 训练模板中的 descriptor/fitting 配置、type map、统计输入、导出产物与下游操作支持范围；不能只替换模型路径 |

模型头不应机械统一：多任务基座需指定其实际存在的头，训练模式可能生成不同的
微调头，单任务或导出后的模型是否需要 head 应按模型和 backend 契约选择。
`training_mode="init"` 会为首个模型使用配置的头，其余模型采用 `RANDOM` 初始化；
它与从训练 checkpoint 恢复不是同一概念。

现有 DPA4 模板位于 `examples/recipes/training/dpa4/`。其中的数据、模型和统计输入
需要自行准备，Slurm 参数需按所在集群调整；这些模板不是自带数据的 Quickstart。
使用前阅读该目录 README 中链接的 DeepMD 兼容性报告，确认所需操作的支持范围。
更换模型或输入后使用新的工作目录，避免混用旧描述符、旧 ensemble 和新候选池。
