flashmap 0.0.1__tar.gz → 0.1.0__tar.gz
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-0.0.1 → flashmap-0.1.0}/LICENSE +1 -2
- flashmap-0.1.0/PKG-INFO +152 -0
- flashmap-0.1.0/README.md +121 -0
- flashmap-0.1.0/flashmap/__init__.py +14 -0
- flashmap-0.1.0/flashmap/configuration_flashmap.py +105 -0
- flashmap-0.1.0/flashmap/modeling_flashmap.py +556 -0
- flashmap-0.1.0/flashmap/sglang/__init__.py +78 -0
- flashmap-0.1.0/flashmap/sglang/jump_bank.py +203 -0
- flashmap-0.1.0/flashmap/sglang/kernels.py +457 -0
- flashmap-0.1.0/flashmap/sglang/model.py +1076 -0
- flashmap-0.1.0/flashmap/sglang/sampler.py +188 -0
- flashmap-0.1.0/flashmap/sglang/tree.py +78 -0
- flashmap-0.1.0/flashmap/sglang/tree_worker.py +396 -0
- flashmap-0.1.0/flashmap/sglang/verify_attention.py +474 -0
- flashmap-0.1.0/flashmap/vllm/__init__.py +268 -0
- flashmap-0.1.0/flashmap/vllm/fold.py +128 -0
- flashmap-0.1.0/flashmap/vllm/kernels.py +443 -0
- flashmap-0.1.0/flashmap/vllm/model.py +881 -0
- flashmap-0.1.0/flashmap/vllm/speculator.py +235 -0
- flashmap-0.1.0/flashmap.egg-info/PKG-INFO +152 -0
- flashmap-0.1.0/flashmap.egg-info/SOURCES.txt +25 -0
- flashmap-0.1.0/flashmap.egg-info/entry_points.txt +5 -0
- flashmap-0.1.0/flashmap.egg-info/requires.txt +14 -0
- flashmap-0.1.0/pyproject.toml +51 -0
- flashmap-0.0.1/.editorconfig +0 -21
- flashmap-0.0.1/.github/ISSUE_TEMPLATE/bug_report.md +0 -25
- flashmap-0.0.1/.github/ISSUE_TEMPLATE/config.yml +0 -10
- flashmap-0.0.1/.github/ISSUE_TEMPLATE/feature_request.md +0 -18
- flashmap-0.0.1/.github/workflows/docs-build.yml +0 -55
- flashmap-0.0.1/.github/workflows/docs.yml +0 -31
- flashmap-0.0.1/.github/workflows/installation.yml +0 -31
- flashmap-0.0.1/.github/workflows/macos.yml +0 -42
- flashmap-0.0.1/.github/workflows/pypi.yml +0 -30
- flashmap-0.0.1/.github/workflows/ubuntu.yml +0 -47
- flashmap-0.0.1/.github/workflows/windows.yml +0 -34
- flashmap-0.0.1/.gitignore +0 -107
- flashmap-0.0.1/MANIFEST.in +0 -7
- flashmap-0.0.1/PKG-INFO +0 -42
- flashmap-0.0.1/README.md +0 -17
- flashmap-0.0.1/docs/changelog.md +0 -11
- flashmap-0.0.1/docs/common.md +0 -3
- flashmap-0.0.1/docs/contributing.md +0 -108
- flashmap-0.0.1/docs/examples/intro.ipynb +0 -21
- flashmap-0.0.1/docs/faq.md +0 -1
- flashmap-0.0.1/docs/flashmap.md +0 -4
- flashmap-0.0.1/docs/index.md +0 -16
- flashmap-0.0.1/docs/installation.md +0 -21
- flashmap-0.0.1/docs/overrides/main.html +0 -11
- flashmap-0.0.1/docs/usage.md +0 -7
- flashmap-0.0.1/flashmap/__init__.py +0 -5
- flashmap-0.0.1/flashmap/common.py +0 -7
- flashmap-0.0.1/flashmap/flashmap.py +0 -1
- flashmap-0.0.1/flashmap.egg-info/PKG-INFO +0 -42
- flashmap-0.0.1/flashmap.egg-info/SOURCES.txt +0 -40
- flashmap-0.0.1/flashmap.egg-info/entry_points.txt +0 -2
- flashmap-0.0.1/flashmap.egg-info/requires.txt +0 -7
- flashmap-0.0.1/mkdocs.yml +0 -86
- flashmap-0.0.1/pyproject.toml +0 -82
- flashmap-0.0.1/requirements.txt +0 -1
- flashmap-0.0.1/requirements_dev.txt +0 -29
- flashmap-0.0.1/tests/__init__.py +0 -1
- flashmap-0.0.1/tests/test_flashmap.py +0 -21
- {flashmap-0.0.1 → flashmap-0.1.0}/flashmap.egg-info/dependency_links.txt +0 -0
- {flashmap-0.0.1 → flashmap-0.1.0}/flashmap.egg-info/top_level.txt +0 -0
- {flashmap-0.0.1 → flashmap-0.1.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c)
|
|
3
|
+
Copyright (c) 2026 Jeff Shen
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -19,4 +19,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
19
19
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
20
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
21
|
SOFTWARE.
|
|
22
|
-
|
flashmap-0.1.0/PKG-INFO
ADDED
|
@@ -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).
|
flashmap-0.1.0/README.md
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# FlashMap: Flow Map Speculative Decoding
|
|
2
|
+
|
|
3
|
+
**[Project page](https://jshen.net/flashmap)** · **Paper** (coming soon) · **[Models](https://huggingface.co/collections/j-shen/flashmap-6ad0feb955bdc30db59769fa)**
|
|
4
|
+
|
|
5
|
+
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.
|
|
6
|
+
|
|
7
|
+
This repository is a small, standalone implementation for Hugging Face `transformers`. For fast serving, use
|
|
8
|
+
the [SGLang](#serve-with-sglang) or [vLLM](#serve-with-vllm) integration.
|
|
9
|
+
|
|
10
|
+
## Models
|
|
11
|
+
|
|
12
|
+
| Drafter | Target | Drafter parameters |
|
|
13
|
+
|---|---|---|
|
|
14
|
+
| [j-shen/FlashMap-Qwen3-8B](https://huggingface.co/j-shen/FlashMap-Qwen3-8B) | [Qwen/Qwen3-8B](https://huggingface.co/Qwen/Qwen3-8B) | 500M |
|
|
15
|
+
| [j-shen/FlashMap-Qwen3-4B](https://huggingface.co/j-shen/FlashMap-Qwen3-4B) | [Qwen/Qwen3-4B](https://huggingface.co/Qwen/Qwen3-4B) | 475M |
|
|
16
|
+
|
|
17
|
+
## Install
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
uv venv --python 3.12
|
|
21
|
+
source .venv/bin/activate
|
|
22
|
+
uv pip install flashmap
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
The package needs only `torch` and `transformers>=4.56`; serving takes the `sglang` or `vllm` extra (below). It
|
|
26
|
+
is tested with torch 2.9 and 2.13 and with transformers 4.57, 5.10, 5.16 and 5.20.
|
|
27
|
+
|
|
28
|
+
## Quickstart
|
|
29
|
+
|
|
30
|
+
```python
|
|
31
|
+
import torch
|
|
32
|
+
from transformers import AutoModel, AutoModelForCausalLM, AutoTokenizer
|
|
33
|
+
|
|
34
|
+
tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen3-8B")
|
|
35
|
+
target = AutoModelForCausalLM.from_pretrained("Qwen/Qwen3-8B", dtype=torch.bfloat16).cuda().eval()
|
|
36
|
+
draft = AutoModel.from_pretrained("j-shen/FlashMap-Qwen3-8B", trust_remote_code=True, dtype=torch.bfloat16).cuda().eval()
|
|
37
|
+
|
|
38
|
+
messages = [{"role": "user", "content": "How many positive whole-number divisors does 196 have?"}]
|
|
39
|
+
input_ids = tokenizer.apply_chat_template(
|
|
40
|
+
messages, add_generation_prompt=True, enable_thinking=False, return_tensors="pt", return_dict=True
|
|
41
|
+
)["input_ids"].cuda()
|
|
42
|
+
|
|
43
|
+
output = draft.spec_generate(target, input_ids, max_new_tokens=512, temperature=0.0, num_steps=1)
|
|
44
|
+
print(tokenizer.decode(output.sequences[0, input_ids.shape[1]:], skip_special_tokens=True))
|
|
45
|
+
print(f"acceptance length: {output.acceptance_length:.2f}")
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
`num_steps=2` drafts with two jumps of the flow map (trading speed for accuracy).
|
|
49
|
+
The model code also ships with the weights, so `AutoModel.from_pretrained(..., trust_remote_code=True)` works without this
|
|
50
|
+
package.
|
|
51
|
+
|
|
52
|
+
## Serve with SGLang
|
|
53
|
+
|
|
54
|
+
The SGLang integration is a plugin in this package (the `sglang` extra), which SGLang loads automatically.
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
uv venv --python 3.12 .venv-sglang
|
|
58
|
+
source .venv-sglang/bin/activate
|
|
59
|
+
uv pip install "sglang==0.5.20" "flashmap[sglang]"
|
|
60
|
+
|
|
61
|
+
python -m sglang.launch_server --model-path Qwen/Qwen3-8B \
|
|
62
|
+
--speculative-algorithm DSPARK --speculative-draft-model-path j-shen/FlashMap-Qwen3-8B
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
[Our SpecForge fork](https://github.com/al-jshen/SpecForge/tree/flashmap) trains FlashMap with SGLang's
|
|
66
|
+
training library, and its `specforge export --to hf` writes a trained map as a release folder that
|
|
67
|
+
`flashmap[sglang]` serves as it is.
|
|
68
|
+
|
|
69
|
+
## Serve with vLLM
|
|
70
|
+
|
|
71
|
+
The vLLM integration is a plugin in this package (the `vllm` extra), which vLLM loads automatically.
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
uv venv --python 3.12 .venv-vllm
|
|
75
|
+
source .venv-vllm/bin/activate
|
|
76
|
+
uv pip install "vllm==0.31.*" "flashmap[vllm]"
|
|
77
|
+
|
|
78
|
+
vllm serve Qwen/Qwen3-8B --speculative-config '{"model": "j-shen/FlashMap-Qwen3-8B", "num_speculative_tokens": 16}'
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
For sampling at `temperature > 0`, add `"draft_sample_method": "probabilistic"` to the speculative config.
|
|
82
|
+
|
|
83
|
+
Drafters you train yourself ([Training](#training)) are served the same way once converted to the release
|
|
84
|
+
format.
|
|
85
|
+
|
|
86
|
+
## Sending requests
|
|
87
|
+
|
|
88
|
+
Both servers expose an OpenAI-compatible API, SGLang on port 30000 and vLLM on port 8000.
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
from openai import OpenAI
|
|
92
|
+
|
|
93
|
+
client = OpenAI(base_url="http://localhost:30000/v1", api_key="none") # vLLM: port 8000
|
|
94
|
+
response = client.chat.completions.create(
|
|
95
|
+
model=client.models.list().data[0].id,
|
|
96
|
+
messages=[{"role": "user", "content": "How many positive whole-number divisors does 196 have?"}],
|
|
97
|
+
temperature=0,
|
|
98
|
+
extra_body={"chat_template_kwargs": {"enable_thinking": False}},
|
|
99
|
+
)
|
|
100
|
+
print(response.choices[0].message.content)
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Training
|
|
104
|
+
|
|
105
|
+
FlashMap is trained in two stages: a flow over one-hot token blocks, then a flow map distilled from it. The
|
|
106
|
+
recipes are in the speculators fork
|
|
107
|
+
([Training FlashMap](https://github.com/al-jshen/speculators/blob/flashmap/docs/user_guide/algorithms/flashmap_training.md))
|
|
108
|
+
and the SpecForge fork ([FlashMap](https://github.com/al-jshen/SpecForge/blob/flashmap/docs/sections/concepts/FlashMap.md)).
|
|
109
|
+
Both write a trained map as a release folder for this package (`speculators convert --algorithm flashmap`,
|
|
110
|
+
`specforge export --to hf`), and [`scripts/convert_checkpoint.py`](https://github.com/al-jshen/flashmap/blob/master/scripts/convert_checkpoint.py) converts
|
|
111
|
+
speculators and SpecForge checkpoints too (`python scripts/convert_checkpoint.py --help`).
|
|
112
|
+
|
|
113
|
+
## License
|
|
114
|
+
|
|
115
|
+
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,
|
|
116
|
+
following Qwen3.
|
|
117
|
+
|
|
118
|
+
FlashMap builds on [DFlash](https://github.com/z-lab/dflash),
|
|
119
|
+
[Flow Map Language Models](https://arxiv.org/abs/2602.16813), [DeepSpec](https://github.com/deepseek-ai/DeepSpec),
|
|
120
|
+
[SGLang](https://github.com/sgl-project/sglang), [vLLM](https://github.com/vllm-project/vllm),
|
|
121
|
+
[speculators](https://github.com/vllm-project/speculators) and [SpecForge](https://github.com/sgl-project/SpecForge).
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from transformers import AutoConfig, AutoModel
|
|
2
|
+
|
|
3
|
+
from .configuration_flashmap import FlashMapConfig
|
|
4
|
+
from .modeling_flashmap import FlashMapCache, FlashMapDraftModel, FlashMapGenerateOutput
|
|
5
|
+
|
|
6
|
+
# With the package imported, AutoModel loads FlashMap folders without trust_remote_code,
|
|
7
|
+
# and save_pretrained writes the model code next to the weights, so that the folder
|
|
8
|
+
# loads with trust_remote_code=True alone.
|
|
9
|
+
AutoConfig.register(FlashMapConfig.model_type, FlashMapConfig, exist_ok=True)
|
|
10
|
+
AutoModel.register(FlashMapConfig, FlashMapDraftModel, exist_ok=True)
|
|
11
|
+
FlashMapConfig.register_for_auto_class()
|
|
12
|
+
FlashMapDraftModel.register_for_auto_class("AutoModel")
|
|
13
|
+
|
|
14
|
+
__all__ = ["FlashMapCache", "FlashMapConfig", "FlashMapDraftModel", "FlashMapGenerateOutput"]
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"""Configuration of a FlashMap draft model."""
|
|
2
|
+
|
|
3
|
+
from transformers import PretrainedConfig
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
# Jump grids of the "decoding_error" time schedule (Flow Map Language Models,
|
|
7
|
+
# eq. 25) at the Qwen3 vocabulary size, with the endpoints set to exactly 0 and 1.
|
|
8
|
+
# A draft with ``n`` steps jumps from grid[i] to grid[i + 1] for i < n.
|
|
9
|
+
DEFAULT_JUMP_GRIDS = {
|
|
10
|
+
"1": [0.0, 1.0],
|
|
11
|
+
"2": [0.0, 0.8172569274902344, 1.0],
|
|
12
|
+
"3": [0.0, 0.8010796308517456, 0.8310279846191406, 1.0],
|
|
13
|
+
"4": [0.0, 0.7906050682067871, 0.8172569274902344, 0.8379518389701843, 1.0],
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class FlashMapConfig(PretrainedConfig):
|
|
18
|
+
r"""A FlashMap drafter for speculative decoding.
|
|
19
|
+
|
|
20
|
+
FlashMap drafts a block of ``block_size`` tokens after the last verified one
|
|
21
|
+
(the anchor) with a flow map: a DiT that jumps from Gaussian noise over the
|
|
22
|
+
target's vocabulary to the block's per-slot token distributions, conditioned on
|
|
23
|
+
the target model's hidden states through cross-attention.
|
|
24
|
+
|
|
25
|
+
The drafter borrows the target's token embedding and lm_head, which are not part
|
|
26
|
+
of its weights.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
target_model (`str`): Hub id of the target model the drafter was trained for.
|
|
30
|
+
target_hidden_size (`int`): Hidden size of the target model.
|
|
31
|
+
vocab_size (`int`): Vocabulary size of the target model.
|
|
32
|
+
target_layer_ids (`list[int]`): Target decoder layers whose outputs (that is,
|
|
33
|
+
`hidden_states[i + 1]` of a transformers forward) are the drafter's context.
|
|
34
|
+
block_size (`int`): Number of draft tokens per block.
|
|
35
|
+
hidden_size (`int`): Width of the DiT.
|
|
36
|
+
num_hidden_layers (`int`): Number of DiT blocks.
|
|
37
|
+
num_attention_heads (`int`): Attention heads of the DiT.
|
|
38
|
+
intermediate_size (`int`): MLP width of the DiT.
|
|
39
|
+
cond_dim (`int`): Width of the time conditioning.
|
|
40
|
+
time_embed_dim (`int`): Size of the sinusoidal time features.
|
|
41
|
+
time_scale (`float`): Times in [0, 1] are multiplied by this before their
|
|
42
|
+
sinusoidal embedding.
|
|
43
|
+
rope_theta (`float`): RoPE base. RoPE rotates interleaved pairs of channels.
|
|
44
|
+
rms_norm_eps (`float`): Epsilon of the context, anchor and state RMSNorms.
|
|
45
|
+
qk_norm_eps (`float`): Epsilon of the query/key RMSNorms.
|
|
46
|
+
layer_norm_eps (`float`): Epsilon of the adaptive LayerNorms.
|
|
47
|
+
noise_gate (`str`): How the noise term of the state embedding is weighted:
|
|
48
|
+
"jump" by `noise_gate * (t - s)` for a jump from `s` to `t`, "constant" by
|
|
49
|
+
`noise_gate` alone.
|
|
50
|
+
time_schedule (`str`): The schedule the jump grids come from.
|
|
51
|
+
num_steps (`int`): Default number of jumps per draft.
|
|
52
|
+
jump_grids (`dict[str, list[float]]`): Jump times for each number of steps.
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
model_type = "flashmap"
|
|
56
|
+
|
|
57
|
+
def __init__(
|
|
58
|
+
self,
|
|
59
|
+
target_model: str = "Qwen/Qwen3-8B",
|
|
60
|
+
target_hidden_size: int = 4096,
|
|
61
|
+
vocab_size: int = 151936,
|
|
62
|
+
target_layer_ids=(1, 9, 17, 25, 33),
|
|
63
|
+
block_size: int = 16,
|
|
64
|
+
hidden_size: int = 2048,
|
|
65
|
+
num_hidden_layers: int = 6,
|
|
66
|
+
num_attention_heads: int = 16,
|
|
67
|
+
intermediate_size: int = 8192,
|
|
68
|
+
cond_dim: int = 256,
|
|
69
|
+
time_embed_dim: int = 256,
|
|
70
|
+
time_scale: float = 1000.0,
|
|
71
|
+
rope_theta: float = 10000.0,
|
|
72
|
+
rms_norm_eps: float = 1e-6,
|
|
73
|
+
qk_norm_eps: float = 1e-5,
|
|
74
|
+
layer_norm_eps: float = 1e-6,
|
|
75
|
+
noise_gate: str = "jump",
|
|
76
|
+
time_schedule: str = "decoding_error",
|
|
77
|
+
num_steps: int = 1,
|
|
78
|
+
jump_grids=None,
|
|
79
|
+
**kwargs,
|
|
80
|
+
):
|
|
81
|
+
self.target_model = target_model
|
|
82
|
+
self.target_hidden_size = target_hidden_size
|
|
83
|
+
self.vocab_size = vocab_size
|
|
84
|
+
self.target_layer_ids = list(target_layer_ids)
|
|
85
|
+
self.block_size = block_size
|
|
86
|
+
self.hidden_size = hidden_size
|
|
87
|
+
self.num_hidden_layers = num_hidden_layers
|
|
88
|
+
self.num_attention_heads = num_attention_heads
|
|
89
|
+
self.intermediate_size = intermediate_size
|
|
90
|
+
self.cond_dim = cond_dim
|
|
91
|
+
self.time_embed_dim = time_embed_dim
|
|
92
|
+
self.time_scale = time_scale
|
|
93
|
+
self.rope_theta = rope_theta
|
|
94
|
+
self.rms_norm_eps = rms_norm_eps
|
|
95
|
+
self.qk_norm_eps = qk_norm_eps
|
|
96
|
+
self.layer_norm_eps = layer_norm_eps
|
|
97
|
+
self.noise_gate = noise_gate
|
|
98
|
+
self.time_schedule = time_schedule
|
|
99
|
+
self.num_steps = num_steps
|
|
100
|
+
self.jump_grids = dict(DEFAULT_JUMP_GRIDS if jump_grids is None else jump_grids)
|
|
101
|
+
kwargs.setdefault("tie_word_embeddings", False)
|
|
102
|
+
super().__init__(**kwargs)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
__all__ = ["FlashMapConfig"]
|