kneebench 0.1.0a1__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.
- kneebench-0.1.0a1/.gitignore +227 -0
- kneebench-0.1.0a1/.python-version +1 -0
- kneebench-0.1.0a1/CHANGELOG.md +204 -0
- kneebench-0.1.0a1/CODE_OF_CONDUCT.md +17 -0
- kneebench-0.1.0a1/CONTRIBUTING.md +62 -0
- kneebench-0.1.0a1/LICENSE +21 -0
- kneebench-0.1.0a1/PKG-INFO +206 -0
- kneebench-0.1.0a1/README.md +159 -0
- kneebench-0.1.0a1/SECURITY.md +27 -0
- kneebench-0.1.0a1/docs/images/chart-curve.png +0 -0
- kneebench-0.1.0a1/docs/images/chart-latency.png +0 -0
- kneebench-0.1.0a1/docs/images/chart-prompt.png +0 -0
- kneebench-0.1.0a1/docs/images/chart-shapes.png +0 -0
- kneebench-0.1.0a1/docs/images/chart-walls.png +0 -0
- kneebench-0.1.0a1/docs/images/new-run.png +0 -0
- kneebench-0.1.0a1/docs/images/report-baseline.png +0 -0
- kneebench-0.1.0a1/docs/images/report-curve.png +0 -0
- kneebench-0.1.0a1/docs/images/report-latency.png +0 -0
- kneebench-0.1.0a1/docs/images/report-shapes.png +0 -0
- kneebench-0.1.0a1/docs/images/report-walls.png +0 -0
- kneebench-0.1.0a1/docs/images/report.png +0 -0
- kneebench-0.1.0a1/docs/images/runs.png +0 -0
- kneebench-0.1.0a1/docs/images/tour.gif +0 -0
- kneebench-0.1.0a1/docs/images/what-if.png +0 -0
- kneebench-0.1.0a1/kneebench.local.toml.example +7 -0
- kneebench-0.1.0a1/pyproject.toml +106 -0
- kneebench-0.1.0a1/scripts/make_demo.py +138 -0
- kneebench-0.1.0a1/scripts/make_screenshots.py +193 -0
- kneebench-0.1.0a1/scripts/make_starter_eval.py +240 -0
- kneebench-0.1.0a1/scripts/measure_aiperf_startup.py +45 -0
- kneebench-0.1.0a1/scripts/record_fixtures.py +149 -0
- kneebench-0.1.0a1/scripts/record_hf_fixtures.py +30 -0
- kneebench-0.1.0a1/src/kneebench/__init__.py +10 -0
- kneebench-0.1.0a1/src/kneebench/__main__.py +3 -0
- kneebench-0.1.0a1/src/kneebench/analysis/__init__.py +1 -0
- kneebench-0.1.0a1/src/kneebench/analysis/compare.py +233 -0
- kneebench-0.1.0a1/src/kneebench/analysis/context.py +344 -0
- kneebench-0.1.0a1/src/kneebench/analysis/engine.py +117 -0
- kneebench-0.1.0a1/src/kneebench/analysis/rate.py +144 -0
- kneebench-0.1.0a1/src/kneebench/analysis/rules/__init__.py +1 -0
- kneebench-0.1.0a1/src/kneebench/analysis/rules/baseline.py +205 -0
- kneebench-0.1.0a1/src/kneebench/analysis/rules/cancel.py +49 -0
- kneebench-0.1.0a1/src/kneebench/analysis/rules/concurrency.py +164 -0
- kneebench-0.1.0a1/src/kneebench/analysis/rules/hygiene.py +279 -0
- kneebench-0.1.0a1/src/kneebench/analysis/rules/interference.py +84 -0
- kneebench-0.1.0a1/src/kneebench/analysis/rules/rate.py +157 -0
- kneebench-0.1.0a1/src/kneebench/analysis/rules/reuse.py +127 -0
- kneebench-0.1.0a1/src/kneebench/analysis/rules/roofline.py +176 -0
- kneebench-0.1.0a1/src/kneebench/analysis/rules/scheduler.py +139 -0
- kneebench-0.1.0a1/src/kneebench/analysis/rules/shape.py +232 -0
- kneebench-0.1.0a1/src/kneebench/analysis/rules/theory.py +159 -0
- kneebench-0.1.0a1/src/kneebench/analysis/rules/walls.py +368 -0
- kneebench-0.1.0a1/src/kneebench/analysis/settings.py +105 -0
- kneebench-0.1.0a1/src/kneebench/analysis/shape.py +119 -0
- kneebench-0.1.0a1/src/kneebench/analysis/steady.py +95 -0
- kneebench-0.1.0a1/src/kneebench/analysis/sweep.py +164 -0
- kneebench-0.1.0a1/src/kneebench/analysis/whatif.py +86 -0
- kneebench-0.1.0a1/src/kneebench/cli.py +534 -0
- kneebench-0.1.0a1/src/kneebench/config.py +52 -0
- kneebench-0.1.0a1/src/kneebench/content/__init__.py +14 -0
- kneebench-0.1.0a1/src/kneebench/content/demo-run.json.gz +0 -0
- kneebench-0.1.0a1/src/kneebench/content/glossary.yaml +24 -0
- kneebench-0.1.0a1/src/kneebench/content/notes.yaml +49 -0
- kneebench-0.1.0a1/src/kneebench/content/profiles.yaml +26 -0
- kneebench-0.1.0a1/src/kneebench/content/quality/starter.jsonl +290 -0
- kneebench-0.1.0a1/src/kneebench/content/render.py +308 -0
- kneebench-0.1.0a1/src/kneebench/content/report.yaml +182 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/A01.yaml +46 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/B01.yaml +47 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/B02.yaml +34 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/B03.yaml +36 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/B04.yaml +38 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/B05.yaml +23 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/B06.yaml +42 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/C01.yaml +18 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/C02.yaml +29 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/C03.yaml +53 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/C04.yaml +18 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/C05.yaml +16 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/E01.yaml +32 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/E02.yaml +47 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/F01.yaml +36 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/F02.yaml +62 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/H01.yaml +19 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/H02.yaml +23 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/H03.yaml +46 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/H04.yaml +26 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/H05.yaml +26 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/H06.yaml +20 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/H07.yaml +22 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/H08.yaml +20 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/H09.yaml +29 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/H10.yaml +32 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/I01.yaml +76 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/P01.yaml +43 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/P02.yaml +33 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/P03.yaml +21 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/P04.yaml +22 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/R01.yaml +39 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/R02.yaml +26 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/R03.yaml +22 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/R04.yaml +28 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/S01.yaml +33 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/S02.yaml +41 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/S03.yaml +24 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/S04.yaml +45 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/S05.yaml +39 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/S06.yaml +38 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/S07.yaml +17 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/T01.yaml +35 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/T02.yaml +22 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/T03.yaml +28 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/T04.yaml +37 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/T05.yaml +26 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/T06.yaml +26 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/T07.yaml +31 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/T08.yaml +19 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/W01.yaml +20 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/W02.yaml +24 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/W03.yaml +25 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/W04.yaml +36 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/W05.yaml +19 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/W06.yaml +43 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/W07.yaml +27 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/W08.yaml +24 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/W09.yaml +14 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/X01.yaml +29 -0
- kneebench-0.1.0a1/src/kneebench/content/rules/X02.yaml +41 -0
- kneebench-0.1.0a1/src/kneebench/content/slo_presets.yaml +31 -0
- kneebench-0.1.0a1/src/kneebench/content/vllm_versions.yaml +47 -0
- kneebench-0.1.0a1/src/kneebench/demo.py +182 -0
- kneebench-0.1.0a1/src/kneebench/detect/__init__.py +1 -0
- kneebench-0.1.0a1/src/kneebench/detect/counters.py +29 -0
- kneebench-0.1.0a1/src/kneebench/detect/endpoint.py +64 -0
- kneebench-0.1.0a1/src/kneebench/detect/hf.py +25 -0
- kneebench-0.1.0a1/src/kneebench/detect/metrics.py +102 -0
- kneebench-0.1.0a1/src/kneebench/detect/netprobe.py +93 -0
- kneebench-0.1.0a1/src/kneebench/detect/server.py +114 -0
- kneebench-0.1.0a1/src/kneebench/doctor.py +316 -0
- kneebench-0.1.0a1/src/kneebench/domain.py +147 -0
- kneebench-0.1.0a1/src/kneebench/experiments.py +261 -0
- kneebench-0.1.0a1/src/kneebench/loadgen/__init__.py +1 -0
- kneebench-0.1.0a1/src/kneebench/loadgen/aiperf/__init__.py +6 -0
- kneebench-0.1.0a1/src/kneebench/loadgen/aiperf/command.py +186 -0
- kneebench-0.1.0a1/src/kneebench/loadgen/aiperf/overhead.py +80 -0
- kneebench-0.1.0a1/src/kneebench/loadgen/aiperf/parse.py +407 -0
- kneebench-0.1.0a1/src/kneebench/loadgen/aiperf/redact.py +48 -0
- kneebench-0.1.0a1/src/kneebench/loadgen/aiperf/runner.py +110 -0
- kneebench-0.1.0a1/src/kneebench/loadgen/aiperf/version.py +57 -0
- kneebench-0.1.0a1/src/kneebench/loadgen/base.py +110 -0
- kneebench-0.1.0a1/src/kneebench/loadgen/texts.py +236 -0
- kneebench-0.1.0a1/src/kneebench/narrate/__init__.py +20 -0
- kneebench-0.1.0a1/src/kneebench/phases/__init__.py +1 -0
- kneebench-0.1.0a1/src/kneebench/phases/plan.py +557 -0
- kneebench-0.1.0a1/src/kneebench/phases/runner.py +346 -0
- kneebench-0.1.0a1/src/kneebench/phases/theory.py +195 -0
- kneebench-0.1.0a1/src/kneebench/physics/__init__.py +1 -0
- kneebench-0.1.0a1/src/kneebench/physics/floors.py +128 -0
- kneebench-0.1.0a1/src/kneebench/physics/gpus.py +109 -0
- kneebench-0.1.0a1/src/kneebench/physics/gpus.yaml +113 -0
- kneebench-0.1.0a1/src/kneebench/physics/model.py +219 -0
- kneebench-0.1.0a1/src/kneebench/physics/roofline.py +140 -0
- kneebench-0.1.0a1/src/kneebench/py.typed +0 -0
- kneebench-0.1.0a1/src/kneebench/quality/__init__.py +2 -0
- kneebench-0.1.0a1/src/kneebench/quality/ask.py +103 -0
- kneebench-0.1.0a1/src/kneebench/quality/cli.py +128 -0
- kneebench-0.1.0a1/src/kneebench/quality/evalset.py +110 -0
- kneebench-0.1.0a1/src/kneebench/quality/grade.py +54 -0
- kneebench-0.1.0a1/src/kneebench/quality/service.py +200 -0
- kneebench-0.1.0a1/src/kneebench/quality/stats.py +204 -0
- kneebench-0.1.0a1/src/kneebench/quality/store.py +134 -0
- kneebench-0.1.0a1/src/kneebench/report/__init__.py +1 -0
- kneebench-0.1.0a1/src/kneebench/report/build.py +34 -0
- kneebench-0.1.0a1/src/kneebench/report/charts.py +905 -0
- kneebench-0.1.0a1/src/kneebench/report/compare.py +179 -0
- kneebench-0.1.0a1/src/kneebench/report/composer.py +679 -0
- kneebench-0.1.0a1/src/kneebench/report/pdf.py +87 -0
- kneebench-0.1.0a1/src/kneebench/report/render_html.py +85 -0
- kneebench-0.1.0a1/src/kneebench/report/render_json.py +12 -0
- kneebench-0.1.0a1/src/kneebench/report/render_md.py +140 -0
- kneebench-0.1.0a1/src/kneebench/runlock.py +76 -0
- kneebench-0.1.0a1/src/kneebench/servers/__init__.py +1 -0
- kneebench-0.1.0a1/src/kneebench/servers/vllm.py +80 -0
- kneebench-0.1.0a1/src/kneebench/service.py +184 -0
- kneebench-0.1.0a1/src/kneebench/store/__init__.py +1 -0
- kneebench-0.1.0a1/src/kneebench/store/db.py +64 -0
- kneebench-0.1.0a1/src/kneebench/store/migrations/001_initial.sql +157 -0
- kneebench-0.1.0a1/src/kneebench/store/migrations/002_request_error_code.sql +2 -0
- kneebench-0.1.0a1/src/kneebench/store/migrations/003_run_plan_and_error.sql +3 -0
- kneebench-0.1.0a1/src/kneebench/store/migrations/004_request_connect_ms.sql +3 -0
- kneebench-0.1.0a1/src/kneebench/store/migrations/005_experiments.sql +23 -0
- kneebench-0.1.0a1/src/kneebench/store/migrations/006_point_series.sql +8 -0
- kneebench-0.1.0a1/src/kneebench/store/migrations/007_quality.sql +40 -0
- kneebench-0.1.0a1/src/kneebench/store/repo.py +616 -0
- kneebench-0.1.0a1/src/kneebench/web/__init__.py +1 -0
- kneebench-0.1.0a1/src/kneebench/web/app.py +699 -0
- kneebench-0.1.0a1/src/kneebench/web/manager.py +128 -0
- kneebench-0.1.0a1/src/kneebench/web/static/fonts/LICENSE-geist.txt +93 -0
- kneebench-0.1.0a1/src/kneebench/web/static/fonts/LICENSE-source-serif-4.txt +93 -0
- kneebench-0.1.0a1/src/kneebench/web/static/fonts/geist-mono.woff2 +0 -0
- kneebench-0.1.0a1/src/kneebench/web/static/fonts/geist.woff2 +0 -0
- kneebench-0.1.0a1/src/kneebench/web/static/fonts/source-serif-4-italic.woff2 +0 -0
- kneebench-0.1.0a1/src/kneebench/web/static/fonts/source-serif-4.woff2 +0 -0
- kneebench-0.1.0a1/src/kneebench/web/static/htmx.min.js +1 -0
- kneebench-0.1.0a1/src/kneebench/web/static/kb.css +341 -0
- kneebench-0.1.0a1/src/kneebench/web/templates/_check.html +19 -0
- kneebench-0.1.0a1/src/kneebench/web/templates/_detected.html +25 -0
- kneebench-0.1.0a1/src/kneebench/web/templates/_doctor.html +18 -0
- kneebench-0.1.0a1/src/kneebench/web/templates/_estimate.html +26 -0
- kneebench-0.1.0a1/src/kneebench/web/templates/_finding.html +53 -0
- kneebench-0.1.0a1/src/kneebench/web/templates/_notice.html +1 -0
- kneebench-0.1.0a1/src/kneebench/web/templates/_plan.html +16 -0
- kneebench-0.1.0a1/src/kneebench/web/templates/_progress.html +27 -0
- kneebench-0.1.0a1/src/kneebench/web/templates/_quality.html +35 -0
- kneebench-0.1.0a1/src/kneebench/web/templates/base.html +50 -0
- kneebench-0.1.0a1/src/kneebench/web/templates/compare.html +60 -0
- kneebench-0.1.0a1/src/kneebench/web/templates/doctor.html +18 -0
- kneebench-0.1.0a1/src/kneebench/web/templates/experiment.html +127 -0
- kneebench-0.1.0a1/src/kneebench/web/templates/experiments.html +33 -0
- kneebench-0.1.0a1/src/kneebench/web/templates/home.html +59 -0
- kneebench-0.1.0a1/src/kneebench/web/templates/live.html +8 -0
- kneebench-0.1.0a1/src/kneebench/web/templates/new.html +138 -0
- kneebench-0.1.0a1/src/kneebench/web/templates/report.html +54 -0
- kneebench-0.1.0a1/src/kneebench/web/templates/report_body.html +187 -0
- kneebench-0.1.0a1/tests/__init__.py +0 -0
- kneebench-0.1.0a1/tests/builders.py +544 -0
- kneebench-0.1.0a1/tests/conftest.py +78 -0
- kneebench-0.1.0a1/tests/fixture_data.py +31 -0
- kneebench-0.1.0a1/tests/fixtures/aiperf/vllm-baseline-c1-512-256/aiperf_config.yaml +44 -0
- kneebench-0.1.0a1/tests/fixtures/aiperf/vllm-baseline-c1-512-256/phase_manifest.json +37 -0
- kneebench-0.1.0a1/tests/fixtures/aiperf/vllm-baseline-c1-512-256/profile_export.jsonl +40 -0
- kneebench-0.1.0a1/tests/fixtures/aiperf/vllm-baseline-c1-512-256/profile_export_aiperf.json +1800 -0
- kneebench-0.1.0a1/tests/fixtures/aiperf/vllm-baseline-c1-512-256/profile_export_aiperf_timeslices.json +4977 -0
- kneebench-0.1.0a1/tests/fixtures/aiperf/vllm-baseline-c1-512-256/server_metrics_export.json +10434 -0
- kneebench-0.1.0a1/tests/fixtures/endpoint/vllm-0.29/metrics.prom +621 -0
- kneebench-0.1.0a1/tests/fixtures/endpoint/vllm-0.29/models.json +30 -0
- kneebench-0.1.0a1/tests/fixtures/endpoint/vllm-0.29/network.json +8 -0
- kneebench-0.1.0a1/tests/fixtures/endpoint/vllm-0.29/version.json +3 -0
- kneebench-0.1.0a1/tests/fixtures/hf/Qwen--Qwen2.5-7B-Instruct/config.json +27 -0
- kneebench-0.1.0a1/tests/fixtures/hf/Qwen--Qwen2.5-7B-Instruct/safetensors_params.json +3 -0
- kneebench-0.1.0a1/tests/fixtures/hf/RedHatAI--Meta-Llama-3.1-8B-Instruct-FP8/config.json +79 -0
- kneebench-0.1.0a1/tests/fixtures/hf/RedHatAI--Meta-Llama-3.1-8B-Instruct-FP8/safetensors_params.json +4 -0
- kneebench-0.1.0a1/tests/fixtures/hf/hugging-quants--Meta-Llama-3.1-8B-Instruct-AWQ-INT4/config.json +46 -0
- kneebench-0.1.0a1/tests/fixtures/hf/hugging-quants--Meta-Llama-3.1-8B-Instruct-AWQ-INT4/safetensors_params.json +4 -0
- kneebench-0.1.0a1/tests/fixtures/hf/unsloth--Meta-Llama-3.1-70B-Instruct/config.json +41 -0
- kneebench-0.1.0a1/tests/fixtures/hf/unsloth--Meta-Llama-3.1-70B-Instruct/safetensors_params.json +3 -0
- kneebench-0.1.0a1/tests/fixtures/hf/unsloth--Meta-Llama-3.1-8B-Instruct/config.json +38 -0
- kneebench-0.1.0a1/tests/fixtures/hf/unsloth--Meta-Llama-3.1-8B-Instruct/safetensors_params.json +3 -0
- kneebench-0.1.0a1/tests/integration/__init__.py +0 -0
- kneebench-0.1.0a1/tests/integration/conftest.py +72 -0
- kneebench-0.1.0a1/tests/integration/test_aiperf_mock.py +65 -0
- kneebench-0.1.0a1/tests/integration/test_run_mock.py +61 -0
- kneebench-0.1.0a1/tests/live/__init__.py +0 -0
- kneebench-0.1.0a1/tests/live/test_vllm_source.py +49 -0
- kneebench-0.1.0a1/tests/rules/__init__.py +0 -0
- kneebench-0.1.0a1/tests/rules/test_baseline_rules.py +116 -0
- kneebench-0.1.0a1/tests/rules/test_cancel_rules.py +45 -0
- kneebench-0.1.0a1/tests/rules/test_compare_rules.py +82 -0
- kneebench-0.1.0a1/tests/rules/test_hygiene_rules.py +156 -0
- kneebench-0.1.0a1/tests/rules/test_interference_rules.py +79 -0
- kneebench-0.1.0a1/tests/rules/test_rate_rules.py +63 -0
- kneebench-0.1.0a1/tests/rules/test_registry.py +80 -0
- kneebench-0.1.0a1/tests/rules/test_reuse_rules.py +77 -0
- kneebench-0.1.0a1/tests/rules/test_roofline_rules.py +44 -0
- kneebench-0.1.0a1/tests/rules/test_scheduler_rules.py +44 -0
- kneebench-0.1.0a1/tests/rules/test_shape_rules.py +119 -0
- kneebench-0.1.0a1/tests/rules/test_sweep_rules.py +268 -0
- kneebench-0.1.0a1/tests/rules/test_theory_rules.py +100 -0
- kneebench-0.1.0a1/tests/snapshots/__init__.py +0 -0
- kneebench-0.1.0a1/tests/snapshots/__snapshots__/test_reports.ambr +2920 -0
- kneebench-0.1.0a1/tests/snapshots/test_reports.py +83 -0
- kneebench-0.1.0a1/tests/unit/__init__.py +0 -0
- kneebench-0.1.0a1/tests/unit/test_aiperf_schema.py +132 -0
- kneebench-0.1.0a1/tests/unit/test_cancel_probe.py +64 -0
- kneebench-0.1.0a1/tests/unit/test_command.py +99 -0
- kneebench-0.1.0a1/tests/unit/test_connect_setup.py +37 -0
- kneebench-0.1.0a1/tests/unit/test_content.py +71 -0
- kneebench-0.1.0a1/tests/unit/test_demo.py +69 -0
- kneebench-0.1.0a1/tests/unit/test_detect.py +47 -0
- kneebench-0.1.0a1/tests/unit/test_doctor.py +140 -0
- kneebench-0.1.0a1/tests/unit/test_endpoint.py +17 -0
- kneebench-0.1.0a1/tests/unit/test_experiments.py +40 -0
- kneebench-0.1.0a1/tests/unit/test_fixtures_sanitized.py +32 -0
- kneebench-0.1.0a1/tests/unit/test_hf.py +22 -0
- kneebench-0.1.0a1/tests/unit/test_next_steps.py +46 -0
- kneebench-0.1.0a1/tests/unit/test_overhead.py +25 -0
- kneebench-0.1.0a1/tests/unit/test_parse.py +67 -0
- kneebench-0.1.0a1/tests/unit/test_physics.py +182 -0
- kneebench-0.1.0a1/tests/unit/test_plan.py +178 -0
- kneebench-0.1.0a1/tests/unit/test_quality.py +158 -0
- kneebench-0.1.0a1/tests/unit/test_redact.py +28 -0
- kneebench-0.1.0a1/tests/unit/test_roofline.py +68 -0
- kneebench-0.1.0a1/tests/unit/test_run_lifecycle.py +126 -0
- kneebench-0.1.0a1/tests/unit/test_settings.py +53 -0
- kneebench-0.1.0a1/tests/unit/test_steady_and_sweep.py +89 -0
- kneebench-0.1.0a1/tests/unit/test_store.py +55 -0
- kneebench-0.1.0a1/tests/unit/test_streams.py +70 -0
- kneebench-0.1.0a1/tests/unit/test_ttft_source.py +30 -0
- kneebench-0.1.0a1/tests/unit/test_version.py +32 -0
- kneebench-0.1.0a1/tests/unit/test_vllm_versions.py +55 -0
- kneebench-0.1.0a1/tests/unit/test_whatif.py +35 -0
- kneebench-0.1.0a1/tests/web/__init__.py +0 -0
- kneebench-0.1.0a1/tests/web/test_app.py +396 -0
- kneebench-0.1.0a1/tests/web/test_quality_web.py +77 -0
- kneebench-0.1.0a1/uv.lock +3725 -0
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[codz]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
# Usually these files are written by a python script from a template
|
|
31
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
32
|
+
*.manifest
|
|
33
|
+
*.spec
|
|
34
|
+
|
|
35
|
+
# Installer logs
|
|
36
|
+
pip-log.txt
|
|
37
|
+
pip-delete-this-directory.txt
|
|
38
|
+
|
|
39
|
+
# Unit test / coverage reports
|
|
40
|
+
htmlcov/
|
|
41
|
+
.tox/
|
|
42
|
+
.nox/
|
|
43
|
+
.coverage
|
|
44
|
+
.coverage.*
|
|
45
|
+
.cache
|
|
46
|
+
nosetests.xml
|
|
47
|
+
coverage.xml
|
|
48
|
+
*.cover
|
|
49
|
+
*.py.cover
|
|
50
|
+
*.lcov
|
|
51
|
+
.hypothesis/
|
|
52
|
+
.pytest_cache/
|
|
53
|
+
cover/
|
|
54
|
+
|
|
55
|
+
# Translations
|
|
56
|
+
*.mo
|
|
57
|
+
*.pot
|
|
58
|
+
|
|
59
|
+
# Django stuff:
|
|
60
|
+
*.log
|
|
61
|
+
local_settings.py
|
|
62
|
+
db.sqlite3
|
|
63
|
+
db.sqlite3-journal
|
|
64
|
+
|
|
65
|
+
# Flask stuff:
|
|
66
|
+
instance/
|
|
67
|
+
.webassets-cache
|
|
68
|
+
|
|
69
|
+
# Scrapy stuff:
|
|
70
|
+
.scrapy
|
|
71
|
+
|
|
72
|
+
# Sphinx documentation
|
|
73
|
+
docs/_build/
|
|
74
|
+
|
|
75
|
+
# PyBuilder
|
|
76
|
+
.pybuilder/
|
|
77
|
+
target/
|
|
78
|
+
|
|
79
|
+
# Jupyter Notebook
|
|
80
|
+
.ipynb_checkpoints
|
|
81
|
+
|
|
82
|
+
# IPython
|
|
83
|
+
profile_default/
|
|
84
|
+
ipython_config.py
|
|
85
|
+
|
|
86
|
+
# pyenv
|
|
87
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
88
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
89
|
+
# .python-version
|
|
90
|
+
|
|
91
|
+
# pipenv
|
|
92
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
93
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
94
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
95
|
+
# install all needed dependencies.
|
|
96
|
+
# Pipfile.lock
|
|
97
|
+
|
|
98
|
+
# uv
|
|
99
|
+
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
|
100
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
101
|
+
# commonly ignored for libraries.
|
|
102
|
+
# uv.lock
|
|
103
|
+
|
|
104
|
+
# poetry
|
|
105
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
106
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
107
|
+
# commonly ignored for libraries.
|
|
108
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
109
|
+
# poetry.lock
|
|
110
|
+
# poetry.toml
|
|
111
|
+
|
|
112
|
+
# pdm
|
|
113
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
114
|
+
# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
|
|
115
|
+
# https://pdm-project.org/en/latest/usage/project/#working-with-version-control
|
|
116
|
+
# pdm.lock
|
|
117
|
+
# pdm.toml
|
|
118
|
+
.pdm-python
|
|
119
|
+
.pdm-build/
|
|
120
|
+
|
|
121
|
+
# pixi
|
|
122
|
+
# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
|
|
123
|
+
# pixi.lock
|
|
124
|
+
# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
|
|
125
|
+
# in the .venv directory. It is recommended not to include this directory in version control.
|
|
126
|
+
.pixi/*
|
|
127
|
+
!.pixi/config.toml
|
|
128
|
+
|
|
129
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
130
|
+
__pypackages__/
|
|
131
|
+
|
|
132
|
+
# Celery stuff
|
|
133
|
+
celerybeat-schedule*
|
|
134
|
+
celerybeat.pid
|
|
135
|
+
|
|
136
|
+
# Redis
|
|
137
|
+
*.rdb
|
|
138
|
+
*.aof
|
|
139
|
+
*.pid
|
|
140
|
+
|
|
141
|
+
# RabbitMQ
|
|
142
|
+
mnesia/
|
|
143
|
+
rabbitmq/
|
|
144
|
+
rabbitmq-data/
|
|
145
|
+
|
|
146
|
+
# ActiveMQ
|
|
147
|
+
activemq-data/
|
|
148
|
+
|
|
149
|
+
# SageMath parsed files
|
|
150
|
+
*.sage.py
|
|
151
|
+
|
|
152
|
+
# Environments
|
|
153
|
+
.env
|
|
154
|
+
.envrc
|
|
155
|
+
.venv
|
|
156
|
+
env/
|
|
157
|
+
venv/
|
|
158
|
+
ENV/
|
|
159
|
+
env.bak/
|
|
160
|
+
venv.bak/
|
|
161
|
+
|
|
162
|
+
# Spyder project settings
|
|
163
|
+
.spyderproject
|
|
164
|
+
.spyproject
|
|
165
|
+
|
|
166
|
+
# Rope project settings
|
|
167
|
+
.ropeproject
|
|
168
|
+
|
|
169
|
+
# mkdocs/Zensical documentation
|
|
170
|
+
/site
|
|
171
|
+
|
|
172
|
+
# mypy
|
|
173
|
+
.mypy_cache/
|
|
174
|
+
.dmypy.json
|
|
175
|
+
dmypy.json
|
|
176
|
+
|
|
177
|
+
# Pyre type checker
|
|
178
|
+
.pyre/
|
|
179
|
+
|
|
180
|
+
# pytype static type analyzer
|
|
181
|
+
.pytype/
|
|
182
|
+
|
|
183
|
+
# Cython debug symbols
|
|
184
|
+
cython_debug/
|
|
185
|
+
|
|
186
|
+
# PyCharm
|
|
187
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
188
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
189
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
190
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
191
|
+
# .idea/
|
|
192
|
+
|
|
193
|
+
# Abstra
|
|
194
|
+
# Abstra is an AI-powered process automation framework.
|
|
195
|
+
# Ignore directories containing user credentials, local state, and settings.
|
|
196
|
+
# Learn more at https://abstra.io/docs
|
|
197
|
+
.abstra/
|
|
198
|
+
|
|
199
|
+
# Visual Studio Code
|
|
200
|
+
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore that
|
|
201
|
+
# can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
|
|
202
|
+
# and can be added to the global gitignore or merged into this file. However, if you prefer, you
|
|
203
|
+
# could uncomment the following to ignore the entire vscode folder
|
|
204
|
+
# .vscode/
|
|
205
|
+
# Temporary file for partial code execution
|
|
206
|
+
tempCodeRunnerFile.py
|
|
207
|
+
|
|
208
|
+
# Ruff stuff:
|
|
209
|
+
.ruff_cache/
|
|
210
|
+
|
|
211
|
+
# PyPI configuration file
|
|
212
|
+
.pypirc
|
|
213
|
+
|
|
214
|
+
# Marimo
|
|
215
|
+
marimo/_static/
|
|
216
|
+
marimo/_lsp/
|
|
217
|
+
__marimo__/
|
|
218
|
+
|
|
219
|
+
# Streamlit
|
|
220
|
+
.streamlit/secrets.toml
|
|
221
|
+
|
|
222
|
+
# kneebench
|
|
223
|
+
# Local endpoint config (may contain internal URLs); see kneebench.local.toml.example.
|
|
224
|
+
kneebench.local.toml
|
|
225
|
+
# Default AIPerf artifact dir and local kneebench data when KNEEBENCH_HOME points here.
|
|
226
|
+
artifacts/
|
|
227
|
+
.kneebench/
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.12
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project uses
|
|
5
|
+
[Semantic Versioning](https://semver.org/).
|
|
6
|
+
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
## [0.1.0a1] - 2026-10-22
|
|
10
|
+
|
|
11
|
+
First alpha on PyPI, to reserve the name. Install from GitHub until 0.1.0.
|
|
12
|
+
|
|
13
|
+
### Fixed (from a clean full run)
|
|
14
|
+
- From far away, first-token percentiles are the lower of the client's (round trip removed)
|
|
15
|
+
and the server's own histogram: network jitter no longer fails every random-arrival rate
|
|
16
|
+
while the server's P99 is well under target, and bucket rounding no longer halves capacity.
|
|
17
|
+
The report says when this applies.
|
|
18
|
+
- H04 relies on the server's output-token count alone when it has one, so sampled answer
|
|
19
|
+
lengths no longer read as answers stopping early.
|
|
20
|
+
- The CLI progress line shows the arrival rate for rate points instead of the concurrency cap.
|
|
21
|
+
- The bundled demo and screenshots come from a clean full run.
|
|
22
|
+
|
|
23
|
+
### Security
|
|
24
|
+
- certifi raised to 2026.10.19 or newer and uv to 0.13.4 or newer: older versions still trust
|
|
25
|
+
the compromised eMudhra intermediate certificates, which allows TLS interception.
|
|
26
|
+
|
|
27
|
+
### Changed (report and UI)
|
|
28
|
+
- Reports open with a Setup block (model, GPU, server, cache, scheduler limits and where they
|
|
29
|
+
came from, traffic, targets, where the test ran, what ran) and an Executive summary in
|
|
30
|
+
bullets: capacity, how much traffic to plan for, the first server change to try, caveats.
|
|
31
|
+
- A light and dark mode toggle in the header; it follows the system until you pick one.
|
|
32
|
+
- The new-run form marks required fields and explains every field in one line behind a (?).
|
|
33
|
+
|
|
34
|
+
### Added (plan gaps)
|
|
35
|
+
- H10 checks kneebench was alone on the server: no requests running or waiting at the start,
|
|
36
|
+
and never more than one running while kneebench sent one. The CLI and the run form warn
|
|
37
|
+
before a run when the server is already busy.
|
|
38
|
+
- max_num_seqs and the per-step token budget are inferred from the engine when its behaviour
|
|
39
|
+
pins them down (the running count flattening while requests wait; steps larger than the
|
|
40
|
+
default, or a lower ceiling across queued levels), and labelled as inferred. E02, W06,
|
|
41
|
+
I01 and H09 use them instead of assuming the version defaults.
|
|
42
|
+
- Comparisons and experiments measure their noise band: changes smaller than the larger
|
|
43
|
+
start-to-end move of either run's repeated baseline count as noise, with 5% as the floor.
|
|
44
|
+
|
|
45
|
+
### Fixed (from the full live run)
|
|
46
|
+
- The latency wall is found at or above the operating point, so a noisy tail at a low level
|
|
47
|
+
no longer reads "4 users comfortably, breaking at about 1".
|
|
48
|
+
- B04 and B06 suggest moving kneebench closer to the server when the network caused the
|
|
49
|
+
spread, not checking the GPU; rule actions can now depend on the finding's case.
|
|
50
|
+
- B06 and B04 compare the client's time per token with the server's own histogram: when the
|
|
51
|
+
server held steady they say the network path changed, instead of blaming the GPU.
|
|
52
|
+
- H04 trusts the server's output-token count over AIPerf's recount of long streamed answers,
|
|
53
|
+
and expects the mixed lengths of a scheduled point. H05 skips multi-turn points, where
|
|
54
|
+
every message adds its own chat-template tokens.
|
|
55
|
+
- "1 users" in sentences.
|
|
56
|
+
|
|
57
|
+
### Changed
|
|
58
|
+
- The bundled demo and README screenshots come from a fresh full run with every phase.
|
|
59
|
+
|
|
60
|
+
### Added (quality gate)
|
|
61
|
+
- Guided experiments can record answers before a change and compare them after (lesson 54):
|
|
62
|
+
the same questions twice for the noise floor, then question by question with flips, the
|
|
63
|
+
paired accuracy change and its 95% interval, an exact McNemar test and per-category
|
|
64
|
+
results. The pass rule is saved before any answer exists; changed answers are listed to read.
|
|
65
|
+
- A 290-question starter set with program-checkable answers, or your own JSONL. Answers are
|
|
66
|
+
graded by rules, never by a model. `kneebench quality ask | runs | compare` on the command
|
|
67
|
+
line, which also covers two endpoints side by side.
|
|
68
|
+
|
|
69
|
+
### Added (roofline and precision what-ifs)
|
|
70
|
+
- F01 places every load level on the GPU's roofline: FLOPs per byte of a decode step against
|
|
71
|
+
the ridge, the throughput each level reached against the line, and where the cache reads
|
|
72
|
+
cap decode at long contexts (lesson 61). With a roofline chart.
|
|
73
|
+
- F02 projects an FP8 KV cache, FP8 or INT8 weights and activations (only where the GPU has
|
|
74
|
+
those tensor cores) and 4-bit weight-only: weight memory, requests that fit, decode and
|
|
75
|
+
prefill speed at your load (lessons 50, 51, 53). When the cache is the limit it suggests
|
|
76
|
+
`--kv-cache-dtype fp8`, which the guided experiment can verify from outside.
|
|
77
|
+
|
|
78
|
+
### Added (prompt reuse)
|
|
79
|
+
- New phase at the operating point: the same load with prompts that never repeat, with one
|
|
80
|
+
shared 1,500-token system prompt, and as six-turn conversations that resend the real
|
|
81
|
+
answers (lessons 47 and 48).
|
|
82
|
+
- P01 reports what the shared prompt saves in first-token time and the server's prefix-cache
|
|
83
|
+
hit rate, and suggests `--enable-prefix-caching` when it is off. P02 shows first-token time
|
|
84
|
+
per turn as the history grows. P03 estimates how many distinct system prompts the cache
|
|
85
|
+
holds before reuse collapses (lesson 49).
|
|
86
|
+
- P04: the same retrieved passages in ranked order and sorted by document id, with the
|
|
87
|
+
reuse and first-token time each gets (lesson 48 section 5).
|
|
88
|
+
- New phase: abandoned requests. Every request asks for a long answer and hangs up after a
|
|
89
|
+
second; kneebench reads the server's token counters before and after. A01 warns when the
|
|
90
|
+
server finishes answers nobody is reading, usually a gateway not passing disconnects on
|
|
91
|
+
(lesson 36 section 3).
|
|
92
|
+
|
|
93
|
+
### Added (long-prompt interference)
|
|
94
|
+
- New phase: 32 streaming chats, once alone and once with a long prompt arriving every 10 s
|
|
95
|
+
(lesson 44), replayed on a fixed schedule. kneebench rebuilds every streamed chunk's arrival
|
|
96
|
+
time and reports the longest pause, P99.9 and stalls, which an average or P99 hides.
|
|
97
|
+
- Rule I01 ties pauses to the long prompts only when they exceed anything the streams showed
|
|
98
|
+
alone, says so when the network is too noisy to tell, and otherwise suggests a smaller
|
|
99
|
+
`--max-num-batched-tokens` sized from your per-token target (lesson 45).
|
|
100
|
+
|
|
101
|
+
### Added (guided tuning and the engine view)
|
|
102
|
+
- Guided experiments: every server change in a report has "Try this change". kneebench shows
|
|
103
|
+
it for your deployment (vllm serve, Kubernetes/Helm or a managed platform), checks from
|
|
104
|
+
outside that the server restarted and that visible settings changed, runs a short
|
|
105
|
+
verification over the load the change can move, and compares it with the run that proposed
|
|
106
|
+
it. Keep or revert; the Experiments page is the ledger.
|
|
107
|
+
- Engine view: E01 splits first-token time into network, queue and prompt read from vLLM's
|
|
108
|
+
own histograms; E02 names the limit that makes requests wait (sequence cap, per-step token
|
|
109
|
+
budget or KV cache).
|
|
110
|
+
- Physics and rules updated for lessons 30-61: KV-aware decode and attention-aware prefill
|
|
111
|
+
floors, p95 block-rounded admission sizing, req/s headroom with a failure margin,
|
|
112
|
+
evictions as a rate, quantization by compute path.
|
|
113
|
+
|
|
114
|
+
### Added (demo run)
|
|
115
|
+
- The UI opens on a real, sanitized demo run with every phase on first start. It is a normal
|
|
116
|
+
run: delete it any time, `kneebench demo` restores it, `KNEEBENCH_NO_DEMO=1` skips it.
|
|
117
|
+
`scripts/make_demo.py` refreshes it from any finished run.
|
|
118
|
+
|
|
119
|
+
### Added (M5: what-ifs and compare)
|
|
120
|
+
- What-if targets: re-judge a stored run against other latency targets from the report page
|
|
121
|
+
or `kneebench report <id> --slo-ttft-ms/--slo-tpot-ms/--slo-percentile`. Nothing is rerun
|
|
122
|
+
or saved, and exports keep the what-if.
|
|
123
|
+
- Request-size estimates in the report: first-token time, per-token speed, answer time and
|
|
124
|
+
cache fit for a prompt and output length the run didn't test, from the shape sweep.
|
|
125
|
+
- Compare two runs (`kneebench compare <before> <after>`, or the form on the run list): setup
|
|
126
|
+
and workload diff, results with ratios and a 5% noise band, overlaid curves, and rules X01
|
|
127
|
+
(what changed, and whether the comparison is clean) and X02 (what it did).
|
|
128
|
+
|
|
129
|
+
### Added (M4: shape sweep)
|
|
130
|
+
- Your own request size (`--shapes 2000/500`, or "Typical request" in the form) becomes the
|
|
131
|
+
main shape, tested next to the standard chat, reasoning and summarization shapes.
|
|
132
|
+
- Request-size sweep: prompt length (output fixed at 256) and output length (prompt fixed at
|
|
133
|
+
1,024), each at 1 user and at the operating point, capped to the context window, plus the
|
|
134
|
+
shape map: every shape at the same load, never averaged.
|
|
135
|
+
- Rules S01-S07 (first-token cost per prompt token, long prompts slowing decode, answer time
|
|
136
|
+
per output token, long answers holding cache, your traffic, the shape map, the prompt to
|
|
137
|
+
output exchange rate), with charts and their own report section ordered by product type.
|
|
138
|
+
|
|
139
|
+
### Added (M3: request-rate sweep)
|
|
140
|
+
- Poisson arrivals at 25% to 110% of the measured capacity and bursty (gamma) arrivals near
|
|
141
|
+
it, 90 seconds each; rates come from the concurrency sweep at run time.
|
|
142
|
+
- Rules R01-R04 (sustainable request rate, run-length dependence past capacity, client
|
|
143
|
+
shortfall, burst penalty).
|
|
144
|
+
|
|
145
|
+
### Added (M2: concurrency sweep, walls, web UI and PDF)
|
|
146
|
+
- Concurrency sweep (1, 2, 4 ... 256, capped by memory and `max_num_seqs`) with 5% length
|
|
147
|
+
variation, a time budget, and early stop once the walls are found or on errors and
|
|
148
|
+
gateway failures. ETAs include AIPerf startup and a physics model of per-token cost.
|
|
149
|
+
- Steady-state throughput that excludes ramp-up and drain.
|
|
150
|
+
- Rules C01-C05 (curve, operating point, peak vs capacity, tails), W01-W09 (saturation, SLO
|
|
151
|
+
wall, capacity as the lowest wall, preemption, `max_num_seqs` advice, errors, headroom)
|
|
152
|
+
and H01, H02, H06, H09 (steady state, weak client, prefix caching, gateways).
|
|
153
|
+
- First-token targets judged on server-side time, without the client's network round trip.
|
|
154
|
+
- Web UI (`kneebench` or `kneebench ui`): detection-first new-run form, live progress with
|
|
155
|
+
stop, doctor page, run list with delete, and the report with a contents sidebar,
|
|
156
|
+
collapsible findings and interactive Plotly charts.
|
|
157
|
+
- Exports: PDF (headless Chromium, with an appendix of raw numbers and the Markdown and
|
|
158
|
+
JSON reports attached), self-contained HTML, Markdown and JSON. Browser printing works
|
|
159
|
+
without Chromium.
|
|
160
|
+
- One run at a time across the CLI and the UI (shared lock); failed, cancelled and
|
|
161
|
+
interrupted runs are recorded with the reason. `kneebench delete` removes a run.
|
|
162
|
+
- Design: warm paper palette with bundled Geist, Geist Mono and Source Serif 4 fonts.
|
|
163
|
+
|
|
164
|
+
### Added (M1: detect, theory and baseline)
|
|
165
|
+
- Auto-detection from the endpoint: vLLM version (`/version`), served model, context length
|
|
166
|
+
and Hugging Face id (`/v1/models`), KV cache size and settings (`vllm:cache_config_info`),
|
|
167
|
+
and client distance (DNS, TCP, TLS and a keep-alive `/health` round trip).
|
|
168
|
+
- Model physics from Hugging Face metadata: exact weight bytes from safetensors (dense, FP8
|
|
169
|
+
and int4 checkpoints), KV bytes per token (GQA, fp8 cache), tensor parallelism.
|
|
170
|
+
MoE and MLA models are rejected with a clear message until after the MVP.
|
|
171
|
+
- GPU catalog (H100 SXM/NVL/PCIe, H200, B200, A100, L40S, L4, A10, MI300X) plus custom GPUs.
|
|
172
|
+
- vLLM defaults per version (`content/vllm_versions.yaml`), verified against vLLM source at
|
|
173
|
+
v0.29.0 to v0.32.0, with a live test that re-reads the source.
|
|
174
|
+
- SQLite storage of setups, runs, points, per-request records, timeslices, server metrics,
|
|
175
|
+
AIPerf warnings and compressed raw artifacts.
|
|
176
|
+
- Phase 0 (theory) and phase 1 (single-request baseline), with ETAs that include AIPerf
|
|
177
|
+
startup overhead.
|
|
178
|
+
- Rules T01-T08, B01-B06, H03-H05, H07, H08, each citing its lesson note, with text in a
|
|
179
|
+
reviewable content layer and a workload-ordered Markdown and JSON report.
|
|
180
|
+
- `kneebench run`, `runs`, `report` (with `--gpu` to correct the GPU entry without a rerun),
|
|
181
|
+
`detect` and `gpus` commands.
|
|
182
|
+
|
|
183
|
+
### Fixed
|
|
184
|
+
- Work around AIPerf 0.13.0 dropping `networkLatency` from YAML configs by also passing
|
|
185
|
+
`--network-latency-automatic` (reported upstream as
|
|
186
|
+
[ai-dynamo/aiperf#1583](https://github.com/ai-dynamo/aiperf/issues/1583)).
|
|
187
|
+
|
|
188
|
+
### Added (M0)
|
|
189
|
+
- Project skeleton managed with uv; Python 3.11 to 3.13; macOS and Linux.
|
|
190
|
+
- AIPerf 0.13.0 bundled as a pinned core dependency. kneebench always launches the
|
|
191
|
+
copy in its own environment and refuses to run with any other version.
|
|
192
|
+
- Per-point AIPerf configs written as YAML. The API key reaches AIPerf only through
|
|
193
|
+
the child process environment, never argv or files, and all artifacts and logs
|
|
194
|
+
are scrubbed after each point.
|
|
195
|
+
- Measured AIPerf per-process startup overhead (about 8 s warm with a Hugging Face
|
|
196
|
+
tokenizer, about 20 s on first launch) for the planner's ETA.
|
|
197
|
+
- `kneebench doctor` with `--offline`, `--url` and `--tokenizer`: checks Python,
|
|
198
|
+
platform, the bundled AIPerf, the data directory, endpoint routes
|
|
199
|
+
(`/health`, `/version`, `/v1/models`, `/metrics`) and the tokenizer download,
|
|
200
|
+
with plain-English fixes.
|
|
201
|
+
- CI on Ubuntu and macOS for Python 3.11 to 3.13, including a clean-install job.
|
|
202
|
+
|
|
203
|
+
### Dependencies
|
|
204
|
+
- `aiperf==0.13.0` (pinned). Upgrade only together with `AIPERF_PIN` and a note here.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Code of Conduct
|
|
2
|
+
|
|
3
|
+
This project follows the [Contributor Covenant, version 2.1](https://www.contributor-covenant.org/version/2/1/code_of_conduct/).
|
|
4
|
+
|
|
5
|
+
## In short
|
|
6
|
+
|
|
7
|
+
- Be kind and assume good intent. Many people arrive here new to inference; questions
|
|
8
|
+
that seem basic are welcome.
|
|
9
|
+
- Critique ideas and code, never people.
|
|
10
|
+
- No harassment, discrimination, personal attacks or unwelcome sexual attention.
|
|
11
|
+
|
|
12
|
+
## Reporting
|
|
13
|
+
|
|
14
|
+
Report unacceptable behavior to the maintainer at pratamesh1867@gmail.com. Reports are
|
|
15
|
+
handled confidentially. Maintainers may remove comments, commits or contributions that
|
|
16
|
+
violate this code, and may ban contributors temporarily or permanently, following the
|
|
17
|
+
enforcement guidelines of the Contributor Covenant.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Contributing to kneebench
|
|
2
|
+
|
|
3
|
+
Thanks for helping. Bug reports, better explanations and new rules are all welcome.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
git clone https://github.com/S1LV3RJ1NX/kneebench && cd kneebench
|
|
9
|
+
uv sync
|
|
10
|
+
uv run kneebench doctor --offline
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Add dependencies with `uv add <pkg>` (or `uv add --dev <pkg>`), never pip, and commit
|
|
14
|
+
`uv.lock`.
|
|
15
|
+
|
|
16
|
+
## Checks
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
uv run ruff format .
|
|
20
|
+
uv run ruff check .
|
|
21
|
+
uv run mypy
|
|
22
|
+
uv run pytest -m "not integration and not live" # fast, no network
|
|
23
|
+
uv run pytest -m integration # bundled AIPerf vs a local mock server
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Integration tests start `guidellm mock-server` through `uvx`, in its own environment.
|
|
27
|
+
`live` tests need a real endpoint: put it in `kneebench.local.toml` (gitignored; see
|
|
28
|
+
`kneebench.local.toml.example`). Never commit real endpoint URLs or keys, including
|
|
29
|
+
in test fixtures.
|
|
30
|
+
|
|
31
|
+
## Ground rules
|
|
32
|
+
|
|
33
|
+
- **Analysis is deterministic.** Verdicts and recommendations come from formulas,
|
|
34
|
+
thresholds and templated text. No LLM in the core.
|
|
35
|
+
- **Every rule cites its source** (a lesson note and section) and has tests for its
|
|
36
|
+
ok, bad and edge cases.
|
|
37
|
+
- **Text lives in the content layer**, not in analysis code, so explanations can be
|
|
38
|
+
reviewed on their own.
|
|
39
|
+
- **No hardcoded models, GPUs or endpoints.** kneebench must work for any setup.
|
|
40
|
+
- **Small, conventional commits** (`feat:`, `fix:`, `docs:`, `test:`, `ci:`, `chore:`).
|
|
41
|
+
|
|
42
|
+
## Upgrading AIPerf
|
|
43
|
+
|
|
44
|
+
Bump `aiperf==` in `pyproject.toml` and `AIPERF_PIN` in
|
|
45
|
+
`src/kneebench/loadgen/aiperf/version.py` together, run the full test suite (the
|
|
46
|
+
schema test validates generated configs against the new version), re-measure startup
|
|
47
|
+
overhead with `scripts/measure_aiperf_startup.py`, and add a CHANGELOG entry.
|
|
48
|
+
|
|
49
|
+
## Refreshing the demo run
|
|
50
|
+
|
|
51
|
+
The UI ships with one real run so first-time users see a full report. Refresh it whenever a
|
|
52
|
+
new rule or phase needs data the current demo doesn't have:
|
|
53
|
+
|
|
54
|
+
1. Run a full benchmark: `KNEEBENCH_HOME=$PWD/.kneebench uv run kneebench run --gpu <id> --yes`.
|
|
55
|
+
2. Export it: `uv run python scripts/make_demo.py --run <id>`. This replaces the endpoint,
|
|
56
|
+
served model name and local paths with placeholders, refuses to write if any survive,
|
|
57
|
+
checks that the export imports and analyzes, and writes `src/kneebench/content/demo-run.json.gz`.
|
|
58
|
+
3. Optionally regenerate the README images: `uv run python scripts/make_screenshots.py ...`.
|
|
59
|
+
4. Commit both. Users get the new demo on their next start unless they deleted the old one.
|
|
60
|
+
|
|
61
|
+
Rule and wording changes alone don't need a refresh: reports are rebuilt from the stored
|
|
62
|
+
measurements every time.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Prathamesh Saraf
|
|
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.
|