whileai 0.60__tar.gz → 0.62__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.
- {whileai-0.60/whileai.egg-info → whileai-0.62}/PKG-INFO +7 -3
- {whileai-0.60 → whileai-0.62}/README.md +6 -2
- {whileai-0.60 → whileai-0.62}/pyproject.toml +5 -1
- {whileai-0.60 → whileai-0.62}/whileai/auth.py +61 -0
- {whileai-0.60 → whileai-0.62}/whileai/cli.py +19 -1
- whileai-0.62/whileai/init_evals.py +553 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/data.py +10 -1
- {whileai-0.60 → whileai-0.62}/whileai/simulations/generate/actionspace.py +14 -5
- {whileai-0.60 → whileai-0.62}/whileai/simulations/generate/adapters.py +25 -1
- {whileai-0.60 → whileai-0.62}/whileai/simulations/generate/generator.py +6 -3
- {whileai-0.60 → whileai-0.62}/whileai/simulations/run/config.py +5 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/run/engine.py +209 -13
- {whileai-0.60 → whileai-0.62}/whileai/simulations/score/hygiene.py +18 -1
- {whileai-0.60 → whileai-0.62}/whileai/simulations/score/judging.py +10 -1
- {whileai-0.60 → whileai-0.62}/whileai/simulations/simulation.py +13 -1
- whileai-0.62/whileai/templates/__init__.py +1 -0
- whileai-0.62/whileai/templates/evals.py +455 -0
- {whileai-0.60 → whileai-0.62/whileai.egg-info}/PKG-INFO +7 -3
- {whileai-0.60 → whileai-0.62}/whileai.egg-info/SOURCES.txt +4 -1
- {whileai-0.60 → whileai-0.62}/whileai.egg-info/entry_points.txt +2 -0
- {whileai-0.60 → whileai-0.62}/LICENSE +0 -0
- {whileai-0.60 → whileai-0.62}/MANIFEST.in +0 -0
- {whileai-0.60 → whileai-0.62}/setup.cfg +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/__init__.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/_env.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/ingest.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/py.typed +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/__init__.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/__main__.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/environment.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/export.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/generate/__init__.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/generate/agents.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/generate/anthropic_backend.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/generate/coverage.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/generate/diversity.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/generate/embeddings.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/generate/explore.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/generate/offline_agent.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/generate/scenarios.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/generate/usage_meter.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/ingest/__init__.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/ingest/otel.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/ingest/platform.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/ingest/traces.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/monitor.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/py.typed +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/run/__init__.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/run/rows.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/run/spec.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/schema.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/schemas/row-v1.json +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/score/__init__.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/score/agreement.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/score/audit.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/score/checklist.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/score/curriculum.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/score/delta.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/score/grade_llm.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/score/grading.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/score/grounding.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/score/hack_scan.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/score/judge_trust.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/score/labels.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/score/llm_judge.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/score/logprobs.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/score/markers.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/score/optimize.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/score/pairwise.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/score/passat.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/score/preflight.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/score/privileged.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/score/publish_gate.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/score/quality.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/score/reference.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/score/rubric.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/score/spec.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/score/stage.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/score/stats.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/score/style.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/score/trace.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/training.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/verify/__init__.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/verify/base.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/verify/code.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/verify/math.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/verify/structured.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/verify/text.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/world/__init__.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai/simulations/world/sandbox.py +0 -0
- {whileai-0.60 → whileai-0.62}/whileai.egg-info/dependency_links.txt +0 -0
- {whileai-0.60 → whileai-0.62}/whileai.egg-info/requires.txt +0 -0
- {whileai-0.60 → whileai-0.62}/whileai.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: whileai
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.62
|
|
4
4
|
Summary: While Python SDK: trace ingestion and verification client, plus agent simulations grounded in your tools and system prompt.
|
|
5
5
|
Author: While
|
|
6
6
|
License: Apache-2.0
|
|
@@ -41,7 +41,9 @@ The While Python SDK. One package, two importable modules:
|
|
|
41
41
|
- `whileai`: the platform client. OTLP trace ingest and trace-dataset listing against the token gate.
|
|
42
42
|
- `whileai.simulations`: post-training data for an agent. Give it the agent's traces, or its tools and system prompt; it simulates the situations, the people, and the world, plays the agent through multi-turn tool-calling conversations, and returns rows for your grader.
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
Have an agent and want a pass rate with an interval? Start at [docs/evals.md](docs/evals.md) (offline, seconds, `coverage_gap` names what your tests miss).
|
|
45
|
+
|
|
46
|
+
**Renamed.** This SDK was `zeroproof` (ZeroProof is now While). `pip install zeroproof` still works: it installs `whileai`, and `import zeroproof` (or the older `zeroproof_simulations`) resolves to the same modules with a deprecation warning. `ZEROPROOF_*` environment variables and a saved `~/.zeroproof/credentials.json` are still read. Change the import when you can; new releases land under `whileai`. zp, ZeroProof and While all name this one product: the package is `whileai`, the import is `whileai.simulations`, keys start with `zp_`. `zp`, `wai` and `whileai` run the same CLI, so `zp login` and `whileai login` do the same thing (the help text says `whileai`). A machine with the old package still picks up `~/.zeroproof/credentials.json`; set `WHILEAI_HOME` to a fresh directory to isolate a new account from it.
|
|
45
47
|
|
|
46
48
|
Releases of `whileai` before 0.3 were an unrelated encrypted agent-to-agent messaging client. That code was removed in 0.04; pin `whileai<0.3` if you still depend on it.
|
|
47
49
|
|
|
@@ -195,7 +197,9 @@ that reads the trajectory, run the asks `k` times each, and read pass@1
|
|
|
195
197
|
with its interval. Offline first, then the hosted writer. The how-to is
|
|
196
198
|
[docs/evals.md](docs/evals.md); the runnable version is
|
|
197
199
|
[`recipes/02-measure/eval-your-agent`](recipes/02-measure/eval-your-agent),
|
|
198
|
-
which ends at a CI gate, not a push.
|
|
200
|
+
which ends at a CI gate, not a push. `whileai init-evals` writes those
|
|
201
|
+
four files for you, wired to the tools, system prompt and callable it
|
|
202
|
+
finds in the project, and prints what it picked.
|
|
199
203
|
|
|
200
204
|
```python
|
|
201
205
|
data = wai.simulate(
|
|
@@ -5,7 +5,9 @@ The While Python SDK. One package, two importable modules:
|
|
|
5
5
|
- `whileai`: the platform client. OTLP trace ingest and trace-dataset listing against the token gate.
|
|
6
6
|
- `whileai.simulations`: post-training data for an agent. Give it the agent's traces, or its tools and system prompt; it simulates the situations, the people, and the world, plays the agent through multi-turn tool-calling conversations, and returns rows for your grader.
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Have an agent and want a pass rate with an interval? Start at [docs/evals.md](docs/evals.md) (offline, seconds, `coverage_gap` names what your tests miss).
|
|
9
|
+
|
|
10
|
+
**Renamed.** This SDK was `zeroproof` (ZeroProof is now While). `pip install zeroproof` still works: it installs `whileai`, and `import zeroproof` (or the older `zeroproof_simulations`) resolves to the same modules with a deprecation warning. `ZEROPROOF_*` environment variables and a saved `~/.zeroproof/credentials.json` are still read. Change the import when you can; new releases land under `whileai`. zp, ZeroProof and While all name this one product: the package is `whileai`, the import is `whileai.simulations`, keys start with `zp_`. `zp`, `wai` and `whileai` run the same CLI, so `zp login` and `whileai login` do the same thing (the help text says `whileai`). A machine with the old package still picks up `~/.zeroproof/credentials.json`; set `WHILEAI_HOME` to a fresh directory to isolate a new account from it.
|
|
9
11
|
|
|
10
12
|
Releases of `whileai` before 0.3 were an unrelated encrypted agent-to-agent messaging client. That code was removed in 0.04; pin `whileai<0.3` if you still depend on it.
|
|
11
13
|
|
|
@@ -159,7 +161,9 @@ that reads the trajectory, run the asks `k` times each, and read pass@1
|
|
|
159
161
|
with its interval. Offline first, then the hosted writer. The how-to is
|
|
160
162
|
[docs/evals.md](docs/evals.md); the runnable version is
|
|
161
163
|
[`recipes/02-measure/eval-your-agent`](recipes/02-measure/eval-your-agent),
|
|
162
|
-
which ends at a CI gate, not a push.
|
|
164
|
+
which ends at a CI gate, not a push. `whileai init-evals` writes those
|
|
165
|
+
four files for you, wired to the tools, system prompt and callable it
|
|
166
|
+
finds in the project, and prints what it picked.
|
|
163
167
|
|
|
164
168
|
```python
|
|
165
169
|
data = wai.simulate(
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "whileai"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.62"
|
|
8
8
|
description = "While Python SDK: trace ingestion and verification client, plus agent simulations grounded in your tools and system prompt."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = {text = "Apache-2.0"}
|
|
@@ -38,6 +38,10 @@ Datasets = "https://huggingface.co/datasets/zero-proof-ai/agent-simulations"
|
|
|
38
38
|
|
|
39
39
|
[project.scripts]
|
|
40
40
|
whileai = "whileai.cli:main"
|
|
41
|
+
# same CLI under the two names people type: the product is "zp"
|
|
42
|
+
# (keys start with zp_) and "wai" is the short import alias.
|
|
43
|
+
zp = "whileai.cli:main"
|
|
44
|
+
wai = "whileai.cli:main"
|
|
41
45
|
whileai-simulations = "whileai.simulations.score.quality:main"
|
|
42
46
|
|
|
43
47
|
[project.optional-dependencies]
|
|
@@ -66,6 +66,27 @@ def trial_note(daily_input_tokens: float | None = None) -> str:
|
|
|
66
66
|
)
|
|
67
67
|
|
|
68
68
|
|
|
69
|
+
def trial_prerun_note() -> str | None:
|
|
70
|
+
"""The one line a trial key needs before a hosted run spends it, or ``None``.
|
|
71
|
+
|
|
72
|
+
Read from the tier the credentials file recorded at sign-up or at the
|
|
73
|
+
last ``whileai status`` / ``whileai login``, so a run can say this
|
|
74
|
+
without a network call. A key from the environment has no recorded
|
|
75
|
+
tier, so this says nothing rather than guess at one.
|
|
76
|
+
"""
|
|
77
|
+
if getenv("API_KEY"):
|
|
78
|
+
return None
|
|
79
|
+
saved = _read(credentials_path()) or {}
|
|
80
|
+
if not saved.get("api_key") or str(saved.get("tier") or "") != "trial":
|
|
81
|
+
return None
|
|
82
|
+
tokens = int(float(saved.get("daily_input_tokens") or DEFAULT_TRIAL_INPUT_TOKENS))
|
|
83
|
+
return (
|
|
84
|
+
f"trial key: the hosted writer covers about {trial_situations(tokens)} situations a day "
|
|
85
|
+
f"({tokens // 1000}k input tokens); simulator=False writes them offline with no quota; "
|
|
86
|
+
f"sign in once at {SIGN_IN_URL} to lift it"
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
|
|
69
90
|
def _api_url() -> str:
|
|
70
91
|
return getenv("API_URL", DEFAULT_API_URL).rstrip("/")
|
|
71
92
|
|
|
@@ -112,6 +133,37 @@ def _read(path: Path) -> dict | None:
|
|
|
112
133
|
return data if isinstance(data, dict) else None
|
|
113
134
|
|
|
114
135
|
|
|
136
|
+
def _tier_fields(payload: dict) -> dict:
|
|
137
|
+
"""The tier facts worth keeping next to the key, from ``/signup`` or ``/me``."""
|
|
138
|
+
tier = str((payload or {}).get("tier") or "").strip()
|
|
139
|
+
if not tier:
|
|
140
|
+
return {}
|
|
141
|
+
fields: dict = {"tier": tier}
|
|
142
|
+
trial = (payload or {}).get("trial") or {}
|
|
143
|
+
if isinstance(trial, dict):
|
|
144
|
+
if trial.get("daily_input_tokens") is not None:
|
|
145
|
+
fields["daily_input_tokens"] = trial["daily_input_tokens"]
|
|
146
|
+
if trial.get("expires_at"):
|
|
147
|
+
fields["expires_at"] = str(trial["expires_at"])
|
|
148
|
+
return fields
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def remember_account(payload: dict) -> None:
|
|
152
|
+
"""Record a ``/signup`` or ``/me`` reply's tier in the credentials file.
|
|
153
|
+
|
|
154
|
+
Only for the key that file holds: a key from the environment may belong
|
|
155
|
+
to another account, and writing its tier here would mislabel this one.
|
|
156
|
+
"""
|
|
157
|
+
fields = _tier_fields(payload)
|
|
158
|
+
saved = _read(credentials_path())
|
|
159
|
+
if not fields or not saved or not saved.get("api_key"):
|
|
160
|
+
return
|
|
161
|
+
if all(saved.get(key) == value for key, value in fields.items()):
|
|
162
|
+
return
|
|
163
|
+
saved.update(fields)
|
|
164
|
+
_write_private(credentials_path(), saved)
|
|
165
|
+
|
|
166
|
+
|
|
115
167
|
def stored_api_key() -> str | None:
|
|
116
168
|
"""The key saved by ``whileai login``, or ``None``."""
|
|
117
169
|
data = _read(credentials_path())
|
|
@@ -264,6 +316,10 @@ def login(
|
|
|
264
316
|
)
|
|
265
317
|
with contextlib.suppress(OSError):
|
|
266
318
|
_pending_path().unlink()
|
|
319
|
+
# the tier the key carries, saved next to it, so a run can
|
|
320
|
+
# name a trial limit before it spends one
|
|
321
|
+
with contextlib.suppress(LoginError, OSError, ValueError):
|
|
322
|
+
remember_account(account(data["api_key"]))
|
|
267
323
|
say(f"Logged in. Key saved to {credentials_path()}")
|
|
268
324
|
return data["api_key"]
|
|
269
325
|
error = data.get("error", "")
|
|
@@ -306,6 +362,9 @@ def signup(email: str, *, name: str | None = None, out: Callable[[str], None] |
|
|
|
306
362
|
"user_id": data.get("user_id"),
|
|
307
363
|
"email": data.get("email", email),
|
|
308
364
|
"created_at": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
|
|
365
|
+
# so simulate() can warn about the trial before a hosted
|
|
366
|
+
# run spends it, without a call to /me
|
|
367
|
+
**_tier_fields(data),
|
|
309
368
|
},
|
|
310
369
|
)
|
|
311
370
|
say(f"Account created for {data.get('email', email)}. Key saved to {credentials_path()}")
|
|
@@ -382,6 +441,8 @@ def status() -> dict:
|
|
|
382
441
|
out["tier"] = f"unknown ({err})"
|
|
383
442
|
else:
|
|
384
443
|
out["tier"] = me.get("tier")
|
|
444
|
+
if not env:
|
|
445
|
+
remember_account(me)
|
|
385
446
|
if me.get("tier") == "trial":
|
|
386
447
|
trial = me.get("trial") or {}
|
|
387
448
|
out["trial_expires_at"] = trial.get("expires_at")
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""``whileai`` command line: login, signup, logout, status."""
|
|
1
|
+
"""``whileai`` command line: login, signup, logout, status, init-evals."""
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
@@ -7,6 +7,7 @@ import json
|
|
|
7
7
|
import sys
|
|
8
8
|
|
|
9
9
|
from . import auth
|
|
10
|
+
from .init_evals import add_arguments as init_evals_args
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
def main(argv: list[str] | None = None) -> int:
|
|
@@ -33,6 +34,12 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
33
34
|
sub.add_parser("logout", help="delete the saved key")
|
|
34
35
|
sub.add_parser("status", help="show which key the SDK will use")
|
|
35
36
|
|
|
37
|
+
p_init = sub.add_parser(
|
|
38
|
+
"init-evals",
|
|
39
|
+
help="write an eval harness (agent, judge, run, test) wired to this project",
|
|
40
|
+
)
|
|
41
|
+
init_evals_args(p_init)
|
|
42
|
+
|
|
36
43
|
p_purge = sub.add_parser(
|
|
37
44
|
"purge", help="delete an agent's traces, datasets and record, or empty datasets"
|
|
38
45
|
)
|
|
@@ -72,6 +79,17 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
72
79
|
return 1
|
|
73
80
|
return 0
|
|
74
81
|
|
|
82
|
+
if args.command == "init-evals":
|
|
83
|
+
from .init_evals import init_evals
|
|
84
|
+
|
|
85
|
+
return init_evals(
|
|
86
|
+
agent=args.agent,
|
|
87
|
+
tools=args.tools,
|
|
88
|
+
system_prompt=args.system_prompt,
|
|
89
|
+
out=args.dir,
|
|
90
|
+
force=args.force,
|
|
91
|
+
)
|
|
92
|
+
|
|
75
93
|
if args.command == "logout":
|
|
76
94
|
print("Logged out." if auth.logout() else "No saved key.")
|
|
77
95
|
return 0
|