llm-benchmark-manager 0.3.0__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.
- llm_benchmark_manager-0.3.0/CHANGELOG.md +35 -0
- llm_benchmark_manager-0.3.0/CONTRIBUTING.md +37 -0
- llm_benchmark_manager-0.3.0/LICENSE +21 -0
- llm_benchmark_manager-0.3.0/MANIFEST.in +7 -0
- llm_benchmark_manager-0.3.0/PKG-INFO +464 -0
- llm_benchmark_manager-0.3.0/README.hu.md +426 -0
- llm_benchmark_manager-0.3.0/README.md +430 -0
- llm_benchmark_manager-0.3.0/SECURITY.md +36 -0
- llm_benchmark_manager-0.3.0/docs/ARCHITECTURE.hu.md +89 -0
- llm_benchmark_manager-0.3.0/docs/ARCHITECTURE.md +89 -0
- llm_benchmark_manager-0.3.0/pyproject.toml +50 -0
- llm_benchmark_manager-0.3.0/setup.cfg +4 -0
- llm_benchmark_manager-0.3.0/src/llm_benchmark_manager.egg-info/PKG-INFO +464 -0
- llm_benchmark_manager-0.3.0/src/llm_benchmark_manager.egg-info/SOURCES.txt +61 -0
- llm_benchmark_manager-0.3.0/src/llm_benchmark_manager.egg-info/dependency_links.txt +1 -0
- llm_benchmark_manager-0.3.0/src/llm_benchmark_manager.egg-info/entry_points.txt +2 -0
- llm_benchmark_manager-0.3.0/src/llm_benchmark_manager.egg-info/requires.txt +14 -0
- llm_benchmark_manager-0.3.0/src/llm_benchmark_manager.egg-info/top_level.txt +1 -0
- llm_benchmark_manager-0.3.0/src/llmbench/__init__.py +1 -0
- llm_benchmark_manager-0.3.0/src/llmbench/api.py +77 -0
- llm_benchmark_manager-0.3.0/src/llmbench/benchmark/__init__.py +2 -0
- llm_benchmark_manager-0.3.0/src/llmbench/benchmark/aiperf.py +90 -0
- llm_benchmark_manager-0.3.0/src/llmbench/benchmark/profiles.py +16 -0
- llm_benchmark_manager-0.3.0/src/llmbench/capabilities.py +77 -0
- llm_benchmark_manager-0.3.0/src/llmbench/classification.py +56 -0
- llm_benchmark_manager-0.3.0/src/llmbench/cli.py +165 -0
- llm_benchmark_manager-0.3.0/src/llmbench/credentials.py +245 -0
- llm_benchmark_manager-0.3.0/src/llmbench/db.py +162 -0
- llm_benchmark_manager-0.3.0/src/llmbench/discovery.py +20 -0
- llm_benchmark_manager-0.3.0/src/llmbench/domain.py +100 -0
- llm_benchmark_manager-0.3.0/src/llmbench/export.py +13 -0
- llm_benchmark_manager-0.3.0/src/llmbench/jobs.py +32 -0
- llm_benchmark_manager-0.3.0/src/llmbench/mcp_server.py +44 -0
- llm_benchmark_manager-0.3.0/src/llmbench/paths.py +35 -0
- llm_benchmark_manager-0.3.0/src/llmbench/progress.py +14 -0
- llm_benchmark_manager-0.3.0/src/llmbench/providers/__init__.py +1 -0
- llm_benchmark_manager-0.3.0/src/llmbench/providers/base.py +9 -0
- llm_benchmark_manager-0.3.0/src/llmbench/providers/openai_compatible.py +150 -0
- llm_benchmark_manager-0.3.0/src/llmbench/response_extract.py +63 -0
- llm_benchmark_manager-0.3.0/src/llmbench/runtime.py +21 -0
- llm_benchmark_manager-0.3.0/src/llmbench/service.py +367 -0
- llm_benchmark_manager-0.3.0/tests/test_aiperf.py +43 -0
- llm_benchmark_manager-0.3.0/tests/test_api.py +48 -0
- llm_benchmark_manager-0.3.0/tests/test_capabilities.py +44 -0
- llm_benchmark_manager-0.3.0/tests/test_classification.py +39 -0
- llm_benchmark_manager-0.3.0/tests/test_cli.py +84 -0
- llm_benchmark_manager-0.3.0/tests/test_credentials.py +75 -0
- llm_benchmark_manager-0.3.0/tests/test_db.py +23 -0
- llm_benchmark_manager-0.3.0/tests/test_discovery.py +22 -0
- llm_benchmark_manager-0.3.0/tests/test_domain.py +6 -0
- llm_benchmark_manager-0.3.0/tests/test_export.py +12 -0
- llm_benchmark_manager-0.3.0/tests/test_integration.py +16 -0
- llm_benchmark_manager-0.3.0/tests/test_jobs.py +12 -0
- llm_benchmark_manager-0.3.0/tests/test_mcp.py +31 -0
- llm_benchmark_manager-0.3.0/tests/test_migration_v01.py +38 -0
- llm_benchmark_manager-0.3.0/tests/test_mixed_catalog.py +48 -0
- llm_benchmark_manager-0.3.0/tests/test_progress_db.py +32 -0
- llm_benchmark_manager-0.3.0/tests/test_progress_service.py +133 -0
- llm_benchmark_manager-0.3.0/tests/test_provider_openai.py +133 -0
- llm_benchmark_manager-0.3.0/tests/test_response_extract.py +26 -0
- llm_benchmark_manager-0.3.0/tests/test_runtime_release.py +75 -0
- llm_benchmark_manager-0.3.0/tests/test_service.py +244 -0
- llm_benchmark_manager-0.3.0/tests/test_version.py +11 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable user-facing changes are documented here.
|
|
4
|
+
|
|
5
|
+
## 0.3.0 - 2026-09-25
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Portable application-data directory selection through `platformdirs`.
|
|
10
|
+
- Reliable AIPerf executable discovery inside the same Python/pipx environment.
|
|
11
|
+
- NVIDIA AIPerf 0.12.0 as a required package dependency.
|
|
12
|
+
- Provider-agnostic bilingual release documentation (English and Hungarian).
|
|
13
|
+
- Public security, contributing and architecture documentation.
|
|
14
|
+
- Capability-aware model lifecycle and exact persisted progress from the v0.2 work.
|
|
15
|
+
- Asymmetric embedding retry with `input_type="query"` only when the provider explicitly requires it.
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
- Package version advanced to 0.3.0 release candidate.
|
|
20
|
+
- Docker installation now relies on normal package dependencies instead of separately installing AIPerf.
|
|
21
|
+
- Direct `BenchmarkService` artifact storage now uses the same portable data-location policy as the runtime.
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
|
|
25
|
+
- Historical run status summaries no longer change when a model receives a different status in a later retest.
|
|
26
|
+
- 404 model invocation failures are represented as `NOT_AVAILABLE` rather than generic model failure.
|
|
27
|
+
- Alternate valid text response shapes are recognized before classifying a response as empty.
|
|
28
|
+
|
|
29
|
+
## 0.2.0 - 2026-09-24
|
|
30
|
+
|
|
31
|
+
- Added capability-aware probes, model states, retries, exact progress, REST/MCP progress surfaces and AIPerf baseline eligibility.
|
|
32
|
+
|
|
33
|
+
## 0.1.0
|
|
34
|
+
|
|
35
|
+
- Initial standalone provider discovery, SQLite history, CLI, REST, MCP and AIPerf integration.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Thank you for contributing to LLM Benchmark Manager.
|
|
4
|
+
|
|
5
|
+
## Development setup
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
python3 -m venv .venv
|
|
9
|
+
. .venv/bin/activate
|
|
10
|
+
pip install -e '.[dev]'
|
|
11
|
+
pytest -q
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Change rules
|
|
15
|
+
|
|
16
|
+
- Keep the benchmark core independent from any particular agent or router.
|
|
17
|
+
- Never hard-code local usernames, host names, home directories or deployment paths.
|
|
18
|
+
- Provider-specific behavior must be narrowly detected; do not apply a provider workaround to unrelated errors.
|
|
19
|
+
- Preserve historical run data. A later retest must not rewrite old run outcomes.
|
|
20
|
+
- Never expose raw credentials through CLI output, REST, MCP, logs, reports or process arguments.
|
|
21
|
+
- Add or update tests for behavior changes and run the full test suite before submitting a change.
|
|
22
|
+
- Keep public documentation in English and Hungarian when a user-facing workflow changes.
|
|
23
|
+
|
|
24
|
+
## Before submitting
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pytest -q
|
|
28
|
+
python -m compileall -q src
|
|
29
|
+
python -m build
|
|
30
|
+
python -m pip check
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Also scan the change for credentials, local paths, databases and generated artifacts.
|
|
34
|
+
|
|
35
|
+
## Generated/local files
|
|
36
|
+
|
|
37
|
+
Do not commit `.venv`, `dist`, `build`, `*.egg-info`, `.pytest_cache`, local databases, `.env` files, credentials or benchmark artifacts.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 LLM Benchmark Manager contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,464 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: llm-benchmark-manager
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Provider-agnostic LLM discovery, stability testing and AIPerf benchmarking
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Project-URL: Homepage, https://github.com/telferi/llm-benchmark-manager
|
|
7
|
+
Project-URL: Repository, https://github.com/telferi/llm-benchmark-manager
|
|
8
|
+
Project-URL: Issues, https://github.com/telferi/llm-benchmark-manager/issues
|
|
9
|
+
Project-URL: Changelog, https://github.com/telferi/llm-benchmark-manager/blob/main/CHANGELOG.md
|
|
10
|
+
Keywords: llm,benchmark,aiperf,mcp,openai-compatible
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Topic :: Software Development :: Testing
|
|
17
|
+
Requires-Python: >=3.11
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
License-File: LICENSE
|
|
20
|
+
Requires-Dist: aiperf==0.12.0
|
|
21
|
+
Requires-Dist: httpx<1,>=0.28
|
|
22
|
+
Requires-Dist: pydantic<3,>=2.11
|
|
23
|
+
Requires-Dist: fastapi<1,>=0.141
|
|
24
|
+
Requires-Dist: uvicorn<1,>=0.35
|
|
25
|
+
Requires-Dist: fastmcp<5,>=4
|
|
26
|
+
Requires-Dist: PyYAML<7,>=6
|
|
27
|
+
Requires-Dist: keyring<26,>=25
|
|
28
|
+
Requires-Dist: cryptography<51,>=45
|
|
29
|
+
Requires-Dist: platformdirs<5,>=4
|
|
30
|
+
Provides-Extra: dev
|
|
31
|
+
Requires-Dist: pytest<9,>=8; extra == "dev"
|
|
32
|
+
Requires-Dist: build<2,>=1; extra == "dev"
|
|
33
|
+
Dynamic: license-file
|
|
34
|
+
|
|
35
|
+
# LLM Benchmark Manager
|
|
36
|
+
|
|
37
|
+
[English](README.md) | [Magyar](README.hu.md)
|
|
38
|
+
|
|
39
|
+
LLM Benchmark Manager is a standalone, open-source tool for discovering models exposed by an LLM provider, validating that they can actually be called, classifying their capabilities and health, benchmarking compatible text-generation models with NVIDIA AIPerf, and preserving historical evidence in SQLite.
|
|
40
|
+
|
|
41
|
+
It is intentionally independent of any agent framework, operating-system user, host name, directory layout, or routing system. It can be used manually from a terminal, automated through a REST API, or controlled by an AI/agent through MCP.
|
|
42
|
+
|
|
43
|
+
## What it does
|
|
44
|
+
|
|
45
|
+
A normal full run performs the following pipeline:
|
|
46
|
+
|
|
47
|
+
1. discover the provider model catalog;
|
|
48
|
+
2. create a persistent progress row for every selected model;
|
|
49
|
+
3. detect or infer the model capability;
|
|
50
|
+
4. run a capability-aware smoke probe;
|
|
51
|
+
5. perform bounded stability checks and retry transient provider failures;
|
|
52
|
+
6. run AIPerf only when the model has a compatible benchmark profile;
|
|
53
|
+
7. classify the model (`ACTIVE`, `UNSTABLE`, `NOT_AVAILABLE`, etc.);
|
|
54
|
+
8. store metrics, normalized errors, progress and status history in SQLite.
|
|
55
|
+
|
|
56
|
+
The tool never deletes historical benchmark evidence when a model changes state later.
|
|
57
|
+
|
|
58
|
+
## Release status
|
|
59
|
+
|
|
60
|
+
Current release: **0.3.0**.
|
|
61
|
+
|
|
62
|
+
The source repository is public on GitHub. Release artifacts are published to PyPI from the GitHub `v*.*.*` release-tag workflow using PyPI Trusted Publishing, so no long-lived PyPI API token is stored in the repository.
|
|
63
|
+
|
|
64
|
+
## Requirements
|
|
65
|
+
|
|
66
|
+
- Python 3.11+
|
|
67
|
+
- Internet/network access to the provider being tested
|
|
68
|
+
- Provider credentials for providers that require authentication
|
|
69
|
+
|
|
70
|
+
**NVIDIA AIPerf 0.12.0 is a required package dependency.** Installing LLM Benchmark Manager installs AIPerf automatically. You do not need to install AIPerf separately.
|
|
71
|
+
|
|
72
|
+
AIPerf is currently used by the built-in `CHAT_TEXT` baseline profile. Discovery, capability detection and non-text probes still use the same installed application even when no AIPerf benchmark is applicable to a particular model.
|
|
73
|
+
|
|
74
|
+
## Installation
|
|
75
|
+
|
|
76
|
+
### From a source checkout
|
|
77
|
+
|
|
78
|
+
Recommended for the current release candidate:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
pipx install .
|
|
82
|
+
llmbench --help
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
For development:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
python3 -m venv .venv
|
|
89
|
+
. .venv/bin/activate
|
|
90
|
+
pip install -e '.[dev]'
|
|
91
|
+
pytest -q
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### From a built wheel
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
pipx install dist/llm_benchmark_manager-0.3.0-py3-none-any.whl
|
|
98
|
+
llmbench --help
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Future PyPI installation
|
|
102
|
+
|
|
103
|
+
After the project is published to PyPI:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
pipx install llm-benchmark-manager
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Docker
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
docker build -t llm-benchmark-manager:0.3.0 .
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Example REST API mode:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
docker run --rm \
|
|
119
|
+
--env-file providers.env \
|
|
120
|
+
-p 8765:8765 \
|
|
121
|
+
-v llmbench-data:/data \
|
|
122
|
+
llm-benchmark-manager:0.3.0 serve --host 0.0.0.0 --port 8765
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
The image stores application data under `/data`. AIPerf is installed automatically because it is a normal project dependency.
|
|
126
|
+
|
|
127
|
+
## Quick start
|
|
128
|
+
|
|
129
|
+
Run the interactive interface:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
llmbench
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
For a new provider, enter only the provider endpoint URL and API key:
|
|
136
|
+
|
|
137
|
+
```text
|
|
138
|
+
New provider
|
|
139
|
+
Endpoint URL: https://provider.example.com
|
|
140
|
+
API key: ***************
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
The provider slug is derived from the endpoint hostname. If that normalized endpoint already exists, the existing provider record is reused rather than duplicated.
|
|
144
|
+
|
|
145
|
+
For an existing provider the interactive menu supports:
|
|
146
|
+
|
|
147
|
+
- full retest;
|
|
148
|
+
- `ACTIVE`-only retest;
|
|
149
|
+
- `UNSTABLE`/`FAILED` retest;
|
|
150
|
+
- refresh discovery and test only `NEW` models;
|
|
151
|
+
- test one model;
|
|
152
|
+
- list known models and states.
|
|
153
|
+
|
|
154
|
+
## Automation CLI
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
llmbench provider list
|
|
158
|
+
llmbench provider discover PROVIDER
|
|
159
|
+
|
|
160
|
+
llmbench run PROVIDER --mode full
|
|
161
|
+
llmbench run PROVIDER --mode new
|
|
162
|
+
llmbench run PROVIDER --mode active
|
|
163
|
+
llmbench run PROVIDER --mode unstable_failed
|
|
164
|
+
llmbench run --all --mode full
|
|
165
|
+
|
|
166
|
+
llmbench model test PROVIDER MODEL_ID
|
|
167
|
+
llmbench results RUN_ID
|
|
168
|
+
llmbench history PROVIDER MODEL_ID
|
|
169
|
+
llmbench export RUN_ID --format json --output run.json
|
|
170
|
+
llmbench export RUN_ID --format csv --output run.csv
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
`PROVIDER` can be the configured provider identifier/slug accepted by the service.
|
|
174
|
+
|
|
175
|
+
## Provider compatibility
|
|
176
|
+
|
|
177
|
+
The built-in generic adapter targets OpenAI-compatible provider APIs and uses conventional endpoints such as:
|
|
178
|
+
|
|
179
|
+
- `/v1/models`
|
|
180
|
+
- `/v1/chat/completions`
|
|
181
|
+
- `/v1/embeddings`
|
|
182
|
+
|
|
183
|
+
Provider-specific behavior is handled conservatively. For example, asymmetric embedding models that explicitly report that `input_type` is required are retried using `input_type="query"`. Unrelated HTTP 400 errors are not blindly retried with provider-specific parameters.
|
|
184
|
+
|
|
185
|
+
A provider may expose models in its catalog that are not callable for the current account or endpoint. Those models are classified separately from genuinely broken models.
|
|
186
|
+
|
|
187
|
+
## Model states
|
|
188
|
+
|
|
189
|
+
- `NEW` — discovered but not evaluated yet.
|
|
190
|
+
- `ACTIVE` — passed its supported probe and, where applicable, compatible benchmark profile.
|
|
191
|
+
- `UNSTABLE` — usable, but transient failures or partial benchmark failures were observed.
|
|
192
|
+
- `NOT_AVAILABLE` — discovered, but not callable with the current provider/account/endpoint. HTTP 404 invocation responses normally map here.
|
|
193
|
+
- `INCOMPATIBLE` — the attempted generic request shape does not match the model capability.
|
|
194
|
+
- `UNSUPPORTED` — capability is known, but this release has no safe generic probe or benchmark path for it.
|
|
195
|
+
- `FAILED` — a definitive non-transient failure occurred on the correct supported capability path.
|
|
196
|
+
- `DISABLED` — manually excluded.
|
|
197
|
+
- `MISSING` — previously known but no longer returned by discovery.
|
|
198
|
+
|
|
199
|
+
A later retest does not rewrite the final-status summary of an earlier run.
|
|
200
|
+
|
|
201
|
+
## Capabilities
|
|
202
|
+
|
|
203
|
+
Capabilities are stored independently of model health:
|
|
204
|
+
|
|
205
|
+
- `CHAT_TEXT`
|
|
206
|
+
- `EMBEDDING`
|
|
207
|
+
- `VISION`
|
|
208
|
+
- `MULTIMODAL`
|
|
209
|
+
- `PARSER`
|
|
210
|
+
- `TRANSLATION`
|
|
211
|
+
- `SAFETY`
|
|
212
|
+
- `RERANK`
|
|
213
|
+
- `SPECIAL`
|
|
214
|
+
- `UNKNOWN`
|
|
215
|
+
|
|
216
|
+
Detection is conservative and may use provider metadata, model-ID heuristics, probe feedback or an explicit manual source. Capability inference alone never marks a model as failed.
|
|
217
|
+
|
|
218
|
+
## Retry and classification rules
|
|
219
|
+
|
|
220
|
+
The default error policy distinguishes provider/account availability from model quality:
|
|
221
|
+
|
|
222
|
+
- `401` / `403` → authentication/provider run issue; not a model failure;
|
|
223
|
+
- `404` → `NOT_AVAILABLE`; no identical retry;
|
|
224
|
+
- `429` → rate limited; bounded retry using 1/2/5/10 seconds or `Retry-After` when supplied;
|
|
225
|
+
- `503` → overloaded; bounded retry using 1/2/5/10 seconds;
|
|
226
|
+
- `500` / `502` / `504` → transient provider error; bounded retry using 1/3 seconds;
|
|
227
|
+
- timeout/network failure → transient; bounded retry using 1/3 seconds;
|
|
228
|
+
- capability-specific `400` mismatch → `INCOMPATIBLE`;
|
|
229
|
+
- deterministic payload failure on the correct request shape → `FAILED`.
|
|
230
|
+
|
|
231
|
+
A model that succeeds only after retry is classified `UNSTABLE`.
|
|
232
|
+
|
|
233
|
+
## AIPerf benchmark profile
|
|
234
|
+
|
|
235
|
+
The built-in `baseline-v1` profile is used for compatible `CHAT_TEXT` models:
|
|
236
|
+
|
|
237
|
+
- input sequence length: 128 tokens;
|
|
238
|
+
- output sequence length: 128 tokens;
|
|
239
|
+
- requests: 10;
|
|
240
|
+
- concurrency: 1;
|
|
241
|
+
- streaming: enabled;
|
|
242
|
+
- deterministic synthetic seed: 42.
|
|
243
|
+
|
|
244
|
+
The provider API key is passed to AIPerf through the child-process environment, never as a command-line argument. The temporary AIPerf configuration file is removed after the run.
|
|
245
|
+
|
|
246
|
+
`EMBEDDING` and other specialized capabilities are not forced through the text-generation AIPerf profile. A successful supported non-text probe may therefore finish with `SKIPPED_UNSUPPORTED_PROFILE` while the model itself is `ACTIVE`.
|
|
247
|
+
|
|
248
|
+
## Progress and history
|
|
249
|
+
|
|
250
|
+
Every selected model receives a `run_model_progress` record before execution. This makes progress exact even when many discovered models never reach AIPerf.
|
|
251
|
+
|
|
252
|
+
Example CLI output:
|
|
253
|
+
|
|
254
|
+
```text
|
|
255
|
+
[37/82] 45.1% provider/model-id
|
|
256
|
+
Capability: CHAT_TEXT
|
|
257
|
+
Smoke: PASS
|
|
258
|
+
Stability: PASS
|
|
259
|
+
AIPerf: RUNNING
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
Progress stages are:
|
|
263
|
+
|
|
264
|
+
- `PENDING`
|
|
265
|
+
- `CAPABILITY`
|
|
266
|
+
- `SMOKE`
|
|
267
|
+
- `STABILITY`
|
|
268
|
+
- `BENCHMARK`
|
|
269
|
+
- `DONE`
|
|
270
|
+
|
|
271
|
+
A run is complete when all selected progress rows reach `DONE`.
|
|
272
|
+
|
|
273
|
+
## Credentials and secret handling
|
|
274
|
+
|
|
275
|
+
Interactive API keys are never stored in SQLite.
|
|
276
|
+
|
|
277
|
+
Credential storage order:
|
|
278
|
+
|
|
279
|
+
1. operating-system keyring when a usable backend exists;
|
|
280
|
+
2. encrypted local credential vault when no usable keyring exists;
|
|
281
|
+
3. environment-variable references for automation and container/system-service deployments.
|
|
282
|
+
|
|
283
|
+
The encrypted fallback uses a local Fernet master key and vault under the application data directory. The key and vault are protected with restrictive file modes where the operating system supports them. The local OS account remains part of the trust boundary; this fallback is not hardware-backed secret storage.
|
|
284
|
+
|
|
285
|
+
For ENV-based automation:
|
|
286
|
+
|
|
287
|
+
```bash
|
|
288
|
+
export PROVIDER_API_KEY='...'
|
|
289
|
+
|
|
290
|
+
llmbench provider add \
|
|
291
|
+
--slug example \
|
|
292
|
+
--name 'Example Provider' \
|
|
293
|
+
--url 'https://provider.example.com' \
|
|
294
|
+
--credential-env PROVIDER_API_KEY
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
Only the environment-variable name is persisted.
|
|
298
|
+
|
|
299
|
+
Provider errors are sanitized before persistence. Active secrets, bearer tokens, UUID-like request identifiers and account-like identifiers are redacted or normalized, and messages are length-capped.
|
|
300
|
+
|
|
301
|
+
## Data location
|
|
302
|
+
|
|
303
|
+
The default data directory is selected with `platformdirs`, so it follows the operating system/user environment instead of a hard-coded home directory.
|
|
304
|
+
|
|
305
|
+
Typical locations are:
|
|
306
|
+
|
|
307
|
+
- Linux: `~/.local/share/llmbench/`
|
|
308
|
+
- macOS: `~/Library/Application Support/llmbench/`
|
|
309
|
+
- Windows: the current user's local application-data directory under `llmbench`
|
|
310
|
+
|
|
311
|
+
Override the location anywhere with:
|
|
312
|
+
|
|
313
|
+
```bash
|
|
314
|
+
export LLMBENCH_DATA_DIR=/path/to/llmbench-data
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
The directory contains:
|
|
318
|
+
|
|
319
|
+
```text
|
|
320
|
+
llmbench.db
|
|
321
|
+
artifacts/
|
|
322
|
+
credentials/ # only when encrypted-file fallback is used
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
No project code assumes a specific username, server name or installation directory.
|
|
326
|
+
|
|
327
|
+
## AIPerf executable resolution
|
|
328
|
+
|
|
329
|
+
AIPerf is a required dependency. LLM Benchmark Manager resolves the executable in this order:
|
|
330
|
+
|
|
331
|
+
1. `LLMBENCH_AIPERF` explicit override;
|
|
332
|
+
2. `aiperf` installed beside the Python interpreter running `llmbench` (important for `pipx` environments);
|
|
333
|
+
3. `aiperf` found on `PATH`.
|
|
334
|
+
|
|
335
|
+
Example override:
|
|
336
|
+
|
|
337
|
+
```bash
|
|
338
|
+
export LLMBENCH_AIPERF=/custom/venv/bin/aiperf
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
## REST API
|
|
342
|
+
|
|
343
|
+
Start the API locally:
|
|
344
|
+
|
|
345
|
+
```bash
|
|
346
|
+
llmbench serve --host 127.0.0.1 --port 8765
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
Available API resources include:
|
|
350
|
+
|
|
351
|
+
```text
|
|
352
|
+
GET /api/v1/providers
|
|
353
|
+
POST /api/v1/providers
|
|
354
|
+
GET /api/v1/providers/{provider_id}
|
|
355
|
+
POST /api/v1/providers/{provider_id}/discover
|
|
356
|
+
GET /api/v1/providers/{provider_id}/models
|
|
357
|
+
|
|
358
|
+
POST /api/v1/runs
|
|
359
|
+
GET /api/v1/runs/{run_id}
|
|
360
|
+
GET /api/v1/runs/{run_id}/progress
|
|
361
|
+
POST /api/v1/runs/{run_id}/cancel
|
|
362
|
+
GET /api/v1/runs/{run_id}/results
|
|
363
|
+
|
|
364
|
+
GET /api/v1/models/{model_db_id}
|
|
365
|
+
GET /api/v1/models/{model_db_id}/history
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
The REST server has no built-in multi-user authentication in 0.3.0. The default bind address is loopback. Do not expose it to an untrusted network without an authentication/network-control layer such as a trusted reverse proxy or private network.
|
|
369
|
+
|
|
370
|
+
## MCP server
|
|
371
|
+
|
|
372
|
+
Start the stdio MCP server:
|
|
373
|
+
|
|
374
|
+
```bash
|
|
375
|
+
llmbench mcp
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
The MCP surface includes:
|
|
379
|
+
|
|
380
|
+
```text
|
|
381
|
+
benchmark_provider_list
|
|
382
|
+
benchmark_provider_get
|
|
383
|
+
benchmark_provider_discover
|
|
384
|
+
benchmark_model_list
|
|
385
|
+
benchmark_model_get
|
|
386
|
+
benchmark_model_history
|
|
387
|
+
benchmark_run_start
|
|
388
|
+
benchmark_run_status
|
|
389
|
+
benchmark_run_progress
|
|
390
|
+
benchmark_run_cancel
|
|
391
|
+
benchmark_run_results
|
|
392
|
+
benchmark_retest_unstable
|
|
393
|
+
benchmark_test_new_models
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
There is intentionally no MCP tool that returns raw provider credentials.
|
|
397
|
+
|
|
398
|
+
This allows an external agent (for example a model-management or model-design service) to request discovery and benchmarks without receiving the underlying secrets.
|
|
399
|
+
|
|
400
|
+
## Exports
|
|
401
|
+
|
|
402
|
+
Run data can be exported as JSON or CSV:
|
|
403
|
+
|
|
404
|
+
```bash
|
|
405
|
+
llmbench export RUN_ID --format json --output run.json
|
|
406
|
+
llmbench export RUN_ID --format csv --output run.csv
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
The SQLite database remains the authoritative local history.
|
|
410
|
+
|
|
411
|
+
## Security notes
|
|
412
|
+
|
|
413
|
+
- Provider credentials are excluded from database records and normal responses.
|
|
414
|
+
- AIPerf receives credentials through environment inheritance, not argv.
|
|
415
|
+
- Persisted provider messages are sanitized.
|
|
416
|
+
- Interactive secret input uses hidden terminal input.
|
|
417
|
+
- Provider URLs may not contain embedded username/password credentials.
|
|
418
|
+
- The REST service should remain private unless an external authentication layer is added.
|
|
419
|
+
- Anyone who can read the encrypted fallback master key and vault as the same OS user can decrypt those credentials; use an OS keyring or external secret manager where a stronger boundary is required.
|
|
420
|
+
|
|
421
|
+
See [SECURITY.md](SECURITY.md) for the disclosure and deployment policy.
|
|
422
|
+
|
|
423
|
+
## Architecture
|
|
424
|
+
|
|
425
|
+
The application is deliberately split into independent layers:
|
|
426
|
+
|
|
427
|
+
```text
|
|
428
|
+
CLI / REST / MCP
|
|
429
|
+
|
|
|
430
|
+
BenchmarkService
|
|
431
|
+
|
|
|
432
|
+
+-----+------------------+
|
|
433
|
+
| |
|
|
434
|
+
Provider adapter SQLite
|
|
435
|
+
| |
|
|
436
|
+
Discovery/probes history/progress
|
|
437
|
+
|
|
|
438
|
+
AIPerfRunner (CHAT_TEXT baseline)
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
The benchmark manager is not a model router and does not modify a production routing system. External systems consume its evidence through CLI, REST, MCP or exported data.
|
|
442
|
+
|
|
443
|
+
See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for details.
|
|
444
|
+
|
|
445
|
+
## Development and verification
|
|
446
|
+
|
|
447
|
+
```bash
|
|
448
|
+
python3 -m venv .venv
|
|
449
|
+
. .venv/bin/activate
|
|
450
|
+
pip install -e '.[dev]'
|
|
451
|
+
pytest -q
|
|
452
|
+
python -m build
|
|
453
|
+
python -m pip check
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
Before publishing a release, also test installation into a clean environment and verify that `llmbench --help` and `aiperf --version` are available from that environment.
|
|
457
|
+
|
|
458
|
+
## Contributing
|
|
459
|
+
|
|
460
|
+
Contributions are welcome. Please read [CONTRIBUTING.md](CONTRIBUTING.md). Do not include real API keys, provider account identifiers, local databases or benchmark artifacts containing private data in issues or commits.
|
|
461
|
+
|
|
462
|
+
## License
|
|
463
|
+
|
|
464
|
+
MIT. See [LICENSE](LICENSE).
|