fitlab 0.1.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.
@@ -0,0 +1,16 @@
1
+ # Environments and caches
2
+ .venv/
3
+ __pycache__/
4
+ .ruff_cache/
5
+ *.egg-info/
6
+
7
+ # Build output
8
+ build/
9
+ dist/
10
+
11
+ # Local run output
12
+ fitlab-results/
13
+ kernel/
14
+ out/
15
+ results/
16
+ this-week-pins.txt
fitlab-0.1.0/LICENSE ADDED
@@ -0,0 +1,3 @@
1
+ Code: Apache License 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
2
+ Data in /data and published registries: CC-BY-4.0 (https://creativecommons.org/licenses/by/4.0/)
3
+ Benchmark results are point-in-time measurements. Models referenced belong to their respective authors and licenses.
fitlab-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,478 @@
1
+ Metadata-Version: 2.5
2
+ Name: fitlab
3
+ Version: 0.1.0
4
+ Summary: Will it run on my setup? Fit-check + benchmark wizard for local LLMs on your GPU — weekly-updated model registry.
5
+ Project-URL: Homepage, https://github.com/ruslanmv/fitlab
6
+ Project-URL: Source, https://github.com/ruslanmv/fitlab
7
+ Project-URL: Issues, https://github.com/ruslanmv/fitlab/issues
8
+ Author: Ruslan Magana Vsevolodovna
9
+ License: Apache-2.0
10
+ License-File: LICENSE
11
+ Keywords: benchmark,colab,gpu,llm,local-ai,ollama,vram
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: Apache Software License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
22
+ Requires-Python: >=3.10
23
+ Requires-Dist: rich>=13
24
+ Provides-Extra: dev
25
+ Requires-Dist: build>=1.2; extra == 'dev'
26
+ Requires-Dist: jsonschema>=4.21; extra == 'dev'
27
+ Requires-Dist: pyyaml>=6.0; extra == 'dev'
28
+ Requires-Dist: ruff>=0.6; extra == 'dev'
29
+ Requires-Dist: twine>=5.1; extra == 'dev'
30
+ Provides-Extra: maintainer
31
+ Requires-Dist: jsonschema>=4.21; extra == 'maintainer'
32
+ Requires-Dist: pyyaml>=6.0; extra == 'maintainer'
33
+ Description-Content-Type: text/markdown
34
+
35
+ <p align="center">
36
+ <img src="site/logo.svg" width="96" alt="FitLab logo" />
37
+ </p>
38
+
39
+ <h1 align="center">LLM FitLab</h1>
40
+
41
+ <p align="center">
42
+ <strong>An evidence-based compatibility radar for running open LLMs on the hardware you actually have.</strong>
43
+ </p>
44
+
45
+ <p align="center">
46
+ <a href="https://github.com/ruslanmv/fitlab/actions/workflows/weekly-sync.yml"><img alt="Weekly sync" src="https://github.com/ruslanmv/fitlab/actions/workflows/weekly-sync.yml/badge.svg" /></a>
47
+ <a href="https://github.com/ruslanmv/fitlab/actions/workflows/weekly-benchmark.yml"><img alt="Weekly benchmark" src="https://github.com/ruslanmv/fitlab/actions/workflows/weekly-benchmark.yml/badge.svg" /></a>
48
+ <img alt="Python" src="https://img.shields.io/badge/python-3.10%2B-blue" />
49
+ <img alt="Code license" src="https://img.shields.io/badge/code-Apache--2.0-green" />
50
+ <img alt="Data license" src="https://img.shields.io/badge/data-CC--BY--4.0-green" />
51
+ <img alt="Status" src="https://img.shields.io/badge/status-beta-orange" />
52
+ </p>
53
+
54
+ ---
55
+
56
+ FitLab answers the three questions every engineer asks before pulling a local model — and it
57
+ answers them with **regenerated data, not a hand-maintained list**. Every claim on the page is
58
+ produced by a script, validated against a JSON Schema, and merged through a reviewed pull request.
59
+
60
+ | Lane | Question it answers | Method | Confidence |
61
+ |---|---|---|---|
62
+ | **FITS** | Will this model fit my GPU? | Deterministic VRAM arithmetic from the model's own `config.json` — weights + KV cache + runtime overhead, per quantization and context length | Computed, reproducible |
63
+ | **RUNS** | How fast is it, really? | A real benchmark on a free T4 16 GB GPU every week, plus community-submitted runs on real consumer hardware | Measured, with raw data retained |
64
+ | **PLUGS** | Does it work with my stack? | Weekly end-to-end probes installing the **latest released** Ollama, [OllaBridge](https://github.com/ruslanmv/ollabridge), LangGraph, CrewAI, Langflow, Langfuse and DeepAgents, then issuing a genuine request through the whole chain | Verified, with exact versions recorded |
65
+
66
+ **Source of truth:** [`data/registry.json`](data/) · **Design rationale:** [`ARCHITECTURE.md`](ARCHITECTURE.md)
67
+
68
+ ## Table of contents
69
+
70
+ - [Why FitLab exists](#why-fitlab-exists)
71
+ - [Installation](#installation)
72
+ - [Quick start](#quick-start)
73
+ - [CLI reference](#cli-reference)
74
+ - [Configuration](#configuration)
75
+ - [Running FitLab inside an organization](#running-fitlab-inside-an-organization)
76
+ - [Data contract](#data-contract)
77
+ - [How the numbers are produced](#how-the-numbers-are-produced)
78
+ - [Automation](#automation)
79
+ - [Development](#development)
80
+ - [Contributing](#contributing)
81
+ - [Security](#security)
82
+ - [Support and versioning](#support-and-versioning)
83
+ - [Related projects](#related-projects)
84
+ - [License](#license)
85
+
86
+ ## Why FitLab exists
87
+
88
+ Curated "best model for X GB" lists go stale within a quarter. FitLab is built so that the
89
+ **data outlives any individual model**:
90
+
91
+ 1. **Nothing is hand-ranked.** A weekly job pulls the leading models per Hugging Face pipeline tag
92
+ through the public API, runs each one through the FITS engine, scores them with a versioned
93
+ formula, and opens a review PR. Humans review; automation refreshes.
94
+ 2. **Claims are tested, not copied.** One model per week receives a real benchmark on a free
95
+ T4 16 GB — the same GPU class the Colab free tier allocates — so the numbers transfer directly.
96
+ 3. **The community is the sensor network.** Anyone can run the
97
+ [one-click Colab notebook](colab/benchmark_colab.ipynb) or the local benchmark script; the result
98
+ is schema-validated and sanity-bounded by CI before it is merged, with attribution.
99
+ 4. **Writes are gated.** Every JSON is validated against [`data/schema/`](data/schema/), and all
100
+ automation writes through pull requests — never directly to the default branch.
101
+ 5. **Compatibility is re-verified, not assumed.** A green PLUGS cell means the integration worked
102
+ *this week*, at version pins recorded alongside the result.
103
+
104
+ ## Installation
105
+
106
+ **Requirements:** Python 3.10 or newer. [Ollama](https://ollama.com) is required only for the
107
+ `bench` command and the wizard's benchmarking step — fit checks need no GPU and no runtime.
108
+
109
+ FitLab is published to PyPI from tagged GitHub releases via
110
+ [Trusted Publishing](https://docs.pypi.org/trusted-publishers/):
111
+
112
+ ```bash
113
+ pip install fitlab
114
+ ```
115
+
116
+ Until the first release lands on PyPI, install from source. The Makefile bootstraps
117
+ [uv](https://docs.astral.sh/uv/), creates `./.venv` and installs everything:
118
+
119
+ ```bash
120
+ git clone https://github.com/ruslanmv/fitlab && cd fitlab
121
+ make install
122
+ make run
123
+ ```
124
+
125
+ Or without make, using any tool that reads `pyproject.toml`:
126
+
127
+ ```bash
128
+ pip install . # or: uv sync
129
+ fitlab --version
130
+ ```
131
+
132
+ The model list refreshes itself at runtime: the CLI fetches the weekly `registry.json`, caches it
133
+ for 24 hours, and falls back to a bundled seed when offline. Upgrading the package is not required
134
+ to see new models.
135
+
136
+ ## Quick start
137
+
138
+ Run the wizard with no arguments — it detects your hardware, shows what fits, and offers to
139
+ benchmark your selection:
140
+
141
+ ```bash
142
+ fitlab
143
+ ```
144
+
145
+ ```text
146
+ // llm fitlab — fit-check console · v0.1.0
147
+ your rig: NVIDIA GeForce RTX 3060 · 12.0 GB VRAM · ~360 GB/s
148
+ registry 2026-08-24 · 22 models · live (weekly)
149
+
150
+ 1 colab-free — Top 10 — Colab free / Kaggle (T4 16 GB)
151
+ 2 local-12gb — Top 10 — local inference, low-end GPU (12 GB)
152
+ 3 multimodal — Top multimodal (vision-language) for 12–16 GB
153
+ 4 all — everything, deduplicated
154
+ ? Category 1-4 (1)
155
+ ```
156
+
157
+ Or check a specific GPU profile without running anything:
158
+
159
+ ```bash
160
+ fitlab check --gpu rtx3060-12 --category local-12gb --limit 6
161
+ ```
162
+
163
+ ```text
164
+ fit check · RTX 3060 12GB · Q4_K_M · 8K ctx
165
+ ┏━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━┳━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
166
+ ┃ # ┃ model ┃ params ┃ est GB ┃ verdict ┃ ~tok/s ┃ ollama tag ┃
167
+ ┡━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━╇━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━━━━┩
168
+ │ 1 │ Qwen/Qwen3-8B │ 8.2B │ 7.2 │ FITS │ ~44.8 │ qwen3:8b │
169
+ │ 2 │ ibm-granite/gran… │ 8.1B │ 7.3 │ FITS │ ~45.4 │ granite3.3:8b │
170
+ │ 3 │ meta-llama/Llama… │ 8.0B │ 7.0 │ FITS │ ~45.9 │ llama3.1:8b │
171
+ │ 4 │ mistralai/Minist… │ 8.0B │ 7.1 │ FITS │ ~45.9 │ ministral-8b │
172
+ │ 5 │ Qwen/Qwen3-14B │ 14.8B │ 11.5 │ TIGHT │ ~24.8 │ qwen3:14b │
173
+ │ 6 │ deepseek-ai/Deep… │ 14.8B │ 11.8 │ TIGHT │ ~24.8 │ deepseek-r1:14b │
174
+ └───┴───────────────────┴────────┴────────┴─────────┴────────┴─────────────────┘
175
+ ```
176
+
177
+ After a benchmark, the CLI prints a prefilled submission link so your result can join the public
178
+ dataset. Submitting is entirely optional; nothing is transmitted automatically.
179
+
180
+ ## CLI reference
181
+
182
+ | Command | Purpose |
183
+ |---|---|
184
+ | `fitlab` | Interactive wizard: detect → fit table → select → benchmark |
185
+ | `fitlab detect` | Print detected hardware (NVIDIA via `nvidia-smi`, Apple Silicon via `sysctl`, CPU fallback) |
186
+ | `fitlab check` | Fit table for a GPU profile. No model download, no GPU required |
187
+ | `fitlab bench` | Benchmark one model non-interactively; writes a schema-valid JSON result |
188
+ | `fitlab update` | Force a registry refresh, bypassing the 24-hour cache |
189
+ | `fitlab --version` | Print the installed version |
190
+
191
+ **`fitlab check`**
192
+
193
+ | Flag | Default | Values |
194
+ |---|---|---|
195
+ | `--gpu` | `auto` | `auto`, `rtx3060-12`, `t4-16`, `rtx4070-12`, `rtx4060ti-16`, `apple-m-16`, `cpu-only` |
196
+ | `--quant` | `Q4_K_M` | `Q2_K`, `Q3_K_M`, `Q4_0`, `Q4_K_M`, `Q5_K_M`, `Q6_K`, `Q8_0`, `MXFP4`, `F16` |
197
+ | `--ctx` | `8192` | `4096`, `8192`, `16384`, `32768` |
198
+ | `--category` | `all` | A registry category id, or `all` |
199
+ | `--limit` | unset | Maximum rows to print |
200
+
201
+ **`fitlab bench`**
202
+
203
+ | Flag | Default | Notes |
204
+ |---|---|---|
205
+ | `--model` | *required* | Ollama tag (`qwen3:8b`) or registry slug (`qwen3-8b`) |
206
+ | `--reps` | `3` | Repetitions; `gen_tps` is reported as the median |
207
+ | `--context` | `4096` | Context length for the run |
208
+ | `--out` | `fitlab-results` | Output directory for the result JSON |
209
+ | `--source` | `community-local` | `ci-kaggle`, `ci-actions-cpu`, `community-colab`, `community-local`, `maintainer` |
210
+ | `--submitter` | empty | GitHub handle recorded for attribution |
211
+ | `--dry-run` | off | Print the fit verdict and execution plan without running |
212
+
213
+ Benchmarks are seeded and fixed-length (`fitlab-v1-256` prompt, `num_predict 256`, `seed 42`) so
214
+ runs are comparable across machines and across time.
215
+
216
+ ## Configuration
217
+
218
+ All configuration is by environment variable — no config file, no implicit state beyond the cache.
219
+
220
+ | Variable | Default | Purpose |
221
+ |---|---|---|
222
+ | `FITLAB_REGISTRY_URL` | Public `registry.json` on the default branch | Point the CLI at a different registry — an internal mirror, a pinned commit, or a `file://` path |
223
+ | `FITLAB_CACHE` | `~/.cache/fitlab` | Cache directory for the fetched registry (24-hour TTL) |
224
+ | `FITLAB_REPO` | `OWNER/llm-fitlab` | Repository used to build benchmark submission links |
225
+ | `OLLABRIDGE_URL` | `http://127.0.0.1:11435/v1` | Gateway endpoint used by the PLUGS compatibility probes |
226
+ | `KAGGLE_USERNAME`, `KAGGLE_KEY` | unset | Required only by the weekly GPU benchmark workflow |
227
+
228
+ Network behaviour is deliberately narrow and predictable:
229
+
230
+ - `check`, `detect` and the wizard's fit stage perform **one** HTTPS GET for the registry.
231
+ - Nothing is uploaded. Benchmark results are written to local disk; sharing is a manual step.
232
+ - With no network, the CLI degrades in a defined order: fresh cache → stale cache → bundled seed,
233
+ and the active source is printed on every run.
234
+
235
+ ## Running FitLab inside an organization
236
+
237
+ **Internal registry mirror.** Fit verdicts and rankings are just data. To decouple from the public
238
+ repository — for change control, or to publish an approved-model list — host your own
239
+ `registry.json` and point clients at it:
240
+
241
+ ```bash
242
+ export FITLAB_REGISTRY_URL="https://models.internal.example.com/fitlab/registry.json"
243
+ fitlab check --gpu rtx4060ti-16
244
+ ```
245
+
246
+ **Pinned, reproducible data.** Because every registry carries `schema_version`, `ranking_version`
247
+ and `generated_at`, you can pin clients to a specific commit and get byte-identical results:
248
+
249
+ ```bash
250
+ export FITLAB_REGISTRY_URL="https://raw.githubusercontent.com/ruslanmv/fitlab/<commit-sha>/data/registry.json"
251
+ ```
252
+
253
+ **Air-gapped use.** Ship a registry file with your image and reference it directly; no egress is
254
+ required for fit checks:
255
+
256
+ ```bash
257
+ export FITLAB_REGISTRY_URL="file:///opt/fitlab/registry.json"
258
+ ```
259
+
260
+ **Custom hardware fleet.** Add your GPUs to [`data/hardware.yaml`](data/hardware.yaml) — including
261
+ capability flags such as `bf16`, `flash_attn2` and `marlin` — and regenerate the registry to get a
262
+ fit matrix for your own fleet rather than the public reference profiles.
263
+
264
+ **Extending the compatibility matrix.** Add a component to [`data/stack.yaml`](data/stack.yaml)
265
+ with a `probe` that exercises it end to end, and it will be verified on the same weekly cadence as
266
+ the rest of the stack.
267
+
268
+ ## Data contract
269
+
270
+ Everything downstream depends on `data/`, and only on `data/`. The site is a renderer; the CLI is a
271
+ client. Both read the same documents.
272
+
273
+ ```
274
+ data/
275
+ registry.json generated — the published source of truth (do not hand-edit)
276
+ models.seed.yaml human-curated seeds and editorial notes
277
+ hardware.yaml GPU profiles: VRAM, bandwidth, architecture capability flags
278
+ stack.yaml ecosystem components and version-discovery rules
279
+ benchmarks/ append-only measured results, one JSON per run
280
+ schema/
281
+ model.schema.json registry model entries
282
+ benchmark.schema.json benchmark result submissions
283
+ ```
284
+
285
+ `registry.json` top-level keys: `schema_version`, `generated_at`, `ranking_version`, `models`,
286
+ `categories`, `benchmarks_latest`, `compat`.
287
+
288
+ Stability guarantees:
289
+
290
+ - Every document carries `schema_version`, so historical data stays parseable indefinitely.
291
+ - `data/benchmarks/` is append-only; results are never rewritten or deleted.
292
+ - Models withdrawn from Hugging Face are marked `stale` and hidden after 60 days — never removed.
293
+ - Fit values are labeled `estimated` until a real benchmark upgrades them to `measured`.
294
+
295
+ ## How the numbers are produced
296
+
297
+ **FITS** is arithmetic, not opinion:
298
+
299
+ ```
300
+ est_vram = weights(params × bpw / 8 × 1.03)
301
+ + kv_cache(2 × layers × kv_heads × head_dim × context × 2 bytes)
302
+ + runtime_overhead
303
+ ```
304
+
305
+ Verdicts are thresholds against the profile's VRAM: `fits` at ≤ 92%, `tight` at ≤ 100%,
306
+ `offload` at ≤ 160% (partial GPU offload viable), otherwise `no`. Mixture-of-experts models are
307
+ sized by *total* parameters for memory and by *active* parameters for speed; the registry stores
308
+ both.
309
+
310
+ **RUNS** measures load time, time-to-first-token, generation tokens/second and peak VRAM through
311
+ Ollama's `/api/generate` timing fields — chosen because Ollama is what the target audience actually
312
+ runs. The weekly rotation is `week_number % queue_length`, so every model is measured and
313
+ periodically re-measured.
314
+
315
+ **Ranking** is a transparent, versioned scored sort (currently `ranking_version` 1.1):
316
+
317
+ ```
318
+ score = 0.35·fit + 0.25·hf_momentum + 0.25·speed + 0.15·plugs
319
+ ```
320
+
321
+ where `speed` uses a measured value when one exists and a bandwidth-model estimate discounted by
322
+ 0.5× otherwise. Changing the weights requires a version bump, making every rank shift visible in
323
+ the pull request diff.
324
+
325
+ ## Automation
326
+
327
+ | Workflow | Schedule | What it does |
328
+ |---|---|---|
329
+ | [`weekly-sync`](.github/workflows/weekly-sync.yml) | Wed 04:41 UTC | Refreshes the registry from Hugging Face, re-runs the FITS engine, validates against the schema, opens a review PR |
330
+ | [`weekly-benchmark`](.github/workflows/weekly-benchmark.yml) | Mon 03:17 UTC | Benchmarks the rotation model on a free T4 via the Kaggle Kernels API, with a CPU lane as fallback, and runs the PLUGS probes |
331
+ | [`community-submission`](.github/workflows/community-submission.yml) | On labeled issues | Extracts, schema-validates and sanity-bounds a submitted result, then merges it via PR with attribution |
332
+ | [`publish-pypi`](.github/workflows/publish-pypi.yml) | On release | Builds, smoke-tests and publishes the package using PyPI Trusted Publishing (OIDC, no long-lived token) |
333
+
334
+ Operational properties: workflows use `concurrency` groups to prevent overlapping writes, every
335
+ script is idempotent and safe to re-run, and degradation is graceful — if Hugging Face is
336
+ unreachable the sync PR is simply not opened and the last-good registry stands; if Kaggle is
337
+ unavailable the CPU lane still lands a datapoint.
338
+
339
+ ## Development
340
+
341
+ The repository is driven by a Makefile backed by [uv](https://docs.astral.sh/uv/). From a clean
342
+ clone, two commands give you a working environment and a running CLI — uv is bootstrapped
343
+ automatically if it is not already installed:
344
+
345
+ ```bash
346
+ git clone https://github.com/ruslanmv/fitlab && cd fitlab
347
+ make install # creates ./.venv and installs fitlab + all tooling
348
+ make run # launches the fit-check wizard
349
+ ```
350
+
351
+ `make run` depends on `make install`, so `make run` alone is enough on a fresh clone. Run
352
+ `make help` to list every target.
353
+
354
+ | Target | What it does |
355
+ |---|---|
356
+ | `make install` | Create `./.venv` and install the package plus the `dev` extra (`uv sync --extra dev`) |
357
+ | `make run` | Launch the interactive wizard |
358
+ | `make detect` / `make check` / `make bench` / `make update` | The corresponding `fitlab` subcommands |
359
+ | `make registry` | Rebuild `data/registry.json` from Hugging Face (FITS + sync) |
360
+ | `make estimate` | Full FITS verdict matrix across seed models × reference GPUs × quantizations |
361
+ | `make probe` | Run the PLUGS end-to-end stack probes |
362
+ | `make validate` | Schema-validate every document in `data/` |
363
+ | `make lint` / `make format` | Ruff check / safe auto-fix |
364
+ | `make smoke` | Exercise the CLI end to end without downloading a model |
365
+ | `make test` | `lint` + `validate` + `smoke` |
366
+ | `make build` | Build sdist and wheel into `dist/`, then `twine check` them |
367
+ | `make site` | Serve the static site on `http://127.0.0.1:8000` |
368
+ | `make clean` / `make distclean` | Remove artifacts / also remove `./.venv` |
369
+
370
+ Targets accept overrides on the command line:
371
+
372
+ ```bash
373
+ make check GPU=t4-16 CATEGORY=colab-free LIMIT=5
374
+ make bench MODEL=qwen3:14b REPS=5
375
+ ```
376
+
377
+ Available variables: `GPU`, `QUANT`, `CTX`, `CATEGORY`, `LIMIT`, `MODEL`, `REPS`, `OUT`.
378
+
379
+ In a checkout, the Makefile points `FITLAB_REGISTRY_URL` at the repository's own
380
+ `data/registry.json`, so every target reads the registry you are editing and works offline.
381
+ Override it to exercise a remote fetch:
382
+
383
+ ```bash
384
+ make run FITLAB_REGISTRY_URL=https://example.com/fitlab/registry.json
385
+ ```
386
+
387
+ Dependency groups live in `pyproject.toml`: the `maintainer` extra carries what the `scripts/`
388
+ engines need (`pyyaml`, `jsonschema`), and `dev` adds `ruff`, `build` and `twine` on top. `uv.lock`
389
+ is committed, so `make install` resolves to identical versions on every machine.
390
+
391
+ The engines can also be invoked directly, without make:
392
+
393
+ ```bash
394
+ # FITS — verdict for one model on one GPU
395
+ python scripts/estimate_vram.py --model Qwen/Qwen3-14B --gpu rtx3060-12 --quant Q4_K_M
396
+
397
+ # Registry refresh from Hugging Face (writes data/registry.json locally)
398
+ python scripts/sync_hf.py
399
+
400
+ # RUNS — benchmark on whatever hardware you are on (local, Colab, or Kaggle)
401
+ python scripts/bench_gguf.py --model qwen3:8b --out data/benchmarks/
402
+
403
+ # PLUGS — end-to-end stack probes (CPU is sufficient)
404
+ python scripts/compat_probe.py --report data/compat_report.json
405
+
406
+ # Schema validation
407
+ python scripts/validate_data.py
408
+ ```
409
+
410
+ `compat_probe.py` and `validate_data.py` both exit with the number of failures, so CI fails
411
+ honestly rather than reporting a green matrix built on skipped probes.
412
+
413
+ There is no unit-test suite yet; `make test` runs linting, schema validation and a CLI smoke test.
414
+
415
+ The published site is static and reads `data/*.json` directly; serve `site/` through GitHub Pages
416
+ or any static host.
417
+
418
+ ## Contributing
419
+
420
+ Benchmark results are the most valuable contribution and take about three minutes on free
421
+ infrastructure:
422
+
423
+ 1. Open [`colab/benchmark_colab.ipynb`](colab/benchmark_colab.ipynb) in Colab, select a T4 runtime,
424
+ and run all cells — or run `python scripts/bench_gguf.py --model <tag> --source community-local`
425
+ on your own machine.
426
+ 2. The final cell prints your result and a link that opens a prefilled GitHub issue.
427
+ 3. CI validates the JSON and merges it; your GPU and handle appear on the page.
428
+
429
+ Model suggestions belong in `data/models.seed.yaml` only — never in the generated `registry.json`.
430
+ Ranks are computed rather than negotiated: to change a rank, change the formula in
431
+ `scripts/sync_hf.py` and bump `ranking_version`. Full guidelines are in
432
+ [`CONTRIBUTING.md`](CONTRIBUTING.md).
433
+
434
+ ## Security
435
+
436
+ - **Community submissions are data, never code.** Submitted JSON is parsed and validated; it is
437
+ never executed.
438
+ - **Untrusted code paths are isolated.** The weekly stack probes install unpinned latest releases
439
+ and run inside ephemeral CI runners, optionally under
440
+ [MatrixLab](https://github.com/agent-matrix/matrixlab) Docker isolation for local maintainer runs
441
+ (see [`docker-compose.matrixlab.yml`](docker-compose.matrixlab.yml)).
442
+ - **Secrets never reach fork-triggered workflows.** `pull_request_target` is deliberately avoided.
443
+ - **Publishing uses OIDC.** PyPI Trusted Publishing means no long-lived API token exists to leak.
444
+
445
+ Please report suspected vulnerabilities privately through
446
+ [GitHub Security Advisories](https://github.com/ruslanmv/fitlab/security/advisories/new) rather
447
+ than in a public issue.
448
+
449
+ ## Support and versioning
450
+
451
+ This is a community open-source project maintained on a best-effort basis; no service level is
452
+ implied. Questions and bug reports belong in
453
+ [GitHub Issues](https://github.com/ruslanmv/fitlab/issues).
454
+
455
+ Three version numbers move independently, and only the first is a package concern:
456
+
457
+ - **Package version** (`fitlab`) follows semantic versioning.
458
+ - **`schema_version`** changes only for breaking data-format changes; consumers should pin it.
459
+ - **`ranking_version`** changes whenever scoring weights change, so ranking shifts are auditable.
460
+
461
+ Benchmark results are point-in-time measurements on specific hardware and driver versions. They are
462
+ a comparative signal, not a guarantee of what your machine will do.
463
+
464
+ ## Related projects
465
+
466
+ - [OllaBridge](https://github.com/ruslanmv/ollabridge) — one OpenAI-compatible URL for all your local models
467
+ - [HomePilot](https://github.com/ruslanmv/HomePilot) — local-first chat, image and video studio
468
+ - [GitPilot](https://github.com/ruslanmv/gitpilot) — Git workflow automation
469
+ - [MatrixLab](https://github.com/agent-matrix/matrixlab) — Docker isolation sandbox used for untrusted probes
470
+ - [Best-of-the-Best](https://github.com/ruslanmv/Best-of-the-Best) — the auto-curation pattern this repository generalizes
471
+
472
+ ## License
473
+
474
+ **Code** is licensed under [Apache-2.0](LICENSE). **Data** in `data/` and all published registries
475
+ are licensed under [CC-BY-4.0](https://creativecommons.org/licenses/by/4.0/).
476
+
477
+ Benchmark results are point-in-time measurements. Models referenced remain the property of their
478
+ respective authors and are subject to their own licenses.