Model or dataset
vllm-project/speculators avatar
vllm-project/speculators

speculators: the version is read from git tags, and two recent tags do not parse

A unified library for building, evaluating, and storing speculative decoding algorithms for LLM inference in vLLM

957 stars291 forksPythonApache-2.0

At a glance

What is it?
A library for training speculative decoding draft models that deploy into vLLM, with DFlash, DSpark, P-EAGLE and MTP training, a multi-node connector plugin and a build system that derives the version from git and the dependency list from a build script.
Who is it for?
speculators suits a team serving large models on vLLM that wants to train its own draft model rather than download one, and that has the hidden states and a verifier of a matching architecture to hand. It does not suit someone who needs a static dependency list, since the dependencies are assembled by a build script, or someone installing from a source archive, since the version comes from git tags.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • vllm-project/speculators957 ★ · +130
Star history
Repository2026-09-132026-11-14
vllm-project/speculators827957

130 Stars in the last 62 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

The version is parsed out of git tags by a three-part regex

There is no version string in this repository. The build backend is setuptools with `setuptools-git-versioning`, and setup.py asks git for the answer:

python
LAST_RELEASE_VERSION = Version("0.7.0")
TAG_VERSION_PATTERN = re.compile(r"^v(\d+\.\d+\.\d+)$")

`get_tags()` returns every tag, the regex keeps only those shaped like v1.2.3, and the survivors are sorted as versions. The last one becomes the base. Now look at the three most recent releases: v0.8.0, v0.7.0.1 and v0.6.0.1. The second and third carry four numeric components, and `\d+\.\d+\.\d+$` does not match them, so those two tags are discarded and the computed base is v0.8.0. The fallback when a checkout has no matching tags is the constant `LAST_RELEASE_VERSION`, which is 0.7.0, one minor behind the current release. So a clone of main with no tags reports 0.7.0, and a tagged clone reports 0.8.0 regardless of the patch-level tags that exist.

Four build types turn one tag into four different version strings

The function that follows the tag lookup is a switch on build type, and it is worth reading because it is the whole release policy. The docstring enumerates the four cases. For `release` it takes the last version and adds a post release segment if there is a build iteration. For `nightly` it increments to the next minor and appends an `a` with the build iteration. For `alpha` it does the same thing. For `dev` it increments to the next minor and appends `dev` with the build iteration. So nightly and alpha are described identically in the source, and a dev build reports a higher version than the release it is derived from. The commit count comes from `count_since(last_tag + "^{commit}")`, which means the number of commits since the tag is part of the version input, not just the tag itself. A branch with a hundred commits since v0.8.0 therefore produces a version that encodes how far it has drifted.

The dependency list is read back out of pyproject by setup.py

PEP 621 lets a project declare its dependencies statically. This one does not, and the manifest explains why in a comment block that is longer than most projects' dependency sections. The dependencies field is marked dynamic, and the base list lives in a custom table instead:

toml
[tool.speculators.dependencies]
base = [
    "aiohttp",
    "click",

The stated reason is that the `hs-connectors` package has to be resolved at build time by a function called `get_hs_connectors_requirement()` in setup.py, based on whether the build type is dev, nightly or release, and that because the whole field then has to be dynamic, setup.py reads the base list back out of the file and appends the computed requirement before calling `setup()`. Two things follow. A tool that reads dependencies from pyproject.toml, which is what most of them do, finds no dependency list at all. And the exact set you get depends on the build type, so a dev checkout and a published wheel legitimately install different things.

hs_connectors is a workspace member, a plugin and a build-time variable

One directory is doing three jobs at once. `hs_connectors/` appears in the root listing, it is declared as a uv workspace member, and it is wired in as a source:

toml
[tool.uv.workspace]
members = ["hs_connectors"]

[tool.uv.sources]
hs-connectors = { workspace = true }

Its job is the one described in the changelog as multi-node online training: transferring hidden states between vLLM and the trainer across nodes, with pluggable backends. Two backends ship. The file-based one uses a shared filesystem. The Mooncake one uses a distributed store, and it exists specifically for environments without shared storage. So the same training code runs two ways depending on whether your cluster has one filesystem or not, and the choice is a property of the deployment rather than of the algorithm. The package is also the reason the dependency field had to become dynamic in the first place, since which hs-connectors you get is decided by the build type rather than written down.

Sliding window attention is the default on every draft layer

DFlash and DSpark speculators use sliding window attention on all draft layers by default, and the two flags for changing that are the only ones named in the changelog entry. `--sliding-window` sets the window size. `--full-attention-indices` opts specific layers into full attention. The stated reason is that sliding window attention reduces KV cache allocation for long-context sequences and can improve per-position acceptance rates compared to full attention. That second half is the interesting one, since the usual argument for a sliding window is memory, and here it is also presented as an acceptance-rate argument. The consequence for a user is that the default is not neutral: unless you pass `--full-attention-indices`, every draft layer sees a window rather than the whole context, and the fix is a list of layer indices rather than a boolean.

DSpark is DFlash plus two heads, and it warm-starts from DFlash

The relationship between the two algorithms is stated precisely enough to be useful. DSpark extends DFlash's anchored-block drafting with two additions: a Markov head that conditions each draft position on the previous token within the block, and a confidence head that predicts per-position acceptance probability. DFlash itself is described as anchored-block drafting using auxiliary hidden states from multiple verifier layers, with CLI options for block size and max anchors, plus its own metrics, utilities and draft model. So the block structure and the hidden-state plumbing come from DFlash, and DSpark adds sequence modelling inside the block plus a prediction of whether the base model will accept. Checkpoints are compatible in one direction only: DSpark checkpoints can warm-start from existing DFlash checkpoints. Deployment of DFlash-trained models in vLLM arrived with a specific pull request, PR #38300, which is the date to check before assuming the format is accepted upstream.

P-EAGLE drafts several tokens at once and MTP heads are tiny

The other two training additions work by shrinking the drafting step. P-EAGLE extends EAGLE-3's architecture with parallel multi-token prediction using Conditional-On-Distribution sampling, so instead of generating draft tokens sequentially it predicts several in a single forward pass, which the changelog frames as reducing drafting latency. A speculator trained this way is published, a P-EAGLE speculator for Qwen3-8B, put out by the Red Hat team. The MTP path goes further and avoids the verifier entirely during training. It finetunes the native multi-token prediction heads of models such as Qwen3-Next on domain data, following the FastMTP approach, and because the MTP head is small at roughly 100 to 400 million parameters it can be trained on pre-extracted hidden states without loading the full verifier. That is the cheapest path in the list, and also the one that only works on models that ship those heads natively.

Two doc generators, two CI systems and four example directories

The root listing carries configuration for more tools than most projects this size. Documentation is configured twice, with `mkdocs.yml` and a `.readthedocs.yaml`, while the recorded homepage and every documentation link point at docs.vllm.ai instead of either of those. CI is configured twice as well, `.github/` and `.buildkite/`, and the README carries a Buildkite badge alongside GitHub ones, so both are live. Agent and review tooling has its own entries in `.claude/`, `AGENTS.md` and `.coderabbit.yaml`, and formatting and link checking are handled by `.mdformat.toml`, `.pre-commit-config.yaml` and a `.lycheeignore` that exists to exclude URLs from the link checker. The examples directory is split four ways, into `convert/`, `demo/`, `evaluate/` and `train/`, which maps onto the library's stated surface: converting external research checkpoints into the standard format, running a demo, evaluating a trained speculator, and training one.

Editorial conclusion

speculators suits a team serving large models on vLLM that wants to train its own draft model rather than download one, and that has the hidden states and a verifier of a matching architecture to hand. It does not suit someone who needs a static dependency list, since the dependencies are assembled by a build script, or someone installing from a source archive, since the version comes from git tags. Check four things before you start. Check that your verifier architecture is in the supported table, because the table separates training support from vLLM deployment support and they are not the same column. Check your git checkout has tags, because the version falls back to a hardcoded 0.7.0 when it does not and the newest release is 0.8.0. Check whether your storage is shared across nodes, because the file-based connector backend needs it and the Mooncake backend exists for when it is not. And check whether you want sliding window attention on every draft layer, because that is the default for DFlash and DSpark and you opt individual layers back in. The licence is Apache-2.0, the authors field names Red Hat, and the default branch was pushed on 2026-10-02.

Frequently asked questions

What is the speculators library used for?

It trains speculative decoding draft models that deploy directly into inference engines like vLLM. A small faster draft model proposes tokens and the larger base model verifies them in a single forward pass, reducing latency while every accepted token matches what the base model would have produced.

How does the speculators package decide its version?

From git tags, parsed by setup.py with the pattern v followed by three numeric components, using setuptools-git-versioning. Four build types produce four different shapes: release adds a post segment, nightly and alpha increment the minor with an a suffix, and dev increments the minor with a dev suffix.

Can speculators train across more than one node?

Yes, through the hs_connectors plugin package, which transfers hidden states between vLLM and the trainer across nodes with pluggable backends. The file-based backend uses a shared filesystem and the Mooncake backend uses a distributed store for environments without shared storage.

What is the difference between DFlash and DSpark in speculators?

DSpark extends DFlash's anchored-block drafting with a Markov head conditioning each draft position on the previous token in the block, plus a confidence head predicting per-position acceptance probability. DSpark checkpoints can warm-start from existing DFlash checkpoints.

Which models can be trained with speculators?

The supported table separates training support from vLLM deployment support. Llama 8B-Instruct and Llama 70B-Instruct are listed with EAGLE-3 training and deployment support, alongside Qwen3 entries. Training covers single and multi-layer draft models, MoE and non-MoE models, and vision language models.

Official sources

  1. License: Apache-2.0
  2. Project website
  3. README
  4. Releases
  5. vllm-project/speculators on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/vllm-project-speculators.svg)](https://hysenlabs.com/projects/vllm-project-speculators)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/vllm-project-speculators.svg)](https://hysenlabs.com/projects/vllm-project-speculators)

Was this useful?