Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
68072ae
feat: add structured SQLite recovery environment
DaoyuanLi2816 Aug 2, 2026
04fb44b
docs: preregister RecoveryBench v1
DaoyuanLi2816 Aug 2, 2026
3d01164
feat: add RecoveryBench provenance and frozen-state KD
DaoyuanLi2816 Aug 2, 2026
665f955
feat: add eval-only RecoveryBench teacher gate
DaoyuanLi2816 Aug 2, 2026
b637689
data: record failed RecoveryBench teacher candidate
DaoyuanLi2816 Aug 2, 2026
17f99bb
feat: allow explicit baseline evaluation control
DaoyuanLi2816 Aug 2, 2026
17083cf
fix: make exported adapters portable
DaoyuanLi2816 Aug 2, 2026
87999c9
feat: share frozen RecoveryBench state
DaoyuanLi2816 Aug 2, 2026
7087b3a
docs: freeze RecoveryBench teacher gate decode
DaoyuanLi2816 Aug 2, 2026
8df941a
feat: enforce complete RecoveryBench teacher gates
DaoyuanLi2816 Aug 2, 2026
ea38dc3
fix: canonicalize exported adapter modules
DaoyuanLi2816 Aug 2, 2026
4dc3319
data: freeze qualified RecoveryBench teacher
DaoyuanLi2816 Aug 2, 2026
15ddfa6
style: format teacher gate regression
DaoyuanLi2816 Aug 2, 2026
2bef929
fix: bind frozen collection seeds to runs
DaoyuanLi2816 Aug 2, 2026
9c99914
bench: freeze RecoveryBench eval calibration
DaoyuanLi2816 Aug 2, 2026
f8d62a2
freeze RecoveryBench v1 final test
DaoyuanLi2816 Aug 2, 2026
dba595f
correct RecoveryBench oracle schedule
DaoyuanLi2816 Aug 2, 2026
6f4fabb
preregister corrected RecoveryBench wall budget
DaoyuanLi2816 Aug 2, 2026
cdad97d
bind corrected wall view to public preregistration
DaoyuanLi2816 Aug 2, 2026
d952e14
Revert "bind corrected wall view to public preregistration"
DaoyuanLi2816 Aug 2, 2026
a2c1c60
Revert "preregister corrected RecoveryBench wall budget"
DaoyuanLi2816 Aug 2, 2026
9175bbe
publish RecoveryBench v1 results
DaoyuanLi2816 Aug 2, 2026
ac4f9e2
record v0.3 validation evidence
DaoyuanLi2816 Aug 2, 2026
e3def22
keep RecoveryBench tests torch-optional
DaoyuanLi2816 Aug 2, 2026
cb339d6
make RecoveryBench artifacts cross-platform reproducible
DaoyuanLi2816 Aug 2, 2026
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 .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
*.jpg binary
*.gif binary
*.ico binary
*.pdf binary
*.whl binary
*.gz binary
*.safetensors binary
38 changes: 38 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,44 @@ All notable changes to miniVERL are recorded here. The format follows

## [Unreleased]

## [0.3.0] - 2026-08-01

RecoveryBench release. The experiment is a scoped mechanism study of fresh
student-visited states, not an alignment benchmark and not evidence that OPD
replaces SFT.

### Added

- A deterministic SQLite recovery environment with structured retryable errors,
executable recovery oracles, disjoint template splits and exact recovery
metrics.
- Schema-v3 benchmark provenance for preregistration, teacher gates, frozen
datasets, task-level artifacts, selected-position and wall-time budget views.
- A public, immutable NF4-qualified SQLite recovery teacher adapter plus
recorded failed teacher candidates and preparation cost.
- Frozen three-seed RecoveryBench results, task-paired bootstrap analysis,
data-bound SVGs and a deterministic six-page technical report.

### Changed

- Public positioning now distinguishes SFT competence-building from OPD as an
online teacher-student mechanism whose transferred behavior depends on the
teacher.
- Frozen-student offline KD records and validates the exact cold checkpoint,
task schedule, adapter and tokenizer identities reused across budget views.

### Results

- Under eight equal continuation updates, frozen-student KD reached 23.2%
strict success and 22.8% recovery after error, versus 10.9% and 9.1% for
strict fresh-state OPD. The fresh-minus-frozen paired differences were
-12.24 and -13.79 percentage points.
- Fresh OPD averaged 686.8 continuation seconds versus 52.1 for frozen KD.
Querying 49.77% of model-generated positions did not reduce teacher backbone
forwards or wall time.
- The nominal 50-second result is retained and explicitly labeled a
cycle-capped wall diagnostic, not exact equal-time evidence.

## [0.2.6] - 2026-08-01

Small concurrency, lifecycle and privacy correctness release. No training
Expand Down
27 changes: 27 additions & 0 deletions PROJECT_STATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,33 @@ and what it printed.

Last updated: 2026-08-01.

## v0.3.0 RecoveryBench development

| item | current state |
| --- | --- |
| audited baseline | fetched all remotes and started `agent/v0.3-recoverybench` from clean public `main` at `6c79c1fcc5a6e55dd9f4af843d446ece1c454431`; no PR was open, main CI/build were green, and development advanced directly from `0.2.7.dev0` to `0.3.0.dev0` without a `0.2.7` release |
| available execution environment | Windows checkout with Python 3.12, Torch 2.13.0+cu130 and an NVIDIA GeForce RTX 4080 (16376 MiB); GitHub and Hugging Face access are available and publication remains restricted to exact validated tags |
| immutable baseline | calculator benchmark SHA-256 is `53fc1d4d5b7adee09618d77ad62d4086ba56b78569832d6fc7c3bcd5c2695bbc`; calculator protocol-teacher HEAD is `23323751318135484c06c043b1f9b9e7016dd89f`; existing tags remain untouched |
| phase boundary | RecoveryBench must be preregistered, fully measured with the sequential engine, frozen, merged, released as `v0.3.0`, publicly verified and state-synced to `0.4.0.dev0` before padded batching begins |
| current highest-risk work | final experiment, artifact audit and data-bound publication are complete; remaining work is release validation, integration, Trusted Publishing verification and the required `0.4.0.dev0` state sync |
| RecoveryBench environment | `sqlite_recovery` has 12 structurally disjoint versioned templates, deterministic controlled/natural/no-intervention subsets, structured tool-error provenance, executable recovery oracles, and exact recovery metrics; focused environment and backward-read tests pass |
| preregistration | public commit `7087b3a333463b88a62ffed73daee2c85d039145` and revision-1.3 digest `9c4c2ec19a56cebb2b2c1c0f3c7e504a9285467c99ae1590488251fbf2ff3934` bind the final procedure; the later public wall-budget amendment was reverted, its partial replacement stopped, and the already-complete frozen experiment was retained without rerun |
| teacher selection so far | the historical calculator teacher completed 96 eval tasks and failed the gate at 25.0% strict, 10.7% recovery, 95.8% parse validity and 14.4% tool execution; candidate A trained for 64 QLoRA SFT updates and its in-process NF4 eval measured 86.5%, 78.1%, 100% and 87.5%; a separately loaded full-precision reapplication failed at 65.6%, 65.6%, 100% and 62.7% and is retained as a noncanonical diagnostic |
| selected RecoveryBench teacher | candidate A reloaded on its preregistered NF4 base passed the independent 96-task eval-only gate at 90.6% strict success, 81.2% recovery, 100% parse validity and 87.1% tool execution; it is public at `DaoyuanLi/mini-verl-qwen3-1.7b-sqlite-recovery-teacher@eb2747895ec32dab47c5b50c2d8aa9c0d9701e0d`, with adapter weights SHA-256 `5355f7007efb904d1b45a1aeb9b73b479b6f52025ab92502ab7895706155b2ba` |
| portable adapters | a regression reproduced PEFT exporting a machine-local snapshot path as the base identity; export now rewrites the configured model ID and immutable revision before checksumming, and the portable export reload test passes |
| shared frozen data | schema-v3 benchmark execution prepares one frozen-student dataset per seed, reuses it across consumers and budget views, and can reuse the exact primary-view cold-start checkpoint; the two-consumer/two-view regression and all 80 v2/v3 benchmark tests pass |
| frozen-data fail closed | persisted offline KD now compares the loaded cold-start checkpoint content digest with the immutable dataset manifest before copying any data; a regression proves mismatched bundles are rejected, and final preparation uses `recoverybench-v1-final-frozen-s{seed}` rather than the calibration bundle |
| eval calibration and final freeze | all three 8-update calibration arms completed on eval only: SFT 6,675 positions / 50.5560895 s, frozen KD 6,467 / 52.0759896 s, and strict OPD 6,224 / 650.9775521 s; preregistration revision 1.2 freezes 6,224 selected positions and 50 continuation seconds, bound to calibration SHA-256 `af0cb73c60655c37c4bafba6ea7893e4bb7260e82c6b2915bb646b8872cbe35e` |
| frozen final specifications | schema-v3 equal-update, equal-selected-position and equal-wall-time configs cover the locked three seeds and test split; deterministic 10,000-replicate paired analysis and all three data-bound SVG generators are committed before final test |
| preserved v1.2 invalidation | the first partial final run exposed a real schedule defect: `offline-kd-oracle` collected only 8 oracle tasks and replayed them rather than using the common 64-task prefix; the process was stopped before that arm's test, the entire partial run and frozen bundle were moved intact to `artifacts/superseded/recoverybench-v1.2-oracle-schedule-defect/`, and none of its outcomes will enter the replacement analysis |
| preregistration correction | revision 1.3 explicitly freezes `offline-kd-oracle.collection_tasks: 64`, documents the defect and required every final arm/seed to restart from fresh cold starts; no invalid v1.2 outcome enters the publication set |
| final artifact audit | all 36 task artifacts, 4,608 trajectories and 101,787,618 raw bytes passed embedded SHA-256 and byte-count checks; each arm contains 128 final-test tasks, task IDs pair within seed, three cold checkpoints and three frozen datasets are reused exactly, and all 75 fresh-OPD update rollouts satisfy rollout policy version = current parameter version |
| equal-update result | frozen-student KD reached 23.2% strict success and 22.8% recovery after error versus 10.9% and 9.1% for strict fresh OPD; paired fresh-minus-frozen differences are -12.24 points (95% paired bootstrap -15.89 to -8.59, 384 tasks) and -13.79 points (-20.69 to -6.90, 116 paired error cases) |
| cost result | strict fresh OPD averaged 686.80 continuation seconds versus 52.10 for frozen KD; budget-50 queried 49.77% of model-generated positions but averaged 720.76 seconds because teacher backbone forwards were unchanged |
| secondary budgets | all equal-selected-position arms crossed the 6,224 target after eight steps with recorded overshoot; the nominal 50-second artifact is explicitly a cycle-capped wall diagnostic because SFT and frozen KD completed eight cycles while fresh OPD crossed the target in one indivisible step |
| immutable RecoveryBench results | equal-updates `6ce2e6837e12b99ebc4fad6d27ce3e69c92e295ff3b9b60e0f68c2d308022384`; equal-selected-positions `fe4c9afc799724dfe7a32e631676a1e5177c44559a7374d2ea31da135354f137`; wall diagnostic `425b0fa568f37b09e61af731d3da5009bd3833bddde6efaf2c66e9dba8355cbe`; task JSONL `aff96bffc6da27240a852410ac041bd4d95badf34cad030e6f437be1491a55ad`; paired analysis `8a6891f74aed80f07ec00d5ea1909895c579346e1abbb1d5d95a354bb46c6b81` |
| technical publication | the generated Markdown analysis, three SVGs and deterministic six-page PDF report are data-bound to the frozen JSON; native/README-width SVG inspection and every-page PDF inspection found no clipping or overlap |

## v0.2.6 concurrency, lifecycle and privacy correctness release

| item | current state |
Expand Down
117 changes: 65 additions & 52 deletions PYPI.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<p align="center">
<img src="https://raw.githubusercontent.com/DaoyuanLi2816/mini-verl/main/docs/banner.svg" alt="miniVERL — on-policy distillation for tool-using agents on one GPU" width="880">
<img src="https://raw.githubusercontent.com/DaoyuanLi2816/mini-verl/main/docs/banner.svg" alt="miniVERL — auditable online post-training on one GPU" width="880">
</p>

<div align="center">
Expand All @@ -16,19 +16,21 @@
<a href="https://pypi.org/project/miniverl/"><strong>PyPI package</strong></a> ·
<a href="#single-gpu-quickstart">Install &amp; train</a> ·
<a href="https://github.com/DaoyuanLi2816/mini-verl/blob/main/docs/single-gpu-guide.md">Bring your own GPU</a> ·
<a href="#measured-result-protocol-aligned-opd-matches-sft">Measured result</a>
<a href="#recoverybench-do-fresh-on-policy-states-justify-their-cost">Measured result</a>
</p>

**A compact, auditable training stack for tool-using agents on one personal GPU.**
**The independent one-GPU companion for prototyping, diagnosing and validating
online post-training workflows before scaling selected artifacts to verl.**

PyPI `v0.2.6` is the stable release; `main` is development and may be ahead.

miniVERL is a compact, auditable training lab for teaching a small language
model from its own multi-turn tool trajectories. It runs real tools, keeps
token provenance explicit, and applies teacher distributional targets only
where they belong — without Ray or a GPU cluster. There is no device-name
allowlist: use the NVIDIA CUDA card you have, then choose a model pair and
sequence budget that fit it.
miniVERL is a compact, auditable lab for online teacher-student training on
multi-turn tool trajectories. SFT establishes task and protocol competence;
OPD then exposes an online mechanism for transferring the teacher's reasoning,
policy, style or other behavior. They are not interchangeable stages, and the
teacher must be qualified for the behavior being transferred. miniVERL runs
without Ray or a cluster and has no CUDA device-name allowlist; fit still
depends on model size, sequence budget and available VRAM.

```bash
python -m pip install miniverl # lightweight core
Expand Down Expand Up @@ -56,7 +58,7 @@ validate artifacts without downloading a multi-gigabyte ML stack; use

[Run the local demo](#local-toy-demo) ·
[Train on your GPU](#single-gpu-quickstart) ·
[Inspect the measured result](#measured-result-protocol-aligned-opd-matches-sft) ·
[Inspect the measured result](#recoverybench-do-fresh-on-policy-states-justify-their-cost) ·
[Read the math](https://github.com/DaoyuanLi2816/mini-verl/blob/main/docs/math.md)

## Why miniVERL exists
Expand Down Expand Up @@ -98,40 +100,53 @@ keeps the whole lifecycle in one readable single-GPU process.
| Self-contained offline HTML report with token-level divergence | yes |
| Ray, FSDP, DeepSpeed, vLLM, VLMs, cross-tokenizer, PPO/GRPO | **no** — see [limitations](https://github.com/DaoyuanLi2816/mini-verl/blob/main/docs/limitations.md) |

## Measured result: protocol-aligned OPD matches SFT
## RecoveryBench: do fresh on-policy states justify their cost?

> [!IMPORTANT]
> **The supported protocol-aligned OPD path reached 100% in both seeds and
> matched continued SFT.** The primary schema-v2 comparison uses two
> prespecified seeds, equal optimizer updates, and the saturated `hard`
> calculator split. The protocol-naive rows are diagnostic negative controls,
> not recommended configurations:

| role | arm | seed 1234 | seed 20260727 |
| --- | --- | ---: | ---: |
| starting point | cold start | 75.0% | 75.0% |
| baseline | continued SFT | **100.0%** | **100.0%** |
| supported OPD | protocol-aligned teacher | **100.0%** | **100.0%** |
| diagnostic control | raw teacher without tool-protocol training | 0.0% | 0.0% |
| diagnostic control | answer-privileged, protocol-naive teacher | 0.0% | 0.0% |

The [public, immutable protocol-teacher adapter](https://huggingface.co/DaoyuanLi/mini-verl-qwen3-1.7b-protocol-teacher)
is the default in the single-GPU recipe. It passed an independently
prespecified policy-competence gate before this benchmark was inspected. Both
controls completed normally and measured 0% in both seeds; they were neither
configuration failures nor crashes. Both used the ambiguous historical
protocol-v1 prompt, so 0% cannot be attributed solely to intrinsic teacher
behaviour; it diagnoses the missing qualification gate in that setup.

The historical gate and benchmark reused the same 24-task v0.2 `test` set.
Candidate A was prespecified and passed first try (no fallback tuning), but the
set was not untouched. Future selection uses `eval`; reporting uses `test`.
See [limitations](https://github.com/DaoyuanLi2816/mini-verl/blob/main/docs/limitations.md).

OPD only ties SFT and takes 6.1× as much continuation time here (523.8 s versus
86.4 s). The task saturates; two seeds support neither significance nor a
general OPD advantage. See the
[full result and legacy transcript diagnosis](https://github.com/DaoyuanLi2816/mini-verl/blob/main/docs/rtx4080-baselines.md).
> **Not in this measured setting.** Under eight equal continuation updates,
> frozen-student-state KD reached 23.2% strict success, while strict fresh-state
> OPD reached 10.9%. The paired fresh-minus-frozen difference was -12.24
> percentage points (95% task-paired bootstrap interval -15.89 to -8.59).

RecoveryBench is a preregistered mechanism study on SQLite tool-error recovery,
not an alignment benchmark. It isolates state freshness while holding the cold
checkpoint, qualified teacher, task schedule, optimizer and update count fixed.
All three seeds and all completed negative results are retained.

| method | strict success | recovery after error | continuation time |
| --- | ---: | ---: | ---: |
| cold start | 10.7% | 13.6% | 0.2 s |
| continued oracle SFT | 4.9% | 1.8% | 51.3 s |
| oracle-state offline KD | **33.1%** | **31.9%** | 58.3 s |
| frozen-student-state KD | **23.2%** | **22.8%** | 52.1 s |
| strict fresh-state OPD | 10.9% | 9.1% | 686.8 s |
| budget-50 fresh-state OPD | 27.3% | 20.7% | 720.8 s |

![RecoveryBench three-seed result](https://raw.githubusercontent.com/DaoyuanLi2816/mini-verl/main/docs/recoverybench/recovery-success.svg)

The equal-selected-position view reached the 6,224-position boundary after
eight updates for every core method, so its quality result matches the primary
view. The budget-50 selector queried 49.77% of model-generated positions but
did not reduce wall time because teacher backbone forwards were unchanged. The
50-second artifact is a **cycle-capped wall diagnostic, not exact equal-time
evidence**: SFT and frozen KD completed their eight-cycle ceiling, while fresh
OPD crossed the target in one indivisible 88-121 second update.

Read the [full analysis](https://github.com/DaoyuanLi2816/mini-verl/blob/main/docs/recoverybench/recoverybench-v1.md), the
[data-bound technical report](https://github.com/DaoyuanLi2816/mini-verl/blob/main/paper/recoverybench-v1/recoverybench-v1.pdf), or
the [immutable schema-v3 artifacts](https://github.com/DaoyuanLi2816/mini-verl/blob/main/benchmarks/README.md#recoverybench-v1).
The result is scoped to one Qwen3 pair, one task family, three seeds and one RTX
4080. It does not show that OPD is universally ineffective or that offline KD
always wins.

<details>
<summary>Case study: why teacher protocol qualification matters</summary>

On the saturated v0.2 calculator task, a protocol-qualified OPD teacher reached
100% in both seeds and tied continued SFT, but took 6.1× as much continuation
time. Two protocol-naive controls completed normally at 0%; they were not
configuration failures. Both used the ambiguous historical protocol-v1 prompt,
so the failure cannot be attributed solely to intrinsic teacher behavior.

![Two-seed protocol-teacher benchmark](https://raw.githubusercontent.com/DaoyuanLi2816/mini-verl/main/docs/gpu-calc-hard-equal-update-v2.svg)

Expand All @@ -141,13 +156,10 @@ general OPD advantage. See the
| [Schema-v2 benchmark](https://github.com/DaoyuanLi2816/mini-verl/blob/main/benchmarks/results/gpu-calc-hard-equal-update-v2.json) | frozen five-arm result |
| [Raw-teacher recipe](https://github.com/DaoyuanLi2816/mini-verl/blob/main/recipes/qwen_consumer_gpu_calc_raw_teacher.yaml) | historical control; not default |

<details>
<summary>Historical 481-second raw-teacher smoke (schema v1)</summary>

On RTX 4080, 16 updates took 481 s, peaked at **4.25/4.76 GiB
allocated/reserved**, and moved 12-task success from **0% to 100%**. Cold start
did most of it (first OPD batch: 83.3%); this proves the pipeline, not OPD over
SFT. [Trace](https://github.com/DaoyuanLi2816/mini-verl/blob/main/docs/rtx4080-baselines.md).
The teacher gate and downstream comparison reused the same 24-task v0.2 test
set, so this is evidence for qualification in that setup, not a general OPD
advantage. The separate schema-v1 481-second smoke proves the pipeline, not OPD
over SFT. [Full diagnosis and caveats](https://github.com/DaoyuanLi2816/mini-verl/blob/main/docs/rtx4080-baselines.md).

</details>

Expand Down Expand Up @@ -465,8 +477,9 @@ The short version; the full list is in [`docs/limitations.md`](https://github.co
pinned to the device they were quantized on.
* Only Qwen3 and Qwen2 architectures are tested. Others may work through the
architecture adapter; nothing here claims they do.
* The primary GPU comparison has two prespecified seeds; legacy GPU artifacts
are single-seed. No statistical significance is claimed.
* RecoveryBench has three prespecified student seeds; the calculator case study
has two, and older GPU artifacts are single-seed. No broad statistical
significance or cross-task generalization is claimed.
* On the measured machine, decoding is kernel-launch bound rather than compute
bound, so throughput figures are platform-specific.

Expand Down Expand Up @@ -527,7 +540,7 @@ actually ran. See [`docs/comparisons.md`](https://github.com/DaoyuanLi2816/mini-

```bibtex
@software{miniverl2026,
title = {miniVERL: On-policy distillation for tool-using agents on one GPU},
title = {miniVERL: Auditable online post-training on one GPU},
author = {Li, Daoyuan},
year = {2026},
url = {https://github.com/DaoyuanLi2816/mini-verl},
Expand Down
Loading