关于 complexa-sweep
complexa-sweep 是用于 Proteina-Complexa 设计流程的参数网格搜索技能。它生成推理与评估配置,运行 `complexa design`,再汇总排名并写出清单。
主要功能
- 01笛卡尔积参数搜索
- 02生成推理和评估配置
- 03通过 `complexa design` 运行配置
- 04汇总指标并排列配置
- 05识别帕累托前沿
- 06生成可重放清单
适用场景
- 01比较同一流程中的设计参数
- 02寻找成功率更高的配置
- 03权衡运行时间与成功率
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ nvidia-bionemo/ bionemo-agent-toolkit --skill complexa-sweep安装后在 Claude Code 中输入/complexa-sweep确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
skill-card.mdevals/evals.jsonreference/sweep_axes.mdSWEEP.md详细介绍
complexa-sweep
针对 Proteina-Complexa 设计流水线运行笛卡尔积参数扫描。选择或编写 configs/sweeps/ 中的扫描器 YAML,通过 script_utils/generate_inference_configs.py 将其展开为 N 个推理配置,然后对这些配置逐一运行 complexa design,最后将每个配置的成功指标汇总为排名摘要 CSV 和清单。
重要:
complexa designCLI 不直接接受--sweeper。扫描由script_utils/generate_inference_configs.py驱动,它会为每种扫描组合写入一个configs/inference_configs/inf_{idx}_{run_name}.yaml。然后对这些生成的配置逐一运行complexa design。
此技能支持的功能
- 从
configs/sweeps/中选择现有扫描器 YAML(beam_width、bb_ca_temperature、search_replicas、example)。 - 使用任意点号表示法的轴编写新的扫描器 YAML(笛卡尔积)。
- 使用
script_utils/generate_inference_configs.py生成 N 对推理和评估配置。 - 对生成的配置逐一运行
complexa design(在单个 GPU 上一次运行一个,或在多 GPU 主机上按CUDA_VISIBLE_DEVICES将配置列表分片并行运行)。 - 遍历每个配置的输出目录,并解析各目录中分析步骤生成的 CSV。
- 生成
sweep_summary.csv(每个配置一行:轴值 + 成功率 + 平均 iPAE + 多样性)和sweep_manifest.json。 - 根据成功率找出最佳配置,以及帕累托前沿(运行时长与成功率)。
步骤 1:准备工作
bash .claude/skills/_shared/scripts/preflight.sh
读取 ./complexa_setup/preflight.json。扫描会根据配置数量按比例增加 GPU 时间。启动前,请与用户确认成本:
“此扫描将生成 N 个配置,每个配置约需 M 分钟,总计约 TOTAL 个 GPU 小时。是否继续?(y / reduce / cancel)”
如果 gpu.available=false,则停止——CPU 无法执行扫描。
步骤 2:选择流水线和目标
使用与 complexa-design 相同的对话流程——此处不要重复说明。请参阅 .claude/skills/complexa-design/SKILL.md 的步骤 2(“选择流水线”)和步骤 3(“收集参数”)。记录以下内容:
pipeline_config_name— 例如search_binder_local_pipeline(默认值)、search_ligand_binder_local_pipeline、search_ame_local_pipeline。task_name— 例如02_PDL1、22_DerF21、39_7V11_LIGAND。作为--override generation.task_name=<task>传入。run_name— 用于输出目录命名的简短标签。
步骤 3:选择或编写扫描器 YAML
扫描器 YAML 位于 configs/sweeps/ 中。每个键都是点号表示法的 Hydra 路径;每个值都是一个列表。笛卡尔积会生成 N 个配置。
预置扫描器
| 文件 | 轴 | 值 | 配置数 |
|---|---|---|---|
configs/sweeps/beam_width.yaml | generation.search.beam_search.beam_width | 1、2、4、8 | 4 |
configs/sweeps/bb_ca_temperature.yaml | generation.model.bb_ca.simulation_step_params.sc_scale_noise | 0.1、0.4 | 2 |
configs/sweeps/search_replicas.yaml | generation.search.best_of_n.replicas | 1、4、16、64 | 4 |
configs/sweeps/example.yaml | beam_width × nsteps | (2、4) × (200、400) | 4 |
如果其中某个符合用户的需求,就直接使用。否则,编写一个新文件。
编写新的扫描器
多轴最简示例(保存到 configs/sweeps/my_sweep.yaml):
# 3 beam widths × 2 nsteps = 6 configs
generation.search.beam_search.beam_width:
- 2
- 4
- 8
generation.args.nsteps:
- 200
- 400
规则(来自 script_utils/generate_inference_configs.py:load_sweeper_file):
- 只接受顶层映射。键为点号表示法的 Hydra 路径。
- 值必须是列表。标量会自动包装为单元素列表(这会固定一个值,但不会增加维度)。
- 笛卡尔积:配置总数 = 各列表长度的乘积。两个各含 4 个值的轴会生成 16 个配置;请据此安排预算。
- 如果扫描器文件中的键也出现在
--override中,则以覆盖值为准,该轴会折叠为单一值。
完整的扫描键目录(包括典型范围、成本倍数以及哪些指标会提升或退化)请参阅 reference/sweep_axes.md。
生成前的试运行预览
始终先确认配置数量:
python script_utils/generate_inference_configs.py \
--config_name search_binder_local_pipeline \
--sweeper configs/sweeps/my_sweep.yaml \
--override generation.task_name=22_DerF21 \
--run_name my_sweep \
--dryrun
输出会列出每个轴及其取值列表,并打印 DRY RUN — would generate N config pair(s)。
第 4 步:生成配置并循环运行 complexa design
试运行结果看起来没问题后,移除 --dryrun,在 configs/inference_configs/ 和 configs/eval_configs/ 下生成 inf_{idx}_{run_name}.yaml + eval_{idx}_{run_name}.yaml 配对文件。然后遍历推理配置,循环运行 complexa design。
# 1. Generate one inf_*.yaml + one eval_*.yaml per combination.
python script_utils/generate_inference_configs.py \
--config_name search_binder_local_pipeline \
--sweeper configs/sweeps/my_sweep.yaml \
--override generation.task_name=22_DerF21 \
--run_name my_sweep
# 2. Loop complexa design over each generated inference config.
for cfg in configs/inference_configs/inf_*_my_sweep.yaml; do
complexa design "$cfg" || echo "FAILED: $cfg"
done
这会在单张 GPU 上串行执行参数扫描——请如实告知用户,实际耗时 = N × 单次运行耗时。
多 GPU 主机(可选加速)
在有 K 张 GPU 的主机上,将配置列表分成 K 份,并为每张 GPU 并行启动一个循环。每次 complexa design 调用在默认 gen_njobs=1 / eval_njobs=1 时恰好使用一张 GPU,因此通过 CUDA_VISIBLE_DEVICES 指定 GPU 可以避免任务相互冲突:
CONFIGS=(configs/inference_configs/inf_*_my_sweep.yaml)
N=${#CONFIGS[@]}; K=4 # 4 GPUs
for gpu in $(seq 0 $((K-1))); do
(
for i in $(seq $gpu $K $((N-1))); do
CUDA_VISIBLE_DEVICES=$gpu complexa design "${CONFIGS[$i]}" \
|| echo "FAILED on GPU $gpu: ${CONFIGS[$i]}"
done
) &
done
wait
只有在有意让每次 complexa design 调用使用多张 GPU(并且有办法避免它们相互干扰)时,才在循环中添加 gen_njobs / eval_njobs 覆盖值。
第 5 步:收集结果
每个扫描配置都会将结果写入其独立的 ./inference/inf_{idx}_{run_name}/ 目录;分析步骤会将结果写入 ./evaluation_results/eval_{idx}_{run_name}/results_*.csv。扫描完成后:
ls -d ./inference/inf_*_my_sweep/
ls ./evaluation_results/eval_*_my_sweep/results_*.csv
对于每个配置,解析分析 CSV(每个生成的 binder 对应一行)。用于排名的标准列:i_pae、i_plddt、sc_rmsd、binder_seq、passes_filter(bool)。如果缺少 passes_filter,则使用用户选定的阈值计算成功标志(默认值:i_pae < 10、i_plddt > 0.7、sc_rmsd < 2.0——请与用户确认)。
第 6 步:对配置排名
在运行目录中生成 sweep_summary.csv。每个配置占一行:
| 列 | 计算方法 |
|---|---|
config_id | inf_{idx}_{run_name} 中的 {idx} |
<axis_1>、<axis_2>、... | 此组合的扫描取值(从各配置的 inf_*.yaml 中读取) |
n_samples | 分析 CSV 的行数 |
success_rate | passes_filter.mean() |
mean_i_pae | i_pae.mean()(越低越好) |
mean_i_plddt | i_plddt.mean()(越高越好) |
diversity_score | 唯一序列数 / n_samples(如果可用,也可使用 TM-score 聚类) |
wall_clock_min | 根据各配置日志的时间戳得出 |
然后报告:
- 最佳配置 =
success_rate最大值对应的配置。若并列,则以mean_i_pae较低者优先。 - Pareto 前沿(
wall_clock_min、success_rate):若不存在其他同时运行更快且成功率更高的配置,则该配置位于前沿上。
在终端打印最佳配置和 Pareto 前沿。将完整表格保存到 sweep_summary.csv。
第 7 步:生成清单
捕获解析后的调用及输出,以便重放。共享辅助工具只接受一个 --output-dir(它会遍历查找 CSV,并从运行目录的 .hydra/ 中提取 Hydra 配置),因此请将其指向最佳配置的评估目录,并传入该次运行的上级 complexa design 命令:
BEST_ID=4 # from Step 6 ranking
python3 .claude/skills/_shared/scripts/write_manifest.py \
--output-dir ./evaluation_results/eval_${BEST_ID}_my_sweep \
--command "python script_utils/generate_inference_configs.py --config_name search_binder_local_pipeline --sweeper configs/sweeps/my_sweep.yaml --override generation.task_name=22_DerF21 --run_name my_sweep && for cfg in configs/inference_configs/inf_*_my_sweep.yaml; do complexa design \"\$cfg\"; done" \
--skill complexa-sweep \
--out ./sweep_runs/my_sweep/sweep_manifest.json
除了清单外,还要将第 6 步生成的排名汇总表 sweep_summary.csv 保存到 ./sweep_runs/my_sweep/sweep_summary.csv,并向用户提供这两个文件的路径。
推荐的扫描方案
| 症状 | 扫描此项 | 原因 |
|---|---|---|
| 质量不够好 | beam_width × nsteps(以 example.yaml 作为起点) | 两者都会增加计算量,从而提升质量;找出能达到目标的最低成本组合。 |
| 速度太慢/想要提速 | 固定 beam_width=4,逐步降低 nsteps(例如 [100, 200, 400]) | 找出能够保持成功率的最小 nsteps。 |
| 模式坍塌/多样性低 | generation.model.bb_ca.simulation_step_params.sc_scale_noise(使用 bb_ca_temperature.yaml) | 增加噪声可生成更多样的骨架。 |
| 奖励过拟合(奖励高,指标差) | generation.reward_model.reward_models.af2folding.reward_weights.{i_pae, plddt} 的比率 | 重新平衡组合奖励。 |
| 想要针对单个配置获得统计稳健性 | search_replicas.yaml(best_of_n.replicas) | 配置不变,增加样本数可使成功率估计更精确。 |
| 算法对比 | 对 [single-pass, best-of-n, beam-search, fk-steering] 扫描 generation.search.algorithm | 比较不同搜索方案;其他所有设置保持不变。 |
硬件
扫描所需的 GPU 总时长 = N_configs × 单次运行 GPU 时长。在一块 A100 上运行一次 search_binder_local_pipeline 大约需要 30–90 分钟(取决于结合体长度和 nsteps)。一个 4 轴 × 每轴 4 个值的扫描 = 256 个配置 × 约 60 分钟 = 约 256 GPU 小时——达到这种规模时,应使用多 GPU 主机,并采用步骤 4 的分片模式。
每次运行的基准值和 VRAM 最低要求,请参阅 .claude/skills/_shared/reference/hardware.md。
故障排除
| 症状 | 原因 | 解决方法 |
|---|---|---|
generate_inference_configs.py 报错 Sweeper file not found | 路径是根据错误的 CWD 解析的 | 使用相对于仓库根目录的路径;或传入绝对路径。 |
Sweeper YAML must be a mapping | 顶层 YAML 是列表或标量 | 改写为 key: [v1, v2] 映射。 |
No configs were generated | 某个值列表为空 [] | Sweeper 文件中有一行 key: []——至少添加一个值。 |
complexa design 拒绝 --sweeper | 混淆了入口点 | CLI 不接受 --sweeper。先使用 generate_inference_configs.py,然后对生成的配置循环运行 complexa design。 |
| 覆盖值导致扫描轴悄然折叠 | --override key=v 覆盖了扫描键 | 删除覆盖参数,或从 sweeper 文件中删除匹配的键。 |
| 循环中的一个配置失败,但扫描仍继续 | 步骤 4 中的 || echo "FAILED…" 吞掉了错误 | 单独重新运行失败的 inf_*.yaml;检查 ./logs/ 下每个配置对应的日志。排名时跳过失败的 config_id。 |
每个轴的参考信息(典型范围、成本、改善/恶化的方面),请参阅 reference/sweep_axes.md。
面向用户的扫描系统概览(配置生成、输出布局),请参阅 docs/SWEEP.md。