Navigam commited on
Commit
ef0aeea
·
1 Parent(s): 4e1a75b

refactor: update training scripts and environment setup for Qwen3 model

Browse files

Modified training scripts to transition from Qwen2.5 to Qwen3, including updates to model and adapter paths in `train_rlvr.py` and `train_grpo.py`. Removed legacy environment variables from setup scripts and README.md, introducing new command-line arguments for stub workers and LLM judge control. Enhanced documentation to reflect these changes and improve user guidance for the updated training process.

env_artifacts/README.md CHANGED
@@ -61,8 +61,6 @@ pip install -e . # picks up project deps without touching the pinned to
61
 
62
  # Per-session exports (stick these in ~/.bashrc if you want):
63
  export HF_HUB_ENABLE_HF_TRANSFER=1
64
- export CORP_STUB_WORKERS=1
65
- export CORP_DISABLE_LLM_JUDGE=1
66
  export TOKENIZERS_PARALLELISM=false
67
  export TRANSFORMERS_VERBOSITY=warning
68
 
@@ -81,17 +79,17 @@ You can pull them locally on a new box with:
81
  huggingface-cli download Navigam/corp-env-sft-qwen2.5-7b --local-dir outputs/sft_adapter
82
  ```
83
 
84
- Then for the RLVR run:
85
 
86
  ```bash
87
  python training/train_rlvr.py \
88
- --model Qwen/Qwen2.5-7B-Instruct \
89
- --adapter outputs/sft_adapter \
90
  --examples data/processed/e1_m1_clean.jsonl,data/processed/h1_seed_clean.jsonl \
91
- --output outputs/rlvr_adapter \
92
  --rounds 3 --n-samples 8 --max-prompts 128 \
93
  --stats-file results/runs/rlvr_stats.jsonl \
94
- --push-to-hub Navigam/corp-env-rlvr-qwen2.5-7b
95
  ```
96
 
97
  ## Notes / gotchas
@@ -99,12 +97,10 @@ python training/train_rlvr.py \
99
  - **First time only on any new box**: `unsloth` writes patched-trainer classes
100
  into `corp_gym/unsloth_compiled_cache/`. Delete that folder if you ever
101
  change TRL/unsloth versions to avoid stale compiled patches.
102
- - **Flash-attn fp32 bug**: in `training/train_grpo.py` (legacy) and
103
- `training/train_rlvr.py` we monkey-patch `flash_attn_func` in both
104
- `flash_attn.flash_attn_interface` and `unsloth.utils.attention_dispatch` to
105
- auto-cast Q/K/V to bf16. Without the dispatcher-level patch, Unsloth's copy
106
- of the symbol bypasses ours and FA2 rejects fp32 tensors during the no-grad
107
- reference logprob forward.
108
  - **max_prompt_length filter**: both legacy GRPO and RLVR scripts tokenise every
109
  prompt up-front and drop rows whose chat-template-encoded length exceeds
110
  `0.9 * max_prompt_length` (long H1 trajectories otherwise produce a causal
 
61
 
62
  # Per-session exports (stick these in ~/.bashrc if you want):
63
  export HF_HUB_ENABLE_HF_TRANSFER=1
 
 
64
  export TOKENIZERS_PARALLELISM=false
65
  export TRANSFORMERS_VERBOSITY=warning
66
 
 
79
  huggingface-cli download Navigam/corp-env-sft-qwen2.5-7b --local-dir outputs/sft_adapter
80
  ```
81
 
82
+ Then for a direct 14B RLVR run:
83
 
84
  ```bash
85
  python training/train_rlvr.py \
86
+ --model Qwen/Qwen3-14B-Instruct \
87
+ --adapter outputs/sft_qwen3_14b \
88
  --examples data/processed/e1_m1_clean.jsonl,data/processed/h1_seed_clean.jsonl \
89
+ --output outputs/rlvr_qwen3_14b \
90
  --rounds 3 --n-samples 8 --max-prompts 128 \
91
  --stats-file results/runs/rlvr_stats.jsonl \
92
+ --push-to-hub <your-user-or-org>/corp-env-rlvr-qwen3-14b
93
  ```
94
 
95
  ## Notes / gotchas
 
97
  - **First time only on any new box**: `unsloth` writes patched-trainer classes
98
  into `corp_gym/unsloth_compiled_cache/`. Delete that folder if you ever
99
  change TRL/unsloth versions to avoid stale compiled patches.
100
+ - **Flash-attn fp32 workaround**: this is now **legacy-only** for
101
+ `training/train_grpo.py`. It is disabled by default and can be enabled only
102
+ when needed via `CORP_ENABLE_FA2_BF16_PATCH=1`.
103
+ - `training/train_rlvr.py` now runs without this monkey patch on modern stacks.
 
 
104
  - **max_prompt_length filter**: both legacy GRPO and RLVR scripts tokenise every
105
  prompt up-front and drop rows whose chat-template-encoded length exceeds
106
  `0.9 * max_prompt_length` (long H1 trajectories otherwise produce a causal
env_artifacts/setup_lightning_h100.sh CHANGED
@@ -71,8 +71,6 @@ log "done. Export env vars in your shell (rc file or per-session):"
71
  cat <<'EOF'
72
 
73
  export HF_HUB_ENABLE_HF_TRANSFER=1
74
- export CORP_STUB_WORKERS=1
75
- export CORP_DISABLE_LLM_JUDGE=1
76
  export TOKENIZERS_PARALLELISM=false
77
  export TRANSFORMERS_VERBOSITY=warning
78
 
 
71
  cat <<'EOF'
72
 
73
  export HF_HUB_ENABLE_HF_TRANSFER=1
 
 
74
  export TOKENIZERS_PARALLELISM=false
75
  export TRANSFORMERS_VERBOSITY=warning
76
 
training/train_grpo.py CHANGED
@@ -48,8 +48,17 @@ from typing import Any, Dict, List
48
 
49
  import torch
50
 
51
- try:
52
- import flash_attn.flash_attn_interface as _fa_mod
 
 
 
 
 
 
 
 
 
53
 
54
  _orig_fa_func = _fa_mod.flash_attn_func
55
  _orig_fa_var = getattr(_fa_mod, "flash_attn_varlen_func", None)
@@ -67,16 +76,14 @@ try:
67
  _fa_mod.flash_attn_func = _fa_func_bf16
68
  if _orig_fa_var is not None:
69
  _fa_mod.flash_attn_varlen_func = _fa_varlen_bf16
70
-
71
  try:
72
  import unsloth.utils.attention_dispatch as _ad_mod
 
73
  _ad_mod.flash_attn_func = _fa_func_bf16
74
  if _orig_fa_var is not None and hasattr(_ad_mod, "flash_attn_varlen_func"):
75
  _ad_mod.flash_attn_varlen_func = _fa_varlen_bf16
76
  except Exception:
77
  pass
78
- except ImportError:
79
- pass
80
 
81
  ROOT = Path(__file__).resolve().parents[1]
82
  if str(ROOT) not in sys.path:
@@ -343,10 +350,23 @@ def main() -> None:
343
  default=1,
344
  help="Filter training examples to traces with at least this many log_reasoning actions.",
345
  )
 
 
 
 
 
 
 
 
 
 
346
  args = parser.parse_args()
347
 
348
- os.environ.setdefault("CORP_STUB_WORKERS", "1")
349
- os.environ.setdefault("CORP_DISABLE_LLM_JUDGE", "1")
 
 
 
350
 
351
  try:
352
  from unsloth import FastLanguageModel, PatchFastRL
 
48
 
49
  import torch
50
 
51
+ def _maybe_patch_flash_attn_bf16() -> None:
52
+ """Legacy workaround for older Unsloth/FA2 stacks.
53
+
54
+ Disabled by default; enable only if your GRPO run hits fp32 FA2 dtype errors.
55
+ """
56
+ if os.environ.get("CORP_ENABLE_FA2_BF16_PATCH", "").strip() != "1":
57
+ return
58
+ try:
59
+ import flash_attn.flash_attn_interface as _fa_mod
60
+ except ImportError:
61
+ return
62
 
63
  _orig_fa_func = _fa_mod.flash_attn_func
64
  _orig_fa_var = getattr(_fa_mod, "flash_attn_varlen_func", None)
 
76
  _fa_mod.flash_attn_func = _fa_func_bf16
77
  if _orig_fa_var is not None:
78
  _fa_mod.flash_attn_varlen_func = _fa_varlen_bf16
 
79
  try:
80
  import unsloth.utils.attention_dispatch as _ad_mod
81
+
82
  _ad_mod.flash_attn_func = _fa_func_bf16
83
  if _orig_fa_var is not None and hasattr(_ad_mod, "flash_attn_varlen_func"):
84
  _ad_mod.flash_attn_varlen_func = _fa_varlen_bf16
85
  except Exception:
86
  pass
 
 
87
 
88
  ROOT = Path(__file__).resolve().parents[1]
89
  if str(ROOT) not in sys.path:
 
350
  default=1,
351
  help="Filter training examples to traces with at least this many log_reasoning actions.",
352
  )
353
+ parser.add_argument(
354
+ "--use-stub-workers",
355
+ action="store_true",
356
+ help="Use deterministic stub workers (default: real workers).",
357
+ )
358
+ parser.add_argument(
359
+ "--disable-llm-judge",
360
+ action="store_true",
361
+ help="Disable LLM judge scoring for deterministic verifier-only runs.",
362
+ )
363
  args = parser.parse_args()
364
 
365
+ if args.use_stub_workers:
366
+ os.environ["CORP_STUB_WORKERS"] = "1"
367
+ if args.disable_llm_judge:
368
+ os.environ["CORP_DISABLE_LLM_JUDGE"] = "1"
369
+ _maybe_patch_flash_attn_bf16()
370
 
371
  try:
372
  from unsloth import FastLanguageModel, PatchFastRL
training/train_rlvr.py CHANGED
@@ -22,12 +22,12 @@ completions, and the advantage-variance collapse in GRPO no longer applies.
22
  Run (after SFT)::
23
 
24
  python training/train_rlvr.py \\
25
- --model Qwen/Qwen2.5-7B-Instruct \\
26
- --adapter outputs/sft_adapter \\
27
  --examples data/processed/e1_m1_clean.jsonl,data/processed/h1_seed_clean.jsonl \\
28
- --output outputs/rlvr_adapter \\
29
  --rounds 3 --n-samples 8 --max-prompts 64 \\
30
- --push-to-hub Navigam/corp-env-rlvr-qwen2.5-7b
31
  """
32
 
33
  from __future__ import annotations
@@ -45,36 +45,6 @@ from typing import Any, Dict, List, Tuple
45
 
46
  import torch
47
 
48
- try:
49
- import flash_attn.flash_attn_interface as _fa_mod
50
-
51
- _orig_fa_func = _fa_mod.flash_attn_func
52
- _orig_fa_var = getattr(_fa_mod, "flash_attn_varlen_func", None)
53
-
54
- def _fa_func_bf16(q, k, v, *args, **kwargs):
55
- if q.dtype not in (torch.bfloat16, torch.float16):
56
- q, k, v = q.to(torch.bfloat16), k.to(torch.bfloat16), v.to(torch.bfloat16)
57
- return _orig_fa_func(q, k, v, *args, **kwargs)
58
-
59
- def _fa_varlen_bf16(q, k, v, *args, **kwargs):
60
- if q.dtype not in (torch.bfloat16, torch.float16):
61
- q, k, v = q.to(torch.bfloat16), k.to(torch.bfloat16), v.to(torch.bfloat16)
62
- return _orig_fa_var(q, k, v, *args, **kwargs)
63
-
64
- _fa_mod.flash_attn_func = _fa_func_bf16
65
- if _orig_fa_var is not None:
66
- _fa_mod.flash_attn_varlen_func = _fa_varlen_bf16
67
-
68
- try:
69
- import unsloth.utils.attention_dispatch as _ad_mod
70
- _ad_mod.flash_attn_func = _fa_func_bf16
71
- if _orig_fa_var is not None and hasattr(_ad_mod, "flash_attn_varlen_func"):
72
- _ad_mod.flash_attn_varlen_func = _fa_varlen_bf16
73
- except Exception:
74
- pass
75
- except ImportError:
76
- pass
77
-
78
  ROOT = Path(__file__).resolve().parents[1]
79
  if str(ROOT) not in sys.path:
80
  sys.path.insert(0, str(ROOT))
@@ -345,8 +315,8 @@ def maybe_push_to_hub(output_dir: str, repo_id: str) -> None:
345
 
346
  def main() -> None:
347
  parser = argparse.ArgumentParser(description="RLVR / Rejection-Sampling FT for CORP-ENV.")
348
- parser.add_argument("--model", default="Qwen/Qwen2.5-7B-Instruct")
349
- parser.add_argument("--adapter", default="outputs/sft_adapter",
350
  help="Start from this LoRA adapter (usually SFT).")
351
  parser.add_argument(
352
  "--examples",
@@ -356,7 +326,7 @@ def main() -> None:
356
  "--tasks",
357
  default="e1_launch_readiness,m1_budget_reallocation,h1_acquisition_defence",
358
  )
359
- parser.add_argument("--output", default="outputs/rlvr_adapter")
360
  parser.add_argument("--rounds", type=int, default=3,
361
  help="Outer rollout -> filter -> SFT iterations.")
362
  parser.add_argument("--n-samples", type=int, default=8,
@@ -396,10 +366,22 @@ def main() -> None:
396
  default="",
397
  help="Optional JSONL to append per-round rollout stats to.",
398
  )
 
 
 
 
 
 
 
 
 
 
399
  args = parser.parse_args()
400
 
401
- os.environ.setdefault("CORP_STUB_WORKERS", "1")
402
- os.environ.setdefault("CORP_DISABLE_LLM_JUDGE", "1")
 
 
403
 
404
  random.seed(args.seed)
405
  torch.manual_seed(args.seed)
 
22
  Run (after SFT)::
23
 
24
  python training/train_rlvr.py \\
25
+ --model Qwen/Qwen3-14B-Instruct \\
26
+ --adapter outputs/sft_qwen3_14b \\
27
  --examples data/processed/e1_m1_clean.jsonl,data/processed/h1_seed_clean.jsonl \\
28
+ --output outputs/rlvr_qwen3_14b \\
29
  --rounds 3 --n-samples 8 --max-prompts 64 \\
30
+ --push-to-hub your-org/corp-env-rlvr-qwen3-14b
31
  """
32
 
33
  from __future__ import annotations
 
45
 
46
  import torch
47
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
  ROOT = Path(__file__).resolve().parents[1]
49
  if str(ROOT) not in sys.path:
50
  sys.path.insert(0, str(ROOT))
 
315
 
316
  def main() -> None:
317
  parser = argparse.ArgumentParser(description="RLVR / Rejection-Sampling FT for CORP-ENV.")
318
+ parser.add_argument("--model", default="Qwen/Qwen3-14B-Instruct")
319
+ parser.add_argument("--adapter", default="outputs/sft_qwen3_14b",
320
  help="Start from this LoRA adapter (usually SFT).")
321
  parser.add_argument(
322
  "--examples",
 
326
  "--tasks",
327
  default="e1_launch_readiness,m1_budget_reallocation,h1_acquisition_defence",
328
  )
329
+ parser.add_argument("--output", default="outputs/rlvr_qwen3_14b")
330
  parser.add_argument("--rounds", type=int, default=3,
331
  help="Outer rollout -> filter -> SFT iterations.")
332
  parser.add_argument("--n-samples", type=int, default=8,
 
366
  default="",
367
  help="Optional JSONL to append per-round rollout stats to.",
368
  )
369
+ parser.add_argument(
370
+ "--use-stub-workers",
371
+ action="store_true",
372
+ help="Use deterministic stub workers (default: real workers).",
373
+ )
374
+ parser.add_argument(
375
+ "--disable-llm-judge",
376
+ action="store_true",
377
+ help="Disable LLM judge scoring for deterministic verifier-only runs.",
378
+ )
379
  args = parser.parse_args()
380
 
381
+ if args.use_stub_workers:
382
+ os.environ["CORP_STUB_WORKERS"] = "1"
383
+ if args.disable_llm_judge:
384
+ os.environ["CORP_DISABLE_LLM_JUDGE"] = "1"
385
 
386
  random.seed(args.seed)
387
  torch.manual_seed(args.seed)