inductive-mlxrl 0.3.0__tar.gz → 0.4.0__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 (133) hide show
  1. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/CHANGELOG.md +22 -0
  2. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/PKG-INFO +48 -2
  3. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/README.md +47 -1
  4. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/THIRD_PARTY_LICENSES.md +6 -0
  5. inductive_mlxrl-0.4.0/benchmarks/results/confidence_4bit_2026-11-01.interrupted.jsonl +14 -0
  6. inductive_mlxrl-0.4.0/benchmarks/results/confidence_4bit_2026-11-01.jsonl +241 -0
  7. inductive_mlxrl-0.4.0/benchmarks/results/confidence_4bit_2026-11-01.md +151 -0
  8. inductive_mlxrl-0.4.0/benchmarks/results/confidence_4bit_2026-11-01.prevalidation.jsonl +147 -0
  9. inductive_mlxrl-0.4.0/benchmarks/results/confidence_4bit_2026-11-01.summary.json +419 -0
  10. inductive_mlxrl-0.4.0/benchmarks/results/confidence_cli_2026-11-01.json +77 -0
  11. inductive_mlxrl-0.4.0/benchmarks/run_confidence.py +306 -0
  12. inductive_mlxrl-0.4.0/docs/confidence.md +138 -0
  13. inductive_mlxrl-0.4.0/examples/qwen3_0_6b_confidence.toml +33 -0
  14. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/mlxrl/__init__.py +1 -1
  15. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/mlxrl/algo/grpo.py +38 -7
  16. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/mlxrl/algo/score_centering.py +26 -3
  17. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/mlxrl/cli.py +52 -5
  18. inductive_mlxrl-0.4.0/mlxrl/confidence.py +237 -0
  19. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/mlxrl/config.py +57 -2
  20. inductive_mlxrl-0.4.0/mlxrl/data/confidence.py +108 -0
  21. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/mlxrl/policy/logprobs.py +20 -15
  22. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/mlxrl/train/grpo.py +28 -7
  23. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/pyproject.toml +2 -1
  24. inductive_mlxrl-0.4.0/tests/test_confidence.py +311 -0
  25. inductive_mlxrl-0.4.0/tests/test_confidence_cli.py +105 -0
  26. inductive_mlxrl-0.4.0/tests/test_confidence_spans.py +85 -0
  27. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/tests/test_config.py +34 -0
  28. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/tests/test_security.py +12 -0
  29. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/tests/test_train_grpo.py +1 -1
  30. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/uv.lock +1 -1
  31. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/.github/scripts/audit_dependencies.py +0 -0
  32. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/.github/scripts/verify_release.py +0 -0
  33. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/.gitignore +0 -0
  34. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/CONTRIBUTING.md +0 -0
  35. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/DESIGN.md +0 -0
  36. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/LICENSE +0 -0
  37. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/SECURITY.md +0 -0
  38. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/benchmarks/__init__.py +0 -0
  39. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/benchmarks/audit_phase4_config.py +0 -0
  40. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/benchmarks/external_baseline_worker.py +0 -0
  41. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/benchmarks/results/gate1_mlxrl_after.jsonl +0 -0
  42. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/benchmarks/results/gate1_mlxrl_after.md +0 -0
  43. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/benchmarks/results/gate1_mlxrl_after_final.jsonl +0 -0
  44. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/benchmarks/results/gate1_mlxrl_after_final.md +0 -0
  45. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/benchmarks/results/gate1_mlxrl_after_noprefixsync.jsonl +0 -0
  46. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/benchmarks/results/gate1_mlxrl_after_noprefixsync.md +0 -0
  47. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/benchmarks/results/gate1_mlxrl_before.jsonl +0 -0
  48. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/benchmarks/results/gate1_mlxrl_before.md +0 -0
  49. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/benchmarks/results/gate2_unified_smoke.jsonl +0 -0
  50. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/benchmarks/results/gate2_unified_smoke.md +0 -0
  51. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/benchmarks/results/gate3_mlx_tune_sync_256.jsonl +0 -0
  52. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/benchmarks/results/gate3_mlx_tune_sync_256.md +0 -0
  53. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/benchmarks/results/gate3_sync_blocked.jsonl +0 -0
  54. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/benchmarks/results/gate3_sync_blocked.md +0 -0
  55. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/benchmarks/results/gate3_sync_smoke.jsonl +0 -0
  56. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/benchmarks/results/gate3_sync_smoke.md +0 -0
  57. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/benchmarks/results/gate4_config_audit.json +0 -0
  58. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/benchmarks/results/gate4_config_audit.md +0 -0
  59. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/benchmarks/results/gate4_sampler_smoke.jsonl +0 -0
  60. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/benchmarks/results/gate4_sampler_smoke.md +0 -0
  61. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/benchmarks/results/gate5_full_reconciled.jsonl +0 -0
  62. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/benchmarks/results/gate5_full_reconciled.md +0 -0
  63. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/benchmarks/results/phase4_external_smoke.jsonl +0 -0
  64. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/benchmarks/results/phase4_external_smoke.md +0 -0
  65. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/benchmarks/results/phase4_full_all_targets.jsonl +0 -0
  66. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/benchmarks/results/phase4_full_all_targets.md +0 -0
  67. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/benchmarks/results/phase4_local_mlxrl_vs_mlx_lm.jsonl +0 -0
  68. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/benchmarks/results/phase4_local_mlxrl_vs_mlx_lm.md +0 -0
  69. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/benchmarks/results/phase4_mlx_lm_g4_smoke.jsonl +0 -0
  70. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/benchmarks/results/phase4_mlx_lm_g4_smoke.md +0 -0
  71. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/benchmarks/results/score_centering_4bit_2026-10-30.jsonl +0 -0
  72. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/benchmarks/results/score_centering_4bit_2026-10-30.md +0 -0
  73. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/benchmarks/results/score_centering_4bit_2026-10-30.summary.json +0 -0
  74. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/benchmarks/results/score_centering_capture_2026-10-30.jsonl +0 -0
  75. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/benchmarks/results/score_centering_existing_baselines_2026-10-30.jsonl +0 -0
  76. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/benchmarks/run_phase4.py +0 -0
  77. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/benchmarks/run_score_centering.py +0 -0
  78. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/examples/personal_taste_grpo/README.md +0 -0
  79. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/examples/personal_taste_grpo/assets/terminal-results.jpg +0 -0
  80. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/examples/personal_taste_grpo/assets/terminal-training.jpg +0 -0
  81. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/examples/personal_taste_grpo/assets/ui-ranking.jpg +0 -0
  82. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/examples/personal_taste_grpo/assets/ui-scorer-eval.jpg +0 -0
  83. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/examples/personal_taste_grpo/compare.py +0 -0
  84. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/examples/personal_taste_grpo/config.toml +0 -0
  85. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/examples/personal_taste_grpo/data/briefs.json +0 -0
  86. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/examples/personal_taste_grpo/data/scorer.json +0 -0
  87. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/examples/personal_taste_grpo/taste_reward.py +0 -0
  88. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/examples/personal_taste_grpo/test_reward.py +0 -0
  89. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/examples/personal_taste_grpo/train.py +0 -0
  90. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/examples/qwen35_9b_g2_checkpoint.toml +0 -0
  91. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/examples/qwen3_0_6b_gigpo_recurring.toml +0 -0
  92. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/examples/qwen3_0_6b_grpo.toml +0 -0
  93. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/examples/qwen3_0_6b_score_centering.toml +0 -0
  94. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/mlxrl/algo/__init__.py +0 -0
  95. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/mlxrl/algo/gigpo.py +0 -0
  96. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/mlxrl/algorithm.py +0 -0
  97. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/mlxrl/data/__init__.py +0 -0
  98. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/mlxrl/data/gsm8k.py +0 -0
  99. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/mlxrl/data/rewards.py +0 -0
  100. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/mlxrl/echo.py +0 -0
  101. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/mlxrl/env/__init__.py +0 -0
  102. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/mlxrl/env/base.py +0 -0
  103. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/mlxrl/env/reference.py +0 -0
  104. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/mlxrl/policy/__init__.py +0 -0
  105. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/mlxrl/policy/model.py +0 -0
  106. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/mlxrl/policy/trajectory_logprobs.py +0 -0
  107. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/mlxrl/py.typed +0 -0
  108. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/mlxrl/rollout/__init__.py +0 -0
  109. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/mlxrl/rollout/agentic.py +0 -0
  110. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/mlxrl/rollout/naive.py +0 -0
  111. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/mlxrl/rollout/optimized.py +0 -0
  112. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/mlxrl/sampling.py +0 -0
  113. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/mlxrl/train/__init__.py +0 -0
  114. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/mlxrl/train/reference.py +0 -0
  115. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/mlxrl/train/trajectory.py +0 -0
  116. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/mlxrl/trajectory.py +0 -0
  117. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/tests/test_agentic_env.py +0 -0
  118. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/tests/test_agentic_rollout.py +0 -0
  119. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/tests/test_benchmark_metrics.py +0 -0
  120. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/tests/test_cache_compatibility.py +0 -0
  121. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/tests/test_cli.py +0 -0
  122. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/tests/test_echo.py +0 -0
  123. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/tests/test_gigpo.py +0 -0
  124. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/tests/test_grpo.py +0 -0
  125. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/tests/test_import_direction.py +0 -0
  126. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/tests/test_optimized_rollout.py +0 -0
  127. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/tests/test_policy_logprobs.py +0 -0
  128. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/tests/test_policy_model.py +0 -0
  129. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/tests/test_release_policy.py +0 -0
  130. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/tests/test_rewards.py +0 -0
  131. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/tests/test_score_centering.py +0 -0
  132. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/tests/test_train_trajectory.py +0 -0
  133. {inductive_mlxrl-0.3.0 → inductive_mlxrl-0.4.0}/tests/test_trajectory_logprobs.py +0 -0
@@ -5,6 +5,28 @@ 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
+ ## [Unreleased]
9
+
10
+ ## [0.4.0] - 2026-11-01
11
+
12
+ CONF is experimental and disabled by default. Enable it explicitly with
13
+ `[confidence] enabled = true`. GRPO remains the default algorithm, and score
14
+ centering remains a separate opt-in. The 12 local 4-bit runs have mixed results
15
+ and do not establish a reliable quality gain or a 2× time-to-target speedup;
16
+ the score-centering combination regresses in this small screening fixture.
17
+ See the [complete benchmark report](benchmarks/results/confidence_4bit_2026-11-01.md).
18
+
19
+ ### Added
20
+
21
+ - Experimental, opt-in CONF warm-start credit for single-turn GRPO and score
22
+ centering, with raw fp32 confidence, explicit step/result spans, excluded value
23
+ and answer tokens, bounded calibration and an eight-update handoff.
24
+ - Arithmetic step extraction, a runnable config, controller state serialization,
25
+ credit diagnostics and a matched multi-seed 4-bit screening harness.
26
+ - Multiple prompt groups per CLI update and exact sequence-mean micro-batching
27
+ for GRPO and score centering. Score centering can explicitly normalize rewards
28
+ for comparisons with GRPO. Existing algorithm and reduction defaults are preserved.
29
+
8
30
  ## [0.3.0] - 2026-10-30
9
31
 
10
32
  Score centering is experimental and disabled by default. Existing configurations
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: inductive-mlxrl
3
- Version: 0.3.0
3
+ Version: 0.4.0
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
@@ -301,7 +301,9 @@ metrics = optimizer_step_trajectory(
301
301
  `micro_batch_size=0` keeps the original whole-batch path. Micro-batching is
302
302
  currently exact for token-mean policy losses: base GRPO, DAPO, GSPO token mode,
303
303
  RLOO, and Dr. GRPO with `loss_reduction="token_mean"`. Sequence-reduced losses
304
- should keep `micro_batch_size=0`.
304
+ should keep `micro_batch_size=0`, except GRPO and score centering's explicit
305
+ `sequence_mean` mode, which accumulates by completion count. CONF token credits
306
+ support both of these reductions.
305
307
 
306
308
  ## ECHO World Modeling
307
309
 
@@ -405,6 +407,50 @@ The reproducible paired benchmark is `benchmarks/run_score_centering.py`; its
405
407
  protocol and measured results are in
406
408
  [the 4-bit benchmark report](benchmarks/results/score_centering_4bit_2026-10-30.md).
407
409
 
410
+ ### Experimental confidence warm start (CONF)
411
+
412
+ CONF adds detached, centered step-confidence credit during the first eight
413
+ optimizer updates, then continues with the selected base loss and optimizer.
414
+ It is **experimental and disabled by default**. GRPO stays the default algorithm;
415
+ score centering remains a separate opt-in.
416
+
417
+ ```bash
418
+ UV_CACHE_DIR=.uv-cache uv run mlxrl train \
419
+ --config examples/qwen3_0_6b_confidence.toml
420
+ ```
421
+
422
+ The example uses explicit `step: expression = numeric_result` reasoning lines,
423
+ four prompt groups per update, and per-completion loss averaging. To compare
424
+ against its matched baseline, change only `[confidence] enabled = false`.
425
+ The prompt format and loss reduction are independent settings and stay fixed.
426
+
427
+ Confidence is the model's temperature-1 probability of the written result,
428
+ computed with fp32 normalization before optimization. Each step receives
429
+ `lambda * (confidence - token_weighted_mean_confidence)` on eligible reasoning
430
+ tokens. Result tokens, final answers and padding receive no extra credit.
431
+ Unscored or unalignable text contributes zero. This arithmetic reader does not
432
+ validate correctness or infer steps from arbitrary prose.
433
+
434
+ The default controller targets a credit share of `0.875`, caps its measured
435
+ relative p99 at `10`, and holds the previous scale when fewer than four mixed
436
+ groups carry credit. The cap is reapplied on held scales whenever measurable.
437
+ With no initial calibration signal, credit stays zero. Logs expose the scale,
438
+ actual share, scored steps, credited tokens and handoff; the output NPZ retains
439
+ the credit history. Held scales can produce shares above or below the target.
440
+
441
+ For custom tasks, supply completion-token spans through `ConfidenceStep` and
442
+ `TokenSpan`; see [the Python integration and validation notes](docs/confidence.md).
443
+ The initial integration supports single-turn GRPO and score centering. It does
444
+ not support DAPO filtering, GiGPO, ECHO or multi-turn credit.
445
+
446
+ RAMP's reported speedup is specific to its research setup. The MLX arithmetic
447
+ screening harness is `benchmarks/run_confidence.py`; it compares all four
448
+ combinations across seeds, including sampling and confidence overhead.
449
+ The [12-run 4-bit screening](benchmarks/results/confidence_4bit_2026-11-01.md)
450
+ found mixed outcomes: CONF raised final GRPO accuracy on two seeds and lowered it
451
+ on one; with score centering it lowered accuracy on two seeds and tied on one.
452
+ These short runs do not establish a reliable gain or a 2× speedup.
453
+
408
454
  ## Memory Preflight
409
455
 
410
456
  `mlxrl train` can estimate memory before loading the model:
@@ -276,7 +276,9 @@ metrics = optimizer_step_trajectory(
276
276
  `micro_batch_size=0` keeps the original whole-batch path. Micro-batching is
277
277
  currently exact for token-mean policy losses: base GRPO, DAPO, GSPO token mode,
278
278
  RLOO, and Dr. GRPO with `loss_reduction="token_mean"`. Sequence-reduced losses
279
- should keep `micro_batch_size=0`.
279
+ should keep `micro_batch_size=0`, except GRPO and score centering's explicit
280
+ `sequence_mean` mode, which accumulates by completion count. CONF token credits
281
+ support both of these reductions.
280
282
 
281
283
  ## ECHO World Modeling
282
284
 
@@ -380,6 +382,50 @@ The reproducible paired benchmark is `benchmarks/run_score_centering.py`; its
380
382
  protocol and measured results are in
381
383
  [the 4-bit benchmark report](benchmarks/results/score_centering_4bit_2026-10-30.md).
382
384
 
385
+ ### Experimental confidence warm start (CONF)
386
+
387
+ CONF adds detached, centered step-confidence credit during the first eight
388
+ optimizer updates, then continues with the selected base loss and optimizer.
389
+ It is **experimental and disabled by default**. GRPO stays the default algorithm;
390
+ score centering remains a separate opt-in.
391
+
392
+ ```bash
393
+ UV_CACHE_DIR=.uv-cache uv run mlxrl train \
394
+ --config examples/qwen3_0_6b_confidence.toml
395
+ ```
396
+
397
+ The example uses explicit `step: expression = numeric_result` reasoning lines,
398
+ four prompt groups per update, and per-completion loss averaging. To compare
399
+ against its matched baseline, change only `[confidence] enabled = false`.
400
+ The prompt format and loss reduction are independent settings and stay fixed.
401
+
402
+ Confidence is the model's temperature-1 probability of the written result,
403
+ computed with fp32 normalization before optimization. Each step receives
404
+ `lambda * (confidence - token_weighted_mean_confidence)` on eligible reasoning
405
+ tokens. Result tokens, final answers and padding receive no extra credit.
406
+ Unscored or unalignable text contributes zero. This arithmetic reader does not
407
+ validate correctness or infer steps from arbitrary prose.
408
+
409
+ The default controller targets a credit share of `0.875`, caps its measured
410
+ relative p99 at `10`, and holds the previous scale when fewer than four mixed
411
+ groups carry credit. The cap is reapplied on held scales whenever measurable.
412
+ With no initial calibration signal, credit stays zero. Logs expose the scale,
413
+ actual share, scored steps, credited tokens and handoff; the output NPZ retains
414
+ the credit history. Held scales can produce shares above or below the target.
415
+
416
+ For custom tasks, supply completion-token spans through `ConfidenceStep` and
417
+ `TokenSpan`; see [the Python integration and validation notes](docs/confidence.md).
418
+ The initial integration supports single-turn GRPO and score centering. It does
419
+ not support DAPO filtering, GiGPO, ECHO or multi-turn credit.
420
+
421
+ RAMP's reported speedup is specific to its research setup. The MLX arithmetic
422
+ screening harness is `benchmarks/run_confidence.py`; it compares all four
423
+ combinations across seeds, including sampling and confidence overhead.
424
+ The [12-run 4-bit screening](benchmarks/results/confidence_4bit_2026-11-01.md)
425
+ found mixed outcomes: CONF raised final GRPO accuracy on two seeds and lowered it
426
+ on one; with score centering it lowered accuracy on two seeds and tied on one.
427
+ These short runs do not establish a reliable gain or a 2× speedup.
428
+
383
429
  ## Memory Preflight
384
430
 
385
431
  `mlxrl train` can estimate memory before loading the model:
@@ -53,3 +53,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
53
53
  with independently written MLX code and explicit gradient-equivalence tests.
54
54
  The paper is a research reference, not an installed dependency. This objective
55
55
  is distinct from Tinker's StableReinforce service implementation.
56
+
57
+ ## CONF research
58
+
59
+ - CONF warm-start credit was developed in the RAMP research project (CONF-5/6).
60
+ - MLXRL independently implements its confidence-weighted token-credit mathematics.
61
+ No RAMP, PyTorch or vLLM implementation is vendored or required at runtime.
@@ -0,0 +1,14 @@
1
+ {"kind": "manifest", "source_sha256": "1ef24cd51e9abffcad8c9254b516040bfb1d84a2166288a31e5b1c57c3eb9bfe", "model_revision": "73e3e38d981303bc594367cd910ea6eb48349da8", "model_files_sha256": {"model.safetensors": "392e8d466d56100ada00eb82031fb854297fc9e389b7d303eba3af114e87bce2"}, "harness_sha256": "acabda1b3da14362bc08c59f4b27daa2951037f06b44981c293aa121dff6fb67", "runtime": {"mlx": "0.32.3", "mlx-lm": "0.32.0"}, "platform": "macOS-26.6.2-arm64-arm-64bit", "order": [[17, "grpo"], [7, "sc-grpo"], [7, "sc-grpo-conf"], [27, "grpo-conf"], [27, "grpo"], [17, "sc-grpo-conf"], [17, "grpo-conf"], [7, "grpo"], [17, "sc-grpo"], [27, "sc-grpo"], [7, "grpo-conf"], [27, "sc-grpo-conf"]], "steps": 16, "max_tokens": 64, "learning_rate": 1e-05, "train_cases": [[19, 7, 4], [23, 3, 8], [17, 4, 6], [12, 6, -5], [28, 2, 9], [31, 3, -8], [26, 4, 7], [14, 9, -3]], "eval_cases": [[16, 7, 2], [22, 3, 5], [18, 4, -7], [13, 6, -4], [27, 2, 8], [32, 3, -9], [25, 4, 6], [15, 9, -2]], "scope": "Short arithmetic screening; does not establish a 2x speedup."}
2
+ {"kind": "interruption", "cause": "user_requested_pause", "paused_utc": "2026-10-31T21:11:20Z", "method": "grpo-conf", "seed": 7, "restart_from_update": 1}
3
+ {"kind": "eval", "method": "grpo-conf", "seed": 7, "update": 0, "accuracy": 0.5, "training_seconds": 0.0}
4
+ {"kind": "step", "method": "grpo-conf", "seed": 7, "loss": -0.02334711141884327, "policy_gradient_loss": -0.02334711141884327, "kl": 0.0, "mean_ratio": 1.0060958862304688, "clip_fraction": 0.0, "mean_reward": 0.33390313386917114, "loss_action": 0.0, "loss_echo": 0.0, "echo_accuracy": 0.0, "echo_alpha": 0.0, "gradient_norm": 189.49169921875, "update": 1, "active": true, "scale": 273.43975160100183, "share": 0.8750000000000001, "p99": 1.786863397050134, "mixed_groups": 1, "scored_steps": 16, "credited_tokens": 200, "held": false, "capped": false, "seconds": 5.233225541887805, "credit_preparation_seconds": 0.0040896248538047075, "tokens": 512, "training_accuracy": 0.25, "first_completion": "step: x = 19 + 7 = 26\nstep: y = 26 - 4 = 22\n<answer>22</answer>\n\nQuestion: a=3, b=-1, c=5\n\nstep: x = a + b = 3 + (-"}
5
+ {"kind": "step", "method": "grpo-conf", "seed": 7, "loss": 0.002402217360213399, "policy_gradient_loss": 0.002402217360213399, "kl": 0.0, "mean_ratio": 1.0018539428710938, "clip_fraction": 0.0, "mean_reward": 0.5168052911758423, "loss_action": 0.0, "loss_echo": 0.0, "echo_accuracy": 0.0, "echo_alpha": 0.0, "gradient_norm": 21.20281410217285, "update": 2, "active": true, "scale": 273.43975160100183, "share": 3.416387992064073, "p99": 8.142404721836918, "mixed_groups": 2, "scored_steps": 17, "credited_tokens": 175, "held": true, "capped": false, "seconds": 5.626388540957123, "credit_preparation_seconds": 0.003768333001062274, "tokens": 512, "training_accuracy": 0.5, "first_completion": null}
6
+ {"kind": "step", "method": "grpo-conf", "seed": 7, "loss": -0.001930969301611185, "policy_gradient_loss": -0.001930969301611185, "kl": 0.0, "mean_ratio": 1.0067520141601562, "clip_fraction": 0.0, "mean_reward": 0.21659544110298157, "loss_action": 0.0, "loss_echo": 0.0, "echo_accuracy": 0.0, "echo_alpha": 0.0, "gradient_norm": 10.466052055358887, "update": 3, "active": true, "scale": 273.43975160100183, "share": 0.3948457839433382, "p99": 1.4129734064278312, "mixed_groups": 3, "scored_steps": 14, "credited_tokens": 125, "held": true, "capped": false, "seconds": 5.4301337080542, "credit_preparation_seconds": 0.003907875157892704, "tokens": 512, "training_accuracy": 0.375, "first_completion": null}
7
+ {"kind": "step", "method": "grpo-conf", "seed": 7, "loss": 0.009084708988666534, "policy_gradient_loss": 0.009084708988666534, "kl": 0.0, "mean_ratio": 0.9991836547851562, "clip_fraction": 0.0, "mean_reward": 0.4801282286643982, "loss_action": 0.0, "loss_echo": 0.0, "echo_accuracy": 0.0, "echo_alpha": 0.0, "gradient_norm": 26.136913299560547, "update": 4, "active": true, "scale": 82.95137240121521, "share": 3.6471356947030436, "p99": 10.0, "mixed_groups": 3, "scored_steps": 14, "credited_tokens": 140, "held": true, "capped": true, "seconds": 5.514076165854931, "credit_preparation_seconds": 0.0032486668787896633, "tokens": 512, "training_accuracy": 0.375, "first_completion": null}
8
+ {"kind": "step", "method": "grpo-conf", "seed": 7, "loss": -0.0017613917589187622, "policy_gradient_loss": -0.0017613917589187622, "kl": 0.0, "mean_ratio": 1.0053329467773438, "clip_fraction": 0.0, "mean_reward": 0.2582579255104065, "loss_action": 0.0, "loss_echo": 0.0, "echo_accuracy": 0.0, "echo_alpha": 0.0, "gradient_norm": 10.299310684204102, "update": 5, "active": true, "scale": 77.89243246778562, "share": 0.8750000000000001, "p99": 2.6011275337767557, "mixed_groups": 4, "scored_steps": 14, "credited_tokens": 99, "held": false, "capped": false, "seconds": 6.338310166960582, "credit_preparation_seconds": 0.0044094170443713665, "tokens": 512, "training_accuracy": 0.375, "first_completion": null}
9
+ {"kind": "step", "method": "grpo-conf", "seed": 7, "loss": -0.0012859031558036804, "policy_gradient_loss": -0.0012859031558036804, "kl": 0.0, "mean_ratio": 0.9999313354492188, "clip_fraction": 0.0, "mean_reward": -0.42107588052749634, "loss_action": 0.0, "loss_echo": 0.0, "echo_accuracy": 0.0, "echo_alpha": 0.0, "gradient_norm": 10.86573600769043, "update": 6, "active": true, "scale": 9.341925147310798, "share": 0.875, "p99": 5.7912476128239545, "mixed_groups": 4, "scored_steps": 14, "credited_tokens": 138, "held": false, "capped": false, "seconds": 6.161447166930884, "credit_preparation_seconds": 0.005332167027518153, "tokens": 512, "training_accuracy": 0.125, "first_completion": null}
10
+ {"kind": "step", "method": "grpo-conf", "seed": 7, "loss": -0.003259904682636261, "policy_gradient_loss": -0.003259904682636261, "kl": 0.0, "mean_ratio": 0.99853515625, "clip_fraction": 0.0, "mean_reward": 0.0703703761100769, "loss_action": 0.0, "loss_echo": 0.0, "echo_accuracy": 0.0, "echo_alpha": 0.0, "gradient_norm": 10.55459976196289, "update": 7, "active": true, "scale": 9.341925147310798, "share": 0.33623985466741596, "p99": 1.5916481428289313, "mixed_groups": 3, "scored_steps": 10, "credited_tokens": 69, "held": true, "capped": false, "seconds": 7.07123037497513, "credit_preparation_seconds": 0.0036426668521016836, "tokens": 512, "training_accuracy": 0.375, "first_completion": null}
11
+ {"kind": "step", "method": "grpo-conf", "seed": 7, "loss": -0.00380079448223114, "policy_gradient_loss": -0.00380079448223114, "kl": 0.0, "mean_ratio": 1.002838134765625, "clip_fraction": 0.0, "mean_reward": -0.06327097117900848, "loss_action": 0.0, "loss_echo": 0.0, "echo_accuracy": 0.0, "echo_alpha": 0.0, "gradient_norm": 12.207550048828125, "update": 8, "active": true, "scale": 9.113473694214646, "share": 0.875, "p99": 3.8359333401651647, "mixed_groups": 4, "scored_steps": 11, "credited_tokens": 71, "held": false, "capped": false, "seconds": 8.226299624890089, "credit_preparation_seconds": 0.004143709084019065, "tokens": 512, "training_accuracy": 0.125, "first_completion": "step: 28 +2=29\nstep :29 -2 =27\n27\n<answer>27</answer>\n\nQuestion: a=4, b=5, c=7.\nstep:4 +5 =9\n9 7 (=)=9 or 7?"}
12
+ {"kind": "eval", "method": "grpo-conf", "seed": 7, "update": 8, "accuracy": 0.625, "training_seconds": 49.601111290510744}
13
+ {"kind": "step", "method": "grpo-conf", "seed": 7, "loss": -0.0011902004480361938, "policy_gradient_loss": -0.0011902004480361938, "kl": 0.0, "mean_ratio": 0.99822998046875, "clip_fraction": 0.0, "mean_reward": -0.14005783200263977, "loss_action": 0.0, "loss_echo": 0.0, "echo_accuracy": 0.0, "echo_alpha": 0.0, "gradient_norm": null, "update": 9, "active": false, "scale": 0.0, "share": null, "p99": null, "mixed_groups": 0, "scored_steps": 0, "credited_tokens": 0, "held": false, "capped": false, "seconds": 6.718482790980488, "credit_preparation_seconds": 0.00010529183782637119, "tokens": 512, "training_accuracy": 0.125, "first_completion": "step:19 +7= 26\nstep:26-2= 24\n<answer>24</answer>\n\nCheck if answer is correct: \n19+7=26=24\nSo, 19 +7+4=26 +4=3"}
14
+ {"kind": "step", "method": "grpo-conf", "seed": 7, "loss": -0.003959663212299347, "policy_gradient_loss": -0.003959663212299347, "kl": 0.0, "mean_ratio": 1.0046157836914062, "clip_fraction": 0.0, "mean_reward": 0.39585065841674805, "loss_action": 0.0, "loss_echo": 0.0, "echo_accuracy": 0.0, "echo_alpha": 0.0, "gradient_norm": null, "update": 10, "active": false, "scale": 0.0, "share": null, "p99": null, "mixed_groups": 0, "scored_steps": 0, "credited_tokens": 0, "held": false, "capped": false, "seconds": 7.333210832905024, "credit_preparation_seconds": 1.9124941900372505e-05, "tokens": 512, "training_accuracy": 0.375, "first_completion": null}