refactor: split submit_sft_via_cml.sh into submit_sft.sh + submit_cml_eval.sh

- submit_sft.sh: pure SFT submission, prints JobID and exits (no embedded watcher)
- submit_cml_eval.sh: pure CML eval, reads workflow_id/version from config.yaml
- jupyter_runtime write_text: rewrite to use Contents API instead of terminal websocket
- SKILL.md: restrict trigger to explicit UI click only
- program.md: update §5.2 docs to reflect two-script workflow

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
hupenglong1
2026-05-25 17:21:42 +08:00
parent d2c221e2da
commit a3ab74b506
8 changed files with 328 additions and 186 deletions
+76
View File
@@ -0,0 +1,76 @@
#!/bin/bash
# 起 CML evaluation workflow**只做这一件事**)。
# workflow_id / version 都从 skills/model-iteration/assets/config.yaml 读,不在这里硬编码。
#
# 用法:
# ./submit_cml_eval.sh <EVAL_RUNDIC> [MODEL_NEW] [MODEL_OLD]
#
# 默认值:
# MODEL_NEW = $AUTORESEARCH_ROOT/sft_output(最新一轮 SFT 产物)
# MODEL_OLD = /mnt/wangsenhao/verl_zk/qwen4b_cispo_wokl_add_bvt_2/global_step_5/actor/huggingface
set -euo pipefail
EVAL_RUNDIC=${1:?usage: $0 <EVAL_RUNDIC> [MODEL_NEW] [MODEL_OLD]}
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ROOT=${AUTORESEARCH_ROOT:-/mnt/wangsenhao/autoresearch-zk}
MODEL_NEW=${2:-${MODEL_NEW:-$ROOT/sft_output}}
MODEL_OLD=${3:-${MODEL_OLD:-/mnt/wangsenhao/verl_zk/qwen4b_cispo_wokl_add_bvt_2/global_step_5/actor/huggingface}}
# 定位 config.yaml:先看脚本旁边的 ../assets/,再看 skills/ 树
find_config() {
local candidates=(
"$SCRIPT_DIR/../assets/config.yaml"
"${ZK_AGENT_SKILLS_ROOT:-}/model-iteration/assets/config.yaml"
"${AUTORESEARCH_CHAT_ROOT:-}/skills/model-iteration/assets/config.yaml"
)
local c
for c in "${candidates[@]}"; do
if [ -n "$c" ] && [ -f "$c" ]; then
echo "$c"
return 0
fi
done
return 1
}
CONFIG=$(find_config) || {
echo "[eval] ❌ 找不到 config.yaml(尝试过:$SCRIPT_DIR/../assets/、\$ZK_AGENT_SKILLS_ROOT/model-iteration/assets/、\$AUTORESEARCH_CHAT_ROOT/skills/..." >&2
exit 1
}
# 极简 yaml 解析:只提 cml_eval.workflow_id / cml_eval.version(与后端 _read_workflow_version 风格保持一致)
read_cml_eval_field() {
local field=$1
awk -v field="$field" '
/^[^[:space:]#]/ { in_cml = ($1 == "cml_eval:") }
in_cml && $1 == field { gsub(/^["\x27]|["\x27]$/, "", $2); print $2; exit }
' "$CONFIG"
}
EVAL_WORKFLOW_ID=$(read_cml_eval_field "workflow_id:")
EVAL_VERSION=$(read_cml_eval_field "version:")
if [ -z "$EVAL_WORKFLOW_ID" ] || [ -z "$EVAL_VERSION" ]; then
echo "[eval] ❌ 从 $CONFIG 读到的 cml_eval 不完整:workflow_id='$EVAL_WORKFLOW_ID' version='$EVAL_VERSION'" >&2
exit 1
fi
if [ -f ~/.cloudml-cli/.profile ]; then
source ~/.cloudml-cli/.profile
else
echo "[eval] ❌ 未找到 ~/.cloudml-cli/.profile,请先安装并初始化 cml" >&2
exit 1
fi
echo "[eval] EVAL_RUNDIC=$EVAL_RUNDIC workflow_id=$EVAL_WORKFLOW_ID version=$EVAL_VERSION (config: $CONFIG)"
echo "[eval] MODEL_NEW=$MODEL_NEW"
echo "[eval] MODEL_OLD=$MODEL_OLD"
cml workflow run \
--workflow_id "$EVAL_WORKFLOW_ID" --version "$EVAL_VERSION" \
--global_inputs runDic="$EVAL_RUNDIC" \
--global_inputs model_path_new="$MODEL_NEW" \
--global_inputs model_path_old="$MODEL_OLD"
echo "[eval] ✅ 已提交 workflow$EVAL_RUNDIC,产物在 /mnt/xiaoai-zk-model-train-tj5/workflow5/workflow${EVAL_RUNDIC}/"