flashmap 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- flashmap/__init__.py +14 -0
- flashmap/configuration_flashmap.py +105 -0
- flashmap/modeling_flashmap.py +556 -0
- flashmap/sglang/__init__.py +78 -0
- flashmap/sglang/jump_bank.py +203 -0
- flashmap/sglang/kernels.py +457 -0
- flashmap/sglang/model.py +1076 -0
- flashmap/sglang/sampler.py +188 -0
- flashmap/sglang/tree.py +78 -0
- flashmap/sglang/tree_worker.py +396 -0
- flashmap/sglang/verify_attention.py +474 -0
- flashmap/vllm/__init__.py +268 -0
- flashmap/vllm/fold.py +128 -0
- flashmap/vllm/kernels.py +443 -0
- flashmap/vllm/model.py +881 -0
- flashmap/vllm/speculator.py +235 -0
- flashmap-0.1.0.dist-info/METADATA +152 -0
- flashmap-0.1.0.dist-info/RECORD +22 -0
- flashmap-0.1.0.dist-info/WHEEL +5 -0
- flashmap-0.1.0.dist-info/entry_points.txt +5 -0
- flashmap-0.1.0.dist-info/licenses/LICENSE +21 -0
- flashmap-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
"""FlashMap speculator for vLLM's model runner V2.
|
|
2
|
+
|
|
3
|
+
FlashMap reuses the DFlash runtime unchanged: model loading
|
|
4
|
+
(``load_dflash_model``, which attaches the target's embedding and LM head), the
|
|
5
|
+
context K/V precompute, the fused input-preparation kernel, the attention
|
|
6
|
+
metadata and the FULL CUDA graph that covers the whole draft step. Its block has
|
|
7
|
+
DSpark's layout (``sample_from_anchor``): ``block_size`` query rows per request,
|
|
8
|
+
row 0 holding the anchor, every row a draft slot. What differs is the draft
|
|
9
|
+
model (model.py) and sampling, which reads logits off the folded head over the
|
|
10
|
+
draft vocabulary.
|
|
11
|
+
|
|
12
|
+
``num_speculative_tokens`` may be smaller than the block: the draft still
|
|
13
|
+
evaluates its whole block (the DiT's self-attention sees all of it) and proposes
|
|
14
|
+
the first ``num_speculative_tokens`` slots, so verification, which dominates at
|
|
15
|
+
high concurrency, checks fewer tokens.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
import torch
|
|
19
|
+
from torch import nn
|
|
20
|
+
from vllm.config import VllmConfig
|
|
21
|
+
from vllm.logger import init_logger
|
|
22
|
+
from vllm.v1.worker.gpu.sample.gumbel import gumbel_sample
|
|
23
|
+
from vllm.v1.worker.gpu.spec_decode.acceptance_estimator import (
|
|
24
|
+
OnlineAcceptanceEstimator,
|
|
25
|
+
)
|
|
26
|
+
from vllm.v1.worker.gpu.spec_decode.dflash.speculator import DFlashSpeculator
|
|
27
|
+
from vllm.v1.worker.gpu.spec_decode.dflash.utils import load_dflash_model
|
|
28
|
+
|
|
29
|
+
from flashmap.vllm.fold import split_argmax
|
|
30
|
+
from flashmap.vllm.kernels import scatter_rows
|
|
31
|
+
|
|
32
|
+
logger = init_logger(__name__)
|
|
33
|
+
|
|
34
|
+
__all__ = ["FlashMapSpeculator"]
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class FlashMapSpeculator(DFlashSpeculator):
|
|
38
|
+
_speculator_name = "FlashMap"
|
|
39
|
+
|
|
40
|
+
def __init__(self, vllm_config: VllmConfig, device: torch.device):
|
|
41
|
+
super().__init__(vllm_config, device)
|
|
42
|
+
block_size = int(self.draft_model_config.hf_config.block_size)
|
|
43
|
+
# Drafts proposed for verification, a prefix of the block.
|
|
44
|
+
self.num_verify = self.num_speculative_steps
|
|
45
|
+
if self.num_verify > block_size:
|
|
46
|
+
raise ValueError(
|
|
47
|
+
f"num_speculative_tokens={self.num_verify} exceeds FlashMap's "
|
|
48
|
+
f"block_size={block_size}"
|
|
49
|
+
)
|
|
50
|
+
# Every one of the block's rows is a draft slot; row 0 is the anchor.
|
|
51
|
+
self.sample_from_anchor = True
|
|
52
|
+
self.num_query_per_req = block_size
|
|
53
|
+
if self.num_verify < block_size:
|
|
54
|
+
# Per-slot buffers for the whole block (the DFlash ones are sized
|
|
55
|
+
# for the verified drafts).
|
|
56
|
+
self.num_speculative_steps = block_size
|
|
57
|
+
num_slots = self.max_num_reqs * block_size
|
|
58
|
+
self.draft_tokens = torch.zeros(
|
|
59
|
+
self.max_num_reqs, block_size, dtype=torch.int64, device=device
|
|
60
|
+
)
|
|
61
|
+
self.sample_indices = torch.zeros(
|
|
62
|
+
num_slots, dtype=torch.int64, device=device
|
|
63
|
+
)
|
|
64
|
+
self.sample_pos = torch.zeros(num_slots, dtype=torch.int64, device=device)
|
|
65
|
+
self.sample_idx_mapping = torch.full(
|
|
66
|
+
(num_slots,), -1, dtype=torch.int32, device=device
|
|
67
|
+
)
|
|
68
|
+
self.sample_col = torch.arange(
|
|
69
|
+
block_size, dtype=torch.int32, device=device
|
|
70
|
+
).repeat(self.max_num_reqs)
|
|
71
|
+
|
|
72
|
+
def draft_logits_spec(self, vllm_config: VllmConfig) -> tuple[torch.dtype, float]:
|
|
73
|
+
# A restricted draft vocabulary writes only its own columns of the
|
|
74
|
+
# cached proposal distribution; every other token has probability 0.
|
|
75
|
+
dtype, fill = super().draft_logits_spec(vllm_config)
|
|
76
|
+
hf_config = self.draft_model_config.hf_config
|
|
77
|
+
draft_vocab_size = getattr(hf_config, "draft_vocab_size", None)
|
|
78
|
+
if draft_vocab_size and draft_vocab_size < hf_config.vocab_size:
|
|
79
|
+
fill = float("-inf")
|
|
80
|
+
return dtype, fill
|
|
81
|
+
|
|
82
|
+
def load_draft_model(
|
|
83
|
+
self,
|
|
84
|
+
target_model: nn.Module,
|
|
85
|
+
target_attn_layer_names: set[str], # noqa: ARG002
|
|
86
|
+
) -> nn.Module:
|
|
87
|
+
model = load_dflash_model(target_model, self.vllm_config)
|
|
88
|
+
model.prepare()
|
|
89
|
+
# Key each query row's noise by its request's seed and its position.
|
|
90
|
+
model.set_noise_keys(self.seeds, self.sample_idx_mapping)
|
|
91
|
+
if self.draft_watermarker is not None and model.hot_ids is not None:
|
|
92
|
+
raise ValueError(
|
|
93
|
+
"Watermarked drafting needs FlashMap's full draft vocabulary."
|
|
94
|
+
)
|
|
95
|
+
return model
|
|
96
|
+
|
|
97
|
+
def load_model(self, target_model: nn.Module) -> None:
|
|
98
|
+
super().load_model(target_model)
|
|
99
|
+
if self.acceptance_estimator is not None:
|
|
100
|
+
# Acceptance is observed for the verified drafts only.
|
|
101
|
+
self.acceptance_estimator = OnlineAcceptanceEstimator(
|
|
102
|
+
self.max_num_reqs, self.num_verify, self.device
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
def set_attn(self, *args, **kwargs) -> None:
|
|
106
|
+
super().set_attn(*args, **kwargs)
|
|
107
|
+
target_attn_groups = kwargs.get("target_attn_groups", args[-1] if args else [])
|
|
108
|
+
# The cross-attention schedules itself (model.py); vLLM's ahead-of-time
|
|
109
|
+
# FlashAttention schedule for the draft group would be unused work, and
|
|
110
|
+
# it mistakes an fp8 draft cache under a bf16 target for an unsupported
|
|
111
|
+
# dtype.
|
|
112
|
+
for groups in self.attn_groups:
|
|
113
|
+
for group in groups:
|
|
114
|
+
builder = group.get_metadata_builder()
|
|
115
|
+
if getattr(builder, "aot_schedule", False):
|
|
116
|
+
builder.aot_schedule = False # type: ignore[attr-defined]
|
|
117
|
+
# The target runner builds metadata for the draft group too (cudagraph
|
|
118
|
+
# capture), through its own builders.
|
|
119
|
+
for gid in self.draft_kv_cache_group_ids:
|
|
120
|
+
for group in target_attn_groups[gid]:
|
|
121
|
+
builder = group.get_metadata_builder()
|
|
122
|
+
if getattr(builder, "aot_schedule", False) and getattr(
|
|
123
|
+
builder, "kv_cache_dtype", None
|
|
124
|
+
) not in (torch.bfloat16, torch.float16):
|
|
125
|
+
builder.aot_schedule = False # type: ignore[attr-defined]
|
|
126
|
+
|
|
127
|
+
def _precompute_context_kv(
|
|
128
|
+
self, start: int, end: int, dummy_run: bool = False
|
|
129
|
+
) -> None:
|
|
130
|
+
# The context rows a draft step stores right before its forward are
|
|
131
|
+
# projected by the forward's GEMM, together with the anchors.
|
|
132
|
+
if start == 0 and not dummy_run and self._layer_group_idx is None:
|
|
133
|
+
self.model.defer_context_kv(
|
|
134
|
+
self.hidden_states[start:end],
|
|
135
|
+
self.context_positions[start:end],
|
|
136
|
+
self._context_slot_mappings[0][start:end],
|
|
137
|
+
)
|
|
138
|
+
return
|
|
139
|
+
super()._precompute_context_kv(start, end, dummy_run)
|
|
140
|
+
|
|
141
|
+
def capture(self) -> None:
|
|
142
|
+
# Record the KV caches' layout (a host-to-device copy) before capturing.
|
|
143
|
+
self.model.cache_layout()
|
|
144
|
+
super().capture()
|
|
145
|
+
|
|
146
|
+
def propose(self, *args, **kwargs) -> torch.Tensor:
|
|
147
|
+
return super().propose(*args, **kwargs)[:, : self.num_verify]
|
|
148
|
+
|
|
149
|
+
def sample_draft(
|
|
150
|
+
self,
|
|
151
|
+
hidden_states: torch.Tensor,
|
|
152
|
+
sample_src_positions: torch.Tensor,
|
|
153
|
+
idx_mapping: torch.Tensor,
|
|
154
|
+
temperature: torch.Tensor,
|
|
155
|
+
seeds: torch.Tensor,
|
|
156
|
+
draft_step: torch.Tensor,
|
|
157
|
+
draft_logits: torch.Tensor | None,
|
|
158
|
+
) -> torch.Tensor:
|
|
159
|
+
block, verify = self.num_speculative_steps, self.num_verify
|
|
160
|
+
if verify == block:
|
|
161
|
+
return self._sample(
|
|
162
|
+
hidden_states,
|
|
163
|
+
sample_src_positions,
|
|
164
|
+
idx_mapping,
|
|
165
|
+
temperature,
|
|
166
|
+
seeds,
|
|
167
|
+
draft_step,
|
|
168
|
+
draft_logits,
|
|
169
|
+
)
|
|
170
|
+
# Sample the verified prefix of each block only; the rest stay zero.
|
|
171
|
+
num_blocks = hidden_states.shape[0] // block
|
|
172
|
+
|
|
173
|
+
def prefix(t: torch.Tensor) -> torch.Tensor:
|
|
174
|
+
return t.view(num_blocks, block, *t.shape[1:])[:, :verify].flatten(0, 1)
|
|
175
|
+
|
|
176
|
+
sampled = self._sample(
|
|
177
|
+
prefix(hidden_states),
|
|
178
|
+
prefix(sample_src_positions),
|
|
179
|
+
prefix(idx_mapping),
|
|
180
|
+
temperature,
|
|
181
|
+
seeds,
|
|
182
|
+
prefix(draft_step),
|
|
183
|
+
draft_logits,
|
|
184
|
+
)
|
|
185
|
+
tokens = sampled.new_zeros(num_blocks, block)
|
|
186
|
+
tokens[:, :verify] = sampled.view(num_blocks, verify)
|
|
187
|
+
return tokens.view(-1)
|
|
188
|
+
|
|
189
|
+
def _sample(
|
|
190
|
+
self,
|
|
191
|
+
hidden_states: torch.Tensor,
|
|
192
|
+
sample_src_positions: torch.Tensor,
|
|
193
|
+
idx_mapping: torch.Tensor,
|
|
194
|
+
temperature: torch.Tensor,
|
|
195
|
+
seeds: torch.Tensor,
|
|
196
|
+
draft_step: torch.Tensor,
|
|
197
|
+
draft_logits: torch.Tensor | None,
|
|
198
|
+
) -> torch.Tensor:
|
|
199
|
+
logits = self.model.compute_draft_logits(hidden_states)
|
|
200
|
+
hot_ids = self.model.hot_ids
|
|
201
|
+
if draft_logits is None:
|
|
202
|
+
sampled = split_argmax(logits)
|
|
203
|
+
elif hot_ids is None:
|
|
204
|
+
sampled = gumbel_sample(
|
|
205
|
+
logits,
|
|
206
|
+
idx_mapping,
|
|
207
|
+
temperature,
|
|
208
|
+
seeds,
|
|
209
|
+
sample_src_positions,
|
|
210
|
+
apply_temperature=True,
|
|
211
|
+
is_drafting=True,
|
|
212
|
+
logits_cache=draft_logits,
|
|
213
|
+
logits_cache_col=draft_step,
|
|
214
|
+
use_fp64=self.use_fp64_gumbel,
|
|
215
|
+
)
|
|
216
|
+
if self.draft_watermarker is not None:
|
|
217
|
+
sampled = self.draft_watermarker.sample(
|
|
218
|
+
logits, sampled, idx_mapping, temperature
|
|
219
|
+
)
|
|
220
|
+
else:
|
|
221
|
+
# Sample over the draft vocabulary and cache its logits for
|
|
222
|
+
# probabilistic verification (the other columns stay -inf).
|
|
223
|
+
sampled = gumbel_sample(
|
|
224
|
+
logits,
|
|
225
|
+
idx_mapping,
|
|
226
|
+
temperature,
|
|
227
|
+
seeds,
|
|
228
|
+
sample_src_positions,
|
|
229
|
+
apply_temperature=True,
|
|
230
|
+
is_drafting=True,
|
|
231
|
+
use_fp64=self.use_fp64_gumbel,
|
|
232
|
+
)
|
|
233
|
+
scatter_rows(logits, idx_mapping, draft_step, hot_ids, draft_logits)
|
|
234
|
+
self._maybe_predict_acceptance(logits, idx_mapping, draft_step)
|
|
235
|
+
return sampled if hot_ids is None else hot_ids[sampled]
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: flashmap
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: FlashMap: flow map speculative decoding for Hugging Face transformers
|
|
5
|
+
Author: Jeff Shen, Zhejian Zhou, Ryan Lee, Jonathan May, Shirley Ho
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://jshen.net/flashmap
|
|
8
|
+
Project-URL: Repository, https://github.com/al-jshen/flashmap
|
|
9
|
+
Project-URL: Documentation, https://github.com/al-jshen/flashmap#readme
|
|
10
|
+
Project-URL: Model (Qwen3-8B), https://huggingface.co/j-shen/FlashMap-Qwen3-8B
|
|
11
|
+
Project-URL: Model (Qwen3-4B), https://huggingface.co/j-shen/FlashMap-Qwen3-4B
|
|
12
|
+
Keywords: speculative decoding,flow map,draft model,llm inference,transformers
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Intended Audience :: Science/Research
|
|
16
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
17
|
+
Requires-Python: >=3.10
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
License-File: LICENSE
|
|
20
|
+
Requires-Dist: torch>=2.1
|
|
21
|
+
Requires-Dist: transformers>=4.56
|
|
22
|
+
Provides-Extra: benchmark
|
|
23
|
+
Requires-Dist: datasets; extra == "benchmark"
|
|
24
|
+
Provides-Extra: test
|
|
25
|
+
Requires-Dist: pytest; extra == "test"
|
|
26
|
+
Provides-Extra: sglang
|
|
27
|
+
Requires-Dist: sglang==0.5.20; extra == "sglang"
|
|
28
|
+
Provides-Extra: vllm
|
|
29
|
+
Requires-Dist: vllm<0.32,>=0.31; extra == "vllm"
|
|
30
|
+
Dynamic: license-file
|
|
31
|
+
|
|
32
|
+
# FlashMap: Flow Map Speculative Decoding
|
|
33
|
+
|
|
34
|
+
**[Project page](https://jshen.net/flashmap)** · **Paper** (coming soon) · **[Models](https://huggingface.co/collections/j-shen/flashmap-6ad0feb955bdc30db59769fa)**
|
|
35
|
+
|
|
36
|
+
FlashMap is a drafter for lossless speculative decoding. It proposes a whole block of K tokens in a single pass. Unlike discrete diffusion drafters, which predict each token of the block independently and ignore inter-token dependencies, FlashMap uses a flow map ([Flow Map Language Models](https://arxiv.org/abs/2602.16813)), which jumps from Gaussian noise to the whole block in a single step and can capture dependencies between its tokens. On Qwen3-8B, FlashMap decodes up to 6x faster than the target alone.
|
|
37
|
+
|
|
38
|
+
This repository is a small, standalone implementation for Hugging Face `transformers`. For fast serving, use
|
|
39
|
+
the [SGLang](#serve-with-sglang) or [vLLM](#serve-with-vllm) integration.
|
|
40
|
+
|
|
41
|
+
## Models
|
|
42
|
+
|
|
43
|
+
| Drafter | Target | Drafter parameters |
|
|
44
|
+
|---|---|---|
|
|
45
|
+
| [j-shen/FlashMap-Qwen3-8B](https://huggingface.co/j-shen/FlashMap-Qwen3-8B) | [Qwen/Qwen3-8B](https://huggingface.co/Qwen/Qwen3-8B) | 500M |
|
|
46
|
+
| [j-shen/FlashMap-Qwen3-4B](https://huggingface.co/j-shen/FlashMap-Qwen3-4B) | [Qwen/Qwen3-4B](https://huggingface.co/Qwen/Qwen3-4B) | 475M |
|
|
47
|
+
|
|
48
|
+
## Install
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
uv venv --python 3.12
|
|
52
|
+
source .venv/bin/activate
|
|
53
|
+
uv pip install flashmap
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
The package needs only `torch` and `transformers>=4.56`; serving takes the `sglang` or `vllm` extra (below). It
|
|
57
|
+
is tested with torch 2.9 and 2.13 and with transformers 4.57, 5.10, 5.16 and 5.20.
|
|
58
|
+
|
|
59
|
+
## Quickstart
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
import torch
|
|
63
|
+
from transformers import AutoModel, AutoModelForCausalLM, AutoTokenizer
|
|
64
|
+
|
|
65
|
+
tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen3-8B")
|
|
66
|
+
target = AutoModelForCausalLM.from_pretrained("Qwen/Qwen3-8B", dtype=torch.bfloat16).cuda().eval()
|
|
67
|
+
draft = AutoModel.from_pretrained("j-shen/FlashMap-Qwen3-8B", trust_remote_code=True, dtype=torch.bfloat16).cuda().eval()
|
|
68
|
+
|
|
69
|
+
messages = [{"role": "user", "content": "How many positive whole-number divisors does 196 have?"}]
|
|
70
|
+
input_ids = tokenizer.apply_chat_template(
|
|
71
|
+
messages, add_generation_prompt=True, enable_thinking=False, return_tensors="pt", return_dict=True
|
|
72
|
+
)["input_ids"].cuda()
|
|
73
|
+
|
|
74
|
+
output = draft.spec_generate(target, input_ids, max_new_tokens=512, temperature=0.0, num_steps=1)
|
|
75
|
+
print(tokenizer.decode(output.sequences[0, input_ids.shape[1]:], skip_special_tokens=True))
|
|
76
|
+
print(f"acceptance length: {output.acceptance_length:.2f}")
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
`num_steps=2` drafts with two jumps of the flow map (trading speed for accuracy).
|
|
80
|
+
The model code also ships with the weights, so `AutoModel.from_pretrained(..., trust_remote_code=True)` works without this
|
|
81
|
+
package.
|
|
82
|
+
|
|
83
|
+
## Serve with SGLang
|
|
84
|
+
|
|
85
|
+
The SGLang integration is a plugin in this package (the `sglang` extra), which SGLang loads automatically.
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
uv venv --python 3.12 .venv-sglang
|
|
89
|
+
source .venv-sglang/bin/activate
|
|
90
|
+
uv pip install "sglang==0.5.20" "flashmap[sglang]"
|
|
91
|
+
|
|
92
|
+
python -m sglang.launch_server --model-path Qwen/Qwen3-8B \
|
|
93
|
+
--speculative-algorithm DSPARK --speculative-draft-model-path j-shen/FlashMap-Qwen3-8B
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
[Our SpecForge fork](https://github.com/al-jshen/SpecForge/tree/flashmap) trains FlashMap with SGLang's
|
|
97
|
+
training library, and its `specforge export --to hf` writes a trained map as a release folder that
|
|
98
|
+
`flashmap[sglang]` serves as it is.
|
|
99
|
+
|
|
100
|
+
## Serve with vLLM
|
|
101
|
+
|
|
102
|
+
The vLLM integration is a plugin in this package (the `vllm` extra), which vLLM loads automatically.
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
uv venv --python 3.12 .venv-vllm
|
|
106
|
+
source .venv-vllm/bin/activate
|
|
107
|
+
uv pip install "vllm==0.31.*" "flashmap[vllm]"
|
|
108
|
+
|
|
109
|
+
vllm serve Qwen/Qwen3-8B --speculative-config '{"model": "j-shen/FlashMap-Qwen3-8B", "num_speculative_tokens": 16}'
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
For sampling at `temperature > 0`, add `"draft_sample_method": "probabilistic"` to the speculative config.
|
|
113
|
+
|
|
114
|
+
Drafters you train yourself ([Training](#training)) are served the same way once converted to the release
|
|
115
|
+
format.
|
|
116
|
+
|
|
117
|
+
## Sending requests
|
|
118
|
+
|
|
119
|
+
Both servers expose an OpenAI-compatible API, SGLang on port 30000 and vLLM on port 8000.
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
from openai import OpenAI
|
|
123
|
+
|
|
124
|
+
client = OpenAI(base_url="http://localhost:30000/v1", api_key="none") # vLLM: port 8000
|
|
125
|
+
response = client.chat.completions.create(
|
|
126
|
+
model=client.models.list().data[0].id,
|
|
127
|
+
messages=[{"role": "user", "content": "How many positive whole-number divisors does 196 have?"}],
|
|
128
|
+
temperature=0,
|
|
129
|
+
extra_body={"chat_template_kwargs": {"enable_thinking": False}},
|
|
130
|
+
)
|
|
131
|
+
print(response.choices[0].message.content)
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Training
|
|
135
|
+
|
|
136
|
+
FlashMap is trained in two stages: a flow over one-hot token blocks, then a flow map distilled from it. The
|
|
137
|
+
recipes are in the speculators fork
|
|
138
|
+
([Training FlashMap](https://github.com/al-jshen/speculators/blob/flashmap/docs/user_guide/algorithms/flashmap_training.md))
|
|
139
|
+
and the SpecForge fork ([FlashMap](https://github.com/al-jshen/SpecForge/blob/flashmap/docs/sections/concepts/FlashMap.md)).
|
|
140
|
+
Both write a trained map as a release folder for this package (`speculators convert --algorithm flashmap`,
|
|
141
|
+
`specforge export --to hf`), and [`scripts/convert_checkpoint.py`](https://github.com/al-jshen/flashmap/blob/master/scripts/convert_checkpoint.py) converts
|
|
142
|
+
speculators and SpecForge checkpoints too (`python scripts/convert_checkpoint.py --help`).
|
|
143
|
+
|
|
144
|
+
## License
|
|
145
|
+
|
|
146
|
+
The code is released under the [MIT license](https://github.com/al-jshen/flashmap/blob/master/LICENSE). The model weights are released under Apache-2.0,
|
|
147
|
+
following Qwen3.
|
|
148
|
+
|
|
149
|
+
FlashMap builds on [DFlash](https://github.com/z-lab/dflash),
|
|
150
|
+
[Flow Map Language Models](https://arxiv.org/abs/2602.16813), [DeepSpec](https://github.com/deepseek-ai/DeepSpec),
|
|
151
|
+
[SGLang](https://github.com/sgl-project/sglang), [vLLM](https://github.com/vllm-project/vllm),
|
|
152
|
+
[speculators](https://github.com/vllm-project/speculators) and [SpecForge](https://github.com/sgl-project/SpecForge).
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
flashmap/__init__.py,sha256=iLu7hWQJMNR304XnHiwdi_GWhfYljkuezvPBHdY4q2k,745
|
|
2
|
+
flashmap/configuration_flashmap.py,sha256=BZl55qpiNyTcQ5thljUkcjAh2EhDjSoK7OKWMxcCOyk,4561
|
|
3
|
+
flashmap/modeling_flashmap.py,sha256=KegDQeqNRc0tWtAaPTZOID3olMGceBgNYV_bROAsiqU,29630
|
|
4
|
+
flashmap/sglang/__init__.py,sha256=b7817GTu7_tZP2U3ZvyqBkVa8UtBBjcKF5we9gbWZJY,3227
|
|
5
|
+
flashmap/sglang/jump_bank.py,sha256=a5GFyXr-BpeJ1oqCoPEO0ZZQ5jCYUrsDjYjJ9mgSfvY,9007
|
|
6
|
+
flashmap/sglang/kernels.py,sha256=k6lugxnjRba6rXW6VFQJNoIFzlpQjReuW0-UL3hjO7s,17409
|
|
7
|
+
flashmap/sglang/model.py,sha256=WYxBbEix5NYFY54TQr4zyYWsVGoj1HJhIfdG-6l4Dvo,48072
|
|
8
|
+
flashmap/sglang/sampler.py,sha256=RqDdDMe3oPpf3TXqS1KhAPqgEk9eLvWEt8K5TzcSZoc,8169
|
|
9
|
+
flashmap/sglang/tree.py,sha256=QAfPpzTcEtU0f8Dt4wu_ldptwEozrwS-XN9A-CH_sIc,3589
|
|
10
|
+
flashmap/sglang/tree_worker.py,sha256=5s2QHocg77dxFfsjMigfrX47ATaQyh5aISN78ykSREY,16276
|
|
11
|
+
flashmap/sglang/verify_attention.py,sha256=uWT4sJ0QePUcP-hhXbraiDJLwxfqJYuH_D_SO_MywyE,15867
|
|
12
|
+
flashmap/vllm/__init__.py,sha256=KXUpQz1PO_ivsVsLz67FfIcsTQ_08cAdiC3gO_hoI_U,10571
|
|
13
|
+
flashmap/vllm/fold.py,sha256=NpYDC3zaMb6dps5OjUO-GHK4wfoOnDtx0WdaJaqQccE,5043
|
|
14
|
+
flashmap/vllm/kernels.py,sha256=wYc_0CqH8_m5W989k6uCEDS0bNy39lo1MsMfUPvK2Ek,15622
|
|
15
|
+
flashmap/vllm/model.py,sha256=LhdGSe5JEVeOn3XKKQNv3pu2MqDKnf4xtPE0AfRbSu4,37405
|
|
16
|
+
flashmap/vllm/speculator.py,sha256=8Ms67rtgscFesi_4TTSdxG2744FizLU2FpenbHmRQG0,9937
|
|
17
|
+
flashmap-0.1.0.dist-info/licenses/LICENSE,sha256=fCprpx2_9vwmNfySvgmLmFvc2h-Qholc22PsEnKX_OU,1066
|
|
18
|
+
flashmap-0.1.0.dist-info/METADATA,sha256=Ws3Y4gnghJcm7c9SMXSO_bSpiOgnzE4ysSKsD66CBe0,7129
|
|
19
|
+
flashmap-0.1.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
20
|
+
flashmap-0.1.0.dist-info/entry_points.txt,sha256=tAz7OjTvfRKJHnn6EVnM5r8uwiqD7EDmpwXlCAhIxCU,115
|
|
21
|
+
flashmap-0.1.0.dist-info/top_level.txt,sha256=L1exL6jCAPP_DKhiqwOmI-PSMo16XxAQlT8K37wK6ok,9
|
|
22
|
+
flashmap-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jeff Shen
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
flashmap
|