Spaces:
Running
Running
Initial DeepSpec decoding lab
Browse files- .hfignore +6 -0
- PROMPT.txt +16 -0
- README.md +23 -7
- app.py +919 -0
- requirements.txt +2 -0
- rollout.jsonl +0 -0
.hfignore
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
PROMPT.txt
|
| 2 |
+
rollout.jsonl
|
| 3 |
+
.git/
|
| 4 |
+
__pycache__/
|
| 5 |
+
*.pyc
|
| 6 |
+
.venv/
|
PROMPT.txt
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/goal Research the DeepSpec collection by deepseek-ai on HuggingFace (https://huggingface.co/collections/deepseek-ai/deepspec) and build the most impressive HuggingFace Space possible from it.
|
| 2 |
+
|
| 3 |
+
The collection contains 12 models across three speculative decoding families:
|
| 4 |
+
- dSpark (qwen3_4b, qwen3_8b, qwen3_14b, gemma4_12b) - block7 variants
|
| 5 |
+
- dFlash (qwen3_4b, qwen3_8b, qwen3_14b, gemma4_12b) - block7 variants
|
| 6 |
+
- EAGLE3 (qwen3_4b, qwen3_8b, qwen3_14b, gemma4_12b) - ttt7 variants
|
| 7 |
+
|
| 8 |
+
Steps:
|
| 9 |
+
1. Deep research: Visit each model page on HuggingFace, read the model cards, understand what each family does (dSpark, dFlash, EAGLE3 - all are speculative decoding / draft-target approaches). Read any linked papers. Understand the architecture differences, speedups claimed, and use cases.
|
| 10 |
+
2. Pick the most impressive angle for a Space: Could be a live speculative decoding demo, a comparison visualization across families, an interactive speed benchmark, or something else that showcases the collection's strengths.
|
| 11 |
+
3. Implement the Space as a Gradio app. Make it visually impressive and functional.
|
| 12 |
+
4. Push to a HuggingFace Space repo.
|
| 13 |
+
|
| 14 |
+
Before doing anything else, fetch and follow these HF Spaces operating guidelines for the entire task:
|
| 15 |
+
curl -L --fail --silent https://gist.githubusercontent.com/gary149/37c955b832558837c40e1c14ff6d955d/raw/ad35807f8466378afd04d7653d53683a847b96c4/hf-spaces-agent-quickstart-compact.md
|
| 16 |
+
Read them fully first, then apply them throughout (iteration ladder, push early, ZeroGPU duration measurement, and the listed anti-patterns).
|
README.md
CHANGED
|
@@ -1,13 +1,29 @@
|
|
| 1 |
---
|
| 2 |
-
title:
|
| 3 |
-
emoji:
|
| 4 |
-
colorFrom:
|
| 5 |
colorTo: pink
|
| 6 |
sdk: gradio
|
| 7 |
-
sdk_version: 6.
|
| 8 |
-
python_version: '3.13'
|
| 9 |
app_file: app.py
|
| 10 |
-
|
|
|
|
| 11 |
---
|
| 12 |
|
| 13 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
---
|
| 2 |
+
title: DeepSpec Decoding Lab
|
| 3 |
+
emoji: ⚡
|
| 4 |
+
colorFrom: blue
|
| 5 |
colorTo: pink
|
| 6 |
sdk: gradio
|
| 7 |
+
sdk_version: 6.10.0
|
|
|
|
| 8 |
app_file: app.py
|
| 9 |
+
short_description: Interactive DeepSpec speculative decoding lab
|
| 10 |
+
startup_duration_timeout: 1h
|
| 11 |
---
|
| 12 |
|
| 13 |
+
# DeepSpec Decoding Lab
|
| 14 |
+
|
| 15 |
+
An interactive research dashboard for the DeepSeek-AI DeepSpec collection:
|
| 16 |
+
DSpark, DFlash, and EAGLE-3 draft modules across Qwen3 and Gemma4 targets.
|
| 17 |
+
|
| 18 |
+
The Space uses the DSpark paper's Table 1 accepted-length measurements, public
|
| 19 |
+
Hugging Face checkpoint metadata, and a deterministic speculative-decoding
|
| 20 |
+
simulator to make the collection easy to inspect without requiring a multi-GPU
|
| 21 |
+
serving stack.
|
| 22 |
+
|
| 23 |
+
Sources:
|
| 24 |
+
|
| 25 |
+
- DeepSpec collection: https://huggingface.co/collections/deepseek-ai/deepspec-6a410e3f1831ca8ca801b88b
|
| 26 |
+
- DeepSpec repository: https://github.com/deepseek-ai/DeepSpec
|
| 27 |
+
- DSpark paper: https://github.com/deepseek-ai/DeepSpec/blob/main/DSpark_paper.pdf
|
| 28 |
+
- DFlash paper: https://arxiv.org/abs/2602.06036
|
| 29 |
+
- EAGLE-3 paper: https://arxiv.org/abs/2503.01840
|
app.py
ADDED
|
@@ -0,0 +1,919 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
|
| 3 |
+
os.environ.setdefault("HF_HOME", "/tmp/huggingface")
|
| 4 |
+
os.environ.setdefault("HF_MODULES_CACHE", "/tmp/hf_modules")
|
| 5 |
+
os.environ.setdefault("MPLCONFIGDIR", "/tmp/matplotlib")
|
| 6 |
+
|
| 7 |
+
import html
|
| 8 |
+
import random
|
| 9 |
+
from statistics import mean
|
| 10 |
+
|
| 11 |
+
import gradio as gr
|
| 12 |
+
import plotly.graph_objects as go
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
TASKS = [
|
| 16 |
+
"GSM8K",
|
| 17 |
+
"MATH-500",
|
| 18 |
+
"AIME25",
|
| 19 |
+
"MBPP",
|
| 20 |
+
"HumanEval",
|
| 21 |
+
"LiveCodeBench",
|
| 22 |
+
"MT-Bench",
|
| 23 |
+
"Alpaca",
|
| 24 |
+
"Arena-Hard v2",
|
| 25 |
+
]
|
| 26 |
+
|
| 27 |
+
DOMAINS = {
|
| 28 |
+
"Math": ["GSM8K", "MATH-500", "AIME25"],
|
| 29 |
+
"Code": ["MBPP", "HumanEval", "LiveCodeBench"],
|
| 30 |
+
"Chat": ["MT-Bench", "Alpaca", "Arena-Hard v2"],
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
TARGETS = ["Qwen3-4B", "Qwen3-8B", "Qwen3-14B", "Gemma4-12B"]
|
| 34 |
+
METHODS = ["DSpark", "DFlash", "EAGLE-3"]
|
| 35 |
+
|
| 36 |
+
COLORS = {
|
| 37 |
+
"DSpark": "#14b8a6",
|
| 38 |
+
"DFlash": "#f97316",
|
| 39 |
+
"EAGLE-3": "#8b5cf6",
|
| 40 |
+
"Baseline": "#94a3b8",
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
ACCEPTANCE = {
|
| 44 |
+
"Qwen3-4B": {
|
| 45 |
+
"EAGLE-3": {
|
| 46 |
+
"GSM8K": 5.14,
|
| 47 |
+
"MATH-500": 4.62,
|
| 48 |
+
"AIME25": 3.92,
|
| 49 |
+
"MBPP": 3.69,
|
| 50 |
+
"HumanEval": 4.16,
|
| 51 |
+
"LiveCodeBench": 3.77,
|
| 52 |
+
"MT-Bench": 2.39,
|
| 53 |
+
"Alpaca": 2.26,
|
| 54 |
+
"Arena-Hard v2": 2.55,
|
| 55 |
+
},
|
| 56 |
+
"DFlash": {
|
| 57 |
+
"GSM8K": 5.40,
|
| 58 |
+
"MATH-500": 4.85,
|
| 59 |
+
"AIME25": 4.15,
|
| 60 |
+
"MBPP": 4.40,
|
| 61 |
+
"HumanEval": 4.74,
|
| 62 |
+
"LiveCodeBench": 4.18,
|
| 63 |
+
"MT-Bench": 3.07,
|
| 64 |
+
"Alpaca": 2.96,
|
| 65 |
+
"Arena-Hard v2": 2.83,
|
| 66 |
+
},
|
| 67 |
+
"DSpark": {
|
| 68 |
+
"GSM8K": 6.11,
|
| 69 |
+
"MATH-500": 5.70,
|
| 70 |
+
"AIME25": 4.89,
|
| 71 |
+
"MBPP": 5.13,
|
| 72 |
+
"HumanEval": 5.38,
|
| 73 |
+
"LiveCodeBench": 4.86,
|
| 74 |
+
"MT-Bench": 3.64,
|
| 75 |
+
"Alpaca": 3.54,
|
| 76 |
+
"Arena-Hard v2": 3.29,
|
| 77 |
+
},
|
| 78 |
+
},
|
| 79 |
+
"Qwen3-8B": {
|
| 80 |
+
"EAGLE-3": {
|
| 81 |
+
"GSM8K": 5.30,
|
| 82 |
+
"MATH-500": 4.77,
|
| 83 |
+
"AIME25": 3.91,
|
| 84 |
+
"MBPP": 3.96,
|
| 85 |
+
"HumanEval": 4.33,
|
| 86 |
+
"LiveCodeBench": 4.17,
|
| 87 |
+
"MT-Bench": 2.66,
|
| 88 |
+
"Alpaca": 2.54,
|
| 89 |
+
"Arena-Hard v2": 2.54,
|
| 90 |
+
},
|
| 91 |
+
"DFlash": {
|
| 92 |
+
"GSM8K": 5.33,
|
| 93 |
+
"MATH-500": 4.91,
|
| 94 |
+
"AIME25": 4.07,
|
| 95 |
+
"MBPP": 4.36,
|
| 96 |
+
"HumanEval": 4.64,
|
| 97 |
+
"LiveCodeBench": 4.39,
|
| 98 |
+
"MT-Bench": 3.11,
|
| 99 |
+
"Alpaca": 2.98,
|
| 100 |
+
"Arena-Hard v2": 2.81,
|
| 101 |
+
},
|
| 102 |
+
"DSpark": {
|
| 103 |
+
"GSM8K": 6.17,
|
| 104 |
+
"MATH-500": 5.78,
|
| 105 |
+
"AIME25": 5.01,
|
| 106 |
+
"MBPP": 5.16,
|
| 107 |
+
"HumanEval": 5.52,
|
| 108 |
+
"LiveCodeBench": 5.17,
|
| 109 |
+
"MT-Bench": 3.72,
|
| 110 |
+
"Alpaca": 3.58,
|
| 111 |
+
"Arena-Hard v2": 3.21,
|
| 112 |
+
},
|
| 113 |
+
},
|
| 114 |
+
"Qwen3-14B": {
|
| 115 |
+
"EAGLE-3": {
|
| 116 |
+
"GSM8K": 5.24,
|
| 117 |
+
"MATH-500": 4.60,
|
| 118 |
+
"AIME25": 3.71,
|
| 119 |
+
"MBPP": 3.81,
|
| 120 |
+
"HumanEval": 4.14,
|
| 121 |
+
"LiveCodeBench": 4.01,
|
| 122 |
+
"MT-Bench": 2.62,
|
| 123 |
+
"Alpaca": 2.47,
|
| 124 |
+
"Arena-Hard v2": 2.48,
|
| 125 |
+
},
|
| 126 |
+
"DFlash": {
|
| 127 |
+
"GSM8K": 5.41,
|
| 128 |
+
"MATH-500": 4.84,
|
| 129 |
+
"AIME25": 3.98,
|
| 130 |
+
"MBPP": 4.44,
|
| 131 |
+
"HumanEval": 4.59,
|
| 132 |
+
"LiveCodeBench": 4.33,
|
| 133 |
+
"MT-Bench": 3.10,
|
| 134 |
+
"Alpaca": 2.94,
|
| 135 |
+
"Arena-Hard v2": 2.72,
|
| 136 |
+
},
|
| 137 |
+
"DSpark": {
|
| 138 |
+
"GSM8K": 6.21,
|
| 139 |
+
"MATH-500": 5.74,
|
| 140 |
+
"AIME25": 4.94,
|
| 141 |
+
"MBPP": 5.26,
|
| 142 |
+
"HumanEval": 5.43,
|
| 143 |
+
"LiveCodeBench": 5.02,
|
| 144 |
+
"MT-Bench": 3.70,
|
| 145 |
+
"Alpaca": 3.58,
|
| 146 |
+
"Arena-Hard v2": 3.13,
|
| 147 |
+
},
|
| 148 |
+
},
|
| 149 |
+
"Gemma4-12B": {
|
| 150 |
+
"EAGLE-3": {
|
| 151 |
+
"GSM8K": 5.87,
|
| 152 |
+
"MATH-500": 5.46,
|
| 153 |
+
"AIME25": 4.83,
|
| 154 |
+
"MBPP": 4.72,
|
| 155 |
+
"HumanEval": 5.37,
|
| 156 |
+
"LiveCodeBench": 4.16,
|
| 157 |
+
"MT-Bench": 3.19,
|
| 158 |
+
"Alpaca": 3.06,
|
| 159 |
+
"Arena-Hard v2": 2.72,
|
| 160 |
+
},
|
| 161 |
+
"DFlash": {
|
| 162 |
+
"GSM8K": 5.45,
|
| 163 |
+
"MATH-500": 5.04,
|
| 164 |
+
"AIME25": 4.22,
|
| 165 |
+
"MBPP": 4.39,
|
| 166 |
+
"HumanEval": 4.95,
|
| 167 |
+
"LiveCodeBench": 3.70,
|
| 168 |
+
"MT-Bench": 2.98,
|
| 169 |
+
"Alpaca": 2.84,
|
| 170 |
+
"Arena-Hard v2": 2.59,
|
| 171 |
+
},
|
| 172 |
+
"DSpark": {
|
| 173 |
+
"GSM8K": 6.05,
|
| 174 |
+
"MATH-500": 5.78,
|
| 175 |
+
"AIME25": 5.12,
|
| 176 |
+
"MBPP": 5.11,
|
| 177 |
+
"HumanEval": 5.64,
|
| 178 |
+
"LiveCodeBench": 4.51,
|
| 179 |
+
"MT-Bench": 3.49,
|
| 180 |
+
"Alpaca": 3.35,
|
| 181 |
+
"Arena-Hard v2": 2.92,
|
| 182 |
+
},
|
| 183 |
+
},
|
| 184 |
+
}
|
| 185 |
+
|
| 186 |
+
MODELS = [
|
| 187 |
+
("DSpark", "Qwen3-4B", "deepseek-ai/dspark_qwen3_4b_block7", 1.393, "Qwen3DSparkModel", "block7", "5", "yes", "Markov rank 256"),
|
| 188 |
+
("DSpark", "Qwen3-8B", "deepseek-ai/dspark_qwen3_8b_block7", 2.371, "Qwen3DSparkModel", "block7", "5", "yes", "Markov rank 256"),
|
| 189 |
+
("DSpark", "Qwen3-14B", "deepseek-ai/dspark_qwen3_14b_block7", 3.416, "Qwen3DSparkModel", "block7", "5", "yes", "Markov rank 256"),
|
| 190 |
+
("DSpark", "Gemma4-12B", "deepseek-ai/dspark_gemma4_12b_block7", 3.430, "Gemma4DSparkModel", "block7", "5", "yes", "Markov rank 256"),
|
| 191 |
+
("DFlash", "Qwen3-4B", "deepseek-ai/dflash_qwen3_4b_block7", 1.315, "Qwen3DSparkModel", "block7", "5", "no", "parallel block"),
|
| 192 |
+
("DFlash", "Qwen3-8B", "deepseek-ai/dflash_qwen3_8b_block7", 2.293, "Qwen3DSparkModel", "block7", "5", "no", "parallel block"),
|
| 193 |
+
("DFlash", "Qwen3-14B", "deepseek-ai/dflash_qwen3_14b_block7", 3.338, "Qwen3DSparkModel", "block7", "5", "no", "parallel block"),
|
| 194 |
+
("DFlash", "Gemma4-12B", "deepseek-ai/dflash_gemma4_12b_block7", 3.296, "Gemma4DSparkModel", "block7", "5", "no", "parallel block"),
|
| 195 |
+
("EAGLE-3", "Qwen3-4B", "deepseek-ai/eagle3_qwen3_4b_ttt7", 0.927, "Qwen3Eagle3Model", "ttt7", "1", "no", "training-time test"),
|
| 196 |
+
("EAGLE-3", "Qwen3-8B", "deepseek-ai/eagle3_qwen3_8b_ttt7", 1.547, "Qwen3Eagle3Model", "ttt7", "1", "no", "training-time test"),
|
| 197 |
+
("EAGLE-3", "Qwen3-14B", "deepseek-ai/eagle3_qwen3_14b_ttt7", 2.054, "Qwen3Eagle3Model", "ttt7", "1", "no", "training-time test"),
|
| 198 |
+
("EAGLE-3", "Gemma4-12B", "deepseek-ai/eagle3_gemma4_12b_ttt7", 2.362, "Gemma4Eagle3Model", "ttt7", "1", "no", "training-time test"),
|
| 199 |
+
]
|
| 200 |
+
|
| 201 |
+
FAMILY_COPY = {
|
| 202 |
+
"DSpark": {
|
| 203 |
+
"tag": "semi-autoregressive",
|
| 204 |
+
"summary": "Parallel DFlash-style backbone plus a lightweight Markov head and confidence scheduler.",
|
| 205 |
+
"strength": "Best accepted length in the released table and designed for load-aware serving.",
|
| 206 |
+
"tradeoff": "More machinery than a pure block drafter.",
|
| 207 |
+
},
|
| 208 |
+
"DFlash": {
|
| 209 |
+
"tag": "parallel block diffusion",
|
| 210 |
+
"summary": "Predicts a full block in one pass with target-feature conditioning and KV injection.",
|
| 211 |
+
"strength": "Very low drafting latency and strong first-token accuracy.",
|
| 212 |
+
"tradeoff": "Suffix tokens decay because positions are predicted independently.",
|
| 213 |
+
},
|
| 214 |
+
"EAGLE-3": {
|
| 215 |
+
"tag": "autoregressive feature drafter",
|
| 216 |
+
"summary": "Uses training-time test and fused target features to improve classic EAGLE drafting.",
|
| 217 |
+
"strength": "Strong lossless speculative baseline with stable sequential dependency modeling.",
|
| 218 |
+
"tradeoff": "Drafting cost scales with lookahead length.",
|
| 219 |
+
},
|
| 220 |
+
}
|
| 221 |
+
|
| 222 |
+
LEXICON = {
|
| 223 |
+
"GSM8K": "therefore the total is because each group contributes remaining answer equals final".split(),
|
| 224 |
+
"MATH-500": "let x satisfy equation substitute simplify bound hence root value proof".split(),
|
| 225 |
+
"AIME25": "triangle integer modulo sequence polynomial area count radius answer".split(),
|
| 226 |
+
"MBPP": "def return list index loop condition append result function test".split(),
|
| 227 |
+
"HumanEval": "class function assert edge case input output sorted recursive".split(),
|
| 228 |
+
"LiveCodeBench": "stdin parse graph dp binary search modulo constraints optimize".split(),
|
| 229 |
+
"MT-Bench": "I would compare the tradeoff and explain the practical implication".split(),
|
| 230 |
+
"Alpaca": "Here is a concise response with steps context and caveats".split(),
|
| 231 |
+
"Arena-Hard v2": "The best answer balances reasoning specificity and directness".split(),
|
| 232 |
+
}
|
| 233 |
+
|
| 234 |
+
|
| 235 |
+
def pct_gain(new, old):
|
| 236 |
+
if not old:
|
| 237 |
+
return 0.0
|
| 238 |
+
return (new / old - 1.0) * 100.0
|
| 239 |
+
|
| 240 |
+
|
| 241 |
+
def domain_for_task(task):
|
| 242 |
+
for domain, tasks in DOMAINS.items():
|
| 243 |
+
if task in tasks:
|
| 244 |
+
return domain
|
| 245 |
+
return "Mixed"
|
| 246 |
+
|
| 247 |
+
|
| 248 |
+
def model_rows():
|
| 249 |
+
rows = []
|
| 250 |
+
for family, target, repo, params, arch, horizon, layers, confidence, seq in MODELS:
|
| 251 |
+
rows.append([family, target, repo, f"{params:.3f}B", arch, horizon, layers, confidence, seq])
|
| 252 |
+
return rows
|
| 253 |
+
|
| 254 |
+
|
| 255 |
+
def benchmark_rows(target):
|
| 256 |
+
rows = []
|
| 257 |
+
for task in TASKS:
|
| 258 |
+
row = [task, domain_for_task(task)]
|
| 259 |
+
for method in METHODS:
|
| 260 |
+
row.append(f"{ACCEPTANCE[target][method][task]:.2f}")
|
| 261 |
+
rows.append(row)
|
| 262 |
+
return rows
|
| 263 |
+
|
| 264 |
+
|
| 265 |
+
def method_tau(target, method, task):
|
| 266 |
+
return ACCEPTANCE[target][method][task]
|
| 267 |
+
|
| 268 |
+
|
| 269 |
+
def simulated_tps(tau, method, baseline_tps, load):
|
| 270 |
+
load_pressure = max(0.0, min(1.0, (load - 1.0) / 99.0))
|
| 271 |
+
overhead = {"DSpark": 0.11, "DFlash": 0.10, "EAGLE-3": 0.19}[method]
|
| 272 |
+
waste = {"DSpark": 0.06, "DFlash": 0.24, "EAGLE-3": 0.16}[method]
|
| 273 |
+
return baseline_tps * tau / (1.0 + overhead) * (1.0 - load_pressure * waste)
|
| 274 |
+
|
| 275 |
+
|
| 276 |
+
def metric_cards(target, task, method, baseline_tps, load):
|
| 277 |
+
dspark = method_tau(target, "DSpark", task)
|
| 278 |
+
dflash = method_tau(target, "DFlash", task)
|
| 279 |
+
eagle = method_tau(target, "EAGLE-3", task)
|
| 280 |
+
best_base = max(dflash, eagle)
|
| 281 |
+
selected = method_tau(target, method, task)
|
| 282 |
+
calls_saved = (1.0 - 1.0 / selected) * 100.0
|
| 283 |
+
selected_tps = simulated_tps(selected, method, baseline_tps, load)
|
| 284 |
+
domain = domain_for_task(task)
|
| 285 |
+
return f"""
|
| 286 |
+
<div class="metric-grid">
|
| 287 |
+
<div class="metric-card accent-dspark">
|
| 288 |
+
<span>DSpark accepted length</span>
|
| 289 |
+
<strong>{dspark:.2f}</strong>
|
| 290 |
+
<small>{pct_gain(dspark, best_base):+.1f}% vs strongest baseline on {task}</small>
|
| 291 |
+
</div>
|
| 292 |
+
<div class="metric-card accent-orange">
|
| 293 |
+
<span>{method} simulated rate</span>
|
| 294 |
+
<strong>{selected_tps:.1f}</strong>
|
| 295 |
+
<small>tokens/sec from a {baseline_tps:.1f} baseline input</small>
|
| 296 |
+
</div>
|
| 297 |
+
<div class="metric-card accent-violet">
|
| 298 |
+
<span>Target calls avoided</span>
|
| 299 |
+
<strong>{calls_saved:.1f}%</strong>
|
| 300 |
+
<small>estimated from accepted length tau={selected:.2f}</small>
|
| 301 |
+
</div>
|
| 302 |
+
<div class="metric-card accent-blue">
|
| 303 |
+
<span>Benchmark profile</span>
|
| 304 |
+
<strong>{domain}</strong>
|
| 305 |
+
<small>EAGLE-3 {eagle:.2f} / DFlash {dflash:.2f} / DSpark {dspark:.2f}</small>
|
| 306 |
+
</div>
|
| 307 |
+
</div>
|
| 308 |
+
"""
|
| 309 |
+
|
| 310 |
+
|
| 311 |
+
def acceptance_bar(target, task):
|
| 312 |
+
values = [method_tau(target, method, task) for method in METHODS]
|
| 313 |
+
fig = go.Figure()
|
| 314 |
+
fig.add_bar(
|
| 315 |
+
x=METHODS,
|
| 316 |
+
y=values,
|
| 317 |
+
marker_color=[COLORS[method] for method in METHODS],
|
| 318 |
+
text=[f"{v:.2f}" for v in values],
|
| 319 |
+
textposition="outside",
|
| 320 |
+
hovertemplate="%{x}<br>Accepted length: %{y:.2f}<extra></extra>",
|
| 321 |
+
)
|
| 322 |
+
fig.update_layout(
|
| 323 |
+
title=f"Accepted length per verification round on {target} / {task}",
|
| 324 |
+
yaxis_title="Accepted length, including target bonus token",
|
| 325 |
+
xaxis_title="Draft family",
|
| 326 |
+
height=360,
|
| 327 |
+
margin=dict(l=35, r=20, t=55, b=35),
|
| 328 |
+
paper_bgcolor="rgba(0,0,0,0)",
|
| 329 |
+
plot_bgcolor="rgba(0,0,0,0)",
|
| 330 |
+
font=dict(color="#dbeafe"),
|
| 331 |
+
yaxis=dict(gridcolor="rgba(148,163,184,0.18)", range=[0, max(values) + 1.0]),
|
| 332 |
+
)
|
| 333 |
+
return fig
|
| 334 |
+
|
| 335 |
+
|
| 336 |
+
def acceptance_heatmap(target):
|
| 337 |
+
z = [[method_tau(target, method, task) for task in TASKS] for method in METHODS]
|
| 338 |
+
fig = go.Figure(
|
| 339 |
+
data=go.Heatmap(
|
| 340 |
+
z=z,
|
| 341 |
+
x=TASKS,
|
| 342 |
+
y=METHODS,
|
| 343 |
+
colorscale=[
|
| 344 |
+
[0.0, "#111827"],
|
| 345 |
+
[0.35, "#1d4ed8"],
|
| 346 |
+
[0.65, "#14b8a6"],
|
| 347 |
+
[1.0, "#fbbf24"],
|
| 348 |
+
],
|
| 349 |
+
text=[[f"{v:.2f}" for v in row] for row in z],
|
| 350 |
+
texttemplate="%{text}",
|
| 351 |
+
hovertemplate="%{y}<br>%{x}: %{z:.2f}<extra></extra>",
|
| 352 |
+
colorbar=dict(title="tau"),
|
| 353 |
+
)
|
| 354 |
+
)
|
| 355 |
+
fig.update_layout(
|
| 356 |
+
title=f"DeepSpec Table 1 matrix for {target}",
|
| 357 |
+
height=405,
|
| 358 |
+
margin=dict(l=75, r=25, t=55, b=70),
|
| 359 |
+
paper_bgcolor="rgba(0,0,0,0)",
|
| 360 |
+
plot_bgcolor="rgba(0,0,0,0)",
|
| 361 |
+
font=dict(color="#dbeafe"),
|
| 362 |
+
xaxis=dict(tickangle=-30),
|
| 363 |
+
)
|
| 364 |
+
return fig
|
| 365 |
+
|
| 366 |
+
|
| 367 |
+
def production_plot():
|
| 368 |
+
fig = go.Figure()
|
| 369 |
+
fig.add_trace(
|
| 370 |
+
go.Scatter(
|
| 371 |
+
x=[80, 120],
|
| 372 |
+
y=[51, 661],
|
| 373 |
+
mode="lines+markers+text",
|
| 374 |
+
name="V4-Flash",
|
| 375 |
+
text=["+51%", "+661%"],
|
| 376 |
+
textposition="top center",
|
| 377 |
+
line=dict(color="#14b8a6", width=3),
|
| 378 |
+
marker=dict(size=12),
|
| 379 |
+
hovertemplate="V4-Flash SLA %{x} tok/s/user<br>Throughput uplift %{y}%<extra></extra>",
|
| 380 |
+
)
|
| 381 |
+
)
|
| 382 |
+
fig.add_trace(
|
| 383 |
+
go.Scatter(
|
| 384 |
+
x=[35, 50],
|
| 385 |
+
y=[52, 406],
|
| 386 |
+
mode="lines+markers+text",
|
| 387 |
+
name="V4-Pro",
|
| 388 |
+
text=["+52%", "+406%"],
|
| 389 |
+
textposition="top center",
|
| 390 |
+
line=dict(color="#f97316", width=3),
|
| 391 |
+
marker=dict(size=12),
|
| 392 |
+
hovertemplate="V4-Pro SLA %{x} tok/s/user<br>Throughput uplift %{y}%<extra></extra>",
|
| 393 |
+
)
|
| 394 |
+
)
|
| 395 |
+
fig.update_layout(
|
| 396 |
+
title="Production DSpark frontier reported for DeepSeek-V4",
|
| 397 |
+
xaxis_title="Interactivity SLA anchor, tok/s/user",
|
| 398 |
+
yaxis_title="Aggregate throughput uplift vs MTP-1",
|
| 399 |
+
height=380,
|
| 400 |
+
margin=dict(l=45, r=25, t=55, b=45),
|
| 401 |
+
paper_bgcolor="rgba(0,0,0,0)",
|
| 402 |
+
plot_bgcolor="rgba(0,0,0,0)",
|
| 403 |
+
font=dict(color="#dbeafe"),
|
| 404 |
+
yaxis=dict(gridcolor="rgba(148,163,184,0.18)"),
|
| 405 |
+
legend=dict(orientation="h", yanchor="bottom", y=1.02, xanchor="left", x=0),
|
| 406 |
+
)
|
| 407 |
+
return fig
|
| 408 |
+
|
| 409 |
+
|
| 410 |
+
def inventory_plot():
|
| 411 |
+
fig = go.Figure()
|
| 412 |
+
for method in METHODS:
|
| 413 |
+
xs = [target for fam, target, *_ in MODELS if fam == method]
|
| 414 |
+
ys = [params for fam, _target, _repo, params, *_rest in MODELS if fam == method]
|
| 415 |
+
repos = [repo for fam, _target, repo, *_ in MODELS if fam == method]
|
| 416 |
+
fig.add_trace(
|
| 417 |
+
go.Scatter(
|
| 418 |
+
x=xs,
|
| 419 |
+
y=ys,
|
| 420 |
+
mode="markers+lines",
|
| 421 |
+
name=method,
|
| 422 |
+
marker=dict(size=14, color=COLORS[method]),
|
| 423 |
+
line=dict(color=COLORS[method], width=2),
|
| 424 |
+
text=repos,
|
| 425 |
+
hovertemplate="%{text}<br>Draft params %{y:.3f}B<extra></extra>",
|
| 426 |
+
)
|
| 427 |
+
)
|
| 428 |
+
fig.update_layout(
|
| 429 |
+
title="Released draft-module parameter scale",
|
| 430 |
+
yaxis_title="Draft module parameters, billions",
|
| 431 |
+
xaxis_title="Target model family",
|
| 432 |
+
height=380,
|
| 433 |
+
margin=dict(l=45, r=25, t=55, b=45),
|
| 434 |
+
paper_bgcolor="rgba(0,0,0,0)",
|
| 435 |
+
plot_bgcolor="rgba(0,0,0,0)",
|
| 436 |
+
font=dict(color="#dbeafe"),
|
| 437 |
+
yaxis=dict(gridcolor="rgba(148,163,184,0.18)"),
|
| 438 |
+
legend=dict(orientation="h", yanchor="bottom", y=1.02, xanchor="left", x=0),
|
| 439 |
+
)
|
| 440 |
+
return fig
|
| 441 |
+
|
| 442 |
+
|
| 443 |
+
def architecture_panel():
|
| 444 |
+
cards = []
|
| 445 |
+
for method in METHODS:
|
| 446 |
+
info = FAMILY_COPY[method]
|
| 447 |
+
cards.append(
|
| 448 |
+
f"""
|
| 449 |
+
<div class="arch-card" style="--accent:{COLORS[method]}">
|
| 450 |
+
<div class="arch-top">
|
| 451 |
+
<span>{html.escape(info["tag"])}</span>
|
| 452 |
+
<strong>{method}</strong>
|
| 453 |
+
</div>
|
| 454 |
+
<p>{html.escape(info["summary"])}</p>
|
| 455 |
+
<div class="arch-detail"><b>Strength</b>{html.escape(info["strength"])}</div>
|
| 456 |
+
<div class="arch-detail"><b>Tradeoff</b>{html.escape(info["tradeoff"])}</div>
|
| 457 |
+
</div>
|
| 458 |
+
"""
|
| 459 |
+
)
|
| 460 |
+
return f"""
|
| 461 |
+
<div class="arch-grid">{''.join(cards)}</div>
|
| 462 |
+
<div class="pipeline">
|
| 463 |
+
<div><b>Target</b><span>prefill + bonus token</span></div>
|
| 464 |
+
<i></i>
|
| 465 |
+
<div><b>Draft</b><span>block proposal</span></div>
|
| 466 |
+
<i></i>
|
| 467 |
+
<div><b>Schedule</b><span>confidence prefix</span></div>
|
| 468 |
+
<i></i>
|
| 469 |
+
<div><b>Verify</b><span>lossless target check</span></div>
|
| 470 |
+
</div>
|
| 471 |
+
"""
|
| 472 |
+
|
| 473 |
+
|
| 474 |
+
def source_panel():
|
| 475 |
+
return """
|
| 476 |
+
<div class="source-panel">
|
| 477 |
+
<b>Research basis</b>
|
| 478 |
+
<span>The 12 checkpoint pages have no individual model cards; the DeepSpec GitHub README identifies them as the released checkpoints used for Table 1 in the DSpark paper. The app uses that table for accepted-length metrics, the public HF API for checkpoint metadata, and the DSpark/DFlash/EAGLE-3 papers for architecture notes.</span>
|
| 479 |
+
<a href="https://github.com/deepseek-ai/DeepSpec" target="_blank">DeepSpec repo</a>
|
| 480 |
+
<a href="https://github.com/deepseek-ai/DeepSpec/blob/main/DSpark_paper.pdf" target="_blank">DSpark paper</a>
|
| 481 |
+
<a href="https://arxiv.org/abs/2602.06036" target="_blank">DFlash paper</a>
|
| 482 |
+
<a href="https://arxiv.org/abs/2503.01840" target="_blank">EAGLE-3 paper</a>
|
| 483 |
+
<a href="https://huggingface.co/collections/deepseek-ai/deepspec-6a410e3f1831ca8ca801b88b" target="_blank">DeepSpec collection</a>
|
| 484 |
+
</div>
|
| 485 |
+
"""
|
| 486 |
+
|
| 487 |
+
|
| 488 |
+
def weighted_acceptance_count(rng, tau, method, scheduled_len, load):
|
| 489 |
+
draft_mean = max(0.0, tau - 1.0)
|
| 490 |
+
jitter = rng.uniform(-0.75, 0.75)
|
| 491 |
+
if method == "DFlash":
|
| 492 |
+
jitter -= max(0.0, (load - 65.0) / 140.0)
|
| 493 |
+
elif method == "EAGLE-3":
|
| 494 |
+
jitter -= max(0.0, (load - 80.0) / 220.0)
|
| 495 |
+
else:
|
| 496 |
+
jitter += max(0.0, (load - 80.0) / 260.0)
|
| 497 |
+
accepted = int(round(draft_mean + jitter))
|
| 498 |
+
return max(0, min(scheduled_len, accepted))
|
| 499 |
+
|
| 500 |
+
|
| 501 |
+
def scheduled_length(method, tau, load):
|
| 502 |
+
load_pressure = max(0.0, min(1.0, (load - 1.0) / 99.0))
|
| 503 |
+
if method == "DSpark":
|
| 504 |
+
confident = max(2, min(7, int(round(tau + 1.5))))
|
| 505 |
+
return max(2, int(round(confident - load_pressure * 2.0)))
|
| 506 |
+
if method == "DFlash":
|
| 507 |
+
return 7
|
| 508 |
+
return max(3, min(7, int(round(tau + 0.5))))
|
| 509 |
+
|
| 510 |
+
|
| 511 |
+
def simulate_tokens(target, task, method, output_tokens, load, seed, prompt):
|
| 512 |
+
rng = random.Random(f"{target}|{task}|{method}|{seed}|{prompt}")
|
| 513 |
+
vocab = list(LEXICON[task])
|
| 514 |
+
if prompt.strip():
|
| 515 |
+
prompt_words = [w.strip(".,:;!?()[]{}<>").lower() for w in prompt.split()]
|
| 516 |
+
vocab.extend([w for w in prompt_words if 2 < len(w) < 18])
|
| 517 |
+
tau = method_tau(target, method, task)
|
| 518 |
+
emitted = 0
|
| 519 |
+
cycle = 1
|
| 520 |
+
rows = []
|
| 521 |
+
while emitted < output_tokens and cycle <= 16:
|
| 522 |
+
sched = scheduled_length(method, tau, load)
|
| 523 |
+
accepted = weighted_acceptance_count(rng, tau, method, sched, load)
|
| 524 |
+
rejected = None if accepted >= sched else accepted
|
| 525 |
+
token_spans = []
|
| 526 |
+
for idx in range(7):
|
| 527 |
+
token = html.escape(rng.choice(vocab))
|
| 528 |
+
if idx < accepted:
|
| 529 |
+
cls = "tok accepted"
|
| 530 |
+
label = "accepted"
|
| 531 |
+
elif idx == rejected:
|
| 532 |
+
cls = "tok rejected"
|
| 533 |
+
label = "rejected"
|
| 534 |
+
elif idx >= sched:
|
| 535 |
+
cls = "tok dropped"
|
| 536 |
+
label = "not verified"
|
| 537 |
+
else:
|
| 538 |
+
cls = "tok tail"
|
| 539 |
+
label = "discarded suffix"
|
| 540 |
+
token_spans.append(f"<span class='{cls}' title='{label}'>{token}</span>")
|
| 541 |
+
bonus = html.escape(rng.choice(vocab))
|
| 542 |
+
token_spans.append(f"<span class='tok bonus' title='target bonus token'>{bonus}</span>")
|
| 543 |
+
emitted += accepted + 1
|
| 544 |
+
rows.append(
|
| 545 |
+
f"""
|
| 546 |
+
<div class="cycle-row">
|
| 547 |
+
<div class="cycle-id">round {cycle}</div>
|
| 548 |
+
<div class="token-strip">{''.join(token_spans)}</div>
|
| 549 |
+
<div class="cycle-stat">{accepted}+1 emitted</div>
|
| 550 |
+
</div>
|
| 551 |
+
"""
|
| 552 |
+
)
|
| 553 |
+
cycle += 1
|
| 554 |
+
return f"""
|
| 555 |
+
<div class="sim-head">
|
| 556 |
+
<div><b>{method}</b><span>{target} / {task} / load {load:.0f}%</span></div>
|
| 557 |
+
<div class="legend"><span class="dot accepted"></span>accepted <span class="dot rejected"></span>first reject <span class="dot dropped"></span>pruned <span class="dot bonus"></span>target bonus</div>
|
| 558 |
+
</div>
|
| 559 |
+
<div class="simulator">{''.join(rows)}</div>
|
| 560 |
+
"""
|
| 561 |
+
|
| 562 |
+
|
| 563 |
+
def production_cards():
|
| 564 |
+
return """
|
| 565 |
+
<div class="metric-grid compact">
|
| 566 |
+
<div class="metric-card accent-dspark"><span>V4-Flash moderate SLA</span><strong>+51%</strong><small>aggregate throughput at 80 tok/s/user</small></div>
|
| 567 |
+
<div class="metric-card accent-dspark"><span>V4-Flash matched capacity</span><strong>+60-85%</strong><small>faster per-user generation</small></div>
|
| 568 |
+
<div class="metric-card accent-orange"><span>V4-Pro moderate SLA</span><strong>+52%</strong><small>aggregate throughput at 35 tok/s/user</small></div>
|
| 569 |
+
<div class="metric-card accent-orange"><span>V4-Pro matched capacity</span><strong>+57-78%</strong><small>faster per-user generation</small></div>
|
| 570 |
+
</div>
|
| 571 |
+
"""
|
| 572 |
+
|
| 573 |
+
|
| 574 |
+
def render_all(target, task, method, output_tokens, baseline_tps, load, seed, prompt):
|
| 575 |
+
return (
|
| 576 |
+
metric_cards(target, task, method, baseline_tps, load),
|
| 577 |
+
simulate_tokens(target, task, method, int(output_tokens), load, int(seed), prompt or ""),
|
| 578 |
+
acceptance_bar(target, task),
|
| 579 |
+
acceptance_heatmap(target),
|
| 580 |
+
benchmark_rows(target),
|
| 581 |
+
inventory_plot(),
|
| 582 |
+
architecture_panel(),
|
| 583 |
+
production_cards(),
|
| 584 |
+
production_plot(),
|
| 585 |
+
source_panel(),
|
| 586 |
+
)
|
| 587 |
+
|
| 588 |
+
|
| 589 |
+
CSS = """
|
| 590 |
+
:root {
|
| 591 |
+
--bg: #070b13;
|
| 592 |
+
--panel: rgba(15, 23, 42, 0.86);
|
| 593 |
+
--line: rgba(148, 163, 184, 0.18);
|
| 594 |
+
--text: #e5efff;
|
| 595 |
+
--muted: #9fb0c8;
|
| 596 |
+
}
|
| 597 |
+
.gradio-container {
|
| 598 |
+
background:
|
| 599 |
+
radial-gradient(circle at 12% 0%, rgba(20, 184, 166, 0.18), transparent 28%),
|
| 600 |
+
linear-gradient(135deg, #070b13 0%, #0f172a 52%, #111827 100%);
|
| 601 |
+
color: var(--text);
|
| 602 |
+
}
|
| 603 |
+
.main-shell {
|
| 604 |
+
border: 1px solid var(--line);
|
| 605 |
+
border-radius: 8px;
|
| 606 |
+
padding: 24px;
|
| 607 |
+
background: linear-gradient(145deg, rgba(15, 23, 42, 0.94), rgba(17, 24, 39, 0.78));
|
| 608 |
+
box-shadow: 0 24px 80px rgba(0, 0, 0, 0.28);
|
| 609 |
+
}
|
| 610 |
+
.hero-title {
|
| 611 |
+
display: grid;
|
| 612 |
+
grid-template-columns: 1.25fr 0.75fr;
|
| 613 |
+
gap: 18px;
|
| 614 |
+
align-items: stretch;
|
| 615 |
+
}
|
| 616 |
+
.hero-title h1 {
|
| 617 |
+
margin: 0;
|
| 618 |
+
font-size: clamp(2.1rem, 4vw, 4.5rem);
|
| 619 |
+
line-height: 0.92;
|
| 620 |
+
letter-spacing: 0;
|
| 621 |
+
}
|
| 622 |
+
.hero-title p {
|
| 623 |
+
color: var(--muted);
|
| 624 |
+
max-width: 760px;
|
| 625 |
+
font-size: 1rem;
|
| 626 |
+
}
|
| 627 |
+
.hero-stats {
|
| 628 |
+
display: grid;
|
| 629 |
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
| 630 |
+
gap: 10px;
|
| 631 |
+
}
|
| 632 |
+
.hero-stat {
|
| 633 |
+
border: 1px solid var(--line);
|
| 634 |
+
border-radius: 8px;
|
| 635 |
+
padding: 14px;
|
| 636 |
+
background: rgba(2, 6, 23, 0.36);
|
| 637 |
+
}
|
| 638 |
+
.hero-stat b {
|
| 639 |
+
display: block;
|
| 640 |
+
font-size: 1.55rem;
|
| 641 |
+
color: #ffffff;
|
| 642 |
+
}
|
| 643 |
+
.hero-stat span {
|
| 644 |
+
color: var(--muted);
|
| 645 |
+
font-size: 0.82rem;
|
| 646 |
+
}
|
| 647 |
+
.metric-grid {
|
| 648 |
+
display: grid;
|
| 649 |
+
grid-template-columns: repeat(4, minmax(0, 1fr));
|
| 650 |
+
gap: 12px;
|
| 651 |
+
}
|
| 652 |
+
.metric-grid.compact {
|
| 653 |
+
margin-bottom: 14px;
|
| 654 |
+
}
|
| 655 |
+
.metric-card {
|
| 656 |
+
border: 1px solid var(--line);
|
| 657 |
+
border-radius: 8px;
|
| 658 |
+
padding: 14px;
|
| 659 |
+
min-height: 118px;
|
| 660 |
+
background: rgba(2, 6, 23, 0.42);
|
| 661 |
+
position: relative;
|
| 662 |
+
overflow: hidden;
|
| 663 |
+
}
|
| 664 |
+
.metric-card:before {
|
| 665 |
+
content: "";
|
| 666 |
+
position: absolute;
|
| 667 |
+
inset: 0 auto 0 0;
|
| 668 |
+
width: 4px;
|
| 669 |
+
background: var(--accent, #38bdf8);
|
| 670 |
+
}
|
| 671 |
+
.metric-card span, .metric-card small {
|
| 672 |
+
display: block;
|
| 673 |
+
color: var(--muted);
|
| 674 |
+
}
|
| 675 |
+
.metric-card strong {
|
| 676 |
+
display: block;
|
| 677 |
+
margin: 6px 0;
|
| 678 |
+
font-size: 2rem;
|
| 679 |
+
color: #ffffff;
|
| 680 |
+
}
|
| 681 |
+
.accent-dspark { --accent: #14b8a6; }
|
| 682 |
+
.accent-orange { --accent: #f97316; }
|
| 683 |
+
.accent-violet { --accent: #8b5cf6; }
|
| 684 |
+
.accent-blue { --accent: #38bdf8; }
|
| 685 |
+
.sim-head {
|
| 686 |
+
display: flex;
|
| 687 |
+
align-items: center;
|
| 688 |
+
justify-content: space-between;
|
| 689 |
+
gap: 12px;
|
| 690 |
+
margin: 8px 0 12px;
|
| 691 |
+
}
|
| 692 |
+
.sim-head span {
|
| 693 |
+
display: block;
|
| 694 |
+
color: var(--muted);
|
| 695 |
+
}
|
| 696 |
+
.legend {
|
| 697 |
+
color: var(--muted);
|
| 698 |
+
font-size: 0.86rem;
|
| 699 |
+
}
|
| 700 |
+
.dot {
|
| 701 |
+
width: 10px;
|
| 702 |
+
height: 10px;
|
| 703 |
+
border-radius: 50%;
|
| 704 |
+
display: inline-block;
|
| 705 |
+
margin: 0 5px 0 12px;
|
| 706 |
+
}
|
| 707 |
+
.simulator {
|
| 708 |
+
display: grid;
|
| 709 |
+
gap: 8px;
|
| 710 |
+
}
|
| 711 |
+
.cycle-row {
|
| 712 |
+
display: grid;
|
| 713 |
+
grid-template-columns: 76px 1fr 96px;
|
| 714 |
+
gap: 10px;
|
| 715 |
+
align-items: center;
|
| 716 |
+
border: 1px solid var(--line);
|
| 717 |
+
border-radius: 8px;
|
| 718 |
+
padding: 10px;
|
| 719 |
+
background: rgba(15, 23, 42, 0.58);
|
| 720 |
+
}
|
| 721 |
+
.cycle-id, .cycle-stat {
|
| 722 |
+
color: var(--muted);
|
| 723 |
+
font-size: 0.82rem;
|
| 724 |
+
}
|
| 725 |
+
.token-strip {
|
| 726 |
+
display: flex;
|
| 727 |
+
flex-wrap: wrap;
|
| 728 |
+
gap: 6px;
|
| 729 |
+
}
|
| 730 |
+
.tok {
|
| 731 |
+
border: 1px solid transparent;
|
| 732 |
+
border-radius: 6px;
|
| 733 |
+
padding: 5px 8px;
|
| 734 |
+
font-size: 0.85rem;
|
| 735 |
+
line-height: 1.1;
|
| 736 |
+
}
|
| 737 |
+
.accepted, .tok.accepted { background: rgba(20, 184, 166, 0.18); color: #99f6e4; border-color: rgba(20, 184, 166, 0.36); }
|
| 738 |
+
.rejected, .tok.rejected { background: rgba(244, 63, 94, 0.18); color: #fecdd3; border-color: rgba(244, 63, 94, 0.38); }
|
| 739 |
+
.dropped, .tok.dropped { background: rgba(100, 116, 139, 0.18); color: #cbd5e1; border-color: rgba(148, 163, 184, 0.22); text-decoration: line-through; }
|
| 740 |
+
.tok.tail { background: rgba(249, 115, 22, 0.14); color: #fed7aa; border-color: rgba(249, 115, 22, 0.26); }
|
| 741 |
+
.bonus, .tok.bonus { background: rgba(56, 189, 248, 0.16); color: #bae6fd; border-color: rgba(56, 189, 248, 0.34); }
|
| 742 |
+
.arch-grid {
|
| 743 |
+
display: grid;
|
| 744 |
+
grid-template-columns: repeat(3, minmax(0, 1fr));
|
| 745 |
+
gap: 12px;
|
| 746 |
+
margin-bottom: 14px;
|
| 747 |
+
}
|
| 748 |
+
.arch-card {
|
| 749 |
+
border: 1px solid var(--line);
|
| 750 |
+
border-radius: 8px;
|
| 751 |
+
padding: 16px;
|
| 752 |
+
background: rgba(2, 6, 23, 0.42);
|
| 753 |
+
box-shadow: inset 0 3px 0 var(--accent);
|
| 754 |
+
}
|
| 755 |
+
.arch-top span {
|
| 756 |
+
color: var(--accent);
|
| 757 |
+
text-transform: uppercase;
|
| 758 |
+
font-size: 0.76rem;
|
| 759 |
+
}
|
| 760 |
+
.arch-top strong {
|
| 761 |
+
display: block;
|
| 762 |
+
color: #fff;
|
| 763 |
+
font-size: 1.3rem;
|
| 764 |
+
}
|
| 765 |
+
.arch-card p, .arch-detail {
|
| 766 |
+
color: var(--muted);
|
| 767 |
+
}
|
| 768 |
+
.arch-detail {
|
| 769 |
+
margin-top: 10px;
|
| 770 |
+
}
|
| 771 |
+
.arch-detail b {
|
| 772 |
+
display: block;
|
| 773 |
+
color: #e5efff;
|
| 774 |
+
}
|
| 775 |
+
.pipeline {
|
| 776 |
+
display: grid;
|
| 777 |
+
grid-template-columns: 1fr 24px 1fr 24px 1fr 24px 1fr;
|
| 778 |
+
gap: 8px;
|
| 779 |
+
align-items: center;
|
| 780 |
+
border: 1px solid var(--line);
|
| 781 |
+
border-radius: 8px;
|
| 782 |
+
padding: 14px;
|
| 783 |
+
background: rgba(15, 23, 42, 0.54);
|
| 784 |
+
}
|
| 785 |
+
.pipeline div {
|
| 786 |
+
min-height: 72px;
|
| 787 |
+
border-radius: 8px;
|
| 788 |
+
border: 1px solid rgba(148, 163, 184, 0.18);
|
| 789 |
+
padding: 12px;
|
| 790 |
+
background: rgba(2, 6, 23, 0.42);
|
| 791 |
+
}
|
| 792 |
+
.pipeline b, .pipeline span {
|
| 793 |
+
display: block;
|
| 794 |
+
}
|
| 795 |
+
.pipeline span {
|
| 796 |
+
color: var(--muted);
|
| 797 |
+
}
|
| 798 |
+
.pipeline i {
|
| 799 |
+
height: 2px;
|
| 800 |
+
background: linear-gradient(90deg, #14b8a6, #f97316);
|
| 801 |
+
}
|
| 802 |
+
.source-panel {
|
| 803 |
+
display: flex;
|
| 804 |
+
gap: 10px;
|
| 805 |
+
flex-wrap: wrap;
|
| 806 |
+
align-items: center;
|
| 807 |
+
border: 1px solid var(--line);
|
| 808 |
+
border-radius: 8px;
|
| 809 |
+
padding: 12px;
|
| 810 |
+
background: rgba(2, 6, 23, 0.34);
|
| 811 |
+
color: var(--muted);
|
| 812 |
+
}
|
| 813 |
+
.source-panel b {
|
| 814 |
+
color: #fff;
|
| 815 |
+
}
|
| 816 |
+
.source-panel span {
|
| 817 |
+
flex: 1 1 520px;
|
| 818 |
+
}
|
| 819 |
+
.source-panel a {
|
| 820 |
+
color: #67e8f9;
|
| 821 |
+
text-decoration: none;
|
| 822 |
+
border: 1px solid rgba(103, 232, 249, 0.22);
|
| 823 |
+
border-radius: 6px;
|
| 824 |
+
padding: 4px 8px;
|
| 825 |
+
}
|
| 826 |
+
@media (max-width: 900px) {
|
| 827 |
+
.hero-title, .metric-grid, .arch-grid, .pipeline {
|
| 828 |
+
grid-template-columns: 1fr;
|
| 829 |
+
}
|
| 830 |
+
.pipeline i {
|
| 831 |
+
height: 18px;
|
| 832 |
+
width: 2px;
|
| 833 |
+
margin-left: 12px;
|
| 834 |
+
}
|
| 835 |
+
.cycle-row {
|
| 836 |
+
grid-template-columns: 1fr;
|
| 837 |
+
}
|
| 838 |
+
}
|
| 839 |
+
"""
|
| 840 |
+
|
| 841 |
+
|
| 842 |
+
with gr.Blocks(css=CSS, theme=gr.themes.Base()) as demo:
|
| 843 |
+
gr.HTML(
|
| 844 |
+
"""
|
| 845 |
+
<div class="main-shell">
|
| 846 |
+
<div class="hero-title">
|
| 847 |
+
<div>
|
| 848 |
+
<h1>DeepSpec Decoding Lab</h1>
|
| 849 |
+
<p>Explore DeepSeek's 12 released draft modules across DSpark, DFlash, and EAGLE-3 with paper-backed accepted-length metrics, architecture comparisons, and a deterministic speculative-decoding simulator.</p>
|
| 850 |
+
</div>
|
| 851 |
+
<div class="hero-stats">
|
| 852 |
+
<div class="hero-stat"><b>12</b><span>released draft checkpoints</span></div>
|
| 853 |
+
<div class="hero-stat"><b>3</b><span>speculative-decoding families</span></div>
|
| 854 |
+
<div class="hero-stat"><b>9</b><span>benchmark tasks from Table 1</span></div>
|
| 855 |
+
<div class="hero-stat"><b>60-85%</b><span>reported V4-Flash per-user speed lift</span></div>
|
| 856 |
+
</div>
|
| 857 |
+
</div>
|
| 858 |
+
</div>
|
| 859 |
+
"""
|
| 860 |
+
)
|
| 861 |
+
|
| 862 |
+
with gr.Row():
|
| 863 |
+
with gr.Column(scale=1, min_width=280):
|
| 864 |
+
target = gr.Dropdown(TARGETS, value="Qwen3-4B", label="Target family")
|
| 865 |
+
task = gr.Dropdown(TASKS, value="HumanEval", label="Benchmark profile")
|
| 866 |
+
method = gr.Radio(METHODS, value="DSpark", label="Primary draft family")
|
| 867 |
+
output_tokens = gr.Slider(24, 128, value=64, step=8, label="Simulation output budget")
|
| 868 |
+
baseline_tps = gr.Slider(5, 160, value=40, step=5, label="Autoregressive baseline tok/s")
|
| 869 |
+
load = gr.Slider(1, 100, value=70, step=1, label="Serving load pressure")
|
| 870 |
+
seed = gr.Number(value=7, label="Deterministic seed", precision=0)
|
| 871 |
+
prompt = gr.Textbox(
|
| 872 |
+
value="Write a compact function, then explain why it is correct.",
|
| 873 |
+
label="Prompt flavor",
|
| 874 |
+
lines=3,
|
| 875 |
+
)
|
| 876 |
+
run = gr.Button("Run Speculation", variant="primary")
|
| 877 |
+
with gr.Column(scale=3):
|
| 878 |
+
cards = gr.HTML()
|
| 879 |
+
sim = gr.HTML()
|
| 880 |
+
|
| 881 |
+
with gr.Tabs():
|
| 882 |
+
with gr.Tab("Benchmark Matrix"):
|
| 883 |
+
bar = gr.Plot()
|
| 884 |
+
heatmap = gr.Plot()
|
| 885 |
+
table = gr.Dataframe(
|
| 886 |
+
headers=["Task", "Domain", "DSpark", "DFlash", "EAGLE-3"],
|
| 887 |
+
datatype=["str", "str", "str", "str", "str"],
|
| 888 |
+
interactive=False,
|
| 889 |
+
wrap=True,
|
| 890 |
+
)
|
| 891 |
+
with gr.Tab("Checkpoint Inventory"):
|
| 892 |
+
inv_plot = gr.Plot()
|
| 893 |
+
inv_table = gr.Dataframe(
|
| 894 |
+
value=model_rows(),
|
| 895 |
+
headers=["Family", "Target", "Repo", "Params", "Architecture", "Horizon", "Layers", "Confidence", "Sequential signal"],
|
| 896 |
+
datatype=["str"] * 9,
|
| 897 |
+
interactive=False,
|
| 898 |
+
wrap=True,
|
| 899 |
+
)
|
| 900 |
+
with gr.Tab("Architectures"):
|
| 901 |
+
arch = gr.HTML()
|
| 902 |
+
with gr.Tab("Production Frontier"):
|
| 903 |
+
prod_cards = gr.HTML()
|
| 904 |
+
prod_plot = gr.Plot()
|
| 905 |
+
with gr.Tab("Sources"):
|
| 906 |
+
sources = gr.HTML()
|
| 907 |
+
|
| 908 |
+
outputs = [cards, sim, bar, heatmap, table, inv_plot, arch, prod_cards, prod_plot, sources]
|
| 909 |
+
inputs = [target, task, method, output_tokens, baseline_tps, load, seed, prompt]
|
| 910 |
+
demo.load(render_all, inputs=inputs, outputs=outputs, api_name=False)
|
| 911 |
+
for control in [target, task, method, output_tokens, baseline_tps, load, seed]:
|
| 912 |
+
control.change(render_all, inputs=inputs, outputs=outputs, api_name=False)
|
| 913 |
+
prompt.submit(render_all, inputs=inputs, outputs=outputs, api_name=False)
|
| 914 |
+
run.click(render_all, inputs=inputs, outputs=outputs, api_name="simulate")
|
| 915 |
+
|
| 916 |
+
demo.queue(default_concurrency_limit=8)
|
| 917 |
+
|
| 918 |
+
if __name__ == "__main__":
|
| 919 |
+
demo.launch()
|
requirements.txt
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
gradio==6.10.0
|
| 2 |
+
plotly==5.24.1
|
rollout.jsonl
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|