whileai 0.65__tar.gz → 0.67__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 (98) hide show
  1. whileai-0.67/PKG-INFO +258 -0
  2. whileai-0.67/README.md +221 -0
  3. {whileai-0.65 → whileai-0.67}/pyproject.toml +3 -3
  4. {whileai-0.65 → whileai-0.67}/whileai/platform.py +116 -19
  5. whileai-0.67/whileai.egg-info/PKG-INFO +258 -0
  6. whileai-0.65/PKG-INFO +0 -1353
  7. whileai-0.65/README.md +0 -1316
  8. whileai-0.65/whileai.egg-info/PKG-INFO +0 -1353
  9. {whileai-0.65 → whileai-0.67}/LICENSE +0 -0
  10. {whileai-0.65 → whileai-0.67}/MANIFEST.in +0 -0
  11. {whileai-0.65 → whileai-0.67}/setup.cfg +0 -0
  12. {whileai-0.65 → whileai-0.67}/whileai/__init__.py +0 -0
  13. {whileai-0.65 → whileai-0.67}/whileai/_env.py +0 -0
  14. {whileai-0.65 → whileai-0.67}/whileai/auth.py +0 -0
  15. {whileai-0.65 → whileai-0.67}/whileai/cli.py +0 -0
  16. {whileai-0.65 → whileai-0.67}/whileai/ingest.py +0 -0
  17. {whileai-0.65 → whileai-0.67}/whileai/init_evals.py +0 -0
  18. {whileai-0.65 → whileai-0.67}/whileai/py.typed +0 -0
  19. {whileai-0.65 → whileai-0.67}/whileai/simulations/__init__.py +0 -0
  20. {whileai-0.65 → whileai-0.67}/whileai/simulations/__main__.py +0 -0
  21. {whileai-0.65 → whileai-0.67}/whileai/simulations/data.py +0 -0
  22. {whileai-0.65 → whileai-0.67}/whileai/simulations/environment.py +0 -0
  23. {whileai-0.65 → whileai-0.67}/whileai/simulations/export.py +0 -0
  24. {whileai-0.65 → whileai-0.67}/whileai/simulations/generate/__init__.py +0 -0
  25. {whileai-0.65 → whileai-0.67}/whileai/simulations/generate/actionspace.py +0 -0
  26. {whileai-0.65 → whileai-0.67}/whileai/simulations/generate/adapters.py +0 -0
  27. {whileai-0.65 → whileai-0.67}/whileai/simulations/generate/agents.py +0 -0
  28. {whileai-0.65 → whileai-0.67}/whileai/simulations/generate/anthropic_backend.py +0 -0
  29. {whileai-0.65 → whileai-0.67}/whileai/simulations/generate/coverage.py +0 -0
  30. {whileai-0.65 → whileai-0.67}/whileai/simulations/generate/diversity.py +0 -0
  31. {whileai-0.65 → whileai-0.67}/whileai/simulations/generate/embeddings.py +0 -0
  32. {whileai-0.65 → whileai-0.67}/whileai/simulations/generate/explore.py +0 -0
  33. {whileai-0.65 → whileai-0.67}/whileai/simulations/generate/generator.py +0 -0
  34. {whileai-0.65 → whileai-0.67}/whileai/simulations/generate/offline_agent.py +0 -0
  35. {whileai-0.65 → whileai-0.67}/whileai/simulations/generate/scenarios.py +0 -0
  36. {whileai-0.65 → whileai-0.67}/whileai/simulations/generate/usage_meter.py +0 -0
  37. {whileai-0.65 → whileai-0.67}/whileai/simulations/ingest/__init__.py +0 -0
  38. {whileai-0.65 → whileai-0.67}/whileai/simulations/ingest/otel.py +0 -0
  39. {whileai-0.65 → whileai-0.67}/whileai/simulations/ingest/platform.py +0 -0
  40. {whileai-0.65 → whileai-0.67}/whileai/simulations/ingest/traces.py +0 -0
  41. {whileai-0.65 → whileai-0.67}/whileai/simulations/monitor.py +0 -0
  42. {whileai-0.65 → whileai-0.67}/whileai/simulations/py.typed +0 -0
  43. {whileai-0.65 → whileai-0.67}/whileai/simulations/run/__init__.py +0 -0
  44. {whileai-0.65 → whileai-0.67}/whileai/simulations/run/config.py +0 -0
  45. {whileai-0.65 → whileai-0.67}/whileai/simulations/run/engine.py +0 -0
  46. {whileai-0.65 → whileai-0.67}/whileai/simulations/run/rows.py +0 -0
  47. {whileai-0.65 → whileai-0.67}/whileai/simulations/run/spec.py +0 -0
  48. {whileai-0.65 → whileai-0.67}/whileai/simulations/schema.py +0 -0
  49. {whileai-0.65 → whileai-0.67}/whileai/simulations/schemas/row-v1.json +0 -0
  50. {whileai-0.65 → whileai-0.67}/whileai/simulations/score/__init__.py +0 -0
  51. {whileai-0.65 → whileai-0.67}/whileai/simulations/score/agreement.py +0 -0
  52. {whileai-0.65 → whileai-0.67}/whileai/simulations/score/audit.py +0 -0
  53. {whileai-0.65 → whileai-0.67}/whileai/simulations/score/checklist.py +0 -0
  54. {whileai-0.65 → whileai-0.67}/whileai/simulations/score/curriculum.py +0 -0
  55. {whileai-0.65 → whileai-0.67}/whileai/simulations/score/delta.py +0 -0
  56. {whileai-0.65 → whileai-0.67}/whileai/simulations/score/grade_llm.py +0 -0
  57. {whileai-0.65 → whileai-0.67}/whileai/simulations/score/grading.py +0 -0
  58. {whileai-0.65 → whileai-0.67}/whileai/simulations/score/grounding.py +0 -0
  59. {whileai-0.65 → whileai-0.67}/whileai/simulations/score/hack_scan.py +0 -0
  60. {whileai-0.65 → whileai-0.67}/whileai/simulations/score/hygiene.py +0 -0
  61. {whileai-0.65 → whileai-0.67}/whileai/simulations/score/judge_trust.py +0 -0
  62. {whileai-0.65 → whileai-0.67}/whileai/simulations/score/judging.py +0 -0
  63. {whileai-0.65 → whileai-0.67}/whileai/simulations/score/labels.py +0 -0
  64. {whileai-0.65 → whileai-0.67}/whileai/simulations/score/llm_judge.py +0 -0
  65. {whileai-0.65 → whileai-0.67}/whileai/simulations/score/logprobs.py +0 -0
  66. {whileai-0.65 → whileai-0.67}/whileai/simulations/score/markers.py +0 -0
  67. {whileai-0.65 → whileai-0.67}/whileai/simulations/score/optimize.py +0 -0
  68. {whileai-0.65 → whileai-0.67}/whileai/simulations/score/pairwise.py +0 -0
  69. {whileai-0.65 → whileai-0.67}/whileai/simulations/score/passat.py +0 -0
  70. {whileai-0.65 → whileai-0.67}/whileai/simulations/score/preflight.py +0 -0
  71. {whileai-0.65 → whileai-0.67}/whileai/simulations/score/privileged.py +0 -0
  72. {whileai-0.65 → whileai-0.67}/whileai/simulations/score/publish_gate.py +0 -0
  73. {whileai-0.65 → whileai-0.67}/whileai/simulations/score/quality.py +0 -0
  74. {whileai-0.65 → whileai-0.67}/whileai/simulations/score/reference.py +0 -0
  75. {whileai-0.65 → whileai-0.67}/whileai/simulations/score/rubric.py +0 -0
  76. {whileai-0.65 → whileai-0.67}/whileai/simulations/score/spec.py +0 -0
  77. {whileai-0.65 → whileai-0.67}/whileai/simulations/score/stage.py +0 -0
  78. {whileai-0.65 → whileai-0.67}/whileai/simulations/score/stats.py +0 -0
  79. {whileai-0.65 → whileai-0.67}/whileai/simulations/score/style.py +0 -0
  80. {whileai-0.65 → whileai-0.67}/whileai/simulations/score/trace.py +0 -0
  81. {whileai-0.65 → whileai-0.67}/whileai/simulations/simulation.py +0 -0
  82. {whileai-0.65 → whileai-0.67}/whileai/simulations/text.py +0 -0
  83. {whileai-0.65 → whileai-0.67}/whileai/simulations/training.py +0 -0
  84. {whileai-0.65 → whileai-0.67}/whileai/simulations/verify/__init__.py +0 -0
  85. {whileai-0.65 → whileai-0.67}/whileai/simulations/verify/base.py +0 -0
  86. {whileai-0.65 → whileai-0.67}/whileai/simulations/verify/code.py +0 -0
  87. {whileai-0.65 → whileai-0.67}/whileai/simulations/verify/math.py +0 -0
  88. {whileai-0.65 → whileai-0.67}/whileai/simulations/verify/structured.py +0 -0
  89. {whileai-0.65 → whileai-0.67}/whileai/simulations/verify/text.py +0 -0
  90. {whileai-0.65 → whileai-0.67}/whileai/simulations/world/__init__.py +0 -0
  91. {whileai-0.65 → whileai-0.67}/whileai/simulations/world/sandbox.py +0 -0
  92. {whileai-0.65 → whileai-0.67}/whileai/templates/__init__.py +0 -0
  93. {whileai-0.65 → whileai-0.67}/whileai/templates/evals.py +0 -0
  94. {whileai-0.65 → whileai-0.67}/whileai.egg-info/SOURCES.txt +0 -0
  95. {whileai-0.65 → whileai-0.67}/whileai.egg-info/dependency_links.txt +0 -0
  96. {whileai-0.65 → whileai-0.67}/whileai.egg-info/entry_points.txt +0 -0
  97. {whileai-0.65 → whileai-0.67}/whileai.egg-info/requires.txt +0 -0
  98. {whileai-0.65 → whileai-0.67}/whileai.egg-info/top_level.txt +0 -0
whileai-0.67/PKG-INFO ADDED
@@ -0,0 +1,258 @@
1
+ Metadata-Version: 2.4
2
+ Name: whileai
3
+ Version: 0.67
4
+ Summary: Post-training data and evaluation for tool-using LLM agents: simulate, grade, measure, select, train, export, with the checks from rlhfbook.com.
5
+ Author: Jacob Weiss
6
+ License: Apache-2.0
7
+ Project-URL: Homepage, https://github.com/whilehq/whileai-sdk
8
+ Project-URL: Repository, https://github.com/whilehq/whileai-sdk
9
+ Project-URL: Issues, https://github.com/whilehq/whileai-sdk/issues
10
+ Project-URL: Datasets, https://huggingface.co/datasets/zero-proof-ai/agent-simulations
11
+ Keywords: zp,zeroproof,while,evals,agent-evals,rl,reinforcement-learning,grpo,synthetic-data,agents,tool-use,evaluation,simulation,llm
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: License :: OSI Approved :: Apache Software License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
22
+ Classifier: Typing :: Typed
23
+ Requires-Python: >=3.10
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Requires-Dist: requests>=2.25.0
27
+ Requires-Dist: pydantic>=2.0
28
+ Provides-Extra: dev
29
+ Requires-Dist: pytest>=8.0; extra == "dev"
30
+ Requires-Dist: pytest-cov>=5.0; extra == "dev"
31
+ Requires-Dist: ruff>=0.12; extra == "dev"
32
+ Requires-Dist: mypy>=1.16; extra == "dev"
33
+ Requires-Dist: types-requests; extra == "dev"
34
+ Provides-Extra: rl
35
+ Requires-Dist: verifiers>=0.3; (python_version >= "3.11" and python_version < "3.14") and extra == "rl"
36
+ Dynamic: license-file
37
+
38
+ <p align="center">
39
+ <a href="https://while.ai">
40
+ <picture>
41
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/whilehq/whileai-sdk/main/docs/assets/wordmark-dark.png">
42
+ <img src="https://raw.githubusercontent.com/whilehq/whileai-sdk/main/docs/assets/wordmark-light.png" alt="while" width="300">
43
+ </picture>
44
+ </a>
45
+ </p>
46
+
47
+ <p align="center"><code>MID-TRAINING AND POST-TRAINING FOR LANGUAGE MODELS</code></p>
48
+
49
+ <p align="center">
50
+ <a href="https://github.com/whilehq/whileai-sdk/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/whilehq/whileai-sdk/ci.yml?branch=main&label=ci&labelColor=0b1220&color=5cb08a" alt="CI"></a>
51
+ <a href="https://pypi.org/project/whileai/"><img src="https://img.shields.io/pypi/v/whileai?labelColor=0b1220&color=5cb08a" alt="PyPI"></a>
52
+ <a href="https://pypi.org/project/whileai/"><img src="https://img.shields.io/pypi/pyversions/whileai?labelColor=0b1220&color=3f8f6b" alt="Python"></a>
53
+ <a href="https://pypistats.org/packages/whileai"><img src="https://img.shields.io/pypi/dm/whileai?labelColor=0b1220&color=3f8f6b" alt="Downloads"></a>
54
+ <a href=".github/workflows/ci.yml"><img src="https://img.shields.io/badge/coverage-%E2%89%A5%2090%25%20gated-5cb08a?labelColor=0b1220" alt="Coverage gate"></a>
55
+ <a href="LICENSE"><img src="https://img.shields.io/badge/license-Apache--2.0-3f8f6b?labelColor=0b1220" alt="License"></a>
56
+ </p>
57
+
58
+ Post-training data and evaluation for tool-using language-model agents.
59
+ `whileai` simulates the situations an agent can meet, grades every rollout
60
+ under one judge contract, and turns graded rows into SFT, preference and
61
+ RL data with the checks the literature calls for. Each method cites its
62
+ source in [References](#references).
63
+
64
+ ```bash
65
+ uv add whileai
66
+ ```
67
+
68
+ Or `pip install whileai`. Python 3.10 to 3.13, one dependency, typed.
69
+ Formerly `zeroproof`; the old name still installs this package.
70
+
71
+ ## Two ways in
72
+
73
+ **Evals and the harness, no training.** A pass rate with an interval, a
74
+ table of where the agent fails, and a check that turns red in CI.
75
+ `whileai init-evals` writes the harness around the agent it finds in your
76
+ project, `coverage_gap` names what your tests never reach, and
77
+ `compare_runs` says whether a prompt or tool edit helped on the same pinned
78
+ tasks. Start at [docs/evals.md](docs/evals.md).
79
+
80
+ **Post-training.** The same graded rows, selected and exported: the loop below.
81
+
82
+ ## Sixty seconds, offline
83
+
84
+ No key, no network. The seeded agent misbehaves on a labeled fraction of
85
+ rollouts, so a judge that catches exactly those rows is a judge that works.
86
+
87
+ ```python
88
+ import whileai.simulations as wai
89
+
90
+ TOOLS = [
91
+ {
92
+ "type": "function",
93
+ "function": {
94
+ "name": "get_order",
95
+ "description": "Look up an order by id.",
96
+ "parameters": {
97
+ "type": "object",
98
+ "properties": {"order_id": {"type": "string"}},
99
+ "required": ["order_id"],
100
+ },
101
+ },
102
+ }
103
+ ]
104
+
105
+ data = wai.simulate(
106
+ wai.seeded_agent(TOOLS),
107
+ tools=TOOLS,
108
+ system_prompt="Help customers with orders.",
109
+ simulator=False, # no model
110
+ mode="rl",
111
+ repeats=4,
112
+ repeat_policy="fixed",
113
+ budget=64,
114
+ )
115
+ scored = data.grade(judge=lambda row: {"reward": int(not row["seeded"])})
116
+ print(scored.pass_at)
117
+ ```
118
+
119
+ ```
120
+ pass@1 0.67 [0.55..0.78] | pass^4 (pass_pow_k) 0.19 [0.00..0.38] | pass@4 1.00 [1.00..1.00] | headroom 0.33 (16 groups, k=4)
121
+ ```
122
+
123
+ Your agent is a callable `agent(message) -> {"steps", "final_text"}` or a
124
+ model spec: `openai:<model>`, `anthropic:<model>`, `vllm:<model>@<url>`,
125
+ `ollama:<model>`. With no `agent=`, hosted Qwen runs on your key
126
+ (`whileai login`) and Phi-4 judges, so the judge is never the policy.
127
+
128
+ ## The loop
129
+
130
+ | Step | Call | What it computes | Refs |
131
+ |---|---|---|---|
132
+ | Simulate | `simulate(agent, tools=, system_prompt=, mode="rl", repeats=k)` | covering array over tools, world state and user stance; k rollouts per prompt; scheduled tool faults | [2], [3] |
133
+ | Grade | `data.grade(judge=)`, `verify.MathEqual`, `verify.CodeExec` | reward per rollout under one contract; verifiable rewards | [4], [5] |
134
+ | Validate the judge | `judge_trust`, `judge_probes` | agreement and Cohen's kappa against human gold; length bias; exploit probes | [6], [7] |
135
+ | Measure | `pass_at`, `delta_report`, `eval_variance`, `holdout_size` | pass@1, pass^k, pass@k with bootstrap intervals over tasks; paired delta with a permutation p-value; noise band; power | [8], [9], [10], [11] |
136
+ | Select | `optimize(mode="rl"\|"sft")`, `build_preference_pairs`, `curriculum` | 20 to 80% difficulty band, unanimous-group drop, rejection sampling, length-matched pairs, curriculum | [12], [13], [14], [15] |
137
+ | Guard | `decontaminate`, `hack_scan`, `trace_markers`, `HackMonitor` | overlap with the eval set; reward-feature correlation within task against a shuffle floor; trajectory lies | [16], [17], [18] |
138
+ | Train and export | `export_dataset`, `export_environment`, `train`, `serve` | loss masks; a `verifiers` environment for GRPO; hosted LoRA SFT, GRPO, DPO, RM | [1], [19], [20] |
139
+
140
+ ## The science
141
+
142
+ **Supervised fine-tuning.** `optimize(mode="sft")` is rejection sampling
143
+ [14], [16] with random selectors as the chance control. Rows carry a
144
+ per-message `loss_mask`, `unroll=True` trains each turn on the context it
145
+ had, and `format="trl"` is what `SFTTrainer` loads [1, ch. 4].
146
+
147
+ **RL with verifiable rewards.** A reward is a program where it can be [5].
148
+ `mode="rl"` probes each prompt twice and fills to k only where the group
149
+ splits: a unanimous group has zero advantage under a group-relative
150
+ baseline [19] (dynamic sampling [12]). `optimize(mode="rl")` keeps the 20
151
+ to 80% band [13] and handles overlong rollouts by policy [12].
152
+ `export_environment` writes tasks, world and reward as a `verifiers`
153
+ package. Rows carry logprobs for the importance ratio [21] and `mean_kl`
154
+ reads drift from a reference [22].
155
+
156
+ **Character training.** A constitution is a versioned object [23], [24]:
157
+ `load_spec` hashes its principles into `spec.version`, the judge is checked
158
+ against the spec's own labels, pairs are length-matched [7], and
159
+ `must_not_regress=spec.behaviors()` fails a run that traded one trait for
160
+ another. [docs/character-training.md](docs/character-training.md).
161
+
162
+ **Evaluation.** pass@1 is a bootstrap over tasks, not rollouts [8], [10],
163
+ [11]. `runs=3` replays an eval and `delta_report` refuses a verdict inside
164
+ twice the re-run standard deviation. `holdout_size` returns the prompts a
165
+ gain needs at 80% power [11]. `decontaminate` applies the 80% n-gram
166
+ coverage rule [16] and an optional embedding pass.
167
+ [docs/evals.md](docs/evals.md).
168
+
169
+ **Over-optimization.** Reward is a proxy and a strong optimizer finds the
170
+ gap [17]. `hack_scan` ranks reward-feature correlation within task against
171
+ a shuffle floor; `judge_probes` tries the exploits a policy finds first,
172
+ sycophancy included [18]; `delta_report(proxy=, target=)` fails when the
173
+ proxy rose and the target did not; `HackMonitor` runs the scan inside a
174
+ TRL loop. [docs/reward-hacking.md](docs/reward-hacking.md).
175
+
176
+ ## Recipes
177
+
178
+ One post-training run as five steps; every recipe runs in CI.
179
+
180
+ | Step | Recipes |
181
+ |---|---|
182
+ | [01-simulate](recipes/01-simulate) | bring your own agent, verifiers, a traced coding agent |
183
+ | [02-measure](recipes/02-measure) | eval your agent, pass@k, reward hacking, safety evals |
184
+ | [03-select](recipes/03-select) | the row schema, GRPO data with a gradient gate, character |
185
+ | [04-train](recipes/04-train) | hosted loop, identity SFT, GRPO and DPO on Modal, text-to-SQL |
186
+ | [05-export](recipes/05-export) | Hugging Face datasets and adapters |
187
+ | [papers](recipes/papers) | one recent paper per recipe, the number it moved with its interval |
188
+
189
+ ## Platform
190
+
191
+ ```python
192
+ v1 = data.push("refunds-v1", holdout=0.2, gate=True) # refuses gradient-free RL data
193
+ run = wai.train(v1["datasetId"], method="grpo", steps=200) # sft | grpo | dpo | rm
194
+ run.wait()
195
+ model = wai.serve("refunds-v2", run) # OpenAI-compatible endpoint
196
+ ```
197
+
198
+ Your own trainer reports through `wai.TrainerCallback`; production traces
199
+ come back as `traces=` and aim the next run at what failed.
200
+
201
+ ## Documentation
202
+
203
+ [docs/reference.md](docs/reference.md): every call, knob, report and gate.
204
+ [docs/engine.md](docs/engine.md): how a row is made.
205
+ [CHANGELOG.md](CHANGELOG.md): one entry per release.
206
+
207
+ ## Development
208
+
209
+ ```bash
210
+ uv sync --extra dev
211
+ uv run pytest
212
+ uv run ruff check . && uv run mypy
213
+ ```
214
+
215
+ CI gates coverage at 90% and runs every recipe's `smoke.sh`.
216
+ [CONTRIBUTING.md](CONTRIBUTING.md).
217
+
218
+ ## Cite
219
+
220
+ ```bibtex
221
+ @software{weiss2026whileai,
222
+ title = {whileai: post-training data and evaluation for tool-using agents},
223
+ author = {Weiss, Jacob},
224
+ year = {2026},
225
+ url = {https://github.com/whilehq/whileai-sdk}
226
+ }
227
+ ```
228
+
229
+ ## References
230
+
231
+ 1. Lambert, N. *Reinforcement Learning from Human Feedback*. arXiv:2504.12501, 2025.
232
+ 2. Kuhn, D. R., Wallace, D. R., Gallo, A. M. Software Fault Interactions and Implications for Software Testing. *IEEE TSE* 30(6), 2004.
233
+ 3. Yao, S. et al. τ-bench: A Benchmark for Tool-Agent-User Interaction in Real-World Domains. arXiv:2406.12045, 2024.
234
+ 4. Ouyang, L. et al. Training Language Models to Follow Instructions with Human Feedback. NeurIPS, 2022.
235
+ 5. Lambert, N. et al. Tülu 3: Pushing Frontiers in Open Language Model Post-Training. arXiv:2411.15124, 2024.
236
+ 6. Cohen, J. A Coefficient of Agreement for Nominal Scales. *Educational and Psychological Measurement* 20(1), 1960.
237
+ 7. Zheng, L. et al. Judging LLM-as-a-Judge with MT-Bench and Chatbot Arena. NeurIPS, 2023.
238
+ 8. Chen, M. et al. Evaluating Large Language Models Trained on Code. arXiv:2107.03374, 2021.
239
+ 9. Wilson, E. B. Probable Inference, the Law of Succession, and Statistical Inference. *JASA* 22(158), 1927.
240
+ 10. Efron, B., Tibshirani, R. J. *An Introduction to the Bootstrap*. Chapman & Hall, 1993.
241
+ 11. Miller, E. Adding Error Bars to Evals. arXiv:2411.00640, 2024.
242
+ 12. Yu, Q. et al. DAPO: An Open-Source LLM Reinforcement Learning System at Scale. arXiv:2503.14476, 2025.
243
+ 13. He, J. et al. Skywork Open Reasoner 1 Technical Report. arXiv:2505.22312, 2025.
244
+ 14. Yuan, Z. et al. Scaling Relationship on Learning Mathematical Reasoning with Large Language Models. arXiv:2308.01825, 2023.
245
+ 15. Rafailov, R. et al. Direct Preference Optimization. NeurIPS, 2023.
246
+ 16. Touvron, H. et al. Llama 2: Open Foundation and Fine-Tuned Chat Models. arXiv:2307.09288, 2023.
247
+ 17. Gao, L., Schulman, J., Hilton, J. Scaling Laws for Reward Model Overoptimization. ICML, 2023.
248
+ 18. Sharma, M. et al. Towards Understanding Sycophancy in Language Models. ICLR, 2024.
249
+ 19. Shao, Z. et al. DeepSeekMath. arXiv:2402.03300, 2024.
250
+ 20. DeepSeek-AI. DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning. arXiv:2501.12948, 2025.
251
+ 21. Schulman, J. et al. Proximal Policy Optimization Algorithms. arXiv:1707.06347, 2017.
252
+ 22. Ziegler, D. M. et al. Fine-Tuning Language Models from Human Preferences. arXiv:1909.08593, 2019.
253
+ 23. Bai, Y. et al. Constitutional AI: Harmlessness from AI Feedback. arXiv:2212.08073, 2022.
254
+ 24. OpenAI. Model Spec, 2024. model-spec.openai.com.
255
+
256
+ ## License
257
+
258
+ Apache-2.0
whileai-0.67/README.md ADDED
@@ -0,0 +1,221 @@
1
+ <p align="center">
2
+ <a href="https://while.ai">
3
+ <picture>
4
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/whilehq/whileai-sdk/main/docs/assets/wordmark-dark.png">
5
+ <img src="https://raw.githubusercontent.com/whilehq/whileai-sdk/main/docs/assets/wordmark-light.png" alt="while" width="300">
6
+ </picture>
7
+ </a>
8
+ </p>
9
+
10
+ <p align="center"><code>MID-TRAINING AND POST-TRAINING FOR LANGUAGE MODELS</code></p>
11
+
12
+ <p align="center">
13
+ <a href="https://github.com/whilehq/whileai-sdk/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/whilehq/whileai-sdk/ci.yml?branch=main&label=ci&labelColor=0b1220&color=5cb08a" alt="CI"></a>
14
+ <a href="https://pypi.org/project/whileai/"><img src="https://img.shields.io/pypi/v/whileai?labelColor=0b1220&color=5cb08a" alt="PyPI"></a>
15
+ <a href="https://pypi.org/project/whileai/"><img src="https://img.shields.io/pypi/pyversions/whileai?labelColor=0b1220&color=3f8f6b" alt="Python"></a>
16
+ <a href="https://pypistats.org/packages/whileai"><img src="https://img.shields.io/pypi/dm/whileai?labelColor=0b1220&color=3f8f6b" alt="Downloads"></a>
17
+ <a href=".github/workflows/ci.yml"><img src="https://img.shields.io/badge/coverage-%E2%89%A5%2090%25%20gated-5cb08a?labelColor=0b1220" alt="Coverage gate"></a>
18
+ <a href="LICENSE"><img src="https://img.shields.io/badge/license-Apache--2.0-3f8f6b?labelColor=0b1220" alt="License"></a>
19
+ </p>
20
+
21
+ Post-training data and evaluation for tool-using language-model agents.
22
+ `whileai` simulates the situations an agent can meet, grades every rollout
23
+ under one judge contract, and turns graded rows into SFT, preference and
24
+ RL data with the checks the literature calls for. Each method cites its
25
+ source in [References](#references).
26
+
27
+ ```bash
28
+ uv add whileai
29
+ ```
30
+
31
+ Or `pip install whileai`. Python 3.10 to 3.13, one dependency, typed.
32
+ Formerly `zeroproof`; the old name still installs this package.
33
+
34
+ ## Two ways in
35
+
36
+ **Evals and the harness, no training.** A pass rate with an interval, a
37
+ table of where the agent fails, and a check that turns red in CI.
38
+ `whileai init-evals` writes the harness around the agent it finds in your
39
+ project, `coverage_gap` names what your tests never reach, and
40
+ `compare_runs` says whether a prompt or tool edit helped on the same pinned
41
+ tasks. Start at [docs/evals.md](docs/evals.md).
42
+
43
+ **Post-training.** The same graded rows, selected and exported: the loop below.
44
+
45
+ ## Sixty seconds, offline
46
+
47
+ No key, no network. The seeded agent misbehaves on a labeled fraction of
48
+ rollouts, so a judge that catches exactly those rows is a judge that works.
49
+
50
+ ```python
51
+ import whileai.simulations as wai
52
+
53
+ TOOLS = [
54
+ {
55
+ "type": "function",
56
+ "function": {
57
+ "name": "get_order",
58
+ "description": "Look up an order by id.",
59
+ "parameters": {
60
+ "type": "object",
61
+ "properties": {"order_id": {"type": "string"}},
62
+ "required": ["order_id"],
63
+ },
64
+ },
65
+ }
66
+ ]
67
+
68
+ data = wai.simulate(
69
+ wai.seeded_agent(TOOLS),
70
+ tools=TOOLS,
71
+ system_prompt="Help customers with orders.",
72
+ simulator=False, # no model
73
+ mode="rl",
74
+ repeats=4,
75
+ repeat_policy="fixed",
76
+ budget=64,
77
+ )
78
+ scored = data.grade(judge=lambda row: {"reward": int(not row["seeded"])})
79
+ print(scored.pass_at)
80
+ ```
81
+
82
+ ```
83
+ pass@1 0.67 [0.55..0.78] | pass^4 (pass_pow_k) 0.19 [0.00..0.38] | pass@4 1.00 [1.00..1.00] | headroom 0.33 (16 groups, k=4)
84
+ ```
85
+
86
+ Your agent is a callable `agent(message) -> {"steps", "final_text"}` or a
87
+ model spec: `openai:<model>`, `anthropic:<model>`, `vllm:<model>@<url>`,
88
+ `ollama:<model>`. With no `agent=`, hosted Qwen runs on your key
89
+ (`whileai login`) and Phi-4 judges, so the judge is never the policy.
90
+
91
+ ## The loop
92
+
93
+ | Step | Call | What it computes | Refs |
94
+ |---|---|---|---|
95
+ | Simulate | `simulate(agent, tools=, system_prompt=, mode="rl", repeats=k)` | covering array over tools, world state and user stance; k rollouts per prompt; scheduled tool faults | [2], [3] |
96
+ | Grade | `data.grade(judge=)`, `verify.MathEqual`, `verify.CodeExec` | reward per rollout under one contract; verifiable rewards | [4], [5] |
97
+ | Validate the judge | `judge_trust`, `judge_probes` | agreement and Cohen's kappa against human gold; length bias; exploit probes | [6], [7] |
98
+ | Measure | `pass_at`, `delta_report`, `eval_variance`, `holdout_size` | pass@1, pass^k, pass@k with bootstrap intervals over tasks; paired delta with a permutation p-value; noise band; power | [8], [9], [10], [11] |
99
+ | Select | `optimize(mode="rl"\|"sft")`, `build_preference_pairs`, `curriculum` | 20 to 80% difficulty band, unanimous-group drop, rejection sampling, length-matched pairs, curriculum | [12], [13], [14], [15] |
100
+ | Guard | `decontaminate`, `hack_scan`, `trace_markers`, `HackMonitor` | overlap with the eval set; reward-feature correlation within task against a shuffle floor; trajectory lies | [16], [17], [18] |
101
+ | Train and export | `export_dataset`, `export_environment`, `train`, `serve` | loss masks; a `verifiers` environment for GRPO; hosted LoRA SFT, GRPO, DPO, RM | [1], [19], [20] |
102
+
103
+ ## The science
104
+
105
+ **Supervised fine-tuning.** `optimize(mode="sft")` is rejection sampling
106
+ [14], [16] with random selectors as the chance control. Rows carry a
107
+ per-message `loss_mask`, `unroll=True` trains each turn on the context it
108
+ had, and `format="trl"` is what `SFTTrainer` loads [1, ch. 4].
109
+
110
+ **RL with verifiable rewards.** A reward is a program where it can be [5].
111
+ `mode="rl"` probes each prompt twice and fills to k only where the group
112
+ splits: a unanimous group has zero advantage under a group-relative
113
+ baseline [19] (dynamic sampling [12]). `optimize(mode="rl")` keeps the 20
114
+ to 80% band [13] and handles overlong rollouts by policy [12].
115
+ `export_environment` writes tasks, world and reward as a `verifiers`
116
+ package. Rows carry logprobs for the importance ratio [21] and `mean_kl`
117
+ reads drift from a reference [22].
118
+
119
+ **Character training.** A constitution is a versioned object [23], [24]:
120
+ `load_spec` hashes its principles into `spec.version`, the judge is checked
121
+ against the spec's own labels, pairs are length-matched [7], and
122
+ `must_not_regress=spec.behaviors()` fails a run that traded one trait for
123
+ another. [docs/character-training.md](docs/character-training.md).
124
+
125
+ **Evaluation.** pass@1 is a bootstrap over tasks, not rollouts [8], [10],
126
+ [11]. `runs=3` replays an eval and `delta_report` refuses a verdict inside
127
+ twice the re-run standard deviation. `holdout_size` returns the prompts a
128
+ gain needs at 80% power [11]. `decontaminate` applies the 80% n-gram
129
+ coverage rule [16] and an optional embedding pass.
130
+ [docs/evals.md](docs/evals.md).
131
+
132
+ **Over-optimization.** Reward is a proxy and a strong optimizer finds the
133
+ gap [17]. `hack_scan` ranks reward-feature correlation within task against
134
+ a shuffle floor; `judge_probes` tries the exploits a policy finds first,
135
+ sycophancy included [18]; `delta_report(proxy=, target=)` fails when the
136
+ proxy rose and the target did not; `HackMonitor` runs the scan inside a
137
+ TRL loop. [docs/reward-hacking.md](docs/reward-hacking.md).
138
+
139
+ ## Recipes
140
+
141
+ One post-training run as five steps; every recipe runs in CI.
142
+
143
+ | Step | Recipes |
144
+ |---|---|
145
+ | [01-simulate](recipes/01-simulate) | bring your own agent, verifiers, a traced coding agent |
146
+ | [02-measure](recipes/02-measure) | eval your agent, pass@k, reward hacking, safety evals |
147
+ | [03-select](recipes/03-select) | the row schema, GRPO data with a gradient gate, character |
148
+ | [04-train](recipes/04-train) | hosted loop, identity SFT, GRPO and DPO on Modal, text-to-SQL |
149
+ | [05-export](recipes/05-export) | Hugging Face datasets and adapters |
150
+ | [papers](recipes/papers) | one recent paper per recipe, the number it moved with its interval |
151
+
152
+ ## Platform
153
+
154
+ ```python
155
+ v1 = data.push("refunds-v1", holdout=0.2, gate=True) # refuses gradient-free RL data
156
+ run = wai.train(v1["datasetId"], method="grpo", steps=200) # sft | grpo | dpo | rm
157
+ run.wait()
158
+ model = wai.serve("refunds-v2", run) # OpenAI-compatible endpoint
159
+ ```
160
+
161
+ Your own trainer reports through `wai.TrainerCallback`; production traces
162
+ come back as `traces=` and aim the next run at what failed.
163
+
164
+ ## Documentation
165
+
166
+ [docs/reference.md](docs/reference.md): every call, knob, report and gate.
167
+ [docs/engine.md](docs/engine.md): how a row is made.
168
+ [CHANGELOG.md](CHANGELOG.md): one entry per release.
169
+
170
+ ## Development
171
+
172
+ ```bash
173
+ uv sync --extra dev
174
+ uv run pytest
175
+ uv run ruff check . && uv run mypy
176
+ ```
177
+
178
+ CI gates coverage at 90% and runs every recipe's `smoke.sh`.
179
+ [CONTRIBUTING.md](CONTRIBUTING.md).
180
+
181
+ ## Cite
182
+
183
+ ```bibtex
184
+ @software{weiss2026whileai,
185
+ title = {whileai: post-training data and evaluation for tool-using agents},
186
+ author = {Weiss, Jacob},
187
+ year = {2026},
188
+ url = {https://github.com/whilehq/whileai-sdk}
189
+ }
190
+ ```
191
+
192
+ ## References
193
+
194
+ 1. Lambert, N. *Reinforcement Learning from Human Feedback*. arXiv:2504.12501, 2025.
195
+ 2. Kuhn, D. R., Wallace, D. R., Gallo, A. M. Software Fault Interactions and Implications for Software Testing. *IEEE TSE* 30(6), 2004.
196
+ 3. Yao, S. et al. τ-bench: A Benchmark for Tool-Agent-User Interaction in Real-World Domains. arXiv:2406.12045, 2024.
197
+ 4. Ouyang, L. et al. Training Language Models to Follow Instructions with Human Feedback. NeurIPS, 2022.
198
+ 5. Lambert, N. et al. Tülu 3: Pushing Frontiers in Open Language Model Post-Training. arXiv:2411.15124, 2024.
199
+ 6. Cohen, J. A Coefficient of Agreement for Nominal Scales. *Educational and Psychological Measurement* 20(1), 1960.
200
+ 7. Zheng, L. et al. Judging LLM-as-a-Judge with MT-Bench and Chatbot Arena. NeurIPS, 2023.
201
+ 8. Chen, M. et al. Evaluating Large Language Models Trained on Code. arXiv:2107.03374, 2021.
202
+ 9. Wilson, E. B. Probable Inference, the Law of Succession, and Statistical Inference. *JASA* 22(158), 1927.
203
+ 10. Efron, B., Tibshirani, R. J. *An Introduction to the Bootstrap*. Chapman & Hall, 1993.
204
+ 11. Miller, E. Adding Error Bars to Evals. arXiv:2411.00640, 2024.
205
+ 12. Yu, Q. et al. DAPO: An Open-Source LLM Reinforcement Learning System at Scale. arXiv:2503.14476, 2025.
206
+ 13. He, J. et al. Skywork Open Reasoner 1 Technical Report. arXiv:2505.22312, 2025.
207
+ 14. Yuan, Z. et al. Scaling Relationship on Learning Mathematical Reasoning with Large Language Models. arXiv:2308.01825, 2023.
208
+ 15. Rafailov, R. et al. Direct Preference Optimization. NeurIPS, 2023.
209
+ 16. Touvron, H. et al. Llama 2: Open Foundation and Fine-Tuned Chat Models. arXiv:2307.09288, 2023.
210
+ 17. Gao, L., Schulman, J., Hilton, J. Scaling Laws for Reward Model Overoptimization. ICML, 2023.
211
+ 18. Sharma, M. et al. Towards Understanding Sycophancy in Language Models. ICLR, 2024.
212
+ 19. Shao, Z. et al. DeepSeekMath. arXiv:2402.03300, 2024.
213
+ 20. DeepSeek-AI. DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning. arXiv:2501.12948, 2025.
214
+ 21. Schulman, J. et al. Proximal Policy Optimization Algorithms. arXiv:1707.06347, 2017.
215
+ 22. Ziegler, D. M. et al. Fine-Tuning Language Models from Human Preferences. arXiv:1909.08593, 2019.
216
+ 23. Bai, Y. et al. Constitutional AI: Harmlessness from AI Feedback. arXiv:2212.08073, 2022.
217
+ 24. OpenAI. Model Spec, 2024. model-spec.openai.com.
218
+
219
+ ## License
220
+
221
+ Apache-2.0
@@ -4,13 +4,13 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "whileai"
7
- version = "0.65"
8
- description = "While Python SDK: trace ingestion and verification client, plus agent simulations grounded in your tools and system prompt."
7
+ version = "0.67"
8
+ description = "Post-training data and evaluation for tool-using LLM agents: simulate, grade, measure, select, train, export, with the checks from rlhfbook.com."
9
9
  readme = "README.md"
10
10
  license = {text = "Apache-2.0"}
11
11
  requires-python = ">=3.10"
12
12
  dependencies = ["requests>=2.25.0", "pydantic>=2.0"]
13
- authors = [{name = "While"}]
13
+ authors = [{name = "Jacob Weiss"}]
14
14
  keywords = [
15
15
  "zp", "zeroproof", "while", "evals", "agent-evals",
16
16
  "rl", "reinforcement-learning", "grpo", "synthetic-data", "agents",