01 背景

在 GPU 集群上跑实验,大部分时间在等。提交 job、等几个小时、看结果、改参数、再提交。整个循环是纯手动的,凌晨三点盯着 squeue 尤其难受。

这篇文章记录我怎么用 OpenClaw 把这个循环自动化——包括最难自动化的那部分:分析结果、决定下一轮怎么改

用到的工具

  • PSC Bridges2(H100)——实际训练
  • AWS EC2(常驻)——编排中心
  • OpenClaw / Hachimi——监控、判断、Telegram 通知
  • GitHub——每轮结果存档到 runs/v{n}/
  • Notion——实时看板

02 先选架构

写训练代码之前,要先知道训什么。自己看论文既慢又容易漏掉东西。我的做法是分两步。

先让 Hachimi 根据我的约束(参数量预算、数据集规模、任务类型)整理成一个研究 prompt,再把这个 prompt 丢给 ChatGPT Deep Research

这个分工是有道理的:OpenClaw 擅长执行任务和管理流程,但 ChatGPT Deep Research 在综合近期文献这件事上明显更强——它能扫最近一个月的论文然后给出有排名的推荐。20 分钟内我就有了一个有 2024–2025 年论文支撑的方向,省去了很多乱试的时间。


03 流水线设计

架构图

你(Telegram)
    ↕  Hachimi 通知 / 等待确认
AWS EC2(常驻编排中心)
    ├── analyze_and_trigger.py   解析日志、调用 LLM、提交下一个 job
    ├── pull_and_commit.sh       git commit + 比赛提交
    └── OpenClaw / Hachimi       监控 + 判断层
         ↕  job 完成后 SSH 回调
PSC Bridges2(GPU 集群)
    └── train.py → results.json → 触发回调

流程

  1. 提交 sbatch submit_v1.sh
  2. 训练结束,脚本 SSH 回调 AWS,传日志路径
  3. AWS 解析训练曲线,调 LLM 分析,生成下一轮 config
  4. 自动提交下一个 job(sbatch submit_v2.sh
  5. 比赛提交、Notion 更新、git commit 全自动完成
  6. Telegram 收到三行摘要:耗时、最终指标、改了什么

配好之后,整个"跑→分析→下一轮"的循环不需要任何手动操作。


04 实现细节

用 HEARTBEAT.md 替代 Cron

OpenClaw 的 heartbeat 系统每次触发时读取 workspace 里的 HEARTBEAT.md,按里面写的逻辑执行。用自然语言写监控逻辑,不需要 cron 语法,不需要守护进程:

## 训练监控
检查 `squeue -u username` 的在跑 job。
- RUNNING:tail 最新日志,报告 epoch/指标,更新 Notion
- COMPLETED:读 results.json,分析曲线,问我下一个版本怎么做
- FAILED:读 .err 日志,报告原因,等指示——不要自动 resubmit

随时改这个文件,下一次 heartbeat 就生效。

SSH 回调

在 SBATCH 脚本末尾加:

ssh -i ~/.ssh/id_ed25519 user@your-aws-server \
  "python3 /home/ubuntu/pipeline/analyze_and_trigger.py \
    --run v1 --log '$LOG_PATH' --next-run v2" \
  || echo "callback failed (non-fatal)"

提前要做好两件事:

  • SSH key 要在集群上生成,不是你的本地机器。计算节点没有你本地的 key——把集群的公钥加到 AWS 的 authorized_keys
  • PSC Bridges2 计算节点上只有 /jet/home/username//home/username 这个软链接只在登录节点存在。所有路径(包括 SBATCH 的 --output--error)都要写绝对路径。

分析脚本

analyze_and_trigger.py 做四件事: 1. 解析训练日志——提取 loss 和指标曲线 2. 用结构化 prompt 调 LLM:当前曲线 + 当前 config → 该改什么? 3. 把回答解析成 config 字段 4. 提交下一个 job

LLM 不需要很强,只需要能判断收敛情况:还在改善吗?val loss 和 train loss 开始分叉了吗?学习率太大了吗?prompt 写清楚,用快一点的模型就够了。


05 踩过的坑

Job 一秒就死了

exit code 0:53(信号 53),没有任何错误输出,连续好几个 job 都这样。是烂节点,不是代码 bug。 解法: 每次先跑一个 smoke test(1 epoch,5% 数据),确认节点没问题再提交完整 job。

SBATCH 输出路径不存在

Slurm 在脚本运行之前就要写输出文件,目录不存在就直接 kill,连日志都没有。 解法: sbatch 之前先 mkdir -p,或者在 SBATCH 脚本第一行加。

回调静默失败

SSH 回调失败的话什么都不会发生——训练正常结束,下一个 job 没提交,没有通知,要等你手动检查才知道。 解法:|| echo "callback failed" 让训练不中断。更重要的是:在真正跑实验之前先测好 SSH 链路。

API key 静默过期

硬编码的 API key 过期了,分析脚本崩,下一个 job 没提交,没有任何提示。 解法: 把 credentials 存在 AWS SSM Parameter Store,运行时读取。key 会过期,脚本会进 git。


06 Hachimi 实际做了什么

Python 脚本是确定性的流水线胶水——每轮做的事一样。Hachimi 处理的是需要判断的情况:

  • 我手动取消了错误的自动提交 job,Hachimi 发现了版本冲突
  • LLM API key 实验中途过期,Hachimi 直接读日志、分析、提出下一轮配置,没等我问
  • 整个实验过程中,我只需要看 Telegram 摘要——从没开过终端

脚本处理 happy path,Hachimi 处理其他所有情况。


07 几点建议

  1. 先禁用自动化。 手动跑通全流程再加回调,再加自动提交。一层一层来。
  2. 每轮都写 results.json 至少记:最终指标、最佳指标 + epoch、参数量。自动分析会简洁很多。
  3. 提前测回调链路。 在第一个真实 job 之前确认 PSC → AWS SSH 通畅,不要等 4 小时之后。
  4. 不要硬编码 credentials。 key 会过期,脚本会进 git。