09 · 使用指南:从零到评测
本篇在总分总中是"分"的实操篇。前序 01 整体架构--08 实验复现 已讲清原理与代码,本篇给出可直接复制运行的端到端命令、5 个实战案例、自定义 target 接入流程与故障排查 FAQ。所有命令中的占位符用
<...>标注,替换即可使用。
总览段(总)
DeepSpec 的使用分四步:环境安装 → 数据准备 → 训练 → 评测。前三步是一次性投入(38TB target cache 生成最重),后两步可反复迭代(改 config 训新算法、换 checkpoint 评测)。
#mermaid-svg-nZcWsJ5aekKdYPzL{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-nZcWsJ5aekKdYPzL .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-nZcWsJ5aekKdYPzL .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-nZcWsJ5aekKdYPzL .error-icon{fill:#552222;}#mermaid-svg-nZcWsJ5aekKdYPzL .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-nZcWsJ5aekKdYPzL .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-nZcWsJ5aekKdYPzL .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-nZcWsJ5aekKdYPzL .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-nZcWsJ5aekKdYPzL .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-nZcWsJ5aekKdYPzL .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-nZcWsJ5aekKdYPzL .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-nZcWsJ5aekKdYPzL .marker{fill:#333333;stroke:#333333;}#mermaid-svg-nZcWsJ5aekKdYPzL .marker.cross{stroke:#333333;}#mermaid-svg-nZcWsJ5aekKdYPzL svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-nZcWsJ5aekKdYPzL p{margin:0;}#mermaid-svg-nZcWsJ5aekKdYPzL .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-nZcWsJ5aekKdYPzL .cluster-label text{fill:#333;}#mermaid-svg-nZcWsJ5aekKdYPzL .cluster-label span{color:#333;}#mermaid-svg-nZcWsJ5aekKdYPzL .cluster-label span p{background-color:transparent;}#mermaid-svg-nZcWsJ5aekKdYPzL .label text,#mermaid-svg-nZcWsJ5aekKdYPzL span{fill:#333;color:#333;}#mermaid-svg-nZcWsJ5aekKdYPzL .node rect,#mermaid-svg-nZcWsJ5aekKdYPzL .node circle,#mermaid-svg-nZcWsJ5aekKdYPzL .node ellipse,#mermaid-svg-nZcWsJ5aekKdYPzL .node polygon,#mermaid-svg-nZcWsJ5aekKdYPzL .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-nZcWsJ5aekKdYPzL .rough-node .label text,#mermaid-svg-nZcWsJ5aekKdYPzL .node .label text,#mermaid-svg-nZcWsJ5aekKdYPzL .image-shape .label,#mermaid-svg-nZcWsJ5aekKdYPzL .icon-shape .label{text-anchor:middle;}#mermaid-svg-nZcWsJ5aekKdYPzL .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-nZcWsJ5aekKdYPzL .rough-node .label,#mermaid-svg-nZcWsJ5aekKdYPzL .node .label,#mermaid-svg-nZcWsJ5aekKdYPzL .image-shape .label,#mermaid-svg-nZcWsJ5aekKdYPzL .icon-shape .label{text-align:center;}#mermaid-svg-nZcWsJ5aekKdYPzL .node.clickable{cursor:pointer;}#mermaid-svg-nZcWsJ5aekKdYPzL .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-nZcWsJ5aekKdYPzL .arrowheadPath{fill:#333333;}#mermaid-svg-nZcWsJ5aekKdYPzL .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-nZcWsJ5aekKdYPzL .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-nZcWsJ5aekKdYPzL .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-nZcWsJ5aekKdYPzL .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-nZcWsJ5aekKdYPzL .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-nZcWsJ5aekKdYPzL .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-nZcWsJ5aekKdYPzL .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-nZcWsJ5aekKdYPzL .cluster text{fill:#333;}#mermaid-svg-nZcWsJ5aekKdYPzL .cluster span{color:#333;}#mermaid-svg-nZcWsJ5aekKdYPzL div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-nZcWsJ5aekKdYPzL .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-nZcWsJ5aekKdYPzL rect.text{fill:none;stroke-width:0;}#mermaid-svg-nZcWsJ5aekKdYPzL .icon-shape,#mermaid-svg-nZcWsJ5aekKdYPzL .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-nZcWsJ5aekKdYPzL .icon-shape p,#mermaid-svg-nZcWsJ5aekKdYPzL .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-nZcWsJ5aekKdYPzL .icon-shape .label rect,#mermaid-svg-nZcWsJ5aekKdYPzL .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-nZcWsJ5aekKdYPzL .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-nZcWsJ5aekKdYPzL .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-nZcWsJ5aekKdYPzL :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 换 config 重训
换 ckpt 重评
④ 评测 可反复迭代
选 9 benchmark 或子集
eval.sh
τ per benchmark
③ 训练 可反复迭代
选 config
train.sh
checkpoint step_latest
② 数据 准备一次性投入
download_and_split
launch_sglang + generate_train_data
prepare_target_cache
① 环境
pip install -r requirements.txt
sglang 单独装
8 GPU + 38TB 磁盘
图说明: 全流程的关键在"数据准备一次性投入"------38TB target cache 生成耗时数天,但生成后可被所有算法的训练复用(只要 target_layer_ids 一致)。训练与评测可快速迭代:改 --opts 训新超参、换 checkpoint 评测。
分述段(分)
9.1 环境安装
bash
# 1. 安装 Python 依赖
python -m pip install -r requirements.txt
# 2. 单独安装 sglang(用于数据阶段的回答重生成)
pip install "sglang[all]"
# 3. 验证 GPU 数
nvidia-smi --list-gpus | wc -l # 期望 8
requirements.txt 不含 sglang,因 sglang 版本与 CUDA 强耦合,需单独装。HuggingFace token 与磁盘空间预先准备。
9.2 案例 1:Qwen3-4B + DSpark 全流程
最完整的 walkthrough,对应论文 Section 4.1 实验设置。
bash
# === Step 1: 下载并切分数据 ===
python scripts/data/download_and_split.py \
--dataset-name mlabonne/open-perfectblend \
--test-size 0.05 \
--train-output-path train_datasets/perfectblend_train.jsonl \
--test-output-dir eval_datasets \
--skip-existing
# 产物:train_datasets/perfectblend_train.jsonl + eval_datasets/*.jsonl
# === Step 2: 用 sglang 重生成回答 ===
# 2.1 启动 8 个 sglang worker(一个终端)
bash scripts/data/launch_sglang_server.sh
# 默认 8 端口 30000-30007,日志在 logs/sglang_qwen3_4b/
# 2.2 另一个终端跑重生成
python scripts/data/generate_train_data.py \
--model Qwen/Qwen3-4B \
--server-address 127.0.0.1:30000 127.0.0.1:30001 127.0.0.1:30002 127.0.0.1:30003 \
127.0.0.1:30004 127.0.0.1:30005 127.0.0.1:30006 127.0.0.1:30007 \
--concurrency 32 \
--temperature 0.7 --top-p 0.8 --top-k 20 --min-p 0 \
--max-tokens 4096 \
--disable-thinking \
--resume \
--input-file-path train_datasets/perfectblend_train.jsonl \
--output-file-path train_datasets/qwen3_4b/perfectblend_train_regen.jsonl
# 产物:train_datasets/qwen3_4b/perfectblend_train_regen.jsonl
# 失败样本:train_datasets/qwen3_4b/perfectblend_train_regen_error.jsonl
# 2.3 停 sglang 释放 GPU
# Ctrl+C 或 pkill -f sglang
# === Step 3: 生成 target cache(38TB!)===
export CUDA_VISIBLE_DEVICES=${CUDA_VISIBLE_DEVICES:-0,1,2,3,4,5,6,7}
export MASTER_ADDR=${MASTER_ADDR:-127.0.0.1}
export MASTER_PORT=${MASTER_PORT:-29500}
export RANK=${RANK:-0}
export WORLD_SIZE=${WORLD_SIZE:-1}
python scripts/data/prepare_target_cache.py \
--config config/dspark/dspark_qwen3_4b.py \
--train-data-path train_datasets/qwen3_4b/perfectblend_train_regen.jsonl \
--output-dir ${HOME}/.cache/deepspec/qwen3_4b_target_cache \
--local-batch-size 16
# 产物:~/.cache/deepspec/qwen3_4b_target_cache/(约 38TB)
# === Step 4: 训练 DSpark ===
bash scripts/train/train.sh
# 等价于:
python train.py \
--config config/dspark/dspark_qwen3_4b.py \
--opts "data.target_cache_path=${HOME}/.cache/deepspec/qwen3_4b_target_cache"
# 产物:~/checkpoints/deepspec/dspark_block8_qwen3_4b/step_<N>/
# ~/checkpoints/deepspec/dspark_block8_qwen3_4b/step_latest
# ~/tensorboard/deepspec/dspark_block8_qwen3_4b/
# === Step 5: 评测 ===
bash scripts/eval/eval.sh
# 等价于:
python eval.py \
--target_name_or_path Qwen/Qwen3-4B \
--draft_name_or_path ~/checkpoints/deepspec/dspark_block8_qwen3_4b/step_latest \
--temperature 1.0 \
--max-new-tokens 2048
# 产物:stdout 打印 9 benchmark 的 τ
预期产出文件 :参考 08 实验复现 §8.7 的清单。
9.3 案例 2:复用 released checkpoint 直接评测
跳过训练,直接用 DeepSeek 发布的 checkpoint 跑 9 benchmark。
bash
# DSpark on Qwen3-4B
python eval.py \
--target_name_or_path Qwen/Qwen3-4B \
--draft_name_or_path deepseek-ai/dspark_qwen3_4b_block7 \
--temperature 1.0
# DSpark on Qwen3-8B
python eval.py \
--target_name_or_path Qwen/Qwen3-8B \
--draft_name_or_path deepseek-ai/dspark_qwen3_8b_block7 \
--temperature 1.0
# DSpark on Gemma4-12B
python eval.py \
--target_name_or_path google/gemma-4-12b-it \
--draft_name_or_path deepseek-ai/dspark_gemma4_12b_block7 \
--temperature 1.0
# Eagle3 对比基线
python eval.py \
--target_name_or_path Qwen/Qwen3-4B \
--draft_name_or_path deepseek-ai/eagle3_qwen3_4b_ttt7 \
--temperature 1.0
# DFlash 对比基线
python eval.py \
--target_name_or_path Qwen/Qwen3-4B \
--draft_name_or_path deepseek-ai/dflash_qwen3_4b_block7 \
--temperature 1.0
released checkpoint 列表见 README.md:55-62(file:///workspace/README.md#L55-62),每行对应论文 Table 1 的一个 cell。
9.4 案例 3:切换到 Gemma4-12B target
Gemma4 与 Qwen3 的差异在 chat template、采样参数、attention 实现。
#mermaid-svg-V1Tm7UR02NykUriD{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-V1Tm7UR02NykUriD .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-V1Tm7UR02NykUriD .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-V1Tm7UR02NykUriD .error-icon{fill:#552222;}#mermaid-svg-V1Tm7UR02NykUriD .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-V1Tm7UR02NykUriD .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-V1Tm7UR02NykUriD .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-V1Tm7UR02NykUriD .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-V1Tm7UR02NykUriD .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-V1Tm7UR02NykUriD .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-V1Tm7UR02NykUriD .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-V1Tm7UR02NykUriD .marker{fill:#333333;stroke:#333333;}#mermaid-svg-V1Tm7UR02NykUriD .marker.cross{stroke:#333333;}#mermaid-svg-V1Tm7UR02NykUriD svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-V1Tm7UR02NykUriD p{margin:0;}#mermaid-svg-V1Tm7UR02NykUriD .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-V1Tm7UR02NykUriD .cluster-label text{fill:#333;}#mermaid-svg-V1Tm7UR02NykUriD .cluster-label span{color:#333;}#mermaid-svg-V1Tm7UR02NykUriD .cluster-label span p{background-color:transparent;}#mermaid-svg-V1Tm7UR02NykUriD .label text,#mermaid-svg-V1Tm7UR02NykUriD span{fill:#333;color:#333;}#mermaid-svg-V1Tm7UR02NykUriD .node rect,#mermaid-svg-V1Tm7UR02NykUriD .node circle,#mermaid-svg-V1Tm7UR02NykUriD .node ellipse,#mermaid-svg-V1Tm7UR02NykUriD .node polygon,#mermaid-svg-V1Tm7UR02NykUriD .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-V1Tm7UR02NykUriD .rough-node .label text,#mermaid-svg-V1Tm7UR02NykUriD .node .label text,#mermaid-svg-V1Tm7UR02NykUriD .image-shape .label,#mermaid-svg-V1Tm7UR02NykUriD .icon-shape .label{text-anchor:middle;}#mermaid-svg-V1Tm7UR02NykUriD .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-V1Tm7UR02NykUriD .rough-node .label,#mermaid-svg-V1Tm7UR02NykUriD .node .label,#mermaid-svg-V1Tm7UR02NykUriD .image-shape .label,#mermaid-svg-V1Tm7UR02NykUriD .icon-shape .label{text-align:center;}#mermaid-svg-V1Tm7UR02NykUriD .node.clickable{cursor:pointer;}#mermaid-svg-V1Tm7UR02NykUriD .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-V1Tm7UR02NykUriD .arrowheadPath{fill:#333333;}#mermaid-svg-V1Tm7UR02NykUriD .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-V1Tm7UR02NykUriD .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-V1Tm7UR02NykUriD .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-V1Tm7UR02NykUriD .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-V1Tm7UR02NykUriD .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-V1Tm7UR02NykUriD .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-V1Tm7UR02NykUriD .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-V1Tm7UR02NykUriD .cluster text{fill:#333;}#mermaid-svg-V1Tm7UR02NykUriD .cluster span{color:#333;}#mermaid-svg-V1Tm7UR02NykUriD div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-V1Tm7UR02NykUriD .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-V1Tm7UR02NykUriD rect.text{fill:none;stroke-width:0;}#mermaid-svg-V1Tm7UR02NykUriD .icon-shape,#mermaid-svg-V1Tm7UR02NykUriD .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-V1Tm7UR02NykUriD .icon-shape p,#mermaid-svg-V1Tm7UR02NykUriD .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-V1Tm7UR02NykUriD .icon-shape .label rect,#mermaid-svg-V1Tm7UR02NykUriD .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-V1Tm7UR02NykUriD .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-V1Tm7UR02NykUriD .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-V1Tm7UR02NykUriD :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Gemma4 vs Qwen3 差异
config: config/dspark/dspark_gemma4_12b.py
chat_template: 'gemma4'
assistant_loss_prefix:
'<|channel>thought
'
attention: global_head_dim
- attention_k_eq_v
logits: final_logit_softcapping
embedding: scaled sqrt H
sglang 采样参数需查官方推荐
图说明: Gemma4 切换需同时改 6 处。最关键的是 assistant_loss_prefix------Gemma4 非思考模式要求每个 assistant content 前加 <|channel>thought\n<channel|> 前缀,否则 loss_mask 会错位(parser.py:30-51(file:///workspace/deepspec/data/parser.py#L30-51) 的 gemma4 注册项)。
bash
# 1. 启动 sglang for Gemma4-12B(采样参数查官方推荐)
bash scripts/data/launch_sglang_server.sh # 改脚本里的 model 路径
# 2. 重生成回答
python scripts/data/generate_train_data.py \
--model google/gemma-4-12b-it \
--server-address 127.0.0.1:30000 127.0.0.1:30001 ... \
--temperature <查官方推荐> --top-p <...> --top-k <...> \
--max-tokens 4096 \
--input-file-path train_datasets/perfectblend_train.jsonl \
--output-file-path train_datasets/gemma4_12b/perfectblend_train_regen.jsonl
# 3. 生成 target cache(用 Gemma4 config)
python scripts/data/prepare_target_cache.py \
--config config/dspark/dspark_gemma4_12b.py \
--train-data-path train_datasets/gemma4_12b/perfectblend_train_regen.jsonl \
--output-dir ${HOME}/.cache/deepspec/gemma4_12b_target_cache \
--local-batch-size 16
# 4. 训练
python train.py \
--config config/dspark/dspark_gemma4_12b.py \
--opts "data.target_cache_path=${HOME}/.cache/deepspec/gemma4_12b_target_cache"
# 5. 评测
python eval.py \
--target_name_or_path google/gemma-4-12b-it \
--draft_name_or_path ~/checkpoints/deepspec/dspark_block8_gemma4_12b/step_latest \
--temperature 1.0
9.5 案例 4:自定义数据集接入
把自有数据集接入评测:
#mermaid-svg-UScPk0VkViNBey0d{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-UScPk0VkViNBey0d .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-UScPk0VkViNBey0d .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-UScPk0VkViNBey0d .error-icon{fill:#552222;}#mermaid-svg-UScPk0VkViNBey0d .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-UScPk0VkViNBey0d .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-UScPk0VkViNBey0d .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-UScPk0VkViNBey0d .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-UScPk0VkViNBey0d .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-UScPk0VkViNBey0d .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-UScPk0VkViNBey0d .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-UScPk0VkViNBey0d .marker{fill:#333333;stroke:#333333;}#mermaid-svg-UScPk0VkViNBey0d .marker.cross{stroke:#333333;}#mermaid-svg-UScPk0VkViNBey0d svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-UScPk0VkViNBey0d p{margin:0;}#mermaid-svg-UScPk0VkViNBey0d .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-UScPk0VkViNBey0d .cluster-label text{fill:#333;}#mermaid-svg-UScPk0VkViNBey0d .cluster-label span{color:#333;}#mermaid-svg-UScPk0VkViNBey0d .cluster-label span p{background-color:transparent;}#mermaid-svg-UScPk0VkViNBey0d .label text,#mermaid-svg-UScPk0VkViNBey0d span{fill:#333;color:#333;}#mermaid-svg-UScPk0VkViNBey0d .node rect,#mermaid-svg-UScPk0VkViNBey0d .node circle,#mermaid-svg-UScPk0VkViNBey0d .node ellipse,#mermaid-svg-UScPk0VkViNBey0d .node polygon,#mermaid-svg-UScPk0VkViNBey0d .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-UScPk0VkViNBey0d .rough-node .label text,#mermaid-svg-UScPk0VkViNBey0d .node .label text,#mermaid-svg-UScPk0VkViNBey0d .image-shape .label,#mermaid-svg-UScPk0VkViNBey0d .icon-shape .label{text-anchor:middle;}#mermaid-svg-UScPk0VkViNBey0d .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-UScPk0VkViNBey0d .rough-node .label,#mermaid-svg-UScPk0VkViNBey0d .node .label,#mermaid-svg-UScPk0VkViNBey0d .image-shape .label,#mermaid-svg-UScPk0VkViNBey0d .icon-shape .label{text-align:center;}#mermaid-svg-UScPk0VkViNBey0d .node.clickable{cursor:pointer;}#mermaid-svg-UScPk0VkViNBey0d .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-UScPk0VkViNBey0d .arrowheadPath{fill:#333333;}#mermaid-svg-UScPk0VkViNBey0d .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-UScPk0VkViNBey0d .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-UScPk0VkViNBey0d .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-UScPk0VkViNBey0d .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-UScPk0VkViNBey0d .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-UScPk0VkViNBey0d .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-UScPk0VkViNBey0d .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-UScPk0VkViNBey0d .cluster text{fill:#333;}#mermaid-svg-UScPk0VkViNBey0d .cluster span{color:#333;}#mermaid-svg-UScPk0VkViNBey0d div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-UScPk0VkViNBey0d .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-UScPk0VkViNBey0d rect.text{fill:none;stroke-width:0;}#mermaid-svg-UScPk0VkViNBey0d .icon-shape,#mermaid-svg-UScPk0VkViNBey0d .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-UScPk0VkViNBey0d .icon-shape p,#mermaid-svg-UScPk0VkViNBey0d .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-UScPk0VkViNBey0d .icon-shape .label rect,#mermaid-svg-UScPk0VkViNBey0d .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-UScPk0VkViNBey0d .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-UScPk0VkViNBey0d .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-UScPk0VkViNBey0d :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 接入步骤
准备 JSONL
每行 {turns: user_msg}
放到 eval_datasets/.jsonl
eval.py 的 TASKS 加
('your_task', N)
跑 eval.py
图说明: 评测数据格式:每行 JSON 含 {"turns": [{"role": "user", "content": "..."}]},只放 user turn(assistant 由 target/draft 生成)。在 eval.py:18-28(file:///workspace/eval.py#L18-28) 的 TASKS 列表加 ("your_task", <样本数>)。parser.py 的 GeneralParser 会用对应 chat_template 渲染。
python
# eval.py 修改示例
TASKS = [
("gsm8k", 500),
...
("your_task", 200), # 新增
]
自定义训练数据类似:JSONL 每行 {"conversations": [{"role": "user", "content": "..."}, {"role": "assistant", "content": "..."}]},用 download_and_split.py 的 ROLE_MAPPING(download_and_split.py:12-18(file:///workspace/scripts/data/download_and_split.py#L12-18))映射角色。若 role 不在已知列表,会被 validate_conversations 过滤(download_and_split.py:131-141(file:///workspace/scripts/data/download_and_split.py#L131-141))。
9.6 案例 5:调参实验
用 --opts 覆盖 config 任意字段,无需改代码:
bash
# 调 block_size(复现论文 Figure 4 proposal length 扫描)
python train.py --config config/dspark/dspark_qwen3_4b.py \
--opts "model.block_size=12" \
"data.target_cache_path=${target_cache_dir}"
# 关闭 Markov head(退化为 DFlash 行为)
python train.py --config config/dspark/dspark_qwen3_4b.py \
--opts "model.markov_rank=0" \
"data.target_cache_path=${target_cache_dir}"
# 切换 Markov head 为 RNN(复现论文 Figure 4 RNN 曲线)
python train.py --config config/dspark/dspark_qwen3_4b.py \
--opts "model.markov_head_type=rnn" \
"data.target_cache_path=${target_cache_dir}"
# 调 loss 权重
python train.py --config config/dspark/dspark_qwen3_4b.py \
--opts "model.ce_loss_alpha=0.5" "model.l1_loss_alpha=0.5" \
"data.target_cache_path=${target_cache_dir}"
# 调训练参数
python train.py --config config/dspark/dspark_qwen3_4b.py \
--opts "train.lr=3.0e-4" "train.num_train_epochs=5" \
"data.target_cache_path=${target_cache_dir}"
# 减小 num_draft_layers(复现 Figure 3 depth 扫描)
python train.py --config config/dspark/dspark_qwen3_4b.py \
--opts "model.num_draft_layers=2" \
"data.target_cache_path=${target_cache_dir}"
--opts 解析逻辑在 utils/config.py:113-131(file:///workspace/deepspec/utils/config.py#L113-131),值用 yaml 解析(数字/字符串/列表都可)。每个 --opts 一次只覆盖一个字段,多个字段多次传 --opts。
9.7 自定义 target 模型接入
#mermaid-svg-hWhlTSQM8E5HkdVw{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-hWhlTSQM8E5HkdVw .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-hWhlTSQM8E5HkdVw .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-hWhlTSQM8E5HkdVw .error-icon{fill:#552222;}#mermaid-svg-hWhlTSQM8E5HkdVw .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-hWhlTSQM8E5HkdVw .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-hWhlTSQM8E5HkdVw .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-hWhlTSQM8E5HkdVw .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-hWhlTSQM8E5HkdVw .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-hWhlTSQM8E5HkdVw .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-hWhlTSQM8E5HkdVw .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-hWhlTSQM8E5HkdVw .marker{fill:#333333;stroke:#333333;}#mermaid-svg-hWhlTSQM8E5HkdVw .marker.cross{stroke:#333333;}#mermaid-svg-hWhlTSQM8E5HkdVw svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-hWhlTSQM8E5HkdVw p{margin:0;}#mermaid-svg-hWhlTSQM8E5HkdVw .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-hWhlTSQM8E5HkdVw .cluster-label text{fill:#333;}#mermaid-svg-hWhlTSQM8E5HkdVw .cluster-label span{color:#333;}#mermaid-svg-hWhlTSQM8E5HkdVw .cluster-label span p{background-color:transparent;}#mermaid-svg-hWhlTSQM8E5HkdVw .label text,#mermaid-svg-hWhlTSQM8E5HkdVw span{fill:#333;color:#333;}#mermaid-svg-hWhlTSQM8E5HkdVw .node rect,#mermaid-svg-hWhlTSQM8E5HkdVw .node circle,#mermaid-svg-hWhlTSQM8E5HkdVw .node ellipse,#mermaid-svg-hWhlTSQM8E5HkdVw .node polygon,#mermaid-svg-hWhlTSQM8E5HkdVw .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-hWhlTSQM8E5HkdVw .rough-node .label text,#mermaid-svg-hWhlTSQM8E5HkdVw .node .label text,#mermaid-svg-hWhlTSQM8E5HkdVw .image-shape .label,#mermaid-svg-hWhlTSQM8E5HkdVw .icon-shape .label{text-anchor:middle;}#mermaid-svg-hWhlTSQM8E5HkdVw .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-hWhlTSQM8E5HkdVw .rough-node .label,#mermaid-svg-hWhlTSQM8E5HkdVw .node .label,#mermaid-svg-hWhlTSQM8E5HkdVw .image-shape .label,#mermaid-svg-hWhlTSQM8E5HkdVw .icon-shape .label{text-align:center;}#mermaid-svg-hWhlTSQM8E5HkdVw .node.clickable{cursor:pointer;}#mermaid-svg-hWhlTSQM8E5HkdVw .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-hWhlTSQM8E5HkdVw .arrowheadPath{fill:#333333;}#mermaid-svg-hWhlTSQM8E5HkdVw .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-hWhlTSQM8E5HkdVw .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-hWhlTSQM8E5HkdVw .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-hWhlTSQM8E5HkdVw .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-hWhlTSQM8E5HkdVw .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-hWhlTSQM8E5HkdVw .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-hWhlTSQM8E5HkdVw .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-hWhlTSQM8E5HkdVw .cluster text{fill:#333;}#mermaid-svg-hWhlTSQM8E5HkdVw .cluster span{color:#333;}#mermaid-svg-hWhlTSQM8E5HkdVw div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-hWhlTSQM8E5HkdVw .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-hWhlTSQM8E5HkdVw rect.text{fill:none;stroke-width:0;}#mermaid-svg-hWhlTSQM8E5HkdVw .icon-shape,#mermaid-svg-hWhlTSQM8E5HkdVw .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-hWhlTSQM8E5HkdVw .icon-shape p,#mermaid-svg-hWhlTSQM8E5HkdVw .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-hWhlTSQM8E5HkdVw .icon-shape .label rect,#mermaid-svg-hWhlTSQM8E5HkdVw .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-hWhlTSQM8E5HkdVw .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-hWhlTSQM8E5HkdVw .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-hWhlTSQM8E5HkdVw :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 接入新 target 步骤
写 config//_.py
参照 config/dspark/dspark_qwen3_4b.py
确定 target_layer_ids
不能含最后一层
确定 mask_token_id
查 target tokenizer
在 parser.py TEMPLATE_REGISTRY
注册 chat template 或复用
确定 sglang 采样参数
查 target 推荐
写 modeling///
若 target 不基于 Qwen3/Gemma4
跑数据准备 + 训练 + 评测
图说明: 接入新 target 分两种情况。情况 1 (target 基于 Qwen3/Gemma4,只是 size 不同):只需写新 config 文件,复用现有 modeling 后端,改 target_model_name_or_path、target_layer_ids(层数对得上)、mask_token_id、chat_template。情况 2 (target 是新架构,如 Llama/Mistral):需要在 deepspec/modeling/dspark/<your_backend>/ 写新后端,参照 qwen3/modeling.py(file:///workspace/deepspec/modeling/dspark/qwen3/modeling.py) 实现 Qwen3DSparkModel 等价的 forward 与 compute_logits,并加 eval/dspark/evaluator.py 的 evaluator 类与 eval.py 的 EVALUATORS 注册项。
9.8 故障排查 FAQ
Q1: OOM(显存不足)
RuntimeError: CUDA out of memory
A :① 减小 model.num_anchors(如 256);② 减小 model.num_draft_layers;③ 关闭 train.torch_compile;④ 改 train.sharding_strategy 为 full_shard。local_batch_size 不要改(已经是 1)。
Q2: target cache 不匹配
AssertionError: target_layer_ids mismatch
A :cache 是用某个 config 生成的,训练用另一个 config 时 target_layer_ids 必须一致。检查 ~/.cache/deepspec/<target>_target_cache/manifest.json 的 target_layer_ids 字段,与训练 config 对齐。
Q3: resume 失败
AssertionError: saved_world_size != world_size
A :resume 时 topology 必须一致。改 world_size/local_batch_size 不能 resume,需从头训。检查 ~/checkpoints/.../training_state.rank0.pt 的 saved_world_size。
Q4: sglang 连接超时
requests.exceptions.ReadTimeout
A :① 检查 sglang server 是否启动(curl http://127.0.0.1:30000/v1/models);② 减小 --concurrency;③ 加 --resume 跳过已完成;④ 检查 --server-address 端口数与 sglang worker 数一致。
Q5: CUDA prefetcher 报错
RuntimeError: Cannot re-initialize CUDA in forked subprocess
A :DataLoader 的 num_workers > 0 时,worker 进程不能初始化 CUDA。CUDAPrefetcher 在主进程初始化 stream,worker 只做 CPU 操作。检查 cuda_prefetcher.py:14-73(file:///workspace/deepspec/data/cuda_prefetcher.py#L14-73) 是否被正确包裹。
Q6: eval 时 confidence 校准无输出
A :--confidence-threshold 必须设为 0.0 才会启用 ConfidenceHeadRecorder(evaluator.py:46-48(file:///workspace/deepspec/eval/dspark/evaluator.py#L46-48))。设了阈值会跳过校准(因采样被截断不再无偏)。
Q7: eval 报 architectures not found
KeyError: 'LlamaForCausalLM'
A :eval.py 的 EVALUATORS 字典只认 DSpark/Eagle3 的 architectures。若 draft 是其它类型,需要:① 在 eval/ 下实现新 evaluator;② 在 eval.py:10-16 注册。
Q8: 训练 loss 不下降
A :① 检查 target_cache_path 是否正确;② 检查 loss_mask 是否覆盖 assistant 部分(用 parser 验证);③ 检查 target_layer_ids 是否在 target 模型层数范围内;④ 检查 lr 是否合适(默认 6.0e-4)。
小结段(总)
DeepSpec 的使用门槛主要在数据准备 (38TB target cache)与config 对齐 (chat template、采样参数、layer_ids)。一旦数据准备完成,训练与评测可快速迭代--------opts 让超参实验零代码改动,released checkpoint 让无训练资源的用户也能复现论文结果。
使用要点回顾:
- 环境 :
pip install -r requirements.txt+ sglang 单独装 + 8 GPU + 38TB 磁盘。 - 数据三步:download_and_split → launch_sglang + generate_train_data → prepare_target_cache。
- 训练 :
python train.py --config ... --opts ...,checkpoint 在~/checkpoints/。 - 评测 :
python eval.py --target ... --draft ...,9 benchmark 自动跑。 - 自定义:新数据集加 JSONL + 改 TASKS;新 target 写 config(基于 Qwen3/Gemma4 则无需新 modeling)。
- 调参 :
--opts "a.b.c=value"覆盖任意 config 字段,零代码改动。 - FAQ:8 类常见问题都有对应代码校验或文档警告。
延伸阅读 :进入 10 总结 看全栈工程经验提炼;进入 08 实验复现 看如何用案例 1-5 复现论文实验。论文 Section 4.1 描述的训练设置在 DSpark_paper.pdf(file:///workspace/DSpark_paper.pdf),README 的 Quick Start(file:///workspace/README.md) 给出最简命令。