Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
229 changes: 71 additions & 158 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# Local-Bench

**A [Companion Intelligence](https://ci.computer/) app for benchmarking local LLMs and comparing them by intelligence.**
A [Companion Intelligence](https://ci.computer/) app for benchmarking local LLMs and comparing them by intelligence.

Local-Bench measures the token-generation speed of models you run locally (via [Ollama](https://ollama.ai/) or AMD STRIX Halo / llama.cpp) and presents the results in a clean, local-first web dashboard. It also ships a curated Companion model catalog ranked by the **Artificial Analysis Intelligence Index**, so you can weigh capability against the throughput your hardware actually delivers.
Local-Bench measures how the language models on your own machine perform. It runs a prompt against one or more models served by [Ollama](https://ollama.ai/), records how fast each model generates text, and shows the results in a local web dashboard with tables, charts, and side by side response comparison. You can also run it from the command line and export a PDF report.

Everything runs locally. Your prompts and the model responses stay on your machine.

![Local-Bench dashboard](docs/screenshots/00-hero.png)

Expand All @@ -18,24 +20,31 @@ Local-Bench measures the token-generation speed of models you run locally (via [
| --- | --- |
| ![Run a benchmark](docs/screenshots/03-run-benchmark.png) | ![Detailed results](docs/screenshots/05-results.png) |

> Full-page view: [`docs/screenshots/01-overview.png`](docs/screenshots/01-overview.png)
Full page view: [`docs/screenshots/01-overview.png`](docs/screenshots/01-overview.png)

## What it does

## Features
- Benchmarks any model installed in Ollama and reports tokens per second, total tokens, and duration.
- Shows a curated catalog of popular models with sizes, context windows, and an intelligence score, so you can compare capability alongside speed.
- Lets you pick a built in prompt, edit it, or write your own before running.
- Shows two model responses at a time so you can read them next to each other.
- Captures your system specs (CPU, memory, OS, GPU) with every run.
- Exports a PDF report with the results table, your system summary, and the full model responses.
- Includes an optional path for benchmarking AMD Strix Halo GPUs with llama.cpp.

- 📊 Benchmark multiple local LLMs and measure **tokens per second** for each
- 🧠 **Model intelligence catalog** — curated Companion models ranked by the Artificial Analysis Intelligence Index, shown alongside size, context window, and modality
- 🧪 A broad prompt library (coding, reasoning, extraction, planning, summarization, translation, instruction-following) plus custom prompts
- 💾 Results stored in SQLite (`benchmark_data.db`) and CSV (`benchmark_results.csv`)
- 💻 Captures system specifications (CPU, memory, OS, GPU, STRIX Halo) with every run
- 🎮 **AMD STRIX Halo** GPU support for `llama.cpp` benchmarking
- 🪶 **Local-first** — Chart.js is vendored into the repo, so the dashboard renders fully offline (it gracefully falls back to CSS bar charts if scripting is unavailable)
- 🎨 Styled to match the **Companion Intelligence Hub design system** — **light & dark** colorways (follows your system theme, with a toggle), teal accents, Montserrat, and the official CI logo banner
## Why it is useful

## Prerequisites
1. Choose the right model for your hardware. See which models run fast enough on your machine before you build them into a workflow.
2. Balance speed against quality. Compare tokens per second against the intelligence score to find the best tradeoff for your needs.
3. Measure a hardware change. Benchmark before and after adding a GPU or more memory to see how much faster inference gets.
4. Compare two models on the same prompt. Read both answers side by side to judge which model responds better for your task.
5. Share findings. Export a PDF with the numbers, system specs, and responses to send to a teammate or attach to a writeup.

- [Node.js](https://nodejs.org/) (v18 or higher)
- **For Ollama benchmarks:** [Ollama](https://ollama.ai/) running locally with at least one model pulled
- **For AMD STRIX Halo benchmarks:** an AMD Ryzen AI Max "Strix Halo" APU — see [STRIX_HALO.md](STRIX_HALO.md)
## Requirements

- [Node.js](https://nodejs.org/) version 18 or higher.
- [Ollama](https://ollama.ai/) running locally with at least one model pulled.
- Optional: an AMD Ryzen AI Max "Strix Halo" machine for the llama.cpp GPU path. See [STRIX_HALO.md](STRIX_HALO.md).

## Quick start

Expand All @@ -44,207 +53,111 @@ git clone https://github.com/companionintelligence/Local-Bench.git
cd Local-Bench
npm install

# make sure Ollama is running (default http://localhost:11434)
# start Ollama if it is not already running (default http://localhost:11434)
ollama serve

# build + start the dashboard
# pull a model or two if you have not already
ollama pull llama3.2:3b
ollama pull qwen3:8b

# build and start the dashboard
npm start
# open http://localhost:3000
```

Don't have Ollama running yet? The dashboard still loads — it shows the curated catalog and intelligence scores, and degrades gracefully (see [First run / no Ollama](#first-run--no-ollama)).
If Ollama is not running yet, the dashboard still loads. It shows the curated catalog and intelligence scores and tells you to start Ollama when you want to run a benchmark.

## Using the web dashboard

```bash
npm start # http://localhost:3000
PORT=8080 npm start # custom port
```

## Usage
In the dashboard you can select installed models, choose and edit a prompt, run a benchmark, watch the charts and results update, compare two responses, and export a PDF.

### Run benchmarks from the CLI
## Running from the command line

```bash
# Benchmark the curated catalog
# benchmark the curated catalog
npm run benchmark

# Benchmark specific installed models
# benchmark specific installed models
node dist/benchmark.js llama3.2:3b qwen3:8b gemma3:4b

# Point at a non-default Ollama
# point at a non default Ollama
OLLAMA_API_URL=http://192.168.1.50:11434 npm run benchmark
```

### Run benchmarks from the web UI

```bash
npm start # http://localhost:3000
PORT=8080 npm start # custom port
```

The dashboard lets you pick installed models, choose a prompt (or write your own), run benchmarks, and watch results, charts, statistics, and system specs update live.

### AMD STRIX Halo
## AMD Strix Halo benchmarks

```bash
npm run strix-halo detect
npm run strix-halo setup llama-rocm-7.2
npm run strix-halo benchmark /path/to/model.gguf --toolbox llama-rocm-7.2
```

Full guide: [STRIX_HALO.md](STRIX_HALO.md).

## Model intelligence scores

Each curated model carries an **intelligence score** sourced from the
[Artificial Analysis Intelligence Index](https://artificialanalysis.ai/) — a
composite benchmark (MMLU-Pro, GPQA Diamond, LiveCodeBench, AIME, and more)
scored roughly 0–100 where higher is more capable. The dashboard surfaces it as
an `IQ` badge on each model and as a ranked "Model intelligence" list.
See [STRIX_HALO.md](STRIX_HALO.md) for the full guide.

A few notes on the data:
## Run it with Docker

- Scores are a **snapshot** (currently `2026-06`) and are version-sensitive — the index evolves as new evaluations and models are added.
- **Vision-only** (`-vl`) variants and very small models are not individually rated by the index and appear as **"Not rated" / `IQ —`**.
- The values are a best-effort public reference and are intended to be **easy to override** with Companion's own curated numbers. They live in a single place — the `intelligenceIndex` field of `SUPPORTED_OLLAMA_MODELS` in [`src/benchmark.ts`](src/benchmark.ts) — which both the CLI and UI read from. The attribution shown in the UI comes from `INTELLIGENCE_INDEX_SOURCE` / `INTELLIGENCE_INDEX_URL` / `INTELLIGENCE_INDEX_AS_OF` in the same file.

## Docker / Companion Intelligence Hub

Local-Bench is published as a public, multi-architecture (amd64 + arm64) container image and runs as a first-party app on the Companion Intelligence Hub.

**Image:** `ghcr.io/companionintelligence/ci-local-bench:latest`
Local-Bench is published as a multi architecture (amd64 and arm64) container image and runs as a first party app on the Companion Intelligence Hub.

```bash
docker run -d -p 3000:3000 ghcr.io/companionintelligence/ci-local-bench:latest
# open http://localhost:3000
```

Point it at an Ollama server with `OLLAMA_API_URL` (inside a container, `localhost` is the container itself):
Point it at your Ollama server with `OLLAMA_API_URL`. Inside a container, `localhost` is the container itself, so use the host address:

```bash
# Ollama on the Docker host
docker run -d -p 3000:3000 \
-e OLLAMA_API_URL=http://host.docker.internal:11434 \
ghcr.io/companionintelligence/ci-local-bench:latest

# Ollama on the LAN
docker run -d -p 3000:3000 \
-e OLLAMA_API_URL=http://192.168.1.50:11434 \
ghcr.io/companionintelligence/ci-local-bench:latest
```

Benchmark data (`benchmark_data.db` + `benchmark_results.csv`) is written to the working directory (`/app` in the container). Mount a volume there to persist results across restarts.
Benchmark data is written to the working directory (`/app` in the container). Mount a volume there to keep results across restarts.

### First run / no Ollama
## Where results are stored

The dashboard degrades gracefully when there's no data and no reachable Ollama:
- `benchmark_results.csv` is a flat record of every run.
- `benchmark_data.db` is a SQLite database with results and system specs.

- It loads and shows a friendly welcome instead of a red error banner.
- The **Model intelligence** catalog still renders (scores come from the bundled catalog, not Ollama).
- The model picker falls back to the curated catalog and notes that Ollama is unavailable; `GET /api/models` returns HTTP `503` with the catalog body.
- System specs, statistics, and the chart show neutral "run a benchmark" placeholders until results exist.
## Model intelligence scores

## API endpoints

| Endpoint | Description |
| --- | --- |
| `GET /api/models` | Curated catalog merged with installed Ollama models (incl. `intelligenceIndex`). `503` + catalog body if Ollama is unreachable. |
| `GET /api/prompts` | The benchmark prompt library |
| `GET /api/results` | All stored benchmark results |
| `GET /api/system-specs` | Latest captured system specifications |
| `GET /api/results-with-specs?limit=N` | Results joined with their system specs |
| `GET /api/meta` | Intelligence-score attribution (source, URL, snapshot date) |
| `POST /api/run-benchmark` | Run a benchmark `{ models: string[], promptId?, customPrompt? }` |

## Output (CSV)

```csv
Model,Tokens Per Second,Total Tokens,Duration (s),Timestamp,Status
gemma3:4b,78.42,412,5.25,2026-06-11T20:36:02.000Z,Success
qwen3:8b,52.31,498,9.52,2026-06-11T20:38:02.000Z,Success
```
Each curated model carries an intelligence score from the [Artificial Analysis Intelligence Index](https://artificialanalysis.ai/), a composite benchmark scored roughly 0 to 100 where higher is more capable. The dashboard shows it as an IQ badge on each model and as a ranked list. Scores are a snapshot and can change as the index evolves. Vision only and very small models are not individually rated and appear as "Not rated". The full catalog is browsable in the app and defined in [`src/benchmark.ts`](src/benchmark.ts).

## Configuration

Edit [`src/benchmark.ts`](src/benchmark.ts) to customize:

- `OLLAMA_API_URL` Ollama endpoint (env var, default `http://localhost:11434`)
- `TEST_PROMPTS`the benchmark prompt library
- `SUPPORTED_OLLAMA_MODELS`the curated catalog, including each model's `intelligenceIndex`
- `OLLAMA_API_URL`, the Ollama endpoint (also an environment variable, default `http://localhost:11434`).
- `TEST_PROMPTS`, the benchmark prompt library.
- `SUPPORTED_OLLAMA_MODELS`, the curated catalog and each model's intelligence score.

## Testing

```bash
npm test # Jest unit tests (server, benchmark, database, system specs, STRIX Halo)
npm test # Jest unit tests
npm run test:coverage
npm run build # typecheck + emit to dist/
npm run build # typecheck and emit to dist/
```

The repository is set up for automated testing:

- **Unit tests** cover the API, the catalog/intelligence data, CSV/DB writes, and system-spec collection.
- **Container smoke test** — [`tests/container/`](tests/container) is a self-contained Playwright harness that boots the published image and asserts the web UI renders, saving a screenshot artifact. It runs in the GHCR publish workflow.
- **Screenshots** in [`docs/screenshots/`](docs/screenshots) are captured against the running server (see that workflow / the Playwright harness) and embedded above.

## Troubleshooting

**Cannot connect to Ollama:** ensure `ollama serve` is running and reachable at `http://localhost:11434`, or set `OLLAMA_API_URL`.
- Cannot connect to Ollama: make sure `ollama serve` is running and reachable at `http://localhost:11434`, or set `OLLAMA_API_URL`.
- Model not found: list installed models with `ollama list`, then pull what you need with `ollama pull <model>`.
- A run takes too long: each model has a two minute timeout. Benchmark fewer or smaller models at a time.

**Model not found:** list installed models with `ollama list`, then `ollama pull <model-name>`.
## Links

**Benchmark takes too long:** larger models are slower; there's a 2-minute per-model timeout. Benchmark fewer/smaller models at once.

**Chart not showing:** the dashboard automatically falls back to CSS bar charts if the vendored Chart.js can't execute — no internet required.
- Documentation: https://docs.ci.computer/
- Discord community: https://discord.com/invite/yQp9hwpzAa

## Contributing

Contributions are welcome — please open a Pull Request.

## Supported Companion catalog

Curated models with their Artificial Analysis Intelligence Index score (snapshot `2026-06`; `—` = not individually rated).

<!-- The table below is generated from SUPPORTED_OLLAMA_MODELS in src/benchmark.ts -->

| Model | Size | Context | Inputs | Intelligence |
| --- | --- | --- | --- | --- |
| gemma3:270m | 292MB | 32K | Text | — |
| qwen3:0.6b | 523MB | 40K | Text | — |
| gemma3:1b | 815MB | 32K | Text | — |
| deepseek-r1:1.5b | 1.1GB | 128K | Text | — |
| llama3.2:1b | 1.3GB | 128K | Text | — |
| qwen3:1.7b | 1.4GB | 40K | Text | 3 |
| qwen3-vl:2b | 1.9GB | 256K | Text, Image | — |
| llama3.2:3b | 2.0GB | 128K | Text | 4 |
| qwen3:4b | 2.5GB | 256K | Text | 6 |
| gemma3:4b | 3.3GB | 128K | Text, Image | 4 |
| qwen3-vl:4b | 3.3GB | 256K | Text, Image | — |
| deepseek-r1:7b | 4.7GB | 128K | Text | 8 |
| llama3.1:8b | 4.9GB | 128K | Text | 8 |
| deepseek-r1:8b | 5.2GB | 128K | Text | 9 |
| qwen3:8b | 5.2GB | 40K | Text | 9 |
| qwen3-vl:8b | 6.1GB | 256K | Text, Image | — |
| gemma3:12b | 8.1GB | 128K | Text, Image | 7 |
| deepseek-r1:14b | 9.0GB | 128K | Text | 13 |
| qwen3:14b | 9.3GB | 40K | Text | 11 |
| gpt-oss:20b | 14GB | 128K | Text | 24 |
| gemma3:27b | 17GB | 128K | Text, Image | 10 |
| qwen3-coder:latest | 19GB | 256K | Text | 20 |
| qwen3-coder:30b | 19GB | 256K | Text | 20 |
| qwen3:30b | 19GB | 256K | Text | 15 |
| deepseek-r1:32b | 20GB | 128K | Text | 18 |
| qwen3:32b | 20GB | 40K | Text | 15 |
| qwen3-vl:30b | 20GB | 256K | Text, Image | — |
| qwen3-vl:32b | 21GB | 256K | Text, Image | — |
| deepseek-r1:70b | 43GB | 128K | Text | 20 |
| llama3.1:70b | 43GB | 128K | Text | 16 |
| gpt-oss:120b | 65GB | 128K | Text | 33 |
| llama4:16x17b | 67GB | 10M | Text, Image | 13 |
| GLM-4.6:TQ1_0 | 84GB | 198K | Text | 30 |
| qwen3:235b | 142GB | 256K | Text | 45 |
| qwen3-vl:235b | 143GB | 256K | Text, Image | — |
| GLM-4.6:Q4_K_M | 216GB | 198K | Text | 30 |
| llama3.1:405b | 243GB | 128K | Text | 17 |
| llama4:128x17b | 245GB | 1M | Text, Image | 18 |
| qwen3-coder:480b | 290GB | 256K | Text | 24 |
| deepseek-v3.1:671b | 404GB | 160K | Text | 28 |
| deepseek-r1:671b | 404GB | 160K | Text | 27 |
| minmax m2 | 968GB | 200K | Text | 44 |

---

> **Private & Confidential — Property of Lifescope Inc. Do not distribute.**
Contributions are welcome. Please open a Pull Request.

## Confidentiality

Private and Confidential. Property of Lifescope Inc. Do not distribute.
Loading
Loading