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
8 changes: 6 additions & 2 deletions .github/workflows/container.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ name: Container
# a prerelease is not tagged :latest.
# - Actions -> Container -> Run workflow builds and pushes any released version.
# - A pull request that changes the Dockerfile or this workflow builds and
# smoke-tests the current pyproject version, and never pushes.
# smoke-tests the newest version already on PyPI (a version-bump PR's own
# version is not released yet), and never pushes.
#
# The image's org.opencontainers.image.source label links the package to this
# repository. Only GITHUB_TOKEN is used (no PAT, no stored secret). Every action
Expand Down Expand Up @@ -73,7 +74,10 @@ jobs:
latest="$INPUT_LATEST"
push=true ;;
*)
version=$(python3 -c "import tomllib; print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")
# Test the Dockerfile and workflow against the newest release on PyPI;
# the PR's own pyproject version may not be published yet.
version=$(curl --silent --fail https://pypi.org/pypi/flashspec/json \
| python3 -c "import json, sys; print(json.load(sys.stdin)['info']['version'])")
latest=false
push=false ;;
esac
Expand Down
27 changes: 27 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,33 @@ Versioning follows [Semantic Versioning 2.0.0](https://semver.org/).

## [Unreleased]

## [0.3.1] — 2026-10-26 — Optional selector, simpler quickstart, container image

Development status stays Alpha. No measurement in this release: 0.3.1 does
not change the decoding path (an omitted selector is the same one-arm UCB1
that one-drafter users already passed), so the README tables remain the
0.3.0 release run (bundle `3c43e08`).

### Highlights
- `SpeculativeEngine(config, [drafter], target)`: with one arm, the bandit
selector argument is optional. The README quickstart no longer needs
`BanditConfig` or a selector, and it prints which drafter strategy ran.
- A GPU-oriented server image on GitHub Container Registry,
`ghcr.io/mattral/flashspec:<version>`, built from the PyPI release and
smoke-tested on every publish (first published for 0.3.0).
- Engineering notes in the docs (`docs/lessons.md`), with figures drawn from
the result JSONs by `scripts/article/`.

### Upgrade notes
- Nothing to change: every 0.3.0 call works as before. Passing a selector
with one arm is still allowed; omitting it with several arms raises a
`ValueError` that says which selector to pass.

### Known issues
- Unchanged from 0.3.0 (first call compiles; fp16 greedy exact ties; batch
> 1 and other GPUs or model pairs not measured; bandit experimental; the
CUDA-graph "distinct sizes" warning).

### Added
- `SpeculativeEngine`'s `bandit` argument is optional (default `None`). When the resolved strategy has one arm (the default
`drafter_strategy="auto"` with one model drafter, an explicit `"bandit"` strategy with one drafter, or a single explicit
Expand Down
2 changes: 1 addition & 1 deletion CITATION.cff
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ abstract: >-
UCB1/Thompson draft selector is experimental: measured once over seven
arms, it did not beat the best fixed arm. The Triton and assembly
kernels are experimental and not on the generation critical path.
version: 0.3.0
version: 0.3.1
date-released: "2026-10-26"
license: Apache-2.0
repository-code: "https://github.com/Mattral/FlashSpec"
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ You need Python 3.11 or later, PyTorch 2.2 or later and transformers 4.40 or lat
**Container image (GPU-oriented).** Each release is also published as a server image on GitHub Container Registry. It is built from the PyPI release on CUDA 13.0, with the torch build the GPU results were measured with, and it runs as a non-root user. It needs an NVIDIA GPU and the NVIDIA Container Toolkit; it starts on CPU too, but CPU is not where FlashSpec is faster. The default command serves the measured pair in fp16 on port 8000.

```bash
docker pull ghcr.io/mattral/flashspec:0.3.0
docker run --gpus all -p 8000:8000 ghcr.io/mattral/flashspec:0.3.0
docker pull ghcr.io/mattral/flashspec:0.3.1
docker run --gpus all -p 8000:8000 ghcr.io/mattral/flashspec:0.3.1
```

## Quickstart
Expand Down Expand Up @@ -153,7 +153,7 @@ python -m flashspec.serve --target Qwen/Qwen2.5-1.5B-Instruct --drafter Qwen/Qwe
Or with the container image. Arguments replace its default command, so pass `--host 0.0.0.0`. The volume keeps downloaded checkpoints between runs:

```bash
docker run --gpus all -p 8000:8000 -v flashspec-hf:/home/flashspec/.cache/huggingface ghcr.io/mattral/flashspec:0.3.0 \
docker run --gpus all -p 8000:8000 -v flashspec-hf:/home/flashspec/.cache/huggingface ghcr.io/mattral/flashspec:0.3.1 \
--target Qwen/Qwen2.5-1.5B-Instruct --drafter Qwen/Qwen2.5-0.5B-Instruct \
--device cuda:0 --dtype float16 --temperature 0 --host 0.0.0.0
```
Expand Down Expand Up @@ -328,7 +328,7 @@ With `compile` on, both models run on static KV caches and the fixed-shape decod

## Status and limitations

FlashSpec is alpha, version 0.3.0.
FlashSpec is alpha, version 0.3.1.

- **Measured scope.** One model pair (`Qwen/Qwen2.5-1.5B-Instruct` verified by `Qwen/Qwen2.5-0.5B-Instruct`), one Tesla T4, fp16, batch 1, 10 MT-Bench and 10 HumanEval prompts, run from `main` at git `3c43e08` with the defaults `compile="auto"` and `drafter_strategy="auto"` (which ran `composite-g6-f2`). No other GPU, model pair or batch size has been measured. Every H100 number in the docs is a design target.
- **The first call compiles.** On CUDA the first `generate` compiles the forwards and captures CUDA graphs, which can take minutes; later calls reuse them. The tables exclude that call.
Expand Down
2 changes: 1 addition & 1 deletion deploy/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# FlashSpec server image: the released PyPI package on a CUDA 13.0 base.
#
# docker build -f deploy/Dockerfile --build-arg FLASHSPEC_VERSION=0.3.0 -t flashspec deploy/
# docker build -f deploy/Dockerfile --build-arg FLASHSPEC_VERSION=0.3.1 -t flashspec deploy/
# docker run --gpus all -p 8000:8000 flashspec
#
# GPU-oriented: torch is the CUDA 13.0 build FlashSpec's GPU results were
Expand Down
2 changes: 1 addition & 1 deletion deploy/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

services:
flashspec:
image: ghcr.io/mattral/flashspec:0.3.0
image: ghcr.io/mattral/flashspec:0.3.1
ports:
- "8000:8000"
volumes:
Expand Down
4 changes: 2 additions & 2 deletions deploy/k8s/flashspec-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ metadata:
name: flashspec
labels:
app: flashspec
version: "0.3.0"
version: "0.3.1"
spec:
replicas: 1
selector:
Expand All @@ -19,7 +19,7 @@ spec:
- name: flashspec
# GPU-oriented image; the default command serves Qwen2.5-1.5B-Instruct
# verified by Qwen2.5-0.5B-Instruct in fp16 on port 8000.
image: ghcr.io/mattral/flashspec:0.3.0
image: ghcr.io/mattral/flashspec:0.3.1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8000
Expand Down
6 changes: 3 additions & 3 deletions docs/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ git clone https://github.com/Mattral/FlashSpec && cd FlashSpec
pip install -e ".[dev,gpu]" # omit ",gpu" on Windows/macOS

# Container image (Linux + NVIDIA GPU), published for each release:
docker pull ghcr.io/mattral/flashspec:0.3.0
docker run --gpus all -p 8000:8000 ghcr.io/mattral/flashspec:0.3.0
docker pull ghcr.io/mattral/flashspec:0.3.1
docker run --gpus all -p 8000:8000 ghcr.io/mattral/flashspec:0.3.1
```

**The container image** (`ghcr.io/mattral/flashspec:<version>` and `:latest`) is
Expand All @@ -48,7 +48,7 @@ built by `.github/workflows/container.yml` when a release is published:
To build it yourself from a released version:

```bash
docker build -f deploy/Dockerfile --build-arg FLASHSPEC_VERSION=0.3.0 -t flashspec deploy/
docker build -f deploy/Dockerfile --build-arg FLASHSPEC_VERSION=0.3.1 -t flashspec deploy/
```

A development checkout, by platform:
Expand Down
2 changes: 1 addition & 1 deletion flashspec/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,5 @@
"register",
]

__version__ = "0.3.0"
__version__ = "0.3.1"
__author__ = "Min Htet Myet (Mattral)"
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "hatchling.build"

[project]
name = "flashspec"
version = "0.3.0"
version = "0.3.1"
description = "Lossless speculative decoding for HuggingFace causal LMs, with a static-cache CUDA-graph fast path; bandit draft selection and Triton kernels are experimental"
readme = {file = "README.md", content-type = "text/markdown"}
license = { file = "LICENSE" }
Expand Down
Loading