Vendor-neutral local-LLM-inference benchmark and hardware-config advisor for omlx and llama.cpp -- measures real tokens/second on your own hardware, live.
Project description
inferbench-cli (Python)
Vendor-neutral benchmark for local-LLM-inference engines -- measures real
tokens/second for omlx and llama.cpp on your own hardware, live, and
recommends the faster engine for your exact machine and model. This
package is the Python distribution -- a genuine, independent port of the
npm package's TypeScript source, not a wrapper around the Node binary.
Why this exists
Every local-inference engine publishes its own benchmark numbers, on its
own hardware, in its own README. None of them tell you which engine is
actually fastest on the machine sitting in front of you. InferBench starts
each engine's own OpenAI-compatible HTTP server on 127.0.0.1, runs a
fixed, varied 8-prompt set through the exact same measurement code against
every engine, and reports the real, measured tokens/second -- not a number
copied from a blog post.
Supported engines today: omlx and llama.cpp. That is the complete
list this v0.1 release supports -- see docs/concepts.md
for why each engine needed its own adapter and what each one's real
constraints are.
Install
pip install inferbench-cli
or with uv:
uv add inferbench-cli
Publish status, stated plainly: this package is built, tested, and
verified end to end (see "Verified" in
CHANGELOG.md),
but the first publish attempt was rejected by PyPI with 429 Too many new projects created -- a registry-side abuse throttle on this account, not a
problem with the package. Publish will be retried once that limit clears;
until then, pip install inferbench-cli will 404. Build it yourself from
source in the meantime: pip install git+https://github.com/RudrenduPaul/InferBench.git#subdirectory=python.
Zero third-party dependencies -- the CLI, the HTTP harness, and the
hardware detector are all built on the Python standard library
(argparse, urllib.request, subprocess, os). The complementary
JS/TS distribution installs the same way on the npm side:
npm install -g inferbench-cli (or npx inferbench-cli run ... to run it
once without installing) -- see the
project README for
that package. Both are meant to be first-class, maintained together.
Honest note on the npm package's current status: at the time of this
Python release, the npm package's own publish was blocked by a transient
npm-registry rate limit (E429), unrelated to code readiness -- the code
itself was already built and verified from a local tarball install. That
is a registry-side issue tracked separately from this PyPI release, which
is unaffected by it.
Either package still requires at least one supported engine already installed on your machine -- neither package installs an inference engine for you:
- llama.cpp:
brew install llama.cpp(macOS) or build from ggml-org/llama.cpp - omlx:
brew tap jundot/omlx https://github.com/jundot/omlx && brew install omlx(Apple Silicon only)
Quickstart
# llama.cpp -- pass a Hugging Face repo spec; llama.cpp downloads and
# caches it automatically, no manual step required
inferbench run --engines llama.cpp --model "bartowski/Qwen2.5-1.5B-Instruct-GGUF:Q4_K_M"
# omlx -- pass the model-directory subdirectory name under ~/.omlx/models/;
# omlx has no CLI download flow, so the model must already be present there
inferbench run --engines omlx --model "qwen2.5-1.5b-instruct-4bit"
# Both installed engines, machine-readable output, saved to a file
inferbench run --model "<spec>" --json --out report.json
Known v0.1 limitation, carried over from the npm package and equally
true here: --model means something different per engine (a
downloadable Hugging Face spec for llama.cpp, a pre-downloaded local
directory name for omlx), because the two engines have genuinely different
model-acquisition capabilities.
Or call the library directly (the agent-native path):
from inferbench import benchmark_engine, detect_hardware, all_engines, recommend
hardware = detect_hardware()
results = [
benchmark_engine(adapter, model="qwen2.5-1.5b-instruct-4bit")
for adapter in all_engines()
]
best = recommend(results)
if best:
print(f"{best.engine}: {best.reason}")
CLI command reference
inferbench run [options]
Options:
--model <spec> Model spec (engine-specific, see Quickstart above) [required]
--engines <list> Comma-separated engines to test (default: all installed --
omlx, llama.cpp)
--max-tokens <n> Max completion tokens per prompt (default: 200)
--json Output machine-readable JSON instead of a human table
--out <file> Also write the full JSON report to this file
--verbose Show raw engine server stdout/stderr
Exit code 0 on a successful run with at least one engine tested; 1 on
a resolvable usage error (e.g. an unknown --engines name) or when no
supported engine is installed. One documented divergence from the npm
CLI: a missing required flag (e.g. no --model at all) exits 2 here,
the standard argparse/Unix convention for a parse-time error, rather than
the npm CLI's 1 for the same case -- see
docs/concepts.md
for the full exit-code table.
How the measurement works
Same architecture as the npm package, ported faithfully: InferBench does
not shell out to each engine's own benchmark tool and parse its output --
omlx has no CLI benchmark command at all (verified against its real
README; its "Performance Benchmark" feature is a GUI-only, one-click
action in its admin dashboard). Instead, this package starts each engine's
own already-standardized OpenAI-compatible HTTP server (omlx serve,
llama-server) and sends the exact same prompts through the exact same
measurement code to every engine, timing the full response -- not just
time-to-first-byte. The original TypeScript harness had a real bug here
once (measuring right after fetch() resolved, which only captures HTTP
headers arriving, produced a physically impossible 64,646 tok/s during a
live end-to-end run before it was caught and fixed); this port measures
after the full response body is read, and a regression test
(tests/test_measure.py) asserts that gap is never reintroduced.
What "recommended" means (and doesn't)
The recommendation names the engine with the highest measured average tokens/second on this specific run, this specific hardware, this specific model -- not a general claim about which engine is best. A different model, a different machine, or different thermal conditions can change the answer.
Security
Neither this package nor the npm package ever eval()s, dynamically
imports, or shells through a string -- every subprocess call
(llama-server, omlx) is a fixed argv list (subprocess.Popen([command, *args], ...)), never a shell string, so a --model value cannot inject
additional shell commands. Honest note: this project does not
currently publish SLSA provenance, Sigstore signatures, or an SBOM, and
has no OpenSSF Scorecard badge set up -- none of that infrastructure
exists yet for either distribution, so it isn't claimed here. See
SECURITY.md
for the vulnerability-reporting process.
Contributing
See CONTRIBUTING.md.
cd python
python3 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pytest
License
Apache 2.0, see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file inferbench_cli-0.1.0.tar.gz.
File metadata
- Download URL: inferbench_cli-0.1.0.tar.gz
- Upload date:
- Size: 26.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c934a0b1695add1275367cb3a3ce156de90e39e502f8d6b30abccc08dbe8fabf
|
|
| MD5 |
5c17e3fb60fe3d86bb7332c6eeb259b1
|
|
| BLAKE2b-256 |
f1240b5fd31053804fb4c10fe073a155506ce5554f2765cd470153023d010b2e
|
Provenance
The following attestation bundles were made for inferbench_cli-0.1.0.tar.gz:
Publisher:
publish-pypi.yml on RudrenduPaul/InferBench
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
inferbench_cli-0.1.0.tar.gz -
Subject digest:
c934a0b1695add1275367cb3a3ce156de90e39e502f8d6b30abccc08dbe8fabf - Sigstore transparency entry: 2194928520
- Sigstore integration time:
-
Permalink:
RudrenduPaul/InferBench@a83832d1f1199e0a138c83c21b8325a038b8831e -
Branch / Tag:
refs/tags/python-v0.1.0 - Owner: https://github.com/RudrenduPaul
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@a83832d1f1199e0a138c83c21b8325a038b8831e -
Trigger Event:
release
-
Statement type:
File details
Details for the file inferbench_cli-0.1.0-py3-none-any.whl.
File metadata
- Download URL: inferbench_cli-0.1.0-py3-none-any.whl
- Upload date:
- Size: 28.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3914190bc7d9c3d56f3da9708503cd66958414ac8d110a4224c7f64a402a632b
|
|
| MD5 |
92a3720e0207a0a28b04f8fbf341f5f6
|
|
| BLAKE2b-256 |
5f6f586d8e8dd92843398ac74646aa351d599ffb016e7dcf1e174342a465154d
|
Provenance
The following attestation bundles were made for inferbench_cli-0.1.0-py3-none-any.whl:
Publisher:
publish-pypi.yml on RudrenduPaul/InferBench
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
inferbench_cli-0.1.0-py3-none-any.whl -
Subject digest:
3914190bc7d9c3d56f3da9708503cd66958414ac8d110a4224c7f64a402a632b - Sigstore transparency entry: 2194928534
- Sigstore integration time:
-
Permalink:
RudrenduPaul/InferBench@a83832d1f1199e0a138c83c21b8325a038b8831e -
Branch / Tag:
refs/tags/python-v0.1.0 - Owner: https://github.com/RudrenduPaul
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@a83832d1f1199e0a138c83c21b8325a038b8831e -
Trigger Event:
release
-
Statement type: