inductive-mlxrl 0.1.1__tar.gz → 0.2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- inductive_mlxrl-0.2.2/CHANGELOG.md +87 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/CONTRIBUTING.md +26 -4
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/DESIGN.md +38 -4
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/PKG-INFO +92 -13
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/README.md +88 -9
- inductive_mlxrl-0.2.2/examples/qwen35_9b_g2_checkpoint.toml +29 -0
- inductive_mlxrl-0.2.2/examples/qwen3_0_6b_gigpo_recurring.toml +33 -0
- inductive_mlxrl-0.2.2/examples/qwen3_0_6b_grpo.toml +29 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/mlxrl/__init__.py +1 -2
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/mlxrl/algo/__init__.py +12 -0
- inductive_mlxrl-0.2.2/mlxrl/algo/gigpo.py +202 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/mlxrl/algo/grpo.py +36 -16
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/mlxrl/algorithm.py +41 -1
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/mlxrl/cli.py +176 -2
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/mlxrl/config.py +64 -7
- inductive_mlxrl-0.2.2/mlxrl/echo.py +43 -0
- inductive_mlxrl-0.2.2/mlxrl/env/__init__.py +27 -0
- inductive_mlxrl-0.2.2/mlxrl/env/base.py +75 -0
- inductive_mlxrl-0.2.2/mlxrl/env/reference.py +104 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/mlxrl/policy/__init__.py +18 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/mlxrl/policy/logprobs.py +98 -38
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/mlxrl/policy/model.py +16 -1
- inductive_mlxrl-0.2.2/mlxrl/policy/trajectory_logprobs.py +239 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/mlxrl/rollout/__init__.py +10 -0
- inductive_mlxrl-0.2.2/mlxrl/rollout/agentic.py +396 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/mlxrl/rollout/optimized.py +78 -34
- inductive_mlxrl-0.2.2/mlxrl/train/__init__.py +18 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/mlxrl/train/grpo.py +99 -29
- inductive_mlxrl-0.2.2/mlxrl/train/reference.py +25 -0
- inductive_mlxrl-0.2.2/mlxrl/train/trajectory.py +557 -0
- inductive_mlxrl-0.2.2/mlxrl/trajectory.py +179 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/pyproject.toml +5 -4
- inductive_mlxrl-0.2.2/tests/test_agentic_env.py +98 -0
- inductive_mlxrl-0.2.2/tests/test_agentic_rollout.py +217 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/tests/test_cli.py +37 -1
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/tests/test_config.py +78 -0
- inductive_mlxrl-0.2.2/tests/test_echo.py +329 -0
- inductive_mlxrl-0.2.2/tests/test_gigpo.py +141 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/tests/test_grpo.py +36 -2
- inductive_mlxrl-0.2.2/tests/test_optimized_rollout.py +181 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/tests/test_policy_logprobs.py +47 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/tests/test_train_grpo.py +130 -1
- inductive_mlxrl-0.2.2/tests/test_train_trajectory.py +286 -0
- inductive_mlxrl-0.2.2/tests/test_trajectory_logprobs.py +89 -0
- inductive_mlxrl-0.1.1/CHANGELOG.md +0 -37
- inductive_mlxrl-0.1.1/mlxrl/train/__init__.py +0 -5
- inductive_mlxrl-0.1.1/tests/test_optimized_rollout.py +0 -76
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/.gitignore +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/LICENSE +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/THIRD_PARTY_LICENSES.md +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/benchmarks/__init__.py +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/benchmarks/audit_phase4_config.py +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/benchmarks/external_baseline_worker.py +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/benchmarks/results/gate1_mlxrl_after.jsonl +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/benchmarks/results/gate1_mlxrl_after.md +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/benchmarks/results/gate1_mlxrl_after_final.jsonl +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/benchmarks/results/gate1_mlxrl_after_final.md +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/benchmarks/results/gate1_mlxrl_after_noprefixsync.jsonl +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/benchmarks/results/gate1_mlxrl_after_noprefixsync.md +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/benchmarks/results/gate1_mlxrl_before.jsonl +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/benchmarks/results/gate1_mlxrl_before.md +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/benchmarks/results/gate2_unified_smoke.jsonl +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/benchmarks/results/gate2_unified_smoke.md +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/benchmarks/results/gate3_mlx_tune_sync_256.jsonl +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/benchmarks/results/gate3_mlx_tune_sync_256.md +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/benchmarks/results/gate3_sync_blocked.jsonl +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/benchmarks/results/gate3_sync_blocked.md +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/benchmarks/results/gate3_sync_smoke.jsonl +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/benchmarks/results/gate3_sync_smoke.md +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/benchmarks/results/gate4_config_audit.json +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/benchmarks/results/gate4_config_audit.md +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/benchmarks/results/gate4_sampler_smoke.jsonl +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/benchmarks/results/gate4_sampler_smoke.md +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/benchmarks/results/gate5_full_reconciled.jsonl +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/benchmarks/results/gate5_full_reconciled.md +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/benchmarks/results/phase4_external_smoke.jsonl +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/benchmarks/results/phase4_external_smoke.md +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/benchmarks/results/phase4_full_all_targets.jsonl +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/benchmarks/results/phase4_full_all_targets.md +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/benchmarks/results/phase4_local_mlxrl_vs_mlx_lm.jsonl +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/benchmarks/results/phase4_local_mlxrl_vs_mlx_lm.md +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/benchmarks/results/phase4_mlx_lm_g4_smoke.jsonl +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/benchmarks/results/phase4_mlx_lm_g4_smoke.md +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/benchmarks/run_phase4.py +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/mlxrl/data/__init__.py +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/mlxrl/data/gsm8k.py +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/mlxrl/data/rewards.py +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/mlxrl/py.typed +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/mlxrl/rollout/naive.py +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/tests/test_benchmark_metrics.py +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/tests/test_import_direction.py +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/tests/test_policy_model.py +0 -0
- {inductive_mlxrl-0.1.1 → inductive_mlxrl-0.2.2}/tests/test_rewards.py +0 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here.
|
|
4
|
+
|
|
5
|
+
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project uses semantic versioning once releases are cut.
|
|
7
|
+
|
|
8
|
+
## [0.2.2] - 2026-06-25
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- ECHO world-modeling support for tagged multi-turn trajectories, composing an
|
|
13
|
+
independently normalized ECHO SFT loss with the existing GiGPO action loss.
|
|
14
|
+
- `echo_alpha` scheduling with constant and linear-taper-to-zero modes, plus
|
|
15
|
+
separate `loss_echo` and `echo_accuracy` diagnostics.
|
|
16
|
+
- Real-Qwen smoke coverage for tagged ECHO batches on Qwen3-0.6B and
|
|
17
|
+
Qwen3.5-9B MLX 4-bit models.
|
|
18
|
+
|
|
19
|
+
## [0.2.1] - 2026-06-25
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- Keep model-backed agentic/GiGPO decode tokens rank-2 during KV-cache decode,
|
|
24
|
+
fixing real Qwen3 model rollouts.
|
|
25
|
+
- Use valid repo-relative output paths in the committed Qwen smoke configs.
|
|
26
|
+
- Preserve eval-mode old-policy/reference logprob prep while restoring caller
|
|
27
|
+
train mode afterward.
|
|
28
|
+
|
|
29
|
+
## [0.2.0] - 2026-06-24
|
|
30
|
+
|
|
31
|
+
### Added
|
|
32
|
+
|
|
33
|
+
- Multi-turn agentic rollout path with Gym-style `Environment` / `EnvFactory`
|
|
34
|
+
protocols and deterministic reference environments.
|
|
35
|
+
- Trajectory data model with action-token spans and full-forward trajectory
|
|
36
|
+
logprob gathering for 4-bit policy, old-policy, and reference semantics.
|
|
37
|
+
- GiGPO (`Group-in-Group Policy Optimization`) with episode-level and
|
|
38
|
+
anchor-state step-level advantages, plus an exact `omega=0` reduction gate.
|
|
39
|
+
- Trajectory batch builder and optimizer step that preserve the existing
|
|
40
|
+
single-turn GRPO-family APIs.
|
|
41
|
+
- Config-driven GiGPO training route with `max_turns`, `rollout_mode`,
|
|
42
|
+
`env_name`, `max_observation_len`, `gigpo_omega`, `gigpo_gamma`, and
|
|
43
|
+
normalization knobs.
|
|
44
|
+
|
|
45
|
+
### Changed
|
|
46
|
+
|
|
47
|
+
- Extend the memory estimator to label multi-turn configs as estimated
|
|
48
|
+
OOM-risk shapes while preserving the measured v0.1 single-turn anchors.
|
|
49
|
+
|
|
50
|
+
## [0.1.2] - 2026-06-24
|
|
51
|
+
|
|
52
|
+
### Fixed
|
|
53
|
+
|
|
54
|
+
- Move the Python `<3.15` ceiling from package-level `Requires-Python` to the
|
|
55
|
+
MLX runtime dependency markers so universal resolvers can add the package to
|
|
56
|
+
projects with broad Python ranges while skipping unsupported MLX splits.
|
|
57
|
+
|
|
58
|
+
## [0.1.1] - 2026-06-24
|
|
59
|
+
|
|
60
|
+
### Fixed
|
|
61
|
+
|
|
62
|
+
- Mark `mlx` and `mlx-lm` runtime dependencies as macOS arm64-only and bound the
|
|
63
|
+
package to Python 3.11 through 3.14 so universal resolvers do not try to solve
|
|
64
|
+
unsupported MLX platform or Python splits.
|
|
65
|
+
|
|
66
|
+
## [0.1.0] - 2026-06-24
|
|
67
|
+
|
|
68
|
+
### Added
|
|
69
|
+
|
|
70
|
+
- Single-process MLX GRPO+QLoRA training path for Apple Silicon.
|
|
71
|
+
- Prefix-cached grouped rollout engine with compiled decode support.
|
|
72
|
+
- Adapter-disabled reference logprob path on one model object.
|
|
73
|
+
- Full-forward old-policy logprob recompute for 4-bit correctness.
|
|
74
|
+
- Algorithm protocol with GRPO, Dr. GRPO, DAPO, GSPO, and RLOO.
|
|
75
|
+
- DAPO `filter_batch` hook for dynamic zero-advantage group filtering.
|
|
76
|
+
- Per-layer MLX-LM gradient checkpointing for DeltaNet/linear-attention models.
|
|
77
|
+
- Micro-batched gradient accumulation for token-mean losses.
|
|
78
|
+
- Typed config schema and memory preflight helper calibrated to measured anchors.
|
|
79
|
+
- Phase 4 benchmark harness for `mlxrl`, `mlx-lm`, `mlx-tune`, and `mlx-lm-lora`.
|
|
80
|
+
- Linux CPU-safe CI for docs/config/import-direction checks.
|
|
81
|
+
|
|
82
|
+
### Notes
|
|
83
|
+
|
|
84
|
+
- `mlxrl` is pre-1.0; public APIs may change while the correctness gates settle.
|
|
85
|
+
- Full MLX/Metal tests require Apple Silicon or a self-hosted Mac runner.
|
|
86
|
+
- Published on PyPI as `inductive-mlxrl`; the import package and CLI command
|
|
87
|
+
remain `mlxrl`.
|
|
@@ -20,7 +20,9 @@ estimator anchor tests are part of the contract.
|
|
|
20
20
|
|
|
21
21
|
## Adding An Algorithm
|
|
22
22
|
|
|
23
|
-
Use `RLOOAlgorithm` in `mlxrl/algo/grpo.py` as the smallest
|
|
23
|
+
Use `RLOOAlgorithm` in `mlxrl/algo/grpo.py` as the smallest single-turn
|
|
24
|
+
template. Use `GiGPOAlgorithm` in `mlxrl/algo/gigpo.py` as the trajectory
|
|
25
|
+
template.
|
|
24
26
|
|
|
25
27
|
Required steps:
|
|
26
28
|
|
|
@@ -35,6 +37,23 @@ Required steps:
|
|
|
35
37
|
If an algorithm needs to drop or reshape examples before the loss, use the
|
|
36
38
|
`filter_batch` hook. Do not special-case it in the trainer.
|
|
37
39
|
|
|
40
|
+
Trajectory algorithms implement `TrajectoryAlgorithm`, ship a hand-computed
|
|
41
|
+
multi-turn loss/gradient test, and prove their reduction to an existing
|
|
42
|
+
objective when a degenerate config should do so. They may consume trajectory
|
|
43
|
+
metadata such as env state ids, but `rollout/`, `policy/`, and `train/` still
|
|
44
|
+
must not import concrete algorithms.
|
|
45
|
+
|
|
46
|
+
## Adding An Environment
|
|
47
|
+
|
|
48
|
+
External envs integrate through `EnvFactory(task, seed, group_index) ->
|
|
49
|
+
Environment`. Implement `reset()`, `step(action)`, `max_turns`, and
|
|
50
|
+
`state_id(observation)`. The env owns the anchor-state definition; the rollout
|
|
51
|
+
engine only records ids, and GiGPO groups them later.
|
|
52
|
+
|
|
53
|
+
Keep envs deterministic under the provided seed when possible. Add a tiny test
|
|
54
|
+
that resets, steps, returns stable state ids, and exercises truncation or
|
|
55
|
+
termination. Do not add omega gym itself to this repo.
|
|
56
|
+
|
|
38
57
|
## MLX And CI
|
|
39
58
|
|
|
40
59
|
GitHub-hosted Linux runners cannot run the MLX/Metal path. Linux CI gates the
|
|
@@ -47,9 +66,11 @@ would close this coverage gap.
|
|
|
47
66
|
|
|
48
67
|
## Package Compatibility
|
|
49
68
|
|
|
50
|
-
The PyPI distribution
|
|
51
|
-
|
|
52
|
-
|
|
69
|
+
The PyPI distribution requires Python 3.11+. The MLX runtime path is supported
|
|
70
|
+
on Apple Silicon with Python 3.11 through 3.14. Keep the `mlx` and `mlx-lm`
|
|
71
|
+
runtime dependencies marked for macOS arm64 and Python `<3.15` so universal
|
|
72
|
+
resolvers do not try to solve MLX wheels for unsupported platform or Python
|
|
73
|
+
splits.
|
|
53
74
|
|
|
54
75
|
## Release Cycle
|
|
55
76
|
|
|
@@ -103,6 +124,7 @@ In scope:
|
|
|
103
124
|
- single-process Apple Silicon RL post-training;
|
|
104
125
|
- QLoRA on local MLX LLMs;
|
|
105
126
|
- critic-free on-policy algorithms;
|
|
127
|
+
- multi-turn agentic environments through the small env protocol;
|
|
106
128
|
- memory-conscious rollout and training paths.
|
|
107
129
|
|
|
108
130
|
Out of scope:
|
|
@@ -7,10 +7,10 @@ fast enough that rollout is the main problem and the loss stays thin.
|
|
|
7
7
|
## Critic-Free By Design
|
|
8
8
|
|
|
9
9
|
The library is intentionally limited to rollout-based policy-gradient methods:
|
|
10
|
-
GRPO, Dr. GRPO, DAPO, GSPO, and
|
|
11
|
-
critic/value model path, a different forward pass, and a different
|
|
12
|
-
profile. DPO and ORPO are also out of scope because they are offline
|
|
13
|
-
objectives rather than on-policy rollout algorithms.
|
|
10
|
+
GRPO, Dr. GRPO, DAPO, GSPO, RLOO, and GiGPO. PPO is out of scope because it
|
|
11
|
+
needs a critic/value model path, a different forward pass, and a different
|
|
12
|
+
memory profile. DPO and ORPO are also out of scope because they are offline
|
|
13
|
+
preference objectives rather than on-policy rollout algorithms.
|
|
14
14
|
|
|
15
15
|
That boundary matters. `mlxrl` keeps one policy model object in memory, attaches
|
|
16
16
|
QLoRA adapters to it, and computes reference logprobs by disabling those
|
|
@@ -32,6 +32,24 @@ stable while algorithms change. DAPO's dynamic sampling is the proof that the
|
|
|
32
32
|
interface is more general than "GRPO with renamed constants": it drops
|
|
33
33
|
zero-advantage groups through `filter_batch` without special trainer branches.
|
|
34
34
|
|
|
35
|
+
Multi-turn algorithms use the sibling `TrajectoryAlgorithm` protocol rather
|
|
36
|
+
than widening the single-turn `Algorithm` contract. GiGPO is the first
|
|
37
|
+
implementation: the rollout engine records env-provided state ids, while the
|
|
38
|
+
algorithm owns anchor-state grouping and credit assignment.
|
|
39
|
+
|
|
40
|
+
## Agentic Environment Seam
|
|
41
|
+
|
|
42
|
+
Agentic rollout is built around `EnvFactory(task, seed, group_index) ->
|
|
43
|
+
Environment`. An environment exposes `reset()`, `step(action)`, `max_turns`,
|
|
44
|
+
and `state_id(observation)`. The state id is deliberately supplied by the env:
|
|
45
|
+
omega gym, WebShop, ALFWorld, or a toy env each decides what counts as the same
|
|
46
|
+
anchor state.
|
|
47
|
+
|
|
48
|
+
The engine records observations, actions, rewards, state ids, full token
|
|
49
|
+
history, and action-token spans. It does not compute anchor groups. This keeps
|
|
50
|
+
rollout reusable for future trajectory algorithms while GiGPO performs the
|
|
51
|
+
group-in-group advantage calculation offline from the same trajectories.
|
|
52
|
+
|
|
35
53
|
## Correctness Gates
|
|
36
54
|
|
|
37
55
|
Speed changes are allowed only behind equivalence gates. The original Phase 1
|
|
@@ -40,6 +58,11 @@ token-for-token at fixed seed and match loss within tolerance. The protocol
|
|
|
40
58
|
refactor was checked against the pre-refactor GRPO and Dr. GRPO losses with
|
|
41
59
|
zero loss and adapter-gradient difference.
|
|
42
60
|
|
|
61
|
+
GiGPO adds two reduction gates: `omega=0` must match episode-level GRPO over the
|
|
62
|
+
same trajectories, and single-turn one-step trajectories with `omega=0` must
|
|
63
|
+
match the v0.1 GRPO path through loss and adapter gradient. Toy multi-turn
|
|
64
|
+
cases also carry hand-computed advantage, loss, and gradient checks.
|
|
65
|
+
|
|
43
66
|
Old-policy changes use a stronger gate than naive equality. At 4-bit, the
|
|
44
67
|
rollout-time cached decode realization and the full-forward realization are not
|
|
45
68
|
numerically identical. Stored rollout logprobs are attractive because they are
|
|
@@ -56,6 +79,11 @@ for gradient-bearing or importance-weighting quantities. Anything used in the
|
|
|
56
79
|
loss denominator, KL, or adapter gradient must come from the full-forward path
|
|
57
80
|
unless a dedicated stability gate proves otherwise.
|
|
58
81
|
|
|
82
|
+
For multi-turn trajectories, this means policy, old-policy, and reference
|
|
83
|
+
logprobs are gathered from a full forward over the complete token history, then
|
|
84
|
+
masked down to action-token spans only. Rollout-time cached logprobs remain
|
|
85
|
+
diagnostic data, not training data.
|
|
86
|
+
|
|
59
87
|
## Memory As A First-Class Constraint
|
|
60
88
|
|
|
61
89
|
Apple Silicon's unified memory is the deployment target, not an afterthought.
|
|
@@ -70,3 +98,9 @@ anchors and labels long-sequence uncheckpointed hybrid configs as OOM-risk
|
|
|
70
98
|
estimates, not measurements. Its purpose is to nudge users toward the knob that
|
|
71
99
|
will most likely make a run fit: enable checkpointing, reduce G, then reduce
|
|
72
100
|
completion length.
|
|
101
|
+
|
|
102
|
+
Multi-turn configs add trajectory length as `prompt + turns * action_tokens +
|
|
103
|
+
(turns - 1) * observation_tokens`. Parallel-per-turn rollout keeps G
|
|
104
|
+
per-trajectory cache/state objects resident; sequential mode is the lower-memory
|
|
105
|
+
fallback. Until more measured anchors exist, multi-turn estimates are labeled as
|
|
106
|
+
OOM-risk estimates rather than confident measurements.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: inductive-mlxrl
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Small single-process RL post-training for LLMs on Apple Silicon with MLX.
|
|
5
5
|
Project-URL: Homepage, https://github.com/inductiveML/mlxrl
|
|
6
6
|
Project-URL: Repository, https://github.com/inductiveML/mlxrl
|
|
@@ -18,23 +18,25 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.13
|
|
19
19
|
Classifier: Programming Language :: Python :: 3.14
|
|
20
20
|
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
21
|
-
Requires-Python:
|
|
22
|
-
Requires-Dist: mlx-lm>=0.31.3; platform_system == 'Darwin' and platform_machine == 'arm64'
|
|
23
|
-
Requires-Dist: mlx>=0.31.2; platform_system == 'Darwin' and platform_machine == 'arm64'
|
|
21
|
+
Requires-Python: >=3.11
|
|
22
|
+
Requires-Dist: mlx-lm>=0.31.3; python_version < '3.15' and platform_system == 'Darwin' and platform_machine == 'arm64'
|
|
23
|
+
Requires-Dist: mlx>=0.31.2; python_version < '3.15' and platform_system == 'Darwin' and platform_machine == 'arm64'
|
|
24
24
|
Description-Content-Type: text/markdown
|
|
25
25
|
|
|
26
26
|
# mlxrl
|
|
27
27
|
|
|
28
|
-
Fast on-policy MLX RL for Apple Silicon
|
|
29
|
-
preference tuning, and
|
|
28
|
+
Fast on-policy MLX RL for Apple Silicon, including single-turn GRPO-family RL
|
|
29
|
+
and multi-turn GiGPO; not a general RL framework, not preference tuning, and
|
|
30
|
+
not distributed training.
|
|
30
31
|
|
|
31
32
|
`mlxrl` is a small, single-process RL post-training library for LLMs on Apple
|
|
32
33
|
Silicon. It is built around one idea: GRPO on MLX should be a fast batched
|
|
33
34
|
rollout path with a thin loss and optimizer step on top, not a framework.
|
|
34
35
|
|
|
35
|
-
The current implementation targets QLoRA GRPO on local 4-bit MLX models.
|
|
36
|
-
reuses `mlx-lm` model loading, LoRA layers, KV caches, and sampling
|
|
37
|
-
and keeps generation and training in one Python process with one
|
|
36
|
+
The current implementation targets QLoRA GRPO/GiGPO on local 4-bit MLX models.
|
|
37
|
+
It reuses `mlx-lm` model loading, LoRA layers, KV caches, and sampling
|
|
38
|
+
utilities, and keeps generation and training in one Python process with one
|
|
39
|
+
model object.
|
|
38
40
|
|
|
39
41
|
`mlxrl` is pre-1.0. The correctness gates are stable, but import APIs and config
|
|
40
42
|
fields may change before a 1.0 release.
|
|
@@ -66,6 +68,9 @@ UV_CACHE_DIR=.uv-cache uv run mlxrl train \
|
|
|
66
68
|
- Adapter-disabled reference policy on the same model object.
|
|
67
69
|
- GRPO, Dr. GRPO, DAPO, and GSPO loss variants.
|
|
68
70
|
- RLOO (REINFORCE Leave-One-Out) as a critic-free rollout objective.
|
|
71
|
+
- Multi-turn agentic rollout through an `Environment` / `EnvFactory` protocol.
|
|
72
|
+
- GiGPO with episode-level and anchor-state step-level advantages.
|
|
73
|
+
- Full-forward trajectory action-logprob recompute for 4-bit correctness.
|
|
69
74
|
- QLoRA injection on dense and heterogeneous/hybrid layer stacks.
|
|
70
75
|
- Qwen3.5-style hybrid support via MLX-LM auto LoRA targeting, including
|
|
71
76
|
DeltaNet `linear_attn.in_proj_*` and dense attention `q/k/v/o_proj`.
|
|
@@ -101,10 +106,11 @@ Run commands through the local environment:
|
|
|
101
106
|
UV_CACHE_DIR=.uv-cache uv run mlxrl --help
|
|
102
107
|
```
|
|
103
108
|
|
|
104
|
-
Python 3.11
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
`
|
|
109
|
+
Python 3.11+ is required. The MLX runtime path is supported on Apple Silicon
|
|
110
|
+
with Python 3.11 through 3.14, matching the current MLX wheel support window.
|
|
111
|
+
Runtime dependencies are intentionally small: `mlx` and `mlx-lm` on macOS
|
|
112
|
+
arm64. Development dependencies include `pytest`, `ruff`, `pyright`,
|
|
113
|
+
`mlx-tune`, and `mlx-lm-lora` for comparison benchmarks.
|
|
108
114
|
The PyPI distribution name is `inductive-mlxrl`; the import package and console
|
|
109
115
|
script remain `mlxrl`.
|
|
110
116
|
|
|
@@ -158,6 +164,14 @@ UV_CACHE_DIR=.uv-cache uv run mlxrl train \
|
|
|
158
164
|
--available-memory-gb 48
|
|
159
165
|
```
|
|
160
166
|
|
|
167
|
+
Reference multi-turn GiGPO run against the built-in recurring-state env:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
UV_CACHE_DIR=.uv-cache uv run mlxrl train \
|
|
171
|
+
--config examples/qwen3_0_6b_gigpo_recurring.toml \
|
|
172
|
+
--available-memory-gb 48
|
|
173
|
+
```
|
|
174
|
+
|
|
161
175
|
The config schema validates model id, quant bits, group size, completion/prompt
|
|
162
176
|
lengths, checkpointing granularity, `iogpu.wired_limit_mb`, optimizer settings,
|
|
163
177
|
algorithm hyperparameters, KL beta, and seed before a model is loaded. CLI
|
|
@@ -242,11 +256,71 @@ metrics = optimizer_step(
|
|
|
242
256
|
)
|
|
243
257
|
```
|
|
244
258
|
|
|
259
|
+
Multi-turn GiGPO uses the additive trajectory path:
|
|
260
|
+
|
|
261
|
+
```python
|
|
262
|
+
from mlxrl.algo import GiGPOAlgorithm
|
|
263
|
+
from mlxrl.env import RecurringStateTextEnv
|
|
264
|
+
from mlxrl.rollout import generate_agentic_trajectories
|
|
265
|
+
from mlxrl.train import batch_from_trajectories, optimizer_step_trajectory
|
|
266
|
+
|
|
267
|
+
algorithm = GiGPOAlgorithm(omega=1.0, gamma=1.0)
|
|
268
|
+
trajectories = generate_agentic_trajectories(
|
|
269
|
+
model=model,
|
|
270
|
+
tokenizer=tokenizer,
|
|
271
|
+
env_factory=lambda task, seed, group: RecurringStateTextEnv(
|
|
272
|
+
task=str(task),
|
|
273
|
+
max_turns=3,
|
|
274
|
+
),
|
|
275
|
+
tasks=["finish the task"],
|
|
276
|
+
group_size=4,
|
|
277
|
+
sampling=sampling,
|
|
278
|
+
rollout_mode="parallel_per_turn",
|
|
279
|
+
)
|
|
280
|
+
batch = batch_from_trajectories(
|
|
281
|
+
model=model,
|
|
282
|
+
trajectories=trajectories,
|
|
283
|
+
group_size=4,
|
|
284
|
+
pad_token_id=pad_token_id,
|
|
285
|
+
algorithm=algorithm,
|
|
286
|
+
compute_reference=beta != 0.0,
|
|
287
|
+
)
|
|
288
|
+
metrics = optimizer_step_trajectory(
|
|
289
|
+
model=model,
|
|
290
|
+
optimizer=optimizer,
|
|
291
|
+
batch=batch,
|
|
292
|
+
beta=beta,
|
|
293
|
+
pad_token_id=pad_token_id,
|
|
294
|
+
algorithm=algorithm,
|
|
295
|
+
)
|
|
296
|
+
```
|
|
297
|
+
|
|
245
298
|
`micro_batch_size=0` keeps the original whole-batch path. Micro-batching is
|
|
246
299
|
currently exact for token-mean policy losses: base GRPO, DAPO, GSPO token mode,
|
|
247
300
|
RLOO, and Dr. GRPO with `loss_reduction="token_mean"`. Sequence-reduced losses
|
|
248
301
|
should keep `micro_batch_size=0`.
|
|
249
302
|
|
|
303
|
+
## ECHO World Modeling
|
|
304
|
+
|
|
305
|
+
ECHO is an additive GiGPO trainer feature for tagged multi-turn trajectories.
|
|
306
|
+
Producer code may attach `token_roles` to each `Trajectory`, aligned to
|
|
307
|
+
`full_token_ids`: `0 = MASKED`, `1 = ACTION`, `2 = ECHO`. ACTION tokens keep
|
|
308
|
+
the normal GiGPO policy-gradient loss. ECHO tokens add an independently
|
|
309
|
+
normalized SFT term, `alpha * NLL`, in the same forward/backward pass.
|
|
310
|
+
|
|
311
|
+
`echo_alpha` defaults to `0.0`, which leaves current GiGPO behavior untouched.
|
|
312
|
+
For early world-modeling, start small, roughly `0.005` to `0.05`, and consider
|
|
313
|
+
`echo_schedule = "linear_taper_to_zero"` with `echo_taper_steps = N` so training
|
|
314
|
+
returns to pure RL. `alpha` is model-size-sensitive; too-high values can
|
|
315
|
+
overfit tool responses or collapse RL.
|
|
316
|
+
|
|
317
|
+
ECHO is content-agnostic by design. `mlxrl` never inspects token text to decide
|
|
318
|
+
what is an environment or tool response. The rollout producer owns the tags:
|
|
319
|
+
MASKED tokens have zero gradient, ACTION tokens receive the RL advantage, and
|
|
320
|
+
ECHO tokens receive only the SFT loss with no KL penalty or importance ratio.
|
|
321
|
+
The trainer logs `loss_echo` and token-level `echo_acc` separately from the
|
|
322
|
+
ACTION loss.
|
|
323
|
+
|
|
250
324
|
## Policy Semantics
|
|
251
325
|
|
|
252
326
|
- The base model is frozen before LoRA injection.
|
|
@@ -277,6 +351,7 @@ import concrete algorithm implementations.
|
|
|
277
351
|
| DAPO | asymmetric low/high clipping plus optional dynamic zero-advantage group filtering |
|
|
278
352
|
| GSPO | sequence-level, length-normalized importance ratio and clipping |
|
|
279
353
|
| RLOO | leave-one-out group baseline, no critic, no std-normalized advantage |
|
|
354
|
+
| GiGPO | multi-turn episode advantage plus anchor-state step advantage |
|
|
280
355
|
|
|
281
356
|
## Memory Preflight
|
|
282
357
|
|
|
@@ -295,6 +370,9 @@ Qwen3.5-9B/G2/seq609/per-layer-checkpointed, `45.9 GB` for
|
|
|
295
370
|
Qwen3.5-9B/G4/seq609/per-layer-checkpointed, and `36 GB` for
|
|
296
371
|
Qwen3.5-9B/G2/seq128/no-checkpoint. For hybrid 9B no-checkpoint long-sequence
|
|
297
372
|
configs, it reports an OOM-risk lower bound rather than a fake precise peak.
|
|
373
|
+
Multi-turn configs include `max_turns` and `max_observation_len` in the
|
|
374
|
+
estimated trajectory length and are labeled as estimated OOM-risk shapes until
|
|
375
|
+
new measured anchors are added.
|
|
298
376
|
For an obviously too-large Qwen3.5-9B/G8/prompt97/T512/no-checkpoint config on
|
|
299
377
|
48 GB, it flags the run and suggests the measured-boundary fallback around
|
|
300
378
|
G4/T512/checkpointed.
|
|
@@ -374,6 +452,7 @@ updates, or benchmark timing boundaries.
|
|
|
374
452
|
```text
|
|
375
453
|
mlxrl/
|
|
376
454
|
rollout/ # batched group generation
|
|
455
|
+
env/ # agentic environment protocols and reference envs
|
|
377
456
|
policy/ # model loading, LoRA setup, logprob passes
|
|
378
457
|
algo/ # GRPO-family advantages and losses
|
|
379
458
|
train/ # value_and_grad and optimizer integration
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
# mlxrl
|
|
2
2
|
|
|
3
|
-
Fast on-policy MLX RL for Apple Silicon
|
|
4
|
-
preference tuning, and
|
|
3
|
+
Fast on-policy MLX RL for Apple Silicon, including single-turn GRPO-family RL
|
|
4
|
+
and multi-turn GiGPO; not a general RL framework, not preference tuning, and
|
|
5
|
+
not distributed training.
|
|
5
6
|
|
|
6
7
|
`mlxrl` is a small, single-process RL post-training library for LLMs on Apple
|
|
7
8
|
Silicon. It is built around one idea: GRPO on MLX should be a fast batched
|
|
8
9
|
rollout path with a thin loss and optimizer step on top, not a framework.
|
|
9
10
|
|
|
10
|
-
The current implementation targets QLoRA GRPO on local 4-bit MLX models.
|
|
11
|
-
reuses `mlx-lm` model loading, LoRA layers, KV caches, and sampling
|
|
12
|
-
and keeps generation and training in one Python process with one
|
|
11
|
+
The current implementation targets QLoRA GRPO/GiGPO on local 4-bit MLX models.
|
|
12
|
+
It reuses `mlx-lm` model loading, LoRA layers, KV caches, and sampling
|
|
13
|
+
utilities, and keeps generation and training in one Python process with one
|
|
14
|
+
model object.
|
|
13
15
|
|
|
14
16
|
`mlxrl` is pre-1.0. The correctness gates are stable, but import APIs and config
|
|
15
17
|
fields may change before a 1.0 release.
|
|
@@ -41,6 +43,9 @@ UV_CACHE_DIR=.uv-cache uv run mlxrl train \
|
|
|
41
43
|
- Adapter-disabled reference policy on the same model object.
|
|
42
44
|
- GRPO, Dr. GRPO, DAPO, and GSPO loss variants.
|
|
43
45
|
- RLOO (REINFORCE Leave-One-Out) as a critic-free rollout objective.
|
|
46
|
+
- Multi-turn agentic rollout through an `Environment` / `EnvFactory` protocol.
|
|
47
|
+
- GiGPO with episode-level and anchor-state step-level advantages.
|
|
48
|
+
- Full-forward trajectory action-logprob recompute for 4-bit correctness.
|
|
44
49
|
- QLoRA injection on dense and heterogeneous/hybrid layer stacks.
|
|
45
50
|
- Qwen3.5-style hybrid support via MLX-LM auto LoRA targeting, including
|
|
46
51
|
DeltaNet `linear_attn.in_proj_*` and dense attention `q/k/v/o_proj`.
|
|
@@ -76,10 +81,11 @@ Run commands through the local environment:
|
|
|
76
81
|
UV_CACHE_DIR=.uv-cache uv run mlxrl --help
|
|
77
82
|
```
|
|
78
83
|
|
|
79
|
-
Python 3.11
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
`
|
|
84
|
+
Python 3.11+ is required. The MLX runtime path is supported on Apple Silicon
|
|
85
|
+
with Python 3.11 through 3.14, matching the current MLX wheel support window.
|
|
86
|
+
Runtime dependencies are intentionally small: `mlx` and `mlx-lm` on macOS
|
|
87
|
+
arm64. Development dependencies include `pytest`, `ruff`, `pyright`,
|
|
88
|
+
`mlx-tune`, and `mlx-lm-lora` for comparison benchmarks.
|
|
83
89
|
The PyPI distribution name is `inductive-mlxrl`; the import package and console
|
|
84
90
|
script remain `mlxrl`.
|
|
85
91
|
|
|
@@ -133,6 +139,14 @@ UV_CACHE_DIR=.uv-cache uv run mlxrl train \
|
|
|
133
139
|
--available-memory-gb 48
|
|
134
140
|
```
|
|
135
141
|
|
|
142
|
+
Reference multi-turn GiGPO run against the built-in recurring-state env:
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
UV_CACHE_DIR=.uv-cache uv run mlxrl train \
|
|
146
|
+
--config examples/qwen3_0_6b_gigpo_recurring.toml \
|
|
147
|
+
--available-memory-gb 48
|
|
148
|
+
```
|
|
149
|
+
|
|
136
150
|
The config schema validates model id, quant bits, group size, completion/prompt
|
|
137
151
|
lengths, checkpointing granularity, `iogpu.wired_limit_mb`, optimizer settings,
|
|
138
152
|
algorithm hyperparameters, KL beta, and seed before a model is loaded. CLI
|
|
@@ -217,11 +231,71 @@ metrics = optimizer_step(
|
|
|
217
231
|
)
|
|
218
232
|
```
|
|
219
233
|
|
|
234
|
+
Multi-turn GiGPO uses the additive trajectory path:
|
|
235
|
+
|
|
236
|
+
```python
|
|
237
|
+
from mlxrl.algo import GiGPOAlgorithm
|
|
238
|
+
from mlxrl.env import RecurringStateTextEnv
|
|
239
|
+
from mlxrl.rollout import generate_agentic_trajectories
|
|
240
|
+
from mlxrl.train import batch_from_trajectories, optimizer_step_trajectory
|
|
241
|
+
|
|
242
|
+
algorithm = GiGPOAlgorithm(omega=1.0, gamma=1.0)
|
|
243
|
+
trajectories = generate_agentic_trajectories(
|
|
244
|
+
model=model,
|
|
245
|
+
tokenizer=tokenizer,
|
|
246
|
+
env_factory=lambda task, seed, group: RecurringStateTextEnv(
|
|
247
|
+
task=str(task),
|
|
248
|
+
max_turns=3,
|
|
249
|
+
),
|
|
250
|
+
tasks=["finish the task"],
|
|
251
|
+
group_size=4,
|
|
252
|
+
sampling=sampling,
|
|
253
|
+
rollout_mode="parallel_per_turn",
|
|
254
|
+
)
|
|
255
|
+
batch = batch_from_trajectories(
|
|
256
|
+
model=model,
|
|
257
|
+
trajectories=trajectories,
|
|
258
|
+
group_size=4,
|
|
259
|
+
pad_token_id=pad_token_id,
|
|
260
|
+
algorithm=algorithm,
|
|
261
|
+
compute_reference=beta != 0.0,
|
|
262
|
+
)
|
|
263
|
+
metrics = optimizer_step_trajectory(
|
|
264
|
+
model=model,
|
|
265
|
+
optimizer=optimizer,
|
|
266
|
+
batch=batch,
|
|
267
|
+
beta=beta,
|
|
268
|
+
pad_token_id=pad_token_id,
|
|
269
|
+
algorithm=algorithm,
|
|
270
|
+
)
|
|
271
|
+
```
|
|
272
|
+
|
|
220
273
|
`micro_batch_size=0` keeps the original whole-batch path. Micro-batching is
|
|
221
274
|
currently exact for token-mean policy losses: base GRPO, DAPO, GSPO token mode,
|
|
222
275
|
RLOO, and Dr. GRPO with `loss_reduction="token_mean"`. Sequence-reduced losses
|
|
223
276
|
should keep `micro_batch_size=0`.
|
|
224
277
|
|
|
278
|
+
## ECHO World Modeling
|
|
279
|
+
|
|
280
|
+
ECHO is an additive GiGPO trainer feature for tagged multi-turn trajectories.
|
|
281
|
+
Producer code may attach `token_roles` to each `Trajectory`, aligned to
|
|
282
|
+
`full_token_ids`: `0 = MASKED`, `1 = ACTION`, `2 = ECHO`. ACTION tokens keep
|
|
283
|
+
the normal GiGPO policy-gradient loss. ECHO tokens add an independently
|
|
284
|
+
normalized SFT term, `alpha * NLL`, in the same forward/backward pass.
|
|
285
|
+
|
|
286
|
+
`echo_alpha` defaults to `0.0`, which leaves current GiGPO behavior untouched.
|
|
287
|
+
For early world-modeling, start small, roughly `0.005` to `0.05`, and consider
|
|
288
|
+
`echo_schedule = "linear_taper_to_zero"` with `echo_taper_steps = N` so training
|
|
289
|
+
returns to pure RL. `alpha` is model-size-sensitive; too-high values can
|
|
290
|
+
overfit tool responses or collapse RL.
|
|
291
|
+
|
|
292
|
+
ECHO is content-agnostic by design. `mlxrl` never inspects token text to decide
|
|
293
|
+
what is an environment or tool response. The rollout producer owns the tags:
|
|
294
|
+
MASKED tokens have zero gradient, ACTION tokens receive the RL advantage, and
|
|
295
|
+
ECHO tokens receive only the SFT loss with no KL penalty or importance ratio.
|
|
296
|
+
The trainer logs `loss_echo` and token-level `echo_acc` separately from the
|
|
297
|
+
ACTION loss.
|
|
298
|
+
|
|
225
299
|
## Policy Semantics
|
|
226
300
|
|
|
227
301
|
- The base model is frozen before LoRA injection.
|
|
@@ -252,6 +326,7 @@ import concrete algorithm implementations.
|
|
|
252
326
|
| DAPO | asymmetric low/high clipping plus optional dynamic zero-advantage group filtering |
|
|
253
327
|
| GSPO | sequence-level, length-normalized importance ratio and clipping |
|
|
254
328
|
| RLOO | leave-one-out group baseline, no critic, no std-normalized advantage |
|
|
329
|
+
| GiGPO | multi-turn episode advantage plus anchor-state step advantage |
|
|
255
330
|
|
|
256
331
|
## Memory Preflight
|
|
257
332
|
|
|
@@ -270,6 +345,9 @@ Qwen3.5-9B/G2/seq609/per-layer-checkpointed, `45.9 GB` for
|
|
|
270
345
|
Qwen3.5-9B/G4/seq609/per-layer-checkpointed, and `36 GB` for
|
|
271
346
|
Qwen3.5-9B/G2/seq128/no-checkpoint. For hybrid 9B no-checkpoint long-sequence
|
|
272
347
|
configs, it reports an OOM-risk lower bound rather than a fake precise peak.
|
|
348
|
+
Multi-turn configs include `max_turns` and `max_observation_len` in the
|
|
349
|
+
estimated trajectory length and are labeled as estimated OOM-risk shapes until
|
|
350
|
+
new measured anchors are added.
|
|
273
351
|
For an obviously too-large Qwen3.5-9B/G8/prompt97/T512/no-checkpoint config on
|
|
274
352
|
48 GB, it flags the run and suggests the measured-boundary fallback around
|
|
275
353
|
G4/T512/checkpointed.
|
|
@@ -349,6 +427,7 @@ updates, or benchmark timing boundaries.
|
|
|
349
427
|
```text
|
|
350
428
|
mlxrl/
|
|
351
429
|
rollout/ # batched group generation
|
|
430
|
+
env/ # agentic environment protocols and reference envs
|
|
352
431
|
policy/ # model loading, LoRA setup, logprob passes
|
|
353
432
|
algo/ # GRPO-family advantages and losses
|
|
354
433
|
train/ # value_and_grad and optimizer integration
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
model_id = "mlx-community/Qwen3.5-9B-MLX-4bit"
|
|
2
|
+
quant_bits = 4
|
|
3
|
+
group_size = 2
|
|
4
|
+
max_prompt_len = 97
|
|
5
|
+
max_completion_len = 512
|
|
6
|
+
steps = 1
|
|
7
|
+
seed = 7
|
|
8
|
+
kl_beta = 0.0
|
|
9
|
+
rank = 16
|
|
10
|
+
scale = 2.0
|
|
11
|
+
dropout = 0.0
|
|
12
|
+
gradient_checkpointing = true
|
|
13
|
+
checkpoint_granularity = "per-layer"
|
|
14
|
+
iogpu_wired_limit_mb = 49152
|
|
15
|
+
micro_batch_size = 0
|
|
16
|
+
output = "reference_outputs/mlxrl_qwen35_9b_g2_checkpoint.npz"
|
|
17
|
+
|
|
18
|
+
[optimizer]
|
|
19
|
+
name = "adam"
|
|
20
|
+
learning_rate = 0.00001
|
|
21
|
+
|
|
22
|
+
[sampling]
|
|
23
|
+
temperature = 0.7
|
|
24
|
+
top_p = 0.95
|
|
25
|
+
min_p = 0.0
|
|
26
|
+
top_k = 0
|
|
27
|
+
|
|
28
|
+
[algorithm]
|
|
29
|
+
name = "grpo"
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
model_id = "mlx-community/Qwen3-0.6B-4bit"
|
|
2
|
+
group_size = 4
|
|
3
|
+
max_prompt_len = 512
|
|
4
|
+
max_completion_len = 32
|
|
5
|
+
max_turns = 3
|
|
6
|
+
max_observation_len = 64
|
|
7
|
+
rollout_mode = "parallel_per_turn"
|
|
8
|
+
env_name = "recurring-text"
|
|
9
|
+
steps = 5
|
|
10
|
+
seed = 7
|
|
11
|
+
kl_beta = 0.0
|
|
12
|
+
rank = 8
|
|
13
|
+
scale = 20.0
|
|
14
|
+
dropout = 0.0
|
|
15
|
+
gradient_checkpointing = false
|
|
16
|
+
micro_batch_size = 0
|
|
17
|
+
output = "reference_outputs/gigpo_recurring_reference.npz"
|
|
18
|
+
|
|
19
|
+
[optimizer]
|
|
20
|
+
name = "adam"
|
|
21
|
+
learning_rate = 0.00001
|
|
22
|
+
|
|
23
|
+
[sampling]
|
|
24
|
+
temperature = 0.7
|
|
25
|
+
top_p = 0.95
|
|
26
|
+
min_p = 0.0
|
|
27
|
+
top_k = 0
|
|
28
|
+
|
|
29
|
+
[algorithm]
|
|
30
|
+
name = "gigpo"
|
|
31
|
+
gigpo_omega = 1.0
|
|
32
|
+
gigpo_gamma = 1.0
|
|
33
|
+
gigpo_normalization = "std"
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
model_id = "mlx-community/Qwen3-0.6B-4bit"
|
|
2
|
+
quant_bits = 4
|
|
3
|
+
group_size = 2
|
|
4
|
+
max_completion_len = 4
|
|
5
|
+
max_prompt_len = 4096
|
|
6
|
+
steps = 1
|
|
7
|
+
seed = 7
|
|
8
|
+
kl_beta = 0.0
|
|
9
|
+
rank = 8
|
|
10
|
+
scale = 20.0
|
|
11
|
+
dropout = 0.0
|
|
12
|
+
gradient_checkpointing = false
|
|
13
|
+
checkpoint_granularity = "per-layer"
|
|
14
|
+
iogpu_wired_limit_mb = 49152
|
|
15
|
+
micro_batch_size = 0
|
|
16
|
+
output = "reference_outputs/mlxrl_config_smoke.npz"
|
|
17
|
+
|
|
18
|
+
[optimizer]
|
|
19
|
+
name = "adam"
|
|
20
|
+
learning_rate = 0.00001
|
|
21
|
+
|
|
22
|
+
[sampling]
|
|
23
|
+
temperature = 0.7
|
|
24
|
+
top_p = 0.95
|
|
25
|
+
min_p = 0.0
|
|
26
|
+
top_k = 0
|
|
27
|
+
|
|
28
|
+
[algorithm]
|
|
29
|
+
name = "grpo"
|