Qwen3.8 27B的后训练项目到今天算是彻底收尾了。写这篇不是为了例行汇报而是因为这一版的结果确实有点超出我自己的预期GPQA、MMLU和LCB三个评测集全部冲过90分同时平均思考量压到了原版模型的四成不到。对于一个27B规模的开源底座来说这个组合在我看来已经不只是够用的水准而是真的具备当主力模型去部署的底气了。可能有人会问三个基准都过90到底意味着什么思考量压缩是不是牺牲了准确率换来的这里我先给个结论不是。我们在把平均思考token从约1200压到约400的同时三大基准分数反而都有小幅上涨。这篇就把整个后训练的配方、踩过的坑、还有最后部署时需要注意的细节一次性讲透。适合正在做开源模型后训练、或者对推理成本和模型能力平衡有刚需的工程师来参考。1. 项目背景与目标设定1.1 为什么硬要卡在27B这个规模先说参数量。27B这个档位在后训练圈子里是一个很有意思的甜点区单卡推理能塞下量化后甚至可以在消费级显卡上跑用两到四张卡做全量微调或者LoRA成本也完全可控。相比之下70B级模型虽然能力上限更高但无论是全参微调显存压力、分布式通信开销还是线上GPU占用对于不追求极限分数的团队来说都有点重。我们当时把目标定在27B还有一个朴素考虑希望最终产物能被更多下游场景直接接走而不是只能躺在训练机房里当玩具。你去看实际业务部署很多RAG、Agent、代码补全场景并不需要模型在所有学科上无所不知但要的是推理快、回答稳、部署成本低。27B正好卡在这个需求和能力都相对均衡的位置。从后训练角度看27B的可调空间其实相当大。参数量越大的模型对数据配比的容忍度越高哪怕喂进去一些噪声它也能靠先验知识兜底。而27B这种中量级模型数据和配比稍微出点问题评测分数立刻就能给你脸色看。所以这个项目天然比其他档位更吃手艺活这也是我们感兴趣的地方。1.2 三个90分各自代表什么能力很多人习惯把MMLU当作模型聪明程度的单一指标其实这是不够的。MMLU本质上是知识广度和通用题型适应能力的测试覆盖从人文到理工的几十个学科。一个模型MMLU过了90意味着它已经有了比较完整的常识性知识覆盖和稳定的选择题答题能力但说明不了多少深度推理的问题。GPQA盯的是另一件事研究生级别的科学推理。题目本身带有相当强的专业性和多步推导要求不是靠记忆正确答案就能蒙过去的。GPQA能过90说明模型在物理、化学、生物这些硬核学科上不是背了答案而是真的具备用已知规律做逻辑推导的能力。这个分数比MMLU更难刷也是我们整个训练过程中最头疼的一项。LCB则完全是工程视角的代码评测。它和HumanEval那类静态单元测试不一样LCB要求模型生成的代码在真实沙箱里编译、运行通过隐藏测试用例才算对。LCB过90意味着模型不仅知道Python语法还能处理有一定复杂度的算法题、边界情况和多语言代码生成这直接决定了它在代码助手类产品里能不能当骨干模型用。三个90同时达成等于给模型画了一个完整的能力三角知识广、推理深、代码可用。单拎一项你可以靠偏科数据硬拉但三项同时达标基本说明整体后训练配方没有明显的短板。1.3 思考量压缩不是锦上添花前几版模型虽然分数好看但一个非常实际的问题是思考量太大。默认配置下模型在给出答案之前会先输出一大段显式思维链动辄上千token。这个开销在评测环境下无所谓真正部署到生产环境就难看了首token延迟高、卡顿感强、每轮对话账单蹭蹭涨尤其在批量离线任务里面别人的模型一分钟刷完的数据量它要三分钟才跑完。所以这次我们把思考量压缩从加分项提到了核心目标的位置并且把它和三大基准考核放在同一个优先级上。我们所定义的思考量是模型在最终答案之前生成的那段推理或草稿内容的token数。压缩它的本质不是砍掉推理能力而是想办法让27B在更少的显式中间步骤里产出同样的结论。这里的核心逻辑是模型在训练中已经学到了大量规律这些规律完全可以内化成参数上的隐式推理不需要每次都把一个完整的内心独白打出来给用户看。后面所有训练手段的设计都围绕一个主线让模型学会想得快、说得短、答得准。2. 后训练管线设计与短思考数据生产2.1 四段式后训练管线的总体编排这版后训练没有用什么花哨的新框架整体还是业内比较经典的四个阶段持续预训练、指令微调、离线偏好对齐、在线强化收尾。但每个阶段里都针对思考量压缩做了专门设计。持续预训练阶段我们只补充了大概几十B高质量token目的是补齐代码和科学领域的最新语料同时把基座的陈旧知识刷新一下。这个阶段没有刻意控制输出格式因为我们不想过早限制模型的表达空间。但数据清洗得非常仔细去重和去毒是主线宁可少喂也不能喂脏。SFT阶段才是重头戏。这一阶段决定了模型像不像一个懂行的助手指令格式、回答风格、思考链长度都在这里定型。我们在这个阶段引入了大量短思考链样本同时保留一部分中等长度的复杂推理样本作为补充让模型既知道怎么直接给答案也知道在什么情况下该多推几步。离线偏好对齐放在第三个阶段用的是DPO路线。这里有一个关键设计在当时看来有点反直觉负样本没有选择错误回答而是选择了啰嗦但正确的回答。后面会专门展开讲。在线强化收尾阶段则通过GRPO把思考长度作为重要反馈信号动态调整策略把最后那口气收敛到位。2.2 三个基准各自的数据构造思路MMLU的数据建设相对常规但也最容易出错。我们按照学科体系重新组织了一份通用知识任务池重点是把课本式问答和实际场景问题混在一起。一个容易被忽略的点是MMLU里有很多题目考查的是排除干扰项的能力我们专门加了一批带对抗干扰选项的样本让模型在做选择时学会找证据而不是凭语感蒙。GPQA的数据构造则更接近一次小型科学研究。我们从论文摘要、专业教材推导、高难度竞赛题三个方向分别采样再把这些问题拆成多步推理链条。这里的关键不是把完整解题过程给模型背下来而是给它看缺失中间步骤的推导逼着模型自己补全。我们把这种训练方式叫作跳步填空它对GPQA这种高密度推理题的提升非常明显。LCB侧重点是执行反馈。我们构造了大量题目-代码-编译执行结果的三元组把每一段生成代码放到沙箱里跑一遍然后把真实报错、超时、边界情况作为后续训练信号。代码和通用问答不一样你让模型生成的函数少个括号它自己觉得回答得再完美也是错的。所以执行反馈数据在整个代码能力提升中的占比非常高。2.3 短思考样本是怎么造出来的思考量压缩的关键落在训练数据四个字上。我们最初试过简单粗暴的办法直接让老师模型生成简短回答把长链输出截断后拿去微调。结果模型确实变短了但分数掉得很厉害因为强行截断破坏了解的完整性。这条路后来被彻底否掉了。真正有效的方法是骨架式思考蒸馏。我们让一个能力更强的老师模型在已经知道最终答案的情况下重新生成思考过程但是明确提出要求只保留那些非写不可的推导步骤省略重复验证、自我纠正和背景铺垫。这样一来老师模型输出的思考链从原来的千把token压到三四百token同时逻辑链条依然完整。再用这批骨架式思考样本做SFT模型学到的不再是思考长度必须很长的隐性偏好而是推理时只输出关键判断的风格。我们自己统计过蒸馏前后的数据在难点覆盖上没有显著差异但在输出分布上却有巨大差别。这也印证了那句话模型不是学不会短思考而是没有在数据里见过足够多优秀的短思考例子。3. 关键训练手段与超参选择3.1 SFT阶段的指令格式与输出长度控制SFT阶段最容易翻车的地方是格式不统一。同一个数据集里一会儿要求模型先输出思考再回答一会儿又要求直接答这种混乱会让27B这种规模的中量级模型变得非常拧巴。我们最终把指令格式统一成两个显式mode。普通问答和知识题走直接回答模式模型生成答案前不要求强制思考复杂推理题走精简思考模式允许模型输出最多选定长度的显式推导但要求推导过程中不允许出现自我怀疑或重复表达。这两种mode靠系统提示词中的标记区分在SFT阶段就是两种不同的训练模板。输出长度控制上我们没有只在训练参数里设max_tokens而是把它写进了训练样本的格式里每个样本都会附带一个目标输出的参考长度区间。这个设计看起来有点笨但实际效果比任何专用loss都要直接——模型在生成时天然会模仿训练样本的长度分布。另一个容易踩的坑是batch size和样本长度之间的关系。短样本多了之后如果仍然按固定token数来切batch每个batch里有效样本数会变得不稳定loss曲线看着没问题但训练出的模型对短输出的稳定性很差。我们后来改成按样本数动态调整batch内token上限训练就顺了很多。3.2 偏好对齐中的长度奖励设计DPO阶段是这次项目的一个胜负手。传统的DPO正负样本通常是好答案对坏答案。我们这次特意把负样本设置成了正确但啰嗦的答案。训练目标变成了模型不仅要答得对还要在答对的前提下尽量精简。这个设计源于一个很朴素的观察如果负样本是错误答案模型会学会区分对错但如果负样本是正确的长答案模型会学会在对和短之间建立偏好。前者提升的是知识后者提升的是表达能力。而在实际推理成本场景里后者的价值往往被严重低估。我们同时还在奖励函数里加了一个思考长度的正则惩罚项。具体做法是在GRPO阶段对每个输出的思考token数量做对数惩罚惩罚系数初期设得比较保守后期逐步加大。这个过程需要非常小心系数太大会让模型产生防御性行为——它会把思考输出隐藏到正文里表面上思考变短了实际上只是把隐性内容挪了个位置。我们后来通过大量人工抽查和关键词统计才确认模型没有把思考走私到答案段。3.3 训练配置与可复现参数给出一份当前版本的实测配置供参考。基础模型采用27B规模上下文窗口设为8192训练阶段分三段推进SFT阶段使用学习率2e-5批大小128累计跑2个epochDPO阶段学习率降到5e-6批大小64只跑1个epochGRPO阶段学习率继续降到2e-6batch是16个rollout组每组采样8条轨迹迭代了约400步。所有训练都用了bf16混合精度。我们没有做额外的梯度裁剪以外的正则化因为SFT数据本身足够干净过强正则反而会让模型输出变得呆板。序列长度上我们刻意把训练样本裁剪在2048以内超出部分直接丢弃或做截断拼接这一做法防止了模型在长上下文上浪费过多计算也让后续部署时的显存预算更加可控。如果你打算在自己的项目里复现这套流程我建议第一优先级是先跑通数据管线再动训练参数。我们最开始有过一次血泪教训训练代码和数据加载没用统一格式跑了一个epoch发现一半样本的标签是乱的白白烧了一整天的卡。4. 三大基准冲刺中必须较真的细节4.1 GPQA高难推理上最容易翻车GPQA对我来说是整个项目里最磨人的一项。它不像MMLU那样有大量常识题可以靠记忆得分每一道题都要求模型具备真正的科学推理链条。第一版模型在GPQA上只有72分左右当时我们用错误的分析去补数据比如无脑增加专业论文数据量结果分数纹丝不动。后来发现问题出在数据的形式上。GPQA的很多题需要模型先识别出题目中隐藏的科学假设再通过排除法逐步逼近正确答案。如果我们给模型的训练样本都是题目-完整解题过程这种直给形式模型学会的是模仿完整的解题套路而不是识别这段套路应该在何时使用。于是我们改成不完整推导数据只给关键结论和部分步骤要求模型推导出剩余内容。这个改变让GPQA分数一周内涨了将近10个点。评测阶段也要特别注意提示词。GPQA官方虽然允许few-shot但我们实测发现示例给多了反而会拉分因为示例的风格会诱导模型输出冗长的思考过程而在评测环境里时间不是我们的优势。最终我们选择了zero-shot加一条精简指令。4.2 MMLU90分背后的隐性风险MMLU过90听起来很漂亮但这个分数段有个隐蔽问题评测集和训练集可能存在学科不平衡。我们第一次跑出89.8分的时候分学科一看计算机和数学类接近满分而法学、经济学等社科类只有80上下。这说明模型偏科只是被整体平均掩盖了。针对这个问题的处理办法是建立分学科的分位数达标机制。我们不在整体MMLU上设单一目标而是要求每个学科小类不低于85。这个目标直接驱动了后续的学科平衡采样策略每次构建训练batch时按照各学科当前评测分数反比加权采样分数低的学科多出现分数高的学科保持热度但不再堆量。还有一点容易忽略MMLU官方题库不同版本答案顺序可能不同。如果直接用网上爬下来的任意版本做评测很可能出现因为答案选项打乱方式不同导致分数忽高忽低的情况。我们在所有评测环境里固定了题库版本和随机种子确保每次对比都在同一个标尺下。4.3 LCB代码执行评测对环境极其敏感LCB和前面两个评测都不一样它跑的是真实代码执行。这意味着评测环境本身的稳定性和依赖版本会直接影响结果。版本不匹配时哪怕模型生成的代码在逻辑上正确也会因为环境差异被判为错误执行。我们在评测机器上固定了Python版本、Node版本、核心依赖库的版本号并且把测试用例的超时阈值统一定为单用例10秒。这些看起来都是小事但如果不做好你会在两天之内收到两种完全不同的LCB分数然后开始怀疑模型训练出了什么问题。代码数据方面我们做了明显多于上一版的多样性格处理函数签名补全、类方法生成、从自然语言描述到完整脚本全部混合在一起。尤其注意提高多轮修复数据的比例让模型在第一次生成失败后有能力通过错误信息自我修正。这个能力的提升对LCB最终过90起到了决定性作用。5. 最终表现、部署配置与边界条件5.1 落地后的量化收益先说结论最终版模型在三大基准上的实测成绩是GPQA 90.2MMLU 91.4LCB 91.8。思考量方面原版模型平均输出约1200个思考token这版压到了约400个降幅接近70%。同时回答的总时长缩短了一半以上单卡部署下的吞吐量提升了接近两倍。这个收益直接换算到业务上就是成本。之前跑一个批量推理任务需要三张卡才能压制延迟现在单卡就能应付GPU开销下降得肉眼可见。对用户侧来说最直观的感受就是打字对话的停顿感明显变短了。很多用户甚至问我们是不是换了小模型来降本因为他们觉得回答变快了之后质量可能下滑实测结果倒是完全反过来。5.2 部署时的推理参数调整压缩思考量之后部署端的采样参数也要跟着调整这是很多人容易忽略的。原版模型因为思考链长温度设为0.7左右问题不大但新版本思考token少生成过程更短更直接温度如果还保持在0.7容易让输出变得略发散。我们在线上环境把temperature降到0.5top_p保持0.9效果最稳定。max_tokens的设置也建议跟着改。如果沿用原来给长思考链预留的4096上限模型不会超但它可能在答完之后继续编造一些补充性内容来填充长度反而拖慢速度。我们最后把max_tokens设为1024对绝大多数问答场景足够。如果服务端用的是vLLM或者类SGLang框架建议开启continuous batching和prefix caching短思考任务在这种模式下能把GPU的利用率拉得非常高。记得同时把streaming打开让用户看到字符逐字输出配合更短的首token延迟体感提升非常明显。5.3 边界与降级策略压缩思考量以后不是没有代价。我们观察到在少数需要超长链条推理的极端问题上比如特别复杂的高等数学证明或超长多跳逻辑题模型偶尔会出现跳步过多导致结论站不住的情况。这其实是压缩思考量的自然边界不代表模型变笨了而是在快和稳之间选择了快。针对这个场景我们在部署层做了一个简单的降级策略系统在链路里保留了一个深度模式开关当上游判断当前问题属于高难度推理题时自动切换到一个允许更多思考token的配置。如果你们的产品并不需要覆盖这种极端长链推理场景可以完全不启用但如果想要两全其美这个开关值得保留。6. 踩坑实录与问题速查表6.1 训练过程中的典型翻车现场第一坑持续预训练阶段喂了新语料结果SFT之后MMLU反而降了。排查了半天发现是持续预训练阶段没有按学科做分布静态检测新语料里的理工科比例过高把原有通识知识在权重里挤掉了。解决办法是给持续预训练语料做严格的知识分布对齐和基础模型的基座分布保持一致。第二坑DPO阶段用了错误答案做负样本模型确实变聪明了但啰嗦的风格一点没改。后来才意识到如果想要解决啰嗦问题负样本就必须是对但长而不是错。这个坑我估计很多人都会踩因为从直觉上总觉得训练目标应该优先答对。第三坑GRPO阶段加了思考长度惩罚之后发现模型开始把推理内容藏进答案正文里表面看思考token降了但总输出token数并没有明显减少。最后靠对答案正文的长度分布做人工监控加入了正文也计入长度惩罚的规则才解决。第四坑评测阶段用不同版本的题库测试发现GPQA分数忽高忽低。锁定题库版本并固定种子之后问题才消失。这也提醒我们很多模型报告的分数如果不说明评测版本根本没有横向对比价值。6.2 常见问题速查表现象排查方向解决建议训练loss下降但评测分数停滞数据污染、评测集在训练集中泄漏做精确去重剔除与评测题重合度高的样本思考量压下来后准确率明显下降短思考样本比例过高保留20%左右的长链推理样本做混合DPO阶段成绩提升缓慢负样本设计不当、batch内对比噪声大改成正确但啰嗦负样本减小对比batch代码评测分数低但本地样例通过沙箱依赖不一致、测试用例覆盖不足固定依赖版本增加隐藏用例执行问答偶尔出现答非所问温度参数偏高、短token响应分发降低temperature至0.5检查max_tokens部署后首token延迟下降不明显未开启prefix caching、模型量化不到位开启缓存用AWQ或GPTQ做4bit量化最后分享一个我们在收尾阶段才摸到的经验如果你也打算做类似压缩思考量的后训练项目最晚应该在SFT阶段就把思考长度监控加入训练指标而不是等项目快结束了才回头压缩。我们这次因为前期没有把长度指标纳入自动评估到了后期只能靠奖励函数硬坳整个过程多了差不多两周的试错成本。先想清楚你要的答案形态再决定训练配方这个顺序不能反。