Skip to content

DecisionFormer v0.2: load, serve and publish decision models on any Hugging Face model - #1

Merged
akanyaani merged 12 commits into
mainfrom
dcv2
Oct 23, 2026
Merged

akanyaani merged 12 commits into
mainfrom
dcv2

Conversation

@akanyaani

Copy link
Copy Markdown
Contributor

DecisionFormer v0.2: train, load and serve decision models on any Hugging Face model, using the checkpoint layout shared with AutoJev and Decision 3.0.

What changes

  • Rename deciformer → decisionformer (package, CLI, docs).
  • Load and run: AutoDecisionModel.from_pretrained(...) loads our exports and other standard checkpoints (Decision 3.0 vllm-sr/d3*, AutoJev), and decide(state, questions) answers choice, noul and score questions in the System One format.
  • Serve: decisionformer serve exposes /v1/systemone (HTTP 422 for requests that don't fit, optional API key). --backend vllm runs Qwen3.5 code-readout checkpoints on vLLM; anything else fails with a clear UnsupportedBackend error.
  • Hub: exports are plain Hugging Face model repos (backbone, tokenizer, decision_config.json, readout.safetensors, model card). decisionformer push uploads them (private by default).
  • Decision Index: an in-process engine, and a server that speaks the Index's http engine protocol.
  • Data: System One requests with gold answers, plus flat one-question rows (e.g. FrontiersMind/deciformer-15k) read as they are. decisionformer data split holds out calibration/dev sets by whole families, keeping each task's share.
  • Precision: bf16 by default. train.mixed_precision, finetune.model_dtype, finetune.export_dtype and the QLoRA compute dtype are all configurable. GPUs without bf16 fall back to fp16. Exports keep the base checkpoint's dtype.
  • Model support: LoRA all-linear skips MoE routers; T5-family encoders reload correctly; seq2seq models without a text encoder (BART) are refused clearly. Non-causal code readouts now export the standard last-token layout.
  • Packaging: sentencepiece/protobuf added for DeBERTa-v3-style tokenizers. A release workflow publishes with PyPI trusted publishing: placeholder-v* tags publish the placeholder, v* tags the real package. CI now also builds the distribution.
  • README rewritten: installation, quick start (Python and API), supported backbones, then fine-tuning details.

Testing

  • 263 tests pass on CPU (12 skipped). This includes tests/test_zoo.py: 12 encoder and 33 decoder families (dense, mixture-of-experts, hybrid linear attention), each trained, exported, reloaded and checked against the Decision Index response rules.
  • GPU validation on one RTX 2060 SUPER (8 GB):
    • vllm-sr/d3-edge loaded with from_pretrained gives probabilities identical to the checkpoint's own runtime (bf16, one question per forward pass).
    • The vLLM backend matches the transformers backend within 7e-4 (median 30 ms per 3-question request).
    • MNLI: Qwen3-0.6B + LoRA reaches 0.828 (v0.1: 0.803). Qwen3.5-0.8B + QLoRA with bidirectional attention reaches 0.840.
    • A private Hub upload round trip reloads with identical answers.
  • PyPI: the decisionformer name is reserved with a 0.0.1 placeholder (no code).

Known issue

Qwen3.5-0.8B with causal attention stays at chance on MNLI. It fails the same way with LoRA, QLoRA and an fp32 base: a loss spike near step 25, then a collapse to the class prior. The same model with bidirectional attention learns, and step-0 readout logits equal the language model's own next-token logits exactly. So this looks like an optimization issue, not a wiring bug. A lower-learning-rate check is in progress. Other backbones are unaffected.

akanyaani and others added 12 commits October 23, 2026 16:30
Checkpoints
- Export the layout used by AutoJev, Decision 3.0 (vLLM), pplx-decider and others: backbone
  config.json + weights at the root, tokenizer, decision_config.json, 255-row readout.safetensors
  (format_id d3-code-readout-v1 with the d3 prompt); LoRA exports are merged by default
- AutoDecisionModel.from_pretrained loads any such checkpoint (local or Hub): deciformer exports,
  AutoJev exports such as Lumma-fev-27B, and Decision 3.0 checkpoints; decide() returns Jev-shaped
  answers (choice, noul, score) with per-type temperatures; save_pretrained / push_to_hub
- Prompt formats d3 (default, vLLM-servable) and autojev, byte-exact, with a format registry

Backbones and attention
- Load decoders with AutoModel so multimodal bases (Qwen3.5/3.8, Gemma 4) stay whole; read
  answer-code rows from tied embeddings or the checkpoint's lm_head
- bidirectional = noncausal_full_attention, now also on Qwen3.5/3.8 hybrids (full-attention
  layers open, Gated DeltaNet layers causal); attention flags confined to the text decoder
- Fix Gemma 4 bidirectional (use_bidirectional_attention takes "all", not True)

Data, training, serving
- System One request format (state + questions{} + gold/expected), single-question shorthand kept
- 255 answer codes by default; inference refuses over-long or over-wide inputs, never truncates
- /v1/systemone server and an in-process Decision Index engine, with the Index's refusal phrases
- CLI: eval, predict, serve, push; data check reads .jsonl.gz suites

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Rename the package, CLI and docs from deciformer to decisionformer.
- serve --backend vllm: vLLM computes the answer-code logits for Qwen3.5
  code-readout checkpoints; prompts, temperatures and answers stay
  decisionformer's, so both backends answer identically. Anything vLLM
  cannot load raises UnsupportedBackend with guidance.
- Decider.code_logits separates the forward pass from answer formatting.
- LoRA all-linear leaves MoE routers (Phi-MoE, Llama 4) out.
- T5-family encoders reload as text encoders; seq2seq models without a
  standalone encoder (BART) are refused with a clear error.
- test_zoo: 12 encoders and 32 decoders (dense, MoE, hybrid) trained,
  exported, reloaded and checked against the Decision Index response rules.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- README: load/decide, fine-tune, upload, serve (transformers and vLLM
  backends), Decision Index, tested model families, measured parity.
- Model cards omit base_model when it is a local path (the Hub rejects
  it); push fills the card's repo placeholders; the vLLM note appears
  only for Qwen3.5 code readouts. decision_config records model_type.
- configs/base.yaml: max_options 255 (was 26).
- A tokenizer with fewer single-token codes than max_options now trains
  with the codes it has and warns, instead of failing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…odel zoo

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The example response is real vllm-sr/d3-edge output (fp32), rounded.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…o recipe

- schema: flat rows as the deciformer pipeline writes them (question text
  plus question_type, options, option_descriptions, label, soft_target)
  are read as they are; labels and soft targets follow option names.
- decisionformer data split: train and held-out sets by whole families,
  each task's share kept in every split; the source is not modified.
- configs/recipes/deciformer15k_qwen35.yaml: Qwen3.5-0.8B LoRA code
  readout on FrontiersMind/deciformer-15k.
- The LoRA recipe exports merged weights, like the default.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Code-readout heads pool at the answer position in every attention
  mode, so non-causal decoders export the Decision 3.0 layout (last
  token, readout.safetensors) instead of decisionformer heads.
- Merged LoRA/QLoRA exports are saved in the base checkpoint's dtype
  (bf16 for Qwen3.5: 1.7 GB instead of 3.4 GB per export); the merge
  still runs in float32.
- sentencepiece and protobuf are dependencies: DeBERTa-v3 and ALBERT
  ship SentencePiece tokenizers that transformers converts with them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…encoders

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…holder

placeholder-v* tags publish packaging/pypi-placeholder (no code); v* tags
publish decisionformer after checking the tag matches the version.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…then the rest

- assets/decisionformer.svg: any Hugging Face model -> one forward pass ->
  calibrated answers, with the four commands of the workflow.
- Sections in order: installation (pip, GitHub), quick start (inference in
  Python, serving as an API), supported backbones (newest decoders first,
  then encoders), fine-tuning, evaluation and upload, results.
- docs/benchmarks.md: v0.2 checks (MNLI reruns, d3-edge parity, vLLM).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…port dtypes

- train.mixed_precision defaults to bf16 (was float32). GPUs without bf16
  fall back to fp16 with loss scaling and a warning; CPU runs use float32.
- finetune.quantization.compute_dtype: auto follows the training precision.
- finetune.export_dtype (auto = the base checkpoint's dtype) applies to
  full fine-tuning exports as well as merged LoRA/QLoRA exports.
- Full fine-tuning keeps float32 master weights under bf16 autocast by
  default; finetune.model_dtype: bfloat16 gives pure bf16.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@akanyaani
akanyaani merged commit b8ded2c into main Oct 23, 2026
1 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant