1# Optional: enable schedule overlapping (experimental, may not be stable)
2# export SGLANG_ENABLE_SPEC_V2=1
3# export SGLANG_ENABLE_DFLASH_SPEC_V2=1
4# export SGLANG_ENABLE_OVERLAP_PLAN_STREAM=1
5
6python -m sglang.launch_server \
7 --model-path meta-llama/Llama-3.1-8B-Instruct \
8 --speculative-algorithm DFLASH \
9 --speculative-draft-model-path z-lab/LLaMA3.1-8B-Instruct-DFlash-UltraChat \
10 --tp-size 1 \
11 --dtype bfloat16 \
12 --attention-backend fa3 \
13 --mem-fraction-static 0.75 \
14 --trust-remote-code
1from openai import OpenAI
2
3client = OpenAI(base_url="http://localhost:30000/v1", api_key="EMPTY")
4
5response = client.chat.completions.create(
6 model="meta-llama/Llama-3.1-8B-Instruct",
7 messages=[{"role": "user", "content": "Write a quicksort in Python."}],
8 max_tokens=2048,
9 temperature=0.0,
10)
11print(response.choices[0].message.content)
1uv pip install vllm
2uv pip install -U vllm --torch-backend=auto --extra-index-url https://wheels.vllm.ai/nightly
1vllm serve meta-llama/Llama-3.1-8B-Instruct \
2 --speculative-config '{"method": "dflash", "model": "z-lab/LLaMA3.1-8B-Instruct-DFlash-UltraChat", "num_speculative_tokens": 9}' \
3 --attention-backend flash_attn \
4 --max-num-batched-tokens 32768
1from openai import OpenAI
2
3client = OpenAI(base_url="http://localhost:8000/v1", api_key="EMPTY")
4
5response = client.chat.completions.create(
6 model="meta-llama/Llama-3.1-8B-Instruct",
7 messages=[{"role": "user", "content": "Write a quicksort in Python."}],
8 max_tokens=2048,
9 temperature=0.0,
10)
11print(response.choices[0].message.content)
1from transformers import AutoModel, AutoModelForCausalLM, AutoTokenizer
2
3model = AutoModel.from_pretrained(
4 "z-lab/LLaMA3.1-8B-Instruct-DFlash-UltraChat",
5 trust_remote_code=True,
6 dtype="auto",
7 device_map="cuda:0"
8).eval()
9
10target = AutoModelForCausalLM.from_pretrained(
11 "meta-llama/Llama-3.1-8B-Instruct",
12 dtype="auto",
13 device_map="cuda:0"
14).eval()
15
16tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-3.1-8B-Instruct")
17prompt = "How many positive whole-number divisors does 196 have?"
18messages = [
19 {"role": "user", "content": prompt}
20]
21text = tokenizer.apply_chat_template(
22 messages,
23 tokenize=False,
24 add_generation_prompt=True,
25)
26model_inputs = tokenizer([text], return_tensors="pt").to(model.device)
27
28generate_ids = model.spec_generate(
29 input_ids=model_inputs["input_ids"],
30 max_new_tokens=2048,
31 temperature=0.0,
32 target=target,
33 stop_token_ids=[tokenizer.eos_token_id]
34)
35
36print(tokenizer.decode(generate_ids[0], skip_special_tokens=True))
DFlash consistently achieves higher speedups than the state-of-the-art speculative decoding method EAGLE-3. All experiments are conducted using SGLang on a single B200 GPU.
For DFlash, we use a block size of 10 during speculation.
We compare against the EAGLE-3 checkpoint
lmsys/sglang-EAGLE3-LLaMA3.1-Instruct-8B, which is the
official EAGLE-3 checkpoint adapted for SGLang inference.
We are grateful to
Yotta Labs for their compute support in training this draft model.
If you find DFlash useful for your research or applications, please cite our project.
1@misc{chen2026dflash,
2 title = {DFlash: Block Diffusion for Flash Speculative Decoding},
3 author = {Chen, Jian and Liang, Yesheng and Liu, Zhijian},
4 year = {2026},
5 eprint = {2602.06036},
6 archivePrefix = {arXiv},
7 primaryClass = {cs.CL},
8 url = {https://arxiv.org/abs/2602.06036}
9}