@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/scripts/sync_config.py
CHANGED
|
@@ -1,105 +1,105 @@
|
|
|
1
|
-
"""Move `extra-openai-models.yaml` between this repo and the llm CLI.
|
|
2
|
-
|
|
3
|
-
The CLI reads its model registrations from one fixed path in its own per-user
|
|
4
|
-
folder (endpoints.LLM_DIR), which is not somewhere anyone thinks to look and
|
|
5
|
-
not somewhere version control reaches. So the data folder holds the canonical
|
|
6
|
-
copy and this moves it into place.
|
|
7
|
-
|
|
8
|
-
python scripts/sync_config.py # data folder -> llm (the usual way)
|
|
9
|
-
python scripts/sync_config.py --pull # llm -> data folder (live has drifted)
|
|
10
|
-
python scripts/sync_config.py --check # report differences, change nothing
|
|
11
|
-
|
|
12
|
-
A backup of whatever is being overwritten is written beside the target first,
|
|
13
|
-
because the live file is the one thing here that is not reproducible if the
|
|
14
|
-
repo copy turns out to be older.
|
|
15
|
-
"""
|
|
16
|
-
|
|
17
|
-
from __future__ import annotations
|
|
18
|
-
|
|
19
|
-
import argparse
|
|
20
|
-
import datetime as dt
|
|
21
|
-
import filecmp
|
|
22
|
-
import pathlib
|
|
23
|
-
import shutil
|
|
24
|
-
import sys
|
|
25
|
-
|
|
26
|
-
sys.path.insert(0, str(pathlib.Path(__file__).resolve().parent.parent / "metrics"))
|
|
27
|
-
from paths import DATA # noqa: E402 -- the install's data folder (metrics/paths.py)
|
|
28
|
-
import endpoints # noqa: E402
|
|
29
|
-
REPO = DATA / "config" / "extra-openai-models.yaml"
|
|
30
|
-
LIVE = endpoints.LLM_DIR / "extra-openai-models.yaml"
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
def _backup(path: pathlib.Path) -> pathlib.Path | None:
|
|
34
|
-
if not path.exists():
|
|
35
|
-
return None
|
|
36
|
-
stamp = dt.datetime.now().strftime("%Y%m%dT%H%M%S")
|
|
37
|
-
dest = path.with_suffix(f".{stamp}.bak")
|
|
38
|
-
shutil.copy2(path, dest)
|
|
39
|
-
return dest
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
def main() -> int:
|
|
43
|
-
ap = argparse.ArgumentParser(description=__doc__)
|
|
44
|
-
ap.add_argument("--pull", action="store_true",
|
|
45
|
-
help="copy the live file back into the repo")
|
|
46
|
-
ap.add_argument("--check", action="store_true",
|
|
47
|
-
help="report whether they differ; change nothing")
|
|
48
|
-
args = ap.parse_args()
|
|
49
|
-
|
|
50
|
-
if not REPO.exists() and not args.pull:
|
|
51
|
-
print(f"repo copy missing: {REPO}", file=sys.stderr)
|
|
52
|
-
return 1
|
|
53
|
-
|
|
54
|
-
if args.check:
|
|
55
|
-
if not LIVE.exists():
|
|
56
|
-
print(f"live file does not exist: {LIVE}")
|
|
57
|
-
return 1
|
|
58
|
-
same = REPO.exists() and filecmp.cmp(REPO, LIVE, shallow=False)
|
|
59
|
-
print("identical" if same else "DIFFERENT")
|
|
60
|
-
if not same:
|
|
61
|
-
print(f" repo: {REPO}")
|
|
62
|
-
print(f" live: {LIVE}")
|
|
63
|
-
return 0 if same else 1
|
|
64
|
-
|
|
65
|
-
src, dst = (LIVE, REPO) if args.pull else (REPO, LIVE)
|
|
66
|
-
if not src.exists():
|
|
67
|
-
print(f"source missing: {src}", file=sys.stderr)
|
|
68
|
-
return 1
|
|
69
|
-
|
|
70
|
-
dst.parent.mkdir(parents=True, exist_ok=True)
|
|
71
|
-
backup = _backup(dst)
|
|
72
|
-
shutil.copy2(src, dst)
|
|
73
|
-
print(f"{src}\n -> {dst}")
|
|
74
|
-
if backup:
|
|
75
|
-
print(f" (previous version kept at {backup.name})")
|
|
76
|
-
if not args.pull:
|
|
77
|
-
apply_options()
|
|
78
|
-
print("\nConfirm with: llm models list")
|
|
79
|
-
return 0
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
def apply_options() -> None:
|
|
83
|
-
"""`config/model-options.json` -> `llm models options set`, per alias.
|
|
84
|
-
|
|
85
|
-
Default options live in the llm CLI's own store, which no repo reaches;
|
|
86
|
-
this file is the canonical copy, as the yaml is for registrations."""
|
|
87
|
-
import json
|
|
88
|
-
import subprocess
|
|
89
|
-
path = REPO.parent / "model-options.json"
|
|
90
|
-
# No llm CLI (the Docker image): no store to set them in, and the
|
|
91
|
-
# built-in client reads this file itself.
|
|
92
|
-
if not path.exists() or not shutil.which("llm"):
|
|
93
|
-
return
|
|
94
|
-
for alias, options in json.loads(path.read_text(encoding="utf-8")).items():
|
|
95
|
-
if alias.startswith("_"):
|
|
96
|
-
continue
|
|
97
|
-
for name, value in options.items():
|
|
98
|
-
done = subprocess.run(["llm", "models", "options", "set", alias, name, str(value)],
|
|
99
|
-
capture_output=True, text=True)
|
|
100
|
-
if done.returncode:
|
|
101
|
-
print(f" could not set {alias} {name}={value}: {done.stderr.strip()[:200]}")
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
if __name__ == "__main__":
|
|
105
|
-
raise SystemExit(main())
|
|
1
|
+
"""Move `extra-openai-models.yaml` between this repo and the llm CLI.
|
|
2
|
+
|
|
3
|
+
The CLI reads its model registrations from one fixed path in its own per-user
|
|
4
|
+
folder (endpoints.LLM_DIR), which is not somewhere anyone thinks to look and
|
|
5
|
+
not somewhere version control reaches. So the data folder holds the canonical
|
|
6
|
+
copy and this moves it into place.
|
|
7
|
+
|
|
8
|
+
python scripts/sync_config.py # data folder -> llm (the usual way)
|
|
9
|
+
python scripts/sync_config.py --pull # llm -> data folder (live has drifted)
|
|
10
|
+
python scripts/sync_config.py --check # report differences, change nothing
|
|
11
|
+
|
|
12
|
+
A backup of whatever is being overwritten is written beside the target first,
|
|
13
|
+
because the live file is the one thing here that is not reproducible if the
|
|
14
|
+
repo copy turns out to be older.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
import argparse
|
|
20
|
+
import datetime as dt
|
|
21
|
+
import filecmp
|
|
22
|
+
import pathlib
|
|
23
|
+
import shutil
|
|
24
|
+
import sys
|
|
25
|
+
|
|
26
|
+
sys.path.insert(0, str(pathlib.Path(__file__).resolve().parent.parent / "metrics"))
|
|
27
|
+
from paths import DATA # noqa: E402 -- the install's data folder (metrics/paths.py)
|
|
28
|
+
import endpoints # noqa: E402
|
|
29
|
+
REPO = DATA / "config" / "extra-openai-models.yaml"
|
|
30
|
+
LIVE = endpoints.LLM_DIR / "extra-openai-models.yaml"
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _backup(path: pathlib.Path) -> pathlib.Path | None:
|
|
34
|
+
if not path.exists():
|
|
35
|
+
return None
|
|
36
|
+
stamp = dt.datetime.now().strftime("%Y%m%dT%H%M%S")
|
|
37
|
+
dest = path.with_suffix(f".{stamp}.bak")
|
|
38
|
+
shutil.copy2(path, dest)
|
|
39
|
+
return dest
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def main() -> int:
|
|
43
|
+
ap = argparse.ArgumentParser(description=__doc__)
|
|
44
|
+
ap.add_argument("--pull", action="store_true",
|
|
45
|
+
help="copy the live file back into the repo")
|
|
46
|
+
ap.add_argument("--check", action="store_true",
|
|
47
|
+
help="report whether they differ; change nothing")
|
|
48
|
+
args = ap.parse_args()
|
|
49
|
+
|
|
50
|
+
if not REPO.exists() and not args.pull:
|
|
51
|
+
print(f"repo copy missing: {REPO}", file=sys.stderr)
|
|
52
|
+
return 1
|
|
53
|
+
|
|
54
|
+
if args.check:
|
|
55
|
+
if not LIVE.exists():
|
|
56
|
+
print(f"live file does not exist: {LIVE}")
|
|
57
|
+
return 1
|
|
58
|
+
same = REPO.exists() and filecmp.cmp(REPO, LIVE, shallow=False)
|
|
59
|
+
print("identical" if same else "DIFFERENT")
|
|
60
|
+
if not same:
|
|
61
|
+
print(f" repo: {REPO}")
|
|
62
|
+
print(f" live: {LIVE}")
|
|
63
|
+
return 0 if same else 1
|
|
64
|
+
|
|
65
|
+
src, dst = (LIVE, REPO) if args.pull else (REPO, LIVE)
|
|
66
|
+
if not src.exists():
|
|
67
|
+
print(f"source missing: {src}", file=sys.stderr)
|
|
68
|
+
return 1
|
|
69
|
+
|
|
70
|
+
dst.parent.mkdir(parents=True, exist_ok=True)
|
|
71
|
+
backup = _backup(dst)
|
|
72
|
+
shutil.copy2(src, dst)
|
|
73
|
+
print(f"{src}\n -> {dst}")
|
|
74
|
+
if backup:
|
|
75
|
+
print(f" (previous version kept at {backup.name})")
|
|
76
|
+
if not args.pull:
|
|
77
|
+
apply_options()
|
|
78
|
+
print("\nConfirm with: llm models list")
|
|
79
|
+
return 0
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def apply_options() -> None:
|
|
83
|
+
"""`config/model-options.json` -> `llm models options set`, per alias.
|
|
84
|
+
|
|
85
|
+
Default options live in the llm CLI's own store, which no repo reaches;
|
|
86
|
+
this file is the canonical copy, as the yaml is for registrations."""
|
|
87
|
+
import json
|
|
88
|
+
import subprocess
|
|
89
|
+
path = REPO.parent / "model-options.json"
|
|
90
|
+
# No llm CLI (the Docker image): no store to set them in, and the
|
|
91
|
+
# built-in client reads this file itself.
|
|
92
|
+
if not path.exists() or not shutil.which("llm"):
|
|
93
|
+
return
|
|
94
|
+
for alias, options in json.loads(path.read_text(encoding="utf-8")).items():
|
|
95
|
+
if alias.startswith("_"):
|
|
96
|
+
continue
|
|
97
|
+
for name, value in options.items():
|
|
98
|
+
done = subprocess.run(["llm", "models", "options", "set", alias, name, str(value)],
|
|
99
|
+
capture_output=True, text=True)
|
|
100
|
+
if done.returncode:
|
|
101
|
+
print(f" could not set {alias} {name}={value}: {done.stderr.strip()[:200]}")
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
if __name__ == "__main__":
|
|
105
|
+
raise SystemExit(main())
|