SaylorTwift HF Staff commited on
Commit
81a1081
·
verified ·
1 Parent(s): 4e22c33

v2: tunnel-free proxy via SPACE_HOST+Jobs expose_public, heartbeat watchdog (30min stall -> fail), keep UploadCheckpointsCallback

Browse files
Files changed (2) hide show
  1. run_job.sh +24 -1
  2. train_lora.py +14 -1
run_job.sh CHANGED
@@ -64,9 +64,32 @@ vllm serve "${MODEL:-LiquidAI/LFM2.5-2.6B}" \
64
  VLLM_PID=$!
65
 
66
  echo "=== [start] env server (CPU) ==="
 
 
 
 
 
 
67
  PREPARED=/app/prepared bash serve_env.sh &
68
  ENV_PID=$!
69
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
  echo "=== [wait] servers ==="
71
  python3 - <<'EOF'
72
  import time, urllib.request
@@ -135,5 +158,5 @@ if repo:
135
  EOF
136
  fi
137
 
138
- kill $VLLM_PID $ENV_PID 2>/dev/null || true
139
  echo "=== done ==="
 
64
  VLLM_PID=$!
65
 
66
  echo "=== [start] env server (CPU) ==="
67
+ # Tunnel-free proxy exposure: with SPACE_HOST set, OpenEnv mounts the capture
68
+ # proxy at /capture on the env server itself, reached through the Jobs proxy at
69
+ # https://<JOB_ID>--8000.hf.jobs — no gradio tunnel to die mid-run
70
+ # (that failure stalled the first full run silently for 13h).
71
+ export SPACE_HOST="${JOB_ID}--8000.hf.jobs"
72
+ echo "capture proxy public base: https://${SPACE_HOST}/capture"
73
  PREPARED=/app/prepared bash serve_env.sh &
74
  ENV_PID=$!
75
 
76
+ echo "=== [start] watchdog (fail the job if no training step for 30 min) ==="
77
+ (
78
+ while true; do
79
+ sleep 300
80
+ if [ -f /tmp/rl-heartbeat ]; then
81
+ age=$(( $(date +%s) - $(stat -c %Y /tmp/rl-heartbeat) ))
82
+ if [ "$age" -gt 1800 ]; then
83
+ echo "WATCHDOG: no training step for ${age}s — rollout path is dead, failing the job"
84
+ pkill -f train_lora.py || true
85
+ sleep 30
86
+ exit 1
87
+ fi
88
+ fi
89
+ done
90
+ ) &
91
+ WATCHDOG_PID=$!
92
+
93
  echo "=== [wait] servers ==="
94
  python3 - <<'EOF'
95
  import time, urllib.request
 
158
  EOF
159
  fi
160
 
161
+ kill $VLLM_PID $ENV_PID $WATCHDOG_PID 2>/dev/null || true
162
  echo "=== done ==="
train_lora.py CHANGED
@@ -84,6 +84,19 @@ class UploadCheckpointsCallback(TrainerCallback):
84
  return control
85
 
86
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
  def correctness_plus_efficiency(outcome):
88
  """1/0 correctness, plus <= 0.1 for a correct answer in fewer tool calls.
89
 
@@ -190,7 +203,7 @@ def main():
190
  processing_class=tokenizer,
191
  rollout_worker=worker,
192
  peft_config=peft_config,
193
- callbacks=[UploadCheckpointsCallback(ADAPTER_REPO)],
194
  )
195
  trainer.train()
196
  trainer.save_model("./checkpoints/final") # adapter_model.safetensors + adapter_config.json
 
84
  return control
85
 
86
 
87
+ class HeartbeatCallback(TrainerCallback):
88
+ """Touch a file at every optimizer step; run_job.sh's watchdog kills the
89
+ job if it goes stale. The first full run stalled silently for 13h when the
90
+ rollout path died — steps just stopped, and nothing noticed."""
91
+
92
+ PATH = "/tmp/rl-heartbeat"
93
+
94
+ def on_step_end(self, args, state, control, **kwargs):
95
+ with open(self.PATH, "w") as f:
96
+ f.write(str(state.global_step))
97
+ return control
98
+
99
+
100
  def correctness_plus_efficiency(outcome):
101
  """1/0 correctness, plus <= 0.1 for a correct answer in fewer tool calls.
102
 
 
203
  processing_class=tokenizer,
204
  rollout_worker=worker,
205
  peft_config=peft_config,
206
+ callbacks=[UploadCheckpointsCallback(ADAPTER_REPO), HeartbeatCallback()],
207
  )
208
  trainer.train()
209
  trainer.save_model("./checkpoints/final") # adapter_model.safetensors + adapter_config.json