Repository navigation
Conversation
2 of 3 tasks
|
The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update. |
imargulis
force-pushed
the
dflash2-pa
branch
5 times, most recently
from
November 4, 2026 17:47
fda6460 to
94ab113
Compare
imargulis
added a commit
to imargulis/openvino.genai
that referenced
this pull request
Nov 4, 2026
The DFlash CI job installs optimum-intel from huggingface/optimum-intel#2098, which adds the DFlash v2 and DSpark exports to openvinotoolkit#2096, and also runs test_dflash_markov_head_cb.py, which skips its module without them. openvinotoolkit#2098 exports Qwen3.5 with transformers 5.15 or later, so the job moves from 5.2.0 to 5.15.1. test_vlm_dspark_matches_main_only pairs optimum-intel-internal-testing/tiny-random-minicpmv47 with its tiny DSpark draft optimum-intel-internal-testing/tiny-random-minicpmv47-dspark: greedy speculative decoding with the Markov head's candidate scorer and with its dense step (markov_head_top_k=0) gives the target's text. It runs in a new job with transformers 5.18, which the target needs. Co-authored-by: Cursor <cursoragent@cursor.com>
This was referenced Nov 5, 2026
DynamicCache(config=...) gives sliding-window layers a sliding cache layer, which keeps only the last window of keys. The draft applies the window through its attention mask instead, so the second cached step built a mask over more keys than the cache held. A plain DynamicCache keeps every key, as the exported graph does. Co-authored-by: Cursor <cursoragent@cursor.com>
…v head DFlash-2 drafts now use the per-row DFlash backbone that SDPAToPagedAttention converts: every row comes out, and the runtime rolls the block rows of the KV cache back through past_lens. The grouped dynamic convolution shifts its taps along the flattened rows and masks them to the block of the row they produce, so the taps hold on the token axis after the PagedAttention conversion too. The DFlash-2 candidate selector is exported as the Markov head of the draft, openvino_markov_head_model.xml with dflash/interface=markov_head_v1 and markov_head_type=dflash2, instead of a separate selector model. It is the packed Top-K lattice of the DSpark Markov head, with transitions gated by the draft hidden states and no dense step. The backbone advertises it through markov_rank and markov_head_type, as a DSpark draft does. DSpark drafts are DFlash v1 drafts to the exporter: the same validation, backbone and RT info, with the candidate offset and the Markov head taken from their config. The tests use optimum-intel-internal-testing/tiny-random-qwen3-dflash2, a two-layer DFlash-2 draft for tiny-random-qwen3 with the tensor layout of the published checkpoints. Co-authored-by: Ofir Zafrir <ofir.zafrir@intel.com> Co-authored-by: Cursor <cursoragent@cursor.com>
main_export read architectures[0] three times, each with its own empty-list guard: to validate DFlash configs and pick the Eagle3 loader, to load native DFlash drafts, and to drop the tokenizer of DFlash drafts. It now derives the architecture once, with config_architecture() from dflash_utils, which the export config, the dummy input generator and the draft model also use instead of their own copies of the same expression. No behavior change: the architecture stays None outside the transformers library and for configs without architectures, and the Eagle3 config update does not touch architectures. Co-authored-by: Cursor <cursoragent@cursor.com>
…t dynamic Item assignment (x[block_rows] = value) strips the leading unit dimension of a one-row value with a view. When the random dummy token_type_ids hold a single block row, the trace freezes that view's shape, and the exported draft fails on any other block length. The query, attention input and output row writes of the Qwen3 and MuseGlimmer drafts now call index_put_ directly. The PagedAttention tests trace the Qwen3 variants with a single block row, so they cover this case regardless of the dummy seed. Co-authored-by: Cursor <cursoragent@cursor.com>
… all layers Since huggingface#1983, the exporter infers text-generation-with-past for the natively loaded draft architectures and compresses DFlash draft IRs to INT4 on all layers, but task inference on a local draft checkpoint still raised RuntimeError. infer_task now falls back to the config architectures for it, as for Eagle-3 drafts, so the CLI needs no --task there either. The DFlash and DSpark CLI tests run without --trust-remote-code. The Markov head package test also omits --task, and checks that no int8 weights remain in the INT4 drafts. Co-authored-by: Cursor <cursoragent@cursor.com>
The PyTorch reference of the PagedAttention tests passed its own DynamicCache, so no test reached the cache the draft builds when it gets none (db5a55c). The reference now takes the draft's cache. With the sliding layers of these tests, a cache built from the config drops past keys and fails both variants. Co-authored-by: Cursor <cursoragent@cursor.com>
The draft export config computes the Markov head spec once and hands it to the Markov head model config and to the RT-info writer, which used to rebuild it from the HF config. The Markov head config takes its gating from the spec's head type. The default Top-K helper, used once, is inlined. Co-authored-by: Cursor <cursoragent@cursor.com>
…Top-K MarkovHeadOpenVINOConfig.markov_head_top_k repeated the K of its Markov head spec and served only to tell convert.py that the graph is a Markov head. A class flag, markov_head_model, now does that, and the dflash/top_k RT info reads the spec, the same one that sizes the exported TopK. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
MarkovHeadOpenVINOConfig.inputs spelled out the three inputs that both heads take twice. It now adds draft_hidden_states for the gated head or prev_token_ids for the DSpark head to the shared ones. The IR keeps its input order, which the export takes from the head's forward signature; the DSpark head test now checks that order, as the gated head test already did. Co-authored-by: Cursor <cursoragent@cursor.com>
…ly compute Since 5be7015 the convolution runs on the packed block rows, so a masked tap reaches another sequence's block (or the zero padding), not a context row. Co-authored-by: Cursor <cursoragent@cursor.com>
- The anchor-layout test is what is left of the one that checked the backbone dropping the anchor row: the offset is checked by the config test and the row count by the PagedAttention tests. - The DFlash-2 target annotation test exported one more Qwen3 target; the decoder locator test now checks one locator per decoder layer. - The two DSpark Markov head export tests export the draft once; the full-model parity loop is covered by the split computations and the bf16 test. - The single-sequence PagedAttention test is folded into the multi-sequence one, which repeats its steps. Co-authored-by: Cursor <cursoragent@cursor.com>
The Markov head model carried dflash/interface=markov_head_v1 to version its contract with runtimes. markov_head_type already names the head, and runtimes find the computations and read their results by port name and check every port, so the tag could only catch a port whose meaning changes without a new name. Such a port gets a new name instead. Co-authored-by: Cursor <cursoragent@cursor.com>
main exports Muse-Glimmer assistants with a DFlash export config, but their config is not a DFlash, DSpark or DFlash-2 one, so the strict parser rejected them. They get the rt_info keys their config has, as on main. Co-authored-by: Cursor <cursoragent@cursor.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
Extends the PagedAttention export of DFlash drafts to the rest of the DFlash family, so that every DFlash-family draft runs in OpenVINO GenAI continuous batching from one exported IR: DFlash, DFlash v2, and DeepSpec DSpark drafts with or without a Markov head, including the MiniCPM-V 4.7 DSpark drafts.
Changes to the export:
DFlash2DraftModel, e.g.incoai/Qwen3.8-27B-DFlash2):openvino_markov_head_model.xmlwithmarkov_head_type=dflash2. It is the packed Top-K lattice of the DSpark Markov head, with transitions gated by the draft hidden states and no dense step. Like the DSpark Markov head, it is never weight-compressed and keeps the checkpoint precision unless--weight-format fp16/fp32is given.dflash/version=2anddflash/gpu_min_activations_scale_factor=32instead of the decoder defaultACTIVATIONS_SCALE_FACTOR=8. OpenVINO GenAI compiles the draft on GPU with at least that scale factor.dflash/interfacetag:markov_head_typenames the head, and runtimes find its computations and read their results by port name.index_put_instead of item assignment. Item assignment strips the leading unit dimension of a one-row value, so when the dummytoken_type_idshold a single block row, the trace freezes that shape and the exported draft fails on any other block length.DynamicCache(config=...)kept only the last window of keys, so the second cached step built its mask over more keys than the cache held.--taskis no longer needed.Runtime support: openvinotoolkit/openvino.genai#4847. On GPU, the paged draft needs PagedAttention with
token_type_idsin the mixed stage and the Markov head needs the radix TopK, both in the OpenVINO nightly from 2026.5.0.dev20261028.How to test
Environment (Python 3.11+). Until openvinotoolkit/openvino.genai#4847 is merged, OpenVINO GenAI is built from its branch, which needs CMake 3.26+ and a C++ compiler:
Export a DSpark draft and its target. Drafts need neither
--tasknor--trust-remote-code:Run with OpenVINO GenAI:
The other drafts export the same way:
The Qwen3.6, Qwen3.8 and MiniCPM-V 4.7 targets are multimodal and have linear attention: they run with
VLMPipeline.Validation
Intel Core Ultra X7 358H, Arc B390 GPU.
HumanEval, greedy; the 27B and 35B targets 5 prompts x 256 new tokens, the others 20 prompts x 2048.
num_assistant_tokensTests
The DFlash v2 tests use a new tiny draft, optimum-intel-internal-testing/tiny-random-qwen3-dflash2, a draft for
tiny-random-qwen3laid out like the published DFlash v2 checkpoints:block_sizein a nesteddflash_config, grouped-query attention with one KV head, a sliding and a full-attention layer, random base kernels that reach the previous rows, and non-defaultoutput_multiplier,final_logit_softcappingandinput_embedding_scale. They cover the checkpoint keys, config normalization and validation, the grouped dynamic convolution against a reference implementation, and the exported package: the rt_info of both IRs and the Markov head's Top-K lattice on packed blocks against a reference formula, also from a bf16 checkpoint.For DFlash and DFlash v2, the draft IR converted to PagedAttention matches the PyTorch draft over several steps of sequences packed into one call, and each input is read only in its own rows. A draft without a Markov head (DFlash, DeepSpec DFlash) still exports a single IR. The CLI test of the Markov head package runs on the DSpark and the DFlash v2 drafts with default, INT8, INT4 and FP16 weights, and the task is inferred for every draft architecture.
Before submitting