HyperQwen 草稿词表工程:用 540 万 token 自建语料把 draft 覆盖率从 92% 拉到 97.5%
HyperQwen 草稿词表工程用 540 万 token 自建语料把 draft 覆盖率从 92% 拉到 97.5%【免费下载链接】HyperQwenServe large Qwen models fast on the GPUs you actually own. Qwen3.8-27B on a single 24 GB card with vLLM: 127 tok/s single-user (381 when the answer quotes the prompt), ~1,035 tok/s at 64 concurrent, 150k-262k context. vLLM patches, requant pipeline, benchmarks.项目地址: https://gitcode.com/gh_mirrors/qw/HyperQwenHyperQwen 是一个把 Qwen3.8-27B 跑在单张 24 GB 显卡上的 vLLM 加速项目单用户可做到 127 tok/s。这篇文章讲它最容易被忽略、却最能拉吞吐的一步给 MTP 投机解码建一份草稿词表draft vocabulary——先用模型自己生成的 540 万 token 语料统计高频词再把 draft 覆盖率从 92% 提到 97.5%单流速度从 98 tok/s 提到 108.6 tok/s。全程无损输出分布与不加速时完全一致。为什么投机解码需要一份草稿词表HyperQwen 的单用户模式靠MTP 投机解码提速Qwen 模型自带一个多 token 预测MTP头它先打草稿猜出接下来的若干 token再由完整模型一次前向并行验证。猜得越准一步能产出的 token 越多。但草稿器每猜一个 token都要扫一遍整个词表。Qwen3.8-27B 的词表有24.8 万行光lm_head矩阵就有 1.3 GBint8每多猜一个 token 就多花约 3 ms——草稿反而成了瓶颈。HyperQwen 的做法是 prepare/build_draft_vocab.py只保留词表里最高频的 40,960 个 token把lm_head切出一个 40k 行的小矩阵给草稿器专用完整流程见 prepare/README.md配合补丁 patches/qwen3_5-mtp-draft-vocab.patch 生效。单个草稿成本降到约 0.5–1 ms。关键规则只有一条不在这份词表里的 token永远不会被猜中——它既是一次必定的拒绝还会直接截断草稿链。所以词表覆盖多少比例的模型真实输出几乎就是投机解码吞吐的上限。92% 覆盖率被网页文本骗过的第一版词表第一版词表听起来很合理统计了丹麦网页文本fineweb-2、英文维基百科、Python 源码外加 880 万 token 的模型旧输出共 8.8M token 语料。实测它只覆盖了模型实际生成的92.1%代码场景更是只有83%。原因不复杂网页文本的词频分布 ≠ 模型在你场景下的输出分布。模型生成时大量使用思考标签、特殊标记、代码缩进、格式词……这些词在网页语料里频次低却被模型高频输出。92% 看起来很高但剩下 8% 的 token 每个都必拒绝 断链等于在每个位置上悄悄压低接受率。docs/gotchas.md 里总结得很直接92% 对 97.5% 的覆盖率差距就是 greedy 解码下98 与 109 tok/s的差距。自建 540 万 token 语料三步生成管线第二版的思路一句话别统计网上常见的词统计这个模型实际会吐出的词。管线在 drafter/ 目录总共约 6 小时 GPU 时间收题drafter/collect_prompts.py 从 UltraChat、Magicoder代码、GSM8K数学等数据集拼出6.8k 条多样化提示约 45% 开启思考模式模拟真实用法自产drafter/gen_data.py 让模型用默认采样参数离线跑完全部提示约 2.2 小时产出5.4M token 的模型自生成语料data/gen.jsonl可断点续跑建表prepare/build_draft_vocab.py 对语料做词频统计取 top 40,960 个 id外加特殊 token从已量化的lm_head中切出对应行写成mtp.draft_lm_head.*张量和mtp_draft_vocab_ids.ptid 映射。仓库已附带统计好的成品词表 prepare/draft_vocab_ids.json正好 40,960 个 id下载即用。值得一提的是防自欺设计脚本会自动把语料中每第 10 条文本留作 hold-out不参与统计、只用来评估覆盖率并顺手打印 16k/32k/48k/64k 各档词表的覆盖曲线。最终结果5.4M 自生成语料统计的词表覆盖模型输出的97.5%代码场景 96% 旧网页语料词表92%代码场景 83%。实测收益5.5 个百分点 10% 吞吐词表之外的其他配置完全没动只换这一份 id 列表草稿词表来源greedy tok/s默认采样 tok/s网页文本语料92% 覆盖98.090.0模型自生成语料97.5% 覆盖108.6107.4这是 single-user/README.md 那张单用户提速阶梯表里幅度最大的单步——从 99 tok/s 直接跳到 109 tok/s。完整优化链条和每一步的收益见 docs/optimizations.md。三个工程细节40k 为什么够、为什么无损、怎么防写坏40k 行是性价比拐点词表扩到 49k覆盖率只从 97.5% 到 98.2%实测速度也不更快——因为这个模型一辈子只会吐出约54k 个不同 token。继续加行纯属浪费显存。截断词表依然无损投机解码用拒绝采样最终样本永远来自目标模型自己的分布猜不出的位置直接用目标模型的采样结果。所以少猜只影响速度不影响质量GSM8K 96.5% 不变。原子发布防写坏脚本的所有产物都经 prepare/atomic_publish.py 走临时文件 rename且索引最后写——中途被 Ctrl-C 杀掉下次启动会自动续完不会留下半截文件。如何用自己的语料重建词表如果你跑的任务和丹麦语聊天不同比如纯中文代码助手值得用自己的语料重统计。支持.txt/.jsonlprompt/response/messages/text字段/.parquet三种格式命令只有两种python prepare/build_draft_vocab.py /path/to/model --ids prepare/draft_vocab_ids.json # 直接用仓库成品词表 python prepare/build_draft_vocab.py /path/to/model --n 40960 --corpus f1 f2 ... # 用自己的语料统计注意要先把模型目录里的lm_head量化成 int8prepare/quant_lm_head.py脚本从量化后的分片里切行运行后记得把生成的draft_vocab_ids.json复制回 prepare/ 目录以便复用。小结投机解码的天花板不在内核、不在并行而在那张 40k 行的词表上。HyperQwen 用让模型自己说话 540 万 token这一朴素手段换来 10% 的白嫖吞吐——这是整个仓库单用户数字里投入产出比最高的一步。【免费下载链接】HyperQwenServe large Qwen models fast on the GPUs you actually own. Qwen3.8-27B on a single 24 GB card with vLLM: 127 tok/s single-user (381 when the answer quotes the prompt), ~1,035 tok/s at 64 concurrent, 150k-262k context. vLLM patches, requant pipeline, benchmarks.项目地址: https://gitcode.com/gh_mirrors/qw/HyperQwen创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考