Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .agents/skills/fine-tuning/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ Train language models with SFT, KTO, and GRPO locally or on supported cloud prov
| Diagnose an offline SFT worker rejection | Read the exact retained `trainer.stderr.log`; closed phase/category/milestone labels locate a boundary, not a cause or retry authority; see `reference/sft-training.md` |
| Native MLX prepared SFT candidate | Internal exact-token batch/loss and runtime comparison only; no native launch CLI or API provider yet; see `reference/native-local-training.md` |
| Plan a derived training image | `python scripts/qualify_derived_training_image.py plan --config Trainers/image_profiles/<profile>.yaml` |
| Private GRPO constructor diagnosis | `python -B examples/training_qualification/grpo_constructor.py --help`; use a private config and separate reviewed build/diagnostic admissions; no public training authority; see `reference/grpo-training.md` and `docs/review/grpo-constructor-diagnostic.md` |
| Warm Space scaffold | `python3 Trainers/cloud/scripts/manage_space.py render --template vllm_warm --output-dir /tmp/my-space --base-image ghcr.io/<org>/<image>:<tag>` |
| Warm Space deploy | `python3 Trainers/cloud/scripts/manage_space.py deploy --space-id <user>/<space> --template vllm_warm --base-image ghcr.io/<org>/<image>:<tag> --hardware a10g-small --sleep-time 3600 --var BASE_MODEL=<model>` |
| ML training | `python tuner.py ml train --config Trainers/ml/configs/templates/regression.yaml` |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ model:
runtime:
provider: modal
lock_path: tuner/execution/providers/modal/modal-runtime-v1.lock.json
expected_lock_sha256: 4f3fa81c9aeb9130258dec23f2b841e6dbdf2d686d1cf6b50249e743c3d496ca
expected_lock_sha256: 3bcd5d9ca2065a1462745e738e4e1d60f89e3c31829964bc2f054b795cf4b561
input:
jsonl_path: /replace/with/private/prepared-dataset.jsonl
mode: text
Expand Down
21 changes: 19 additions & 2 deletions .agents/skills/fine-tuning/reference/grpo-training.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,23 @@

Group Relative Policy Optimization — optimizes model behavior using reward functions against generated completions.

For the consumed 0d515 Modal trainer-setup failure and restricted,
constructor-only Modal diagnostic, see
`docs/review/grpo-constructor-diagnostic.md`. The pinned Unsloth Zoo 2026.1.2
source requires an accelerator at import, so a CPU-only patched-constructor
probe cannot reach that boundary. The checked-in
`scripts/qualify_derived_training_image.py release plan-grpo-constructor-input`
command derives the exact four-row input. The private configured consumer is
`examples/training_qualification/grpo_constructor.py`; use its owner-only
example config and separate `prepare-model`, `plan`, `prepare`, `admit`,
`execute-once`, and `readback` review gates. It requires reviewed new
image/source and independent read-only retained snapshot custody. A diagnostic
claim is consumed; it grants no training replay or qualification. The old
deployment's superseded app generation is retained evidence, while the exact
old model Volume identity is rehydrated read-only. Generated Unsloth code is
not source-attested by pinned wheel files, so its type-site label remains
`OTHER` unless a future exact generated-code proof is added.

## Public GRPO declarations and CPU preparation

The provider-neutral `TrainingInputV1` accepts explicit method `grpo` with
Expand Down Expand Up @@ -206,7 +223,7 @@ auto-select BF16 on BF16-capable hardware while the recipe requests FP16 can
fail at `TRAINER_SETUP`. A closed `TypeError` marker alone cannot establish
that this was the historical cause, and it does not authorize replay.

GRPO has a separate fixed 131-member offline inventory and 13-member outer
GRPO has a separate fixed 133-member offline inventory and 14-member outer
closure. Existing SFT inventories remain unchanged. Maintenance uses the
checked-in command, offline first because the outer closure binds its bytes:

Expand Down Expand Up @@ -633,7 +650,7 @@ actual accepted wheel anchor is replaced by the actual newly built current-sourc
wheel in bound build material, using the existing normal builder. Never invent a
future SHA or embed a circular self-hash. Actual derived-image inventory and CPU
GRPO qualification remain separate from the 396-distribution base observation.
The old SFT profiles and fixed SFT68/outer5 and GRPO131/outer13 inventories stay
The old SFT profiles and fixed SFT68/outer5 and GRPO133/outer14 inventories stay
unchanged. Installed candidate tests require an actual fresh wheel, verify the
runtime YAML/inventory are shipped and the source image profile is absent, and
label their synthetic Git preplan observation as CPU control-flow evidence only.
Expand Down
1 change: 1 addition & 0 deletions .claude/skills/fine-tuning/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ Train language models with SFT, KTO, and GRPO locally or on supported cloud prov
| Diagnose an offline SFT worker rejection | Read the exact retained `trainer.stderr.log`; closed phase/category/milestone labels locate a boundary, not a cause or retry authority; see `reference/sft-training.md` |
| Native MLX prepared SFT candidate | Internal exact-token batch/loss and runtime comparison only; no native launch CLI or API provider yet; see `reference/native-local-training.md` |
| Plan a derived training image | `python scripts/qualify_derived_training_image.py plan --config Trainers/image_profiles/<profile>.yaml` |
| Private GRPO constructor diagnosis | `python -B examples/training_qualification/grpo_constructor.py --help`; use a private config and separate reviewed build/diagnostic admissions; no public training authority; see `reference/grpo-training.md` and `docs/review/grpo-constructor-diagnostic.md` |
| Warm Space scaffold | `python3 Trainers/cloud/scripts/manage_space.py render --template vllm_warm --output-dir /tmp/my-space --base-image ghcr.io/<org>/<image>:<tag>` |
| Warm Space deploy | `python3 Trainers/cloud/scripts/manage_space.py deploy --space-id <user>/<space> --template vllm_warm --base-image ghcr.io/<org>/<image>:<tag> --hardware a10g-small --sleep-time 3600 --var BASE_MODEL=<model>` |
| ML training | `python tuner.py ml train --config Trainers/ml/configs/templates/regression.yaml` |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ model:
runtime:
provider: modal
lock_path: tuner/execution/providers/modal/modal-runtime-v1.lock.json
expected_lock_sha256: 4f3fa81c9aeb9130258dec23f2b841e6dbdf2d686d1cf6b50249e743c3d496ca
expected_lock_sha256: 3bcd5d9ca2065a1462745e738e4e1d60f89e3c31829964bc2f054b795cf4b561
input:
jsonl_path: /replace/with/private/prepared-dataset.jsonl
mode: text
Expand Down
21 changes: 19 additions & 2 deletions .claude/skills/fine-tuning/reference/grpo-training.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,23 @@

Group Relative Policy Optimization — optimizes model behavior using reward functions against generated completions.

For the consumed 0d515 Modal trainer-setup failure and restricted,
constructor-only Modal diagnostic, see
`docs/review/grpo-constructor-diagnostic.md`. The pinned Unsloth Zoo 2026.1.2
source requires an accelerator at import, so a CPU-only patched-constructor
probe cannot reach that boundary. The checked-in
`scripts/qualify_derived_training_image.py release plan-grpo-constructor-input`
command derives the exact four-row input. The private configured consumer is
`examples/training_qualification/grpo_constructor.py`; use its owner-only
example config and separate `prepare-model`, `plan`, `prepare`, `admit`,
`execute-once`, and `readback` review gates. It requires reviewed new
image/source and independent read-only retained snapshot custody. A diagnostic
claim is consumed; it grants no training replay or qualification. The old
deployment's superseded app generation is retained evidence, while the exact
old model Volume identity is rehydrated read-only. Generated Unsloth code is
not source-attested by pinned wheel files, so its type-site label remains
`OTHER` unless a future exact generated-code proof is added.

## Public GRPO declarations and CPU preparation

The provider-neutral `TrainingInputV1` accepts explicit method `grpo` with
Expand Down Expand Up @@ -206,7 +223,7 @@ auto-select BF16 on BF16-capable hardware while the recipe requests FP16 can
fail at `TRAINER_SETUP`. A closed `TypeError` marker alone cannot establish
that this was the historical cause, and it does not authorize replay.

GRPO has a separate fixed 131-member offline inventory and 13-member outer
GRPO has a separate fixed 133-member offline inventory and 14-member outer
closure. Existing SFT inventories remain unchanged. Maintenance uses the
checked-in command, offline first because the outer closure binds its bytes:

Expand Down Expand Up @@ -633,7 +650,7 @@ actual accepted wheel anchor is replaced by the actual newly built current-sourc
wheel in bound build material, using the existing normal builder. Never invent a
future SHA or embed a circular self-hash. Actual derived-image inventory and CPU
GRPO qualification remain separate from the 396-distribution base observation.
The old SFT profiles and fixed SFT68/outer5 and GRPO131/outer13 inventories stay
The old SFT profiles and fixed SFT68/outer5 and GRPO133/outer14 inventories stay
unchanged. Installed candidate tests require an actual fresh wheel, verify the
runtime YAML/inventory are shipped and the source image profile is absent, and
label their synthetic Git preplan observation as CPU control-flow evidence only.
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/provider-free-conformance.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1079,8 +1079,8 @@ jobs:
import hashlib
from tuner.runtime.offline_grpo_worker import verify_installed_grpo_members
from tuner.runtime.packaged_grpo_worker_closure import load_packaged_grpo_worker_closure
assert len(verify_installed_grpo_members().closure.members) == 131
assert len(load_packaged_grpo_worker_closure().members) == 13
assert len(verify_installed_grpo_members().closure.members) == 133
assert len(load_packaged_grpo_worker_closure().members) == 14
for package, relative in (
("tuner.runtime", "manifests/offline-grpo-worker-v1.json"),
("tuner.runtime", "manifests/packaged-grpo-worker-v1.json"),
Expand Down
1 change: 1 addition & 0 deletions .skills/fine-tuning/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ Train language models with SFT, KTO, and GRPO locally or on supported cloud prov
| Diagnose an offline SFT worker rejection | Read the exact retained `trainer.stderr.log`; closed phase/category/milestone labels locate a boundary, not a cause or retry authority; see `reference/sft-training.md` |
| Native MLX prepared SFT candidate | Internal exact-token batch/loss and runtime comparison only; no native launch CLI or API provider yet; see `reference/native-local-training.md` |
| Plan a derived training image | `python scripts/qualify_derived_training_image.py plan --config Trainers/image_profiles/<profile>.yaml` |
| Private GRPO constructor diagnosis | `python -B examples/training_qualification/grpo_constructor.py --help`; use a private config and separate reviewed build/diagnostic admissions; no public training authority; see `reference/grpo-training.md` and `docs/review/grpo-constructor-diagnostic.md` |
| Warm Space scaffold | `python3 Trainers/cloud/scripts/manage_space.py render --template vllm_warm --output-dir /tmp/my-space --base-image ghcr.io/<org>/<image>:<tag>` |
| Warm Space deploy | `python3 Trainers/cloud/scripts/manage_space.py deploy --space-id <user>/<space> --template vllm_warm --base-image ghcr.io/<org>/<image>:<tag> --hardware a10g-small --sleep-time 3600 --var BASE_MODEL=<model>` |
| ML training | `python tuner.py ml train --config Trainers/ml/configs/templates/regression.yaml` |
Expand Down
2 changes: 1 addition & 1 deletion .skills/fine-tuning/configs/qwen35_4b_token_profile.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ model:
runtime:
provider: modal
lock_path: tuner/execution/providers/modal/modal-runtime-v1.lock.json
expected_lock_sha256: 4f3fa81c9aeb9130258dec23f2b841e6dbdf2d686d1cf6b50249e743c3d496ca
expected_lock_sha256: 3bcd5d9ca2065a1462745e738e4e1d60f89e3c31829964bc2f054b795cf4b561
input:
jsonl_path: /replace/with/private/prepared-dataset.jsonl
mode: text
Expand Down
21 changes: 19 additions & 2 deletions .skills/fine-tuning/reference/grpo-training.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,23 @@

Group Relative Policy Optimization — optimizes model behavior using reward functions against generated completions.

For the consumed 0d515 Modal trainer-setup failure and restricted,
constructor-only Modal diagnostic, see
`docs/review/grpo-constructor-diagnostic.md`. The pinned Unsloth Zoo 2026.1.2
source requires an accelerator at import, so a CPU-only patched-constructor
probe cannot reach that boundary. The checked-in
`scripts/qualify_derived_training_image.py release plan-grpo-constructor-input`
command derives the exact four-row input. The private configured consumer is
`examples/training_qualification/grpo_constructor.py`; use its owner-only
example config and separate `prepare-model`, `plan`, `prepare`, `admit`,
`execute-once`, and `readback` review gates. It requires reviewed new
image/source and independent read-only retained snapshot custody. A diagnostic
claim is consumed; it grants no training replay or qualification. The old
deployment's superseded app generation is retained evidence, while the exact
old model Volume identity is rehydrated read-only. Generated Unsloth code is
not source-attested by pinned wheel files, so its type-site label remains
`OTHER` unless a future exact generated-code proof is added.

## Public GRPO declarations and CPU preparation

The provider-neutral `TrainingInputV1` accepts explicit method `grpo` with
Expand Down Expand Up @@ -206,7 +223,7 @@ auto-select BF16 on BF16-capable hardware while the recipe requests FP16 can
fail at `TRAINER_SETUP`. A closed `TypeError` marker alone cannot establish
that this was the historical cause, and it does not authorize replay.

GRPO has a separate fixed 131-member offline inventory and 13-member outer
GRPO has a separate fixed 133-member offline inventory and 14-member outer
closure. Existing SFT inventories remain unchanged. Maintenance uses the
checked-in command, offline first because the outer closure binds its bytes:

Expand Down Expand Up @@ -633,7 +650,7 @@ actual accepted wheel anchor is replaced by the actual newly built current-sourc
wheel in bound build material, using the existing normal builder. Never invent a
future SHA or embed a circular self-hash. Actual derived-image inventory and CPU
GRPO qualification remain separate from the 396-distribution base observation.
The old SFT profiles and fixed SFT68/outer5 and GRPO131/outer13 inventories stay
The old SFT profiles and fixed SFT68/outer5 and GRPO133/outer14 inventories stay
unchanged. Installed candidate tests require an actual fresh wheel, verify the
runtime YAML/inventory are shipped and the source image profile is absent, and
label their synthetic Git preplan observation as CPU control-flow evidence only.
Expand Down
29 changes: 23 additions & 6 deletions Trainers/grpo/runtime_v1.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,12 +177,21 @@ def build_grpo_config(config: dict, checkpoints_dir: Path, *, config_class, bf16


def train_grpo_core(*, model, tokenizer, reward_fn, formatted_dataset,
training_args, callbacks, trainer_class, resume=None, _runtime_milestone=None):
training_args, callbacks, trainer_class, resume=None, _runtime_milestone=None,
_constructor_only=False, _constructor_observer=None):
if type(_constructor_only) is not bool or (
_constructor_only and (resume is not None or not callable(_constructor_observer))
) or (_constructor_observer is not None and not callable(_constructor_observer)):
raise ValueError("invalid constructor diagnostic selection")
if _runtime_milestone is not None:
_runtime_milestone("TRAINER_SETUP")
trainer = create_grpo_trainer(trainer_class=trainer_class, model=model, processing_class=tokenizer,
reward_funcs=reward_fn, args=training_args,
train_dataset=formatted_dataset, callbacks=callbacks)
kwargs = dict(model=model, processing_class=tokenizer, reward_funcs=reward_fn,
args=training_args, train_dataset=formatted_dataset, callbacks=callbacks)
if _constructor_observer is not None:
_constructor_observer(trainer_class, kwargs)
trainer = create_grpo_trainer(trainer_class=trainer_class, **kwargs)
if _constructor_only:
return trainer, None
if _runtime_milestone is not None:
_runtime_milestone("TRAIN_CALL")
result = train_grpo_trainer(trainer, resume=resume)
Expand Down Expand Up @@ -422,7 +431,8 @@ def unique(pairs):
def run_grpo(*, config, dataset_bytes, reward_documents, reward_schema,
model_snapshot, model_identity, output_root, workload,
metric_sink=None, _dependency_factory=None, _packaged_artifacts=False,
qualification_evidence=None, _child_deadline=None, _runtime_milestone=None):
qualification_evidence=None, _child_deadline=None, _runtime_milestone=None,
_constructor_only=False, _constructor_observer=None):
"""Run the existing GRPO core with explicit immutable admitted inputs.

This entry does not authenticate a public plan or attest model member
Expand All @@ -431,6 +441,10 @@ def run_grpo(*, config, dataset_bytes, reward_documents, reward_schema,
"""
if _runtime_milestone is not None and not callable(_runtime_milestone):
raise ValueError("invalid private runtime milestone callback")
if type(_constructor_only) is not bool or (
_constructor_only and (not _packaged_artifacts or not callable(_constructor_observer))
) or (_constructor_observer is not None and not callable(_constructor_observer)):
raise ValueError("invalid constructor diagnostic selection")
def mark(value):
if _runtime_milestone is not None:
_runtime_milestone(value)
Expand Down Expand Up @@ -528,7 +542,10 @@ def on_log(self, args, state, control, logs=None, **kwargs):
trainer, result = train_grpo_core(model=model, tokenizer=tokenizer, reward_fn=reward_fn,
formatted_dataset=dataset, training_args=args, callbacks=callbacks,
trainer_class=deps['trainer_class'],
**({"_runtime_milestone": mark} if _runtime_milestone is not None else {}))
**({"_runtime_milestone": mark} if _runtime_milestone is not None else {}),
_constructor_only=_constructor_only, _constructor_observer=_constructor_observer)
if _constructor_only:
return trainer
mark("MEASUREMENT_RECORD")
evidence = measurements.record(workload) if measurements is not None else None
mark("SAVE")
Expand Down
Loading
Loading