agentleFS
SystemPanicSystemPanic/vllm-windows/.agents/skills/transformers-upgrade/SKILL.md

transformers-upgrade

Skill683 starsChanged 19 days agoApache-2.0View on GitHub

Playbook for changing vLLM's Transformers version bounds. Use when bumping the pinned or maximum Transformers version, raising the minimum Transformers version, or deleting vendored configs, processors, or compat shims that upstream Transformers now provides.

2 other projects use a version of this; 2 new projects in the last 4 weeks, against 0 the 4 before.

Adopted by

Surging: 2 new projects took it in the last 4 weeks, none the 4 weeks before.thin data

Week of Sep 13: 0 new projectsWeek of Sep 20: 0 new projectsWeek of Sep 27: 0 new projectsWeek of Oct 4: 0 new projectsWeek of Oct 11: 1 new projectWeek of Oct 18: 0 new projectsWeek of Oct 25: 0 new projectsWeek of Nov 1: 1 new project
Sep 2026Oct 2026Nov 2026
New projects taking a version of this file each week, over the 8 weeks our latest run read: only 2 in all, so this is a hint, not a trend.

Most recently taken up by

The file

Show its rules and text

We split this skill into the rules it gives an agent

15 rules. About 0 are common, 8 are distinctive, and 7 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈8

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 7

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Every floor raise ends with an unvendoring pass.

    line 16
  2. Distinctive:

    Read the release notes for config validation changes, renamed auto-mapping formats, and removed attributes.

    line 23
  3. Very specific:

    Search tests/ for min_transformers_version and skip markers naming the new version, and run those tests on the new pin.

    line 25
  4. Very specific:

    Run the suites in Testing and fix what breaks.

    line 29
  5. Distinctive:

    Every hit is deleted by default.

    line 60
  6. Distinctive:

    Keep a vendored class only when upstream cannot load a checkpoint vLLM must keep serving, and record why in the PR description.

    line 69
  7. Distinctive:

    Run both dumps; each catches what the other misses:

    line 78
  8. Very specific:

    Add --trust-remote-code for checkpoints whose config.json has an auto_map, and dump both ways.

    line 96
  9. Very specific:

    Remove its entries from _CLASS_TO_MODULE and __all__ in vllm/transformers_utils/configs/__init__.py.

    line 115
  10. Very specific:

    Remove its entries from _CONFIG_REGISTRY in vllm/transformers_utils/config.py.

    line 117
  11. Very specific:

    Remove the source_file_dependencies lines naming the file from .buildkite/.

    line 120
  12. Distinctive:

    Before merging, rebase and grep again for the old field names: PRs that land in between still read them.

    line 126
  13. Distinctive:

    Code: only reachable below the floor is deleted.

    line 155
  14. Distinctive:

    Delete the patch when its fix is in the floor release.

    line 167
  15. Very specific:

    Add tests/models/test_initialization.py -k "<archs>" where a GPU is available, and a model eval for any model whose resolved config changed.

    line 184

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Upgrading Transformers

The supported range lives in requirements/common.txt. CI pins one exact version in requirements/test/*.in and the compiled requirements/test/*.txt. A version change is one of two jobs, and they usually come as a pair:

  • Bump the pin: a new Transformers release becomes the CI version and the upper bound. vLLM grows compat code for it.
  • Raise the floor: the minimum moves up. That compat code, and every vendored config or processor upstream now ships, becomes dead weight. Every floor raise ends with an unvendoring pass.

Bump the pin

  1. Edit the pin line in each requirements/test/*.in and *.txt and the upper bound in requirements/common.txt. Past bumps edit only the pin line in the compiled files; see git log -- requirements/common.txt.
  2. Read the release notes for config validation changes, renamed auto-mapping formats, and removed attributes; these are what break vLLM.
  3. Search tests/ for min_transformers_version and skip markers naming the new version, and run those tests on the new pin. Keep the gates: older versions in the supported range still lack the feature, so a gate goes only when the floor reaches it.
  4. Run the suites in Testing and fix what breaks. Mark every shim with a # Transformers >= X comment so the next floor raise finds it.

Done when the Testing suites and every test gated on this version pass on the new pin.

Raise the floor (unvendoring pass)

1. Inventory

Inventory candidates with the floor version installed (no vLLM install needed):

uv run --no-project --with transformers==<floor> \
    python .agents/skills/transformers-upgrade/scripts/find_upstreamed.py

It lists:

  • vendored configs whose model_type upstream now owns;
  • _CONFIG_REGISTRY overrides of upstream types;
  • registered processors that collide with upstream class names or models;
  • version-gated code at or below the floor;
  • code that reads the installed Transformers version, whatever its threshold;
  • patches citing a Transformers issue or PR (with whether a referenced PR is in the floor release) or a future minimum version.

It finds candidates by name only. Every hit still needs a verdict.

2. Port each candidate to upstream

Every hit is deleted by default. A vendored copy is a liability: it drifts from upstream, hides upstream fixes, and shadows the native class. Port the vLLM model code to the upstream schema instead, renaming attribute reads and deriving values from upstream fields.

Fan candidates out to parallel subagents. Each one compares the vendored and upstream classes, then greps every attribute the vLLM model code reads. Upstreaming hazards lists the usual fixes.

Keep a vendored class only when upstream cannot load a checkpoint vLLM must keep serving, and record why in the PR description. A different upstream schema, a model-code rewrite, or a needed eval is work for the PR, not a reason to keep.

3. Prove it on real checkpoints

For every checkpoint in tests/models/registry.py that uses a ported config, dump what vLLM builds before and after the change, then diff the two. Run both dumps; each catches what the other misses:

  • dump_configs.py: the resolved config, attribute by attribute.
  • dump_model.py: the model built on the meta device with no GPU or weights. It records ModelConfig sizes, every parameter shape, and every module's scalar attributes (head_dim, num_kv_heads, scaling, ...). Missing fields that are read with defaults only show up here.
git worktree add --detach <scratch>/vllm-base upstream/main
S=.agents/skills/transformers-upgrade/scripts
for dump in dump_configs dump_model; do
    PYTHONPATH=<scratch>/vllm-base .venv/bin/python $S/$dump.py before.jsonl <repos>
    PYTHONPATH=$PWD .venv/bin/python $S/$dump.py after.jsonl <repos>
    .venv/bin/python $S/diff_dumps.py before.jsonl after.jsonl
done

Add --trust-remote-code for checkpoints whose config.json has an auto_map, and dump both ways.

How to read the diffs:

  • A <MISSING> config field the model reads: this crashes or silently falls back to a default. Port the model code to the upstream field.
  • New upstream-only defaults (attention_bias=False, pad_token_id=None): usually benign. A model diff of 0 confirms it.
  • Any model diff: this is a numerics change, and the PR needs a model eval. For example, A.X-K1 gained the checkpoint's YaRN rope scaling, which the vendored class had been dropping; it shows up as layers.*.self_attn.scaling (x61).

4. Delete

For each deleted config:

  • Delete the file.
  • Remove its entries from _CLASS_TO_MODULE and __all__ in vllm/transformers_utils/configs/__init__.py.
  • Remove its entries from _CONFIG_REGISTRY in vllm/transformers_utils/config.py.
  • Switch every importer, including tests, to from transformers import ....
  • Remove the source_file_dependencies lines naming the file from .buildkite/.

Deleted processors follow the same steps in vllm/transformers_utils/processors/__init__.py.

Before merging, rebase and grep again for the old field names: PRs that land in between still read them.

Done when every line of the inventory output is deleted, or kept with a reason that meets the bar in step 2. The PR also carries the config diff results and evals for any changed values.

Upstreaming hazards

Upstream configs are @strict dataclasses. Checkpoint keys upstream does not declare survive as plain attributes, but only when the checkpoint sets them. Defaults that only vLLM sets, and values vLLM derives, vanish.

HazardSignalFix
Upstream consumes legacy keys__post_init__ pops keys the model reads (deepseek_v4 compress_ratios)Read the upstream replacement (layer_types, mlp_layer_types, per-layer rope_parameters)
Renamed or dropped fieldsDiff shows <MISSING> for a field the model readsRead the upstream name; derive dropped flags from what implies them (enable_moe_block from num_experts)
Undeclared field without a defaultconfig.x raises AttributeError for configs that omit x, e.g. minimal test configs (A.X-K1 scoring_func). Dumps of real checkpoints miss itUpstream ignoring x usually means vLLM can stop reading it; if vLLM truly needs it, read getattr(config, "x", <old default>)
Top-level config stops forwardingThe vendored top-level config forwarded reads to text_config; upstream does not. getattr(config, "x", default) silently takes the default, e.g. on MTP draft configs from SpeculativeConfig.hf_config_override, which the dumps do not buildRead from get_text_config(); grep getattr reads of every field, including speculative-decoding paths
Type check on the configctx.get_hf_config(SomeConfig) relies on the vendored base classAccept the upstream class too, e.g. a Cosmos3ProcessingInfo overriding get_hf_config
Remote code takes overCheckpoint config.json has auto_map; with --trust-remote-code, the hub class replaces the native one once vLLM stops registering its ownCheck the remote class loads; if not, register the upstream class for that model_type
Read-only upstream fieldsProperties or derived fields break subclasses and hf_overrides (nemotron_h hybrid_override_pattern)Override the source field (layers_block_type) instead
Behavioural rewriteUpstream derives fields differently (diffusion_gemma sliding_window)Upstream matches the reference implementation; verify with an eval
Original checkpoint formatUpstream targets -hf conversions; vLLM serves the originals (qwen3_asr, qianfan_ocr)Keep only if upstream cannot load the original at all
Processor output contractModel code consumes keys upstream does not emitPort the model to upstream's keys
Name collisionA registered vendored processor shares an upstream class name and hijacks get_processor (InternVLProcessor)Drop the registry entry

Version gates from the inventory need a decision:

  • Code only reachable below the floor is deleted. This covers:

    • comparisons against TRANSFORMERS_VERSION;
    • branches labelled # Transformers < X;
    • fallbacks for fields that upstream configs now always set, e.g. mlp_layer_types, per_layer_config or legacy layer_types names.

    A skipif whose condition is now always true becomes an unconditional skip with the same reason.

  • min_transformers_version at or below the floor is removed.
  • max_transformers_version below the floor means CI never tests that model; report it rather than deleting it silently.
  • Patches citing a Transformers issue or PR:
    • Delete the patch when its fix is in the floor release.
    • For an issue, find the PR that closed it and check that PR. A closed issue is not a fixed one: issues get closed while the bug is still in the release.
    • Re-run the patched behaviour before deleting. A fix in the release does not always cover vLLM's path: Emu3's processor gained BOS upstream, but vLLM tokenizes without the processor.
    • Links that only explain a design choice (e.g. a float32 RoPE note) are not patches; leave them.

Testing

.venv/bin/python -m pytest tests/transformers_utils tests/config tests/tokenizers_
.venv/bin/python -m pytest tests/models/multimodal/processing/test_common.py -k "<models>"

Add tests/models/test_initialization.py -k "<archs>" where a GPU is available, and a model eval for any model whose resolved config changed.

Models in vllm/models/ are high priority: whenever their config or model code changes, run GSM8k (tests/evals/gsm8k/) and GPQA Diamond (tests/evals/gpt_oss/) on main and the branch, even when the dumps show no diff, and put both scores in the PR. FlashInfer autotuning picks kernel tactics afresh on every server start, which moved DeepSeek-V4-Flash GSM8k by about 1 point; pass --kernel-config '{"enable_flashinfer_autotune": false}' to both servers so greedy outputs are comparable.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.