inductive-mlxrl 0.2.1__tar.gz → 0.2.3__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.
Files changed (104) hide show
  1. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/CHANGELOG.md +34 -0
  2. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/CONTRIBUTING.md +5 -0
  3. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/PKG-INFO +23 -2
  4. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/README.md +21 -0
  5. inductive_mlxrl-0.2.3/examples/personal_taste_grpo/README.md +763 -0
  6. inductive_mlxrl-0.2.3/examples/personal_taste_grpo/assets/terminal-results.jpg +0 -0
  7. inductive_mlxrl-0.2.3/examples/personal_taste_grpo/assets/terminal-training.jpg +0 -0
  8. inductive_mlxrl-0.2.3/examples/personal_taste_grpo/assets/ui-ranking.jpg +0 -0
  9. inductive_mlxrl-0.2.3/examples/personal_taste_grpo/assets/ui-scorer-eval.jpg +0 -0
  10. inductive_mlxrl-0.2.3/examples/personal_taste_grpo/compare.py +164 -0
  11. inductive_mlxrl-0.2.3/examples/personal_taste_grpo/config.toml +48 -0
  12. inductive_mlxrl-0.2.3/examples/personal_taste_grpo/data/briefs.json +120 -0
  13. inductive_mlxrl-0.2.3/examples/personal_taste_grpo/data/scorer.json +1584 -0
  14. inductive_mlxrl-0.2.3/examples/personal_taste_grpo/taste_reward.py +535 -0
  15. inductive_mlxrl-0.2.3/examples/personal_taste_grpo/test_reward.py +54 -0
  16. inductive_mlxrl-0.2.3/examples/personal_taste_grpo/train.py +282 -0
  17. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/mlxrl/__init__.py +1 -1
  18. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/mlxrl/algorithm.py +3 -0
  19. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/mlxrl/cli.py +47 -13
  20. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/mlxrl/config.py +16 -1
  21. inductive_mlxrl-0.2.3/mlxrl/echo.py +43 -0
  22. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/mlxrl/policy/__init__.py +8 -0
  23. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/mlxrl/policy/logprobs.py +50 -7
  24. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/mlxrl/policy/trajectory_logprobs.py +117 -0
  25. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/mlxrl/rollout/agentic.py +3 -3
  26. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/mlxrl/rollout/naive.py +2 -2
  27. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/mlxrl/rollout/optimized.py +20 -9
  28. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/mlxrl/train/grpo.py +10 -6
  29. inductive_mlxrl-0.2.3/mlxrl/train/trajectory.py +557 -0
  30. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/mlxrl/trajectory.py +23 -0
  31. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/pyproject.toml +5 -1
  32. inductive_mlxrl-0.2.3/tests/test_cache_compatibility.py +67 -0
  33. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/tests/test_config.py +12 -0
  34. inductive_mlxrl-0.2.3/tests/test_echo.py +329 -0
  35. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/tests/test_gigpo.py +2 -2
  36. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/tests/test_grpo.py +16 -16
  37. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/tests/test_optimized_rollout.py +52 -3
  38. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/tests/test_policy_logprobs.py +195 -8
  39. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/tests/test_train_grpo.py +2 -2
  40. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/tests/test_trajectory_logprobs.py +1 -1
  41. inductive_mlxrl-0.2.1/mlxrl/train/trajectory.py +0 -292
  42. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/.gitignore +0 -0
  43. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/DESIGN.md +0 -0
  44. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/LICENSE +0 -0
  45. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/THIRD_PARTY_LICENSES.md +0 -0
  46. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/benchmarks/__init__.py +0 -0
  47. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/benchmarks/audit_phase4_config.py +0 -0
  48. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/benchmarks/external_baseline_worker.py +0 -0
  49. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/benchmarks/results/gate1_mlxrl_after.jsonl +0 -0
  50. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/benchmarks/results/gate1_mlxrl_after.md +0 -0
  51. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/benchmarks/results/gate1_mlxrl_after_final.jsonl +0 -0
  52. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/benchmarks/results/gate1_mlxrl_after_final.md +0 -0
  53. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/benchmarks/results/gate1_mlxrl_after_noprefixsync.jsonl +0 -0
  54. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/benchmarks/results/gate1_mlxrl_after_noprefixsync.md +0 -0
  55. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/benchmarks/results/gate1_mlxrl_before.jsonl +0 -0
  56. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/benchmarks/results/gate1_mlxrl_before.md +0 -0
  57. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/benchmarks/results/gate2_unified_smoke.jsonl +0 -0
  58. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/benchmarks/results/gate2_unified_smoke.md +0 -0
  59. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/benchmarks/results/gate3_mlx_tune_sync_256.jsonl +0 -0
  60. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/benchmarks/results/gate3_mlx_tune_sync_256.md +0 -0
  61. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/benchmarks/results/gate3_sync_blocked.jsonl +0 -0
  62. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/benchmarks/results/gate3_sync_blocked.md +0 -0
  63. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/benchmarks/results/gate3_sync_smoke.jsonl +0 -0
  64. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/benchmarks/results/gate3_sync_smoke.md +0 -0
  65. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/benchmarks/results/gate4_config_audit.json +0 -0
  66. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/benchmarks/results/gate4_config_audit.md +0 -0
  67. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/benchmarks/results/gate4_sampler_smoke.jsonl +0 -0
  68. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/benchmarks/results/gate4_sampler_smoke.md +0 -0
  69. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/benchmarks/results/gate5_full_reconciled.jsonl +0 -0
  70. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/benchmarks/results/gate5_full_reconciled.md +0 -0
  71. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/benchmarks/results/phase4_external_smoke.jsonl +0 -0
  72. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/benchmarks/results/phase4_external_smoke.md +0 -0
  73. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/benchmarks/results/phase4_full_all_targets.jsonl +0 -0
  74. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/benchmarks/results/phase4_full_all_targets.md +0 -0
  75. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/benchmarks/results/phase4_local_mlxrl_vs_mlx_lm.jsonl +0 -0
  76. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/benchmarks/results/phase4_local_mlxrl_vs_mlx_lm.md +0 -0
  77. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/benchmarks/results/phase4_mlx_lm_g4_smoke.jsonl +0 -0
  78. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/benchmarks/results/phase4_mlx_lm_g4_smoke.md +0 -0
  79. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/benchmarks/run_phase4.py +0 -0
  80. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/examples/qwen35_9b_g2_checkpoint.toml +0 -0
  81. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/examples/qwen3_0_6b_gigpo_recurring.toml +0 -0
  82. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/examples/qwen3_0_6b_grpo.toml +0 -0
  83. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/mlxrl/algo/__init__.py +0 -0
  84. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/mlxrl/algo/gigpo.py +0 -0
  85. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/mlxrl/algo/grpo.py +0 -0
  86. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/mlxrl/data/__init__.py +0 -0
  87. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/mlxrl/data/gsm8k.py +0 -0
  88. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/mlxrl/data/rewards.py +0 -0
  89. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/mlxrl/env/__init__.py +0 -0
  90. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/mlxrl/env/base.py +0 -0
  91. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/mlxrl/env/reference.py +0 -0
  92. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/mlxrl/policy/model.py +0 -0
  93. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/mlxrl/py.typed +0 -0
  94. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/mlxrl/rollout/__init__.py +0 -0
  95. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/mlxrl/train/__init__.py +0 -0
  96. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/mlxrl/train/reference.py +0 -0
  97. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/tests/test_agentic_env.py +0 -0
  98. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/tests/test_agentic_rollout.py +0 -0
  99. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/tests/test_benchmark_metrics.py +0 -0
  100. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/tests/test_cli.py +0 -0
  101. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/tests/test_import_direction.py +0 -0
  102. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/tests/test_policy_model.py +0 -0
  103. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/tests/test_rewards.py +0 -0
  104. {inductive_mlxrl-0.2.1 → inductive_mlxrl-0.2.3}/tests/test_train_trajectory.py +0 -0
@@ -5,6 +5,40 @@ All notable changes to this project are documented here.
5
5
  The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project uses semantic versioning once releases are cut.
7
7
 
8
+ ## [0.2.3] - 2026-10-21
9
+
10
+ ### Changed
11
+
12
+ - Project only completion positions through the output head for stock Qwen2,
13
+ Qwen3, and Llama models, reducing training logit memory while preserving
14
+ logprobs and gradients. Custom subclasses and wrappers retain the full
15
+ forward path. Thanks to @TarangKhanna for PR #6.
16
+ - Refresh runtime, development, and benchmark dependencies while preserving
17
+ the seven-day package-age cutoff in the lockfile.
18
+ - Include the Pillow, aiohttp, AnyIO, and urllib3 updates from Dependabot
19
+ PRs #1 through #4.
20
+
21
+ ### Fixed
22
+
23
+ - Support MLX-LM 0.32 prompt-cache cloning while retaining older cache support.
24
+ Thanks to @TarangKhanna for PR #5.
25
+ - Use valid prefix lengths when building compiled decode caches from MLX-LM
26
+ 0.32 cache buffers, and restore random state through MLX 0.32's mutable key.
27
+ - Keep scalar metric conversions compatible with the current MLX type stubs.
28
+ - Override the benchmark-only mlx-tune dependency's old datasets constraint
29
+ to use patched datasets 5.x (CVE-2026-66007).
30
+
31
+ ## [0.2.2] - 2026-06-25
32
+
33
+ ### Added
34
+
35
+ - ECHO world-modeling support for tagged multi-turn trajectories, composing an
36
+ independently normalized ECHO SFT loss with the existing GiGPO action loss.
37
+ - `echo_alpha` scheduling with constant and linear-taper-to-zero modes, plus
38
+ separate `loss_echo` and `echo_accuracy` diagnostics.
39
+ - Real-Qwen smoke coverage for tagged ECHO batches on Qwen3-0.6B and
40
+ Qwen3.5-9B MLX 4-bit models.
41
+
8
42
  ## [0.2.1] - 2026-06-25
9
43
 
10
44
  ### Fixed
@@ -72,6 +72,11 @@ runtime dependencies marked for macOS arm64 and Python `<3.15` so universal
72
72
  resolvers do not try to solve MLX wheels for unsupported platform or Python
73
73
  splits.
74
74
 
75
+ The development environment overrides mlx-tune 0.6's `datasets<4` constraint
76
+ with `datasets>=5.0.1,<6` to avoid CVE-2026-66007. This only affects the external
77
+ benchmark tools; the published package depends on MLX and MLX-LM. Remove the
78
+ override when mlx-tune accepts a patched datasets release.
79
+
75
80
  ## Release Cycle
76
81
 
77
82
  Releases are tag-driven and publish to PyPI through Trusted Publishing. Do not
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: inductive-mlxrl
3
- Version: 0.2.1
3
+ Version: 0.2.3
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
@@ -300,6 +300,27 @@ currently exact for token-mean policy losses: base GRPO, DAPO, GSPO token mode,
300
300
  RLOO, and Dr. GRPO with `loss_reduction="token_mean"`. Sequence-reduced losses
301
301
  should keep `micro_batch_size=0`.
302
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
+
303
324
  ## Policy Semantics
304
325
 
305
326
  - The base model is frozen before LoRA injection.
@@ -275,6 +275,27 @@ currently exact for token-mean policy losses: base GRPO, DAPO, GSPO token mode,
275
275
  RLOO, and Dr. GRPO with `loss_reduction="token_mean"`. Sequence-reduced losses
276
276
  should keep `micro_batch_size=0`.
277
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
+
278
299
  ## Policy Semantics
279
300
 
280
301
  - The base model is frozen before LoRA injection.