@wendellresearch-ai/benchwarmers 0.2.0 → 0.2.1
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.
- package/AGENTS.md +147 -147
- package/BENCHMARKS.md +262 -262
- package/GATEWAY.md +272 -272
- package/NOTICE +28 -28
- package/PRIVACY.md +46 -46
- package/README.md +368 -314
- package/SECURITY.md +83 -83
- package/TERMS.md +22 -22
- package/USAGE.md +170 -163
- package/VERSION +1 -1
- package/bin/benchwarmers.js +16 -74
- package/cli.py +666 -0
- package/examples/config/gateway.json +5 -5
- package/examples/config/model-roles.json +11 -11
- package/gateway.py +755 -755
- package/launcher.py +120 -0
- package/mcp_server.py +266 -266
- package/metrics/alerts.py +116 -116
- package/metrics/aliases.py +41 -41
- package/metrics/bench_collections.py +141 -141
- package/metrics/catalog.py +295 -295
- package/metrics/client.py +394 -394
- package/metrics/cliproxy.py +191 -191
- package/metrics/connect.py +691 -691
- package/metrics/cost.py +152 -152
- package/metrics/decide.py +227 -227
- package/metrics/discover.py +318 -318
- package/metrics/endpoints.py +436 -436
- package/metrics/guard.py +617 -592
- package/metrics/learn.py +221 -221
- package/metrics/litellm_hub.py +206 -206
- package/metrics/model_roles.py +84 -84
- package/metrics/offload.py +166 -166
- package/metrics/owui.py +205 -205
- package/metrics/paths.py +60 -60
- package/metrics/route.py +579 -579
- package/metrics/scheduler.py +275 -275
- package/metrics/sources.py +167 -167
- package/metrics/wrong.py +144 -144
- package/package.json +68 -65
- package/perf/README.md +89 -89
- package/perf/run.py +261 -261
- package/scripts/auto_retire.py +367 -367
- package/scripts/check.py +108 -106
- package/scripts/check_deprecations.py +378 -378
- package/scripts/check_themes.py +103 -103
- package/scripts/init.py +124 -124
- package/scripts/list_served.py +78 -78
- package/scripts/notice.py +78 -78
- package/scripts/onboard.py +401 -331
- package/scripts/provider_tags.py +129 -129
- package/scripts/reprefix.py +136 -136
- package/scripts/sync_config.py +105 -105
- package/scripts/test_auth.py +255 -255
- package/scripts/test_cli.py +189 -0
- package/scripts/test_client.py +233 -233
- package/scripts/test_connect.py +222 -222
- package/scripts/test_first_run.py +180 -180
- package/scripts/test_hubs.py +328 -328
- package/scripts/test_launcher.py +67 -0
- package/scripts/test_llm_log.py +85 -81
- package/scripts/test_mcp.py +178 -178
- package/scripts/test_merged.py +214 -214
- package/scripts/test_no_owui.py +291 -291
- package/scripts/test_owui.py +90 -90
- package/scripts/test_serve_edit.py +448 -438
- package/scripts/test_verdict.py +98 -98
- package/scripts/test_vision.py +228 -228
- package/serve.py +3904 -3764
- package/suite/mine.py +154 -154
- package/suite/pace.py +145 -145
- package/suite/run.py +1046 -1042
- package/suite/seed.py +421 -421
- package/suite/tasks/claim-alias-unbound/fixtures/onboard.py +286 -286
- package/suite/tasks/claim-error-text-string/fixtures/decide.py +187 -187
- package/suite/tasks/claim-list-body/fixtures/gateway.py +235 -235
- package/suite/tasks/claim-member-nominated-twice/fixtures/gateway.py +284 -284
- package/suite/tasks/claim-nominee-uses-slot/fixtures/gateway.py +284 -284
- package/suite/tasks/claim-silent-exit/fixtures/gateway.py +235 -235
- package/suite/tasks/claim-sse-hang/fixtures/gateway.py +235 -235
- package/suite/tasks/claim-unknown-nominee-crash/fixtures/gateway.py +284 -284
- package/suite/tasks/rebench-matchms-809-bug/task.json +23 -23
- package/suite/tasks/rebench-matchms-809-control/task.json +27 -27
- package/suite/tasks/rebench-more-itertools-1028-bug/task.json +23 -23
- package/suite/tasks/rebench-more-itertools-1028-control/task.json +27 -27
- package/suite/tasks/rebench-narwhals-2864-bug/task.json +23 -23
- package/suite/tasks/rebench-narwhals-2864-control/task.json +27 -27
- package/suite/tasks/rebench-quantecon-py-769-bug/task.json +23 -23
- package/suite/tasks/rebench-quantecon-py-769-control/task.json +27 -27
- package/suite/tasks/rebench-scrapy-6867-bug/task.json +23 -23
- package/suite/tasks/rebench-scrapy-6867-control/task.json +27 -27
- package/ui/bench.css +430 -425
- package/ui/bench.js +1756 -1576
- package/ui/themes/dark.css +35 -35
- package/ui/themes/hardwood.css +52 -52
- package/ui/themes/rainforest.css +32 -32
package/SECURITY.md
CHANGED
|
@@ -1,83 +1,83 @@
|
|
|
1
|
-
# Security
|
|
2
|
-
|
|
3
|
-
## Supported versions
|
|
4
|
-
|
|
5
|
-
Fixes ship on `main` and in the next release. Use the latest of either.
|
|
6
|
-
|
|
7
|
-
| Version | Supported |
|
|
8
|
-
| --- | --- |
|
|
9
|
-
| latest release, `main` | ✅ |
|
|
10
|
-
| older releases | ❌ |
|
|
11
|
-
|
|
12
|
-
## Reporting a vulnerability
|
|
13
|
-
|
|
14
|
-
Report it privately through
|
|
15
|
-
[GitHub Security Advisories](https://github.com/WendellResearch-AI/benchwarmers/security/advisories/new).
|
|
16
|
-
Please don't open a public issue for a vulnerability.
|
|
17
|
-
|
|
18
|
-
Include what you can: the version or commit, how it is run (from source or
|
|
19
|
-
Docker, bound to 127.0.0.1 or wider, with or without an admin token), steps to
|
|
20
|
-
reproduce, and what an attacker gains.
|
|
21
|
-
|
|
22
|
-
## The model
|
|
23
|
-
|
|
24
|
-
**On this machine by default.** The dashboard (`serve.py`, port 8122) and the
|
|
25
|
-
gateway (on the same port at `/v1`, or alone with `gateway.py` on 8123) listen
|
|
26
|
-
on 127.0.0.1. Every request is checked for the server's own host name (against
|
|
27
|
-
DNS rebinding), and every write must be a same-origin JSON request, so a web
|
|
28
|
-
page open in your browser cannot drive either server. With no admin token
|
|
29
|
-
there is no login and the gateway asks for no key.
|
|
30
|
-
|
|
31
|
-
**Anywhere else, only with a login.** To listen beyond this machine
|
|
32
|
-
(`BENCH_BIND`, and `BENCH_PORT` / `BENCH_GATEWAY_PORT` for the ports), set
|
|
33
|
-
`BENCHWARMERS_ADMIN_TOKEN` (16 or more characters) first; without it both
|
|
34
|
-
servers refuse to start. With a token:
|
|
35
|
-
|
|
36
|
-
- the dashboard asks for it once, then keeps an `HttpOnly; SameSite=Strict`
|
|
37
|
-
session cookie for a week (changing the token signs everyone out);
|
|
38
|
-
- the gateway's routes (`/v1/...`, `/bench/verdict`) take a **gateway key** as
|
|
39
|
-
`Authorization: Bearer <key>`. Make named keys on Settings: each is shown
|
|
40
|
-
once, kept only as a hash, revocable, and never opens the dashboard;
|
|
41
|
-
- `BENCHWARMERS_PUBLIC_URL` (e.g. `https://bench.example.com`) is the address
|
|
42
|
-
browsers use behind a proxy or on a LAN address; its host and origin are
|
|
43
|
-
accepted, and the cookie is `Secure` when it is https;
|
|
44
|
-
- every request is logged to stderr: route, status, and who (a key's name or
|
|
45
|
-
admin), never a secret.
|
|
46
|
-
|
|
47
|
-
`BENCHWARMERS_REQUIRE_KEYS=1` asks for gateway keys on this machine too, with
|
|
48
|
-
the dashboard left open, so each local app has its own. A key can be limited
|
|
49
|
-
to some collections and to a number of requests a minute, and its name is on
|
|
50
|
-
every call it makes. A browser app on another origin is let in by
|
|
51
|
-
`BENCH_ALLOWED_ORIGINS` (CORS on the gateway's routes only; never `*`).
|
|
52
|
-
|
|
53
|
-
Settings, under Server and access, shows how all of this stands right now
|
|
54
|
-
(whether a secret is set, never its value). It is changed only in the
|
|
55
|
-
environment, then a restart: a page that could change its own login could
|
|
56
|
-
open itself to anyone.
|
|
57
|
-
|
|
58
|
-
## What Benchwarmers touches
|
|
59
|
-
|
|
60
|
-
- **Keys.** Endpoint keys come from `BENCHWARMERS_KEY_<NAME>` (the key name
|
|
61
|
-
upper-cased, `-` as `_`) first, then from the `llm` CLI's key store. They are
|
|
62
|
-
never written to the data folder, never shown back, and never put in a log.
|
|
63
|
-
Sign-ins through a provider's page store their token the same way.
|
|
64
|
-
- **The network.** Your prompts go only to the endpoints you add; the probes,
|
|
65
|
-
the suite and onboarding spend calls there too. Otherwise: public catalog
|
|
66
|
-
reads (models.dev, FreeLLMAPI, OpenRouter's model list), a provider's
|
|
67
|
-
sign-in page when you choose one, Observable Plot from jsDelivr in the
|
|
68
|
-
dashboard's page, and Hugging Face and GitHub only when you run
|
|
69
|
-
`suite/rebench.py`. [PRIVACY.md](PRIVACY.md) lists them.
|
|
70
|
-
- **Files.** It writes inside its data folder (`BENCHWARMERS_HOME`, or the
|
|
71
|
-
folder `.benchwarmers-home` names) and, in the `llm` CLI's own folder, its
|
|
72
|
-
key store (when you paste a key or sign in) and its model list (when it
|
|
73
|
-
registers a model). Images sent to the gateway are never written to a log.
|
|
74
|
-
- **Processes.** Onboarding, the probes and the suite run this repository's
|
|
75
|
-
own scripts with the same Python. Model ids that reach a command line are
|
|
76
|
-
checked against a strict pattern first.
|
|
77
|
-
|
|
78
|
-
## Endpoints you add
|
|
79
|
-
|
|
80
|
-
An endpoint receives everything sent to the models on it, including any code
|
|
81
|
-
or document in a prompt. Benchwarmers cannot vouch for a provider; the
|
|
82
|
-
Endpoints page says the same. Some providers' free tiers keep prompts or train
|
|
83
|
-
on them: check each one's terms before you send it private work.
|
|
1
|
+
# Security
|
|
2
|
+
|
|
3
|
+
## Supported versions
|
|
4
|
+
|
|
5
|
+
Fixes ship on `main` and in the next release. Use the latest of either.
|
|
6
|
+
|
|
7
|
+
| Version | Supported |
|
|
8
|
+
| --- | --- |
|
|
9
|
+
| latest release, `main` | ✅ |
|
|
10
|
+
| older releases | ❌ |
|
|
11
|
+
|
|
12
|
+
## Reporting a vulnerability
|
|
13
|
+
|
|
14
|
+
Report it privately through
|
|
15
|
+
[GitHub Security Advisories](https://github.com/WendellResearch-AI/benchwarmers/security/advisories/new).
|
|
16
|
+
Please don't open a public issue for a vulnerability.
|
|
17
|
+
|
|
18
|
+
Include what you can: the version or commit, how it is run (from source or
|
|
19
|
+
Docker, bound to 127.0.0.1 or wider, with or without an admin token), steps to
|
|
20
|
+
reproduce, and what an attacker gains.
|
|
21
|
+
|
|
22
|
+
## The model
|
|
23
|
+
|
|
24
|
+
**On this machine by default.** The dashboard (`serve.py`, port 8122) and the
|
|
25
|
+
gateway (on the same port at `/v1`, or alone with `gateway.py` on 8123) listen
|
|
26
|
+
on 127.0.0.1. Every request is checked for the server's own host name (against
|
|
27
|
+
DNS rebinding), and every write must be a same-origin JSON request, so a web
|
|
28
|
+
page open in your browser cannot drive either server. With no admin token
|
|
29
|
+
there is no login and the gateway asks for no key.
|
|
30
|
+
|
|
31
|
+
**Anywhere else, only with a login.** To listen beyond this machine
|
|
32
|
+
(`BENCH_BIND`, and `BENCH_PORT` / `BENCH_GATEWAY_PORT` for the ports), set
|
|
33
|
+
`BENCHWARMERS_ADMIN_TOKEN` (16 or more characters) first; without it both
|
|
34
|
+
servers refuse to start. With a token:
|
|
35
|
+
|
|
36
|
+
- the dashboard asks for it once, then keeps an `HttpOnly; SameSite=Strict`
|
|
37
|
+
session cookie for a week (changing the token signs everyone out);
|
|
38
|
+
- the gateway's routes (`/v1/...`, `/bench/verdict`) take a **gateway key** as
|
|
39
|
+
`Authorization: Bearer <key>`. Make named keys on Settings: each is shown
|
|
40
|
+
once, kept only as a hash, revocable, and never opens the dashboard;
|
|
41
|
+
- `BENCHWARMERS_PUBLIC_URL` (e.g. `https://bench.example.com`) is the address
|
|
42
|
+
browsers use behind a proxy or on a LAN address; its host and origin are
|
|
43
|
+
accepted, and the cookie is `Secure` when it is https;
|
|
44
|
+
- every request is logged to stderr: route, status, and who (a key's name or
|
|
45
|
+
admin), never a secret.
|
|
46
|
+
|
|
47
|
+
`BENCHWARMERS_REQUIRE_KEYS=1` asks for gateway keys on this machine too, with
|
|
48
|
+
the dashboard left open, so each local app has its own. A key can be limited
|
|
49
|
+
to some collections and to a number of requests a minute, and its name is on
|
|
50
|
+
every call it makes. A browser app on another origin is let in by
|
|
51
|
+
`BENCH_ALLOWED_ORIGINS` (CORS on the gateway's routes only; never `*`).
|
|
52
|
+
|
|
53
|
+
Settings, under Server and access, shows how all of this stands right now
|
|
54
|
+
(whether a secret is set, never its value). It is changed only in the
|
|
55
|
+
environment, then a restart: a page that could change its own login could
|
|
56
|
+
open itself to anyone.
|
|
57
|
+
|
|
58
|
+
## What Benchwarmers touches
|
|
59
|
+
|
|
60
|
+
- **Keys.** Endpoint keys come from `BENCHWARMERS_KEY_<NAME>` (the key name
|
|
61
|
+
upper-cased, `-` as `_`) first, then from the `llm` CLI's key store. They are
|
|
62
|
+
never written to the data folder, never shown back, and never put in a log.
|
|
63
|
+
Sign-ins through a provider's page store their token the same way.
|
|
64
|
+
- **The network.** Your prompts go only to the endpoints you add; the probes,
|
|
65
|
+
the suite and onboarding spend calls there too. Otherwise: public catalog
|
|
66
|
+
reads (models.dev, FreeLLMAPI, OpenRouter's model list), a provider's
|
|
67
|
+
sign-in page when you choose one, Observable Plot from jsDelivr in the
|
|
68
|
+
dashboard's page, and Hugging Face and GitHub only when you run
|
|
69
|
+
`suite/rebench.py`. [PRIVACY.md](PRIVACY.md) lists them.
|
|
70
|
+
- **Files.** It writes inside its data folder (`BENCHWARMERS_HOME`, or the
|
|
71
|
+
folder `.benchwarmers-home` names) and, in the `llm` CLI's own folder, its
|
|
72
|
+
key store (when you paste a key or sign in) and its model list (when it
|
|
73
|
+
registers a model). Images sent to the gateway are never written to a log.
|
|
74
|
+
- **Processes.** Onboarding, the probes and the suite run this repository's
|
|
75
|
+
own scripts with the same Python. Model ids that reach a command line are
|
|
76
|
+
checked against a strict pattern first.
|
|
77
|
+
|
|
78
|
+
## Endpoints you add
|
|
79
|
+
|
|
80
|
+
An endpoint receives everything sent to the models on it, including any code
|
|
81
|
+
or document in a prompt. Benchwarmers cannot vouch for a provider; the
|
|
82
|
+
Endpoints page says the same. Some providers' free tiers keep prompts or train
|
|
83
|
+
on them: check each one's terms before you send it private work.
|
package/TERMS.md
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
# Terms of use
|
|
2
|
-
|
|
3
|
-
*Effective 22 October 2026.*
|
|
4
|
-
|
|
5
|
-
Benchwarmers is free to use under its [license](LICENSE) (MIT). These terms
|
|
6
|
-
add only the following.
|
|
7
|
-
|
|
8
|
-
- **Provided as is.** It comes with no warranty of any kind. Its panels,
|
|
9
|
-
scores and verdicts are evidence to weigh, not advice: models agree with each
|
|
10
|
-
other and are still wrong, so check what they say before you act on it.
|
|
11
|
-
- **Your responsibility.** You are responsible for the endpoints you add, for
|
|
12
|
-
what you send to them, for the calls it makes on your keys, and for following
|
|
13
|
-
each provider's terms, rate limits and usage policies.
|
|
14
|
-
- **No liability.** To the extent the law allows, Wendell Research is not
|
|
15
|
-
liable for any loss or damage arising from its use, including the cost of
|
|
16
|
-
model calls.
|
|
17
|
-
- **Not affiliated.** It isn't made or endorsed by any model provider,
|
|
18
|
-
aggregator or hub it works with. Names belong to their owners.
|
|
19
|
-
- **Changes.** These terms may change; the current version is always this
|
|
20
|
-
file, with its history in the repository's commits.
|
|
21
|
-
|
|
22
|
-
Questions: [open an issue](https://github.com/WendellResearch-AI/benchwarmers/issues).
|
|
1
|
+
# Terms of use
|
|
2
|
+
|
|
3
|
+
*Effective 22 October 2026.*
|
|
4
|
+
|
|
5
|
+
Benchwarmers is free to use under its [license](LICENSE) (MIT). These terms
|
|
6
|
+
add only the following.
|
|
7
|
+
|
|
8
|
+
- **Provided as is.** It comes with no warranty of any kind. Its panels,
|
|
9
|
+
scores and verdicts are evidence to weigh, not advice: models agree with each
|
|
10
|
+
other and are still wrong, so check what they say before you act on it.
|
|
11
|
+
- **Your responsibility.** You are responsible for the endpoints you add, for
|
|
12
|
+
what you send to them, for the calls it makes on your keys, and for following
|
|
13
|
+
each provider's terms, rate limits and usage policies.
|
|
14
|
+
- **No liability.** To the extent the law allows, Wendell Research is not
|
|
15
|
+
liable for any loss or damage arising from its use, including the cost of
|
|
16
|
+
model calls.
|
|
17
|
+
- **Not affiliated.** It isn't made or endorsed by any model provider,
|
|
18
|
+
aggregator or hub it works with. Names belong to their owners.
|
|
19
|
+
- **Changes.** These terms may change; the current version is always this
|
|
20
|
+
file, with its history in the repository's commits.
|
|
21
|
+
|
|
22
|
+
Questions: [open an issue](https://github.com/WendellResearch-AI/benchwarmers/issues).
|
package/USAGE.md
CHANGED
|
@@ -1,163 +1,170 @@
|
|
|
1
|
-
# Using Benchwarmers
|
|
2
|
-
|
|
3
|
-
Day-to-day use, once it runs: the dashboard's pages, onboarding models,
|
|
4
|
-
collections, connecting your apps and recording verdicts. Setting it up is in
|
|
5
|
-
the README's [Try it](README.md#try-it) (or [AGENTS.md](AGENTS.md), for a
|
|
6
|
-
coding agent doing it with you); the gateway's whole contract is in
|
|
7
|
-
[GATEWAY.md](GATEWAY.md).
|
|
8
|
-
|
|
9
|
-
## Contents
|
|
10
|
-
|
|
11
|
-
- [The dashboard](#the-dashboard)
|
|
12
|
-
- [Onboarding models](#onboarding-models)
|
|
13
|
-
- [Collections](#collections)
|
|
14
|
-
- [Connecting an app](#connecting-an-app)
|
|
15
|
-
- [Recording verdicts](#recording-verdicts)
|
|
16
|
-
- [Discover: finding models to add](#discover-finding-models-to-add)
|
|
17
|
-
- [The scheduler](#the-scheduler)
|
|
18
|
-
- [Your data folder](#your-data-folder)
|
|
19
|
-
|
|
20
|
-
## The dashboard
|
|
21
|
-
|
|
22
|
-
`python serve.py`, then http://localhost:8122. The sidebar groups its pages:
|
|
23
|
-
|
|
24
|
-
| Group | Page | What it is for |
|
|
25
|
-
| --- | --- | --- |
|
|
26
|
-
| Observe | **At a glance** | Every model on the bench: whether it works right now, its role, and its connection. Click a name for its popup: role, alias, facts, options, retire. |
|
|
27
|
-
| | **Benchmarks** | How models do on the suite and on real work: bugs found against false alarms, who is confidently wrong, and speed. |
|
|
28
|
-
| | **Quota management** | What limits each connection, and which models are resting after hitting one. |
|
|
29
|
-
| | **Logs** | Gateway calls (who sat and how it went, never the prompt), changes made from the dashboard, the scheduler, and onboarding runs. |
|
|
30
|
-
| Gateway | **Endpoints** | Where models are served from. Add an endpoint (a provider's sign-in, or any OpenAI-compatible API key), change a key, and see what each one serves. Also your own app registrations and rate limits per connection. |
|
|
31
|
-
| | **Models** | Every model on the bench, by the connection it comes from. |
|
|
32
|
-
| | **Collections** | The named panels your apps ask for, and the gateway's settings. |
|
|
33
|
-
| | **Discover** | Models worth adding, from public catalogs, with the ways this install can reach each one. |
|
|
34
|
-
| Control | **Settings** | Theme, gateway keys, the scheduler, the model client, providers whose free models work only in their own app, and how the install is reached (shown only). |
|
|
35
|
-
| | **Info** | Version, Python, data folder and counts. |
|
|
36
|
-
|
|
37
|
-
"Action needed", above the pages, lists what will not fix itself, such as a
|
|
38
|
-
model about to be retired, with Retry, Open and Retire now beside it. Hide
|
|
39
|
-
folds it away until something new turns up.
|
|
40
|
-
|
|
41
|
-
## Onboarding models
|
|
42
|
-
|
|
43
|
-
**Onboard a model**, top right, lists everything your endpoints serve that is
|
|
44
|
-
not on the bench yet. Search, and tick one or several: the ticks survive a new
|
|
45
|
-
search, so you can gather models from different connections in one go.
|
|
46
|
-
Dismiss hides one you never want offered (an image model, say); the dismissed
|
|
47
|
-
list brings it back.
|
|
48
|
-
|
|
49
|
-
Each model is registered, probed with four short calls, and, if it answers,
|
|
50
|
-
run through the suite. That takes minutes and spends calls, so they run **one
|
|
51
|
-
at a time**, in a queue the dashboard keeps:
|
|
52
|
-
|
|
53
|
-
- One model with nothing ahead of it is followed step by step in the popup.
|
|
54
|
-
- Otherwise the popup shows the queue, and a chip beside the button shows the
|
|
55
|
-
progress ("Onboarding 2 of 5: ..."), filling as models finish. It turns green
|
|
56
|
-
when every model is on the bench, and red when one failed or did not answer.
|
|
57
|
-
- Closing the popup or reloading the page stops nothing. **Details** reopens
|
|
58
|
-
the queue: each model's state, its alias, why it stopped, and its log.
|
|
59
|
-
- **Stop** lets the model running now finish and skips the rest. **Clear**
|
|
60
|
-
forgets a finished batch's results; the logs stay in `runs/`.
|
|
61
|
-
|
|
62
|
-
A model that registered but did not answer stays on the bench as
|
|
63
|
-
unavailable, so the daily probe keeps watching it.
|
|
64
|
-
|
|
65
|
-
## Collections
|
|
66
|
-
|
|
67
|
-
A collection is a named panel: the models it always includes, the shape of
|
|
68
|
-
work it is for (review, design, enumeration, ...), and how its reply comes
|
|
69
|
-
back. On the **Collections** page, **New collection**, then pick the members.
|
|
70
|
-
Each call also seats explorers, the models unused longest, up to the gateway's
|
|
71
|
-
limits (Gateway settings, on the same page: how many calls a request may make,
|
|
72
|
-
and how many of them explore).
|
|
73
|
-
|
|
74
|
-
## Connecting an app
|
|
75
|
-
|
|
76
|
-
Any OpenAI-compatible client works. Point it at the dashboard's port and ask
|
|
77
|
-
for the model `bench/<collection>`:
|
|
78
|
-
|
|
79
|
-
| Setting | Value |
|
|
80
|
-
| --- | --- |
|
|
81
|
-
| Base URL | `http://127.0.0.1:8122/v1` (or `gateway.py` alone: `http://127.0.0.1:8123/v1`) |
|
|
82
|
-
| API key | any text on this machine; a **gateway key** from Settings when keys are required |
|
|
83
|
-
| Model | `bench/<collection>`, or `bench/<collection>:merged` for one merged answer |
|
|
84
|
-
|
|
85
|
-
With the OpenAI Python SDK:
|
|
86
|
-
|
|
87
|
-
```python
|
|
88
|
-
from openai import OpenAI
|
|
89
|
-
|
|
90
|
-
bench = OpenAI(base_url="http://127.0.0.1:8122/v1", api_key="local")
|
|
91
|
-
reply = bench.chat.completions.create(
|
|
92
|
-
model="bench/<collection>",
|
|
93
|
-
messages=[{"role": "user", "content": "Where can this function return a stale value? ..."}],
|
|
94
|
-
)
|
|
95
|
-
print(reply.choices[0].message.content) # every seat's answer, labelled
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
In a chat app such as Open WebUI, add the base URL as an OpenAI connection;
|
|
99
|
-
the collections appear as models. For a chat window, the `:merged` form reads
|
|
100
|
-
best: a merger model writes one answer saying where the seats agreed and
|
|
101
|
-
disagreed, and every seat is still in the reply's `bench` field.
|
|
102
|
-
|
|
103
|
-
Images go in as OpenAI `image_url` parts; only models that take images sit,
|
|
104
|
-
and the rest are listed in `bench.skipped`. [GATEWAY.md](GATEWAY.md) has the
|
|
105
|
-
limits and the reply's full shape.
|
|
106
|
-
|
|
107
|
-
**A coding agent** connects over MCP instead: the Claude Code plugin
|
|
108
|
-
(`/plugin marketplace add WendellResearch-AI/benchwarmers`, then
|
|
109
|
-
`/plugin install benchwarmers@benchwarmers`), or `benchwarmers mcp` in any MCP
|
|
110
|
-
client, with `BENCHWARMERS_URL` and, where keys are required, a gateway key in
|
|
111
|
-
`BENCHWARMERS_KEY`. Its `ask` tool returns every seat with its call id and its
|
|
112
|
-
`verdict` tool records the verdicts; README, "From Claude Code and other
|
|
113
|
-
agents", has the set-up.
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
1
|
+
# Using Benchwarmers
|
|
2
|
+
|
|
3
|
+
Day-to-day use, once it runs: the dashboard's pages, onboarding models,
|
|
4
|
+
collections, connecting your apps and recording verdicts. Setting it up is in
|
|
5
|
+
the README's [Try it](README.md#try-it) (or [AGENTS.md](AGENTS.md), for a
|
|
6
|
+
coding agent doing it with you); the gateway's whole contract is in
|
|
7
|
+
[GATEWAY.md](GATEWAY.md).
|
|
8
|
+
|
|
9
|
+
## Contents
|
|
10
|
+
|
|
11
|
+
- [The dashboard](#the-dashboard)
|
|
12
|
+
- [Onboarding models](#onboarding-models)
|
|
13
|
+
- [Collections](#collections)
|
|
14
|
+
- [Connecting an app](#connecting-an-app)
|
|
15
|
+
- [Recording verdicts](#recording-verdicts)
|
|
16
|
+
- [Discover: finding models to add](#discover-finding-models-to-add)
|
|
17
|
+
- [The scheduler](#the-scheduler)
|
|
18
|
+
- [Your data folder](#your-data-folder)
|
|
19
|
+
|
|
20
|
+
## The dashboard
|
|
21
|
+
|
|
22
|
+
`python serve.py`, then http://localhost:8122. The sidebar groups its pages:
|
|
23
|
+
|
|
24
|
+
| Group | Page | What it is for |
|
|
25
|
+
| --- | --- | --- |
|
|
26
|
+
| Observe | **At a glance** | Every model on the bench: whether it works right now, its role, and its connection. Click a name for its popup: role, alias, facts, options, retire. |
|
|
27
|
+
| | **Benchmarks** | How models do on the suite and on real work: bugs found against false alarms, who is confidently wrong, and speed. |
|
|
28
|
+
| | **Quota management** | What limits each connection, and which models are resting after hitting one. |
|
|
29
|
+
| | **Logs** | Gateway calls (who sat and how it went, never the prompt), changes made from the dashboard, the scheduler, and onboarding runs. |
|
|
30
|
+
| Gateway | **Endpoints** | Where models are served from. Add an endpoint (a provider's sign-in, or any OpenAI-compatible API key), change a key, and see what each one serves. Also your own app registrations and rate limits per connection. |
|
|
31
|
+
| | **Models** | Every model on the bench, by the connection it comes from. |
|
|
32
|
+
| | **Collections** | The named panels your apps ask for, and the gateway's settings. |
|
|
33
|
+
| | **Discover** | Models worth adding, from public catalogs, with the ways this install can reach each one. |
|
|
34
|
+
| Control | **Settings** | Theme, gateway keys, the scheduler, the model client, providers whose free models work only in their own app, and how the install is reached (shown only). |
|
|
35
|
+
| | **Info** | Version, Python, data folder and counts. |
|
|
36
|
+
|
|
37
|
+
"Action needed", above the pages, lists what will not fix itself, such as a
|
|
38
|
+
model about to be retired, with Retry, Open and Retire now beside it. Hide
|
|
39
|
+
folds it away until something new turns up.
|
|
40
|
+
|
|
41
|
+
## Onboarding models
|
|
42
|
+
|
|
43
|
+
**Onboard a model**, top right, lists everything your endpoints serve that is
|
|
44
|
+
not on the bench yet. Search, and tick one or several: the ticks survive a new
|
|
45
|
+
search, so you can gather models from different connections in one go.
|
|
46
|
+
Dismiss hides one you never want offered (an image model, say); the dismissed
|
|
47
|
+
list brings it back.
|
|
48
|
+
|
|
49
|
+
Each model is registered, probed with four short calls, and, if it answers,
|
|
50
|
+
run through the suite. That takes minutes and spends calls, so they run **one
|
|
51
|
+
at a time**, in a queue the dashboard keeps:
|
|
52
|
+
|
|
53
|
+
- One model with nothing ahead of it is followed step by step in the popup.
|
|
54
|
+
- Otherwise the popup shows the queue, and a chip beside the button shows the
|
|
55
|
+
progress ("Onboarding 2 of 5: ..."), filling as models finish. It turns green
|
|
56
|
+
when every model is on the bench, and red when one failed or did not answer.
|
|
57
|
+
- Closing the popup or reloading the page stops nothing. **Details** reopens
|
|
58
|
+
the queue: each model's state, its alias, why it stopped, and its log.
|
|
59
|
+
- **Stop** lets the model running now finish and skips the rest. **Clear**
|
|
60
|
+
forgets a finished batch's results; the logs stay in `runs/`.
|
|
61
|
+
|
|
62
|
+
A model that registered but did not answer stays on the bench as
|
|
63
|
+
unavailable, so the daily probe keeps watching it.
|
|
64
|
+
|
|
65
|
+
## Collections
|
|
66
|
+
|
|
67
|
+
A collection is a named panel: the models it always includes, the shape of
|
|
68
|
+
work it is for (review, design, enumeration, ...), and how its reply comes
|
|
69
|
+
back. On the **Collections** page, **New collection**, then pick the members.
|
|
70
|
+
Each call also seats explorers, the models unused longest, up to the gateway's
|
|
71
|
+
limits (Gateway settings, on the same page: how many calls a request may make,
|
|
72
|
+
and how many of them explore).
|
|
73
|
+
|
|
74
|
+
## Connecting an app
|
|
75
|
+
|
|
76
|
+
Any OpenAI-compatible client works. Point it at the dashboard's port and ask
|
|
77
|
+
for the model `bench/<collection>`:
|
|
78
|
+
|
|
79
|
+
| Setting | Value |
|
|
80
|
+
| --- | --- |
|
|
81
|
+
| Base URL | `http://127.0.0.1:8122/v1` (or `gateway.py` alone: `http://127.0.0.1:8123/v1`) |
|
|
82
|
+
| API key | any text on this machine; a **gateway key** from Settings when keys are required |
|
|
83
|
+
| Model | `bench/<collection>`, or `bench/<collection>:merged` for one merged answer |
|
|
84
|
+
|
|
85
|
+
With the OpenAI Python SDK:
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
from openai import OpenAI
|
|
89
|
+
|
|
90
|
+
bench = OpenAI(base_url="http://127.0.0.1:8122/v1", api_key="local")
|
|
91
|
+
reply = bench.chat.completions.create(
|
|
92
|
+
model="bench/<collection>",
|
|
93
|
+
messages=[{"role": "user", "content": "Where can this function return a stale value? ..."}],
|
|
94
|
+
)
|
|
95
|
+
print(reply.choices[0].message.content) # every seat's answer, labelled
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
In a chat app such as Open WebUI, add the base URL as an OpenAI connection;
|
|
99
|
+
the collections appear as models. For a chat window, the `:merged` form reads
|
|
100
|
+
best: a merger model writes one answer saying where the seats agreed and
|
|
101
|
+
disagreed, and every seat is still in the reply's `bench` field.
|
|
102
|
+
|
|
103
|
+
Images go in as OpenAI `image_url` parts; only models that take images sit,
|
|
104
|
+
and the rest are listed in `bench.skipped`. [GATEWAY.md](GATEWAY.md) has the
|
|
105
|
+
limits and the reply's full shape.
|
|
106
|
+
|
|
107
|
+
**A coding agent** connects over MCP instead: the Claude Code plugin
|
|
108
|
+
(`/plugin marketplace add WendellResearch-AI/benchwarmers`, then
|
|
109
|
+
`/plugin install benchwarmers@benchwarmers`), or `benchwarmers mcp` in any MCP
|
|
110
|
+
client, with `BENCHWARMERS_URL` and, where keys are required, a gateway key in
|
|
111
|
+
`BENCHWARMERS_KEY`. Its `ask` tool returns every seat with its call id and its
|
|
112
|
+
`verdict` tool records the verdicts; README, "From Claude Code and other
|
|
113
|
+
agents", has the set-up.
|
|
114
|
+
|
|
115
|
+
**From a terminal or a script**, `bench ask <collection> "..."` (a pipe or
|
|
116
|
+
`-f FILE` adds the text to review) prints every seat's answer and a table of
|
|
117
|
+
call ids, and `bench verdict <call id> --useful|--not-useful` judges one. The
|
|
118
|
+
rest of this guide's pages have commands too (`bench models`, `bench onboard`,
|
|
119
|
+
`bench collection save`, `bench endpoint add`, `bench key create`, `bench
|
|
120
|
+
settings`); README, "From the command line", lists them.
|
|
121
|
+
|
|
122
|
+
## Recording verdicts
|
|
123
|
+
|
|
124
|
+
A panel's answers are worth something only once someone has checked them
|
|
125
|
+
against the real work. Every seat has a call id; record a verdict per call on
|
|
126
|
+
the Collections page (the Gateway card lists recent requests: click a seat),
|
|
127
|
+
or:
|
|
128
|
+
|
|
129
|
+
curl http://127.0.0.1:8122/bench/verdict -H "Content-Type: application/json" \
|
|
130
|
+
-d '{"call": "<call id>", "useful": true, "note": "found the real bug", "real": ["..."], "false": ["..."]}'
|
|
131
|
+
|
|
132
|
+
`real` and `false` list the specific claims you verified either way. False
|
|
133
|
+
claims feed **Confidently wrong** on Benchmarks, and verdicts together decide
|
|
134
|
+
who sits on the next panel. Agreement between models is not evidence: they
|
|
135
|
+
are often wrong together.
|
|
136
|
+
|
|
137
|
+
## Discover: finding models to add
|
|
138
|
+
|
|
139
|
+
**Discover** merges models.dev and FreeLLMAPI into one list, free models
|
|
140
|
+
first, with what is new this week badged. A row opens its popup: what the
|
|
141
|
+
model takes and does, its price, and every route this install has to it, each
|
|
142
|
+
with an **Add via this**. Adding through a hub (Open WebUI, LiteLLM, CLI Proxy
|
|
143
|
+
API) puts it in that hub too; adding direct registers it on its own endpoint
|
|
144
|
+
only. Either way the onboarding joins the same queue.
|
|
145
|
+
|
|
146
|
+
Some providers' free models work only inside their own app; Discover leaves
|
|
147
|
+
those out and keeps their paid models. Settings, **Free only in their own
|
|
148
|
+
app**, switches a provider either way or adds one.
|
|
149
|
+
|
|
150
|
+
## The scheduler
|
|
151
|
+
|
|
152
|
+
The recurring jobs (the morning availability probe, the catalog refresh, the
|
|
153
|
+
deprecation check and auto-retire, suite passes, the weekly speed and
|
|
154
|
+
capability tests) run inside the dashboard. Settings, **Scheduler**:
|
|
155
|
+
|
|
156
|
+
- **Off**: nothing runs; a fresh install spends no calls until you opt in.
|
|
157
|
+
- **Log only**: writes "would run" to `runs/scheduler.log` at each due time,
|
|
158
|
+
to check the times before anything spends calls.
|
|
159
|
+
- **Run**: runs each job at its time, one at a time per job.
|
|
160
|
+
|
|
161
|
+
If something else already runs these jobs (cron, Windows Task Scheduler),
|
|
162
|
+
turn it off in the same step, or every job runs twice.
|
|
163
|
+
|
|
164
|
+
## Your data folder
|
|
165
|
+
|
|
166
|
+
Everything that is yours (endpoints, registrations, collections, verdicts,
|
|
167
|
+
call logs, probe history, task answers) lives in the data folder: the one
|
|
168
|
+
`BENCHWARMERS_HOME` names, else the one in `.benchwarmers-home` at the top of
|
|
169
|
+
the checkout. Back it up by copying it; move it by copying it and pointing one
|
|
170
|
+
of those two at the new place. Info shows which folder is in use.
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.2.
|
|
1
|
+
0.2.1
|