
先说一个我最近经常碰到的画面团队手里有一个很强的开源底座模型拿去做行业问答比如设备故障码是啥意思、某个工艺参数怎么定、一份合同里的违约责任怎么表述。模型回答得挺流利但细看全是编的。绝大多数人的第一反应是上指令微调SFT标一批问答对调完发现模型确实会“好好说话了”但该不懂的还是不懂。问题出在哪出在你把“学会表达”和“学会知识”这两件事混为一谈了。通用大模型在预训练阶段压根没见过你手里的行业语料设备型号、工单记录、操作规范、企业内部的缩写体系这些对它来说完全是另一种语言。想真正把行业知识“吃进”模型参数里靠的是继续预训练Continued Pre-TrainingCPT而不是一轮 SFT 就能解决的。这篇文章我不绕理论直接把它讲透CPT 到底是干嘛的、行业数据怎么做、训练参数怎么配、有哪些坑、怎么评测最后给一个制造业设备运维场景的完整实战案例。不管你团队只有一两张卡还是有八卡机都能找到能直接照抄的那部分。1. 为什么通用模型已经很能打还要做继续预训练1.1 行业模型缺的不是“会聊天”而是“懂行”你把一个名校毕业的聪明人招进公司他能言善道、逻辑清楚但入职第一周你让他直接接客户电话他大概率会翻车。因为他不懂你们的产品线、内部术语、常见故障模式。他需要先读一两个月的文档把“上下文”补上然后才谈得上好好做事。大模型也是一样的道理。通用大模型的知识覆盖范围是“全网级别”的但具体到一个行业它的知识密度严重不够。问它“变压器油温异常怎么判断”它可能给出一个教科书式泛泛回答问它“你们厂这套润滑系统的换油周期为什么和标准不一样”它连你们厂是什么都不知道自然只能瞎编。这里有个关键区别要讲清楚SFT 解决的是“行为对齐”不是“知识注入”。你标了一万条问答对告诉模型“用户这么问你就这么答”模型确实学会了回答格式和语气但它回答所依赖的事实如果本身没学过那就是在记忆里硬找相似片段拼接结果就是一本正经地胡说八道。所以很多团队做完 SFT效果“看起来顺滑了”一问细节就露馅。知识注入这件事要在预训练的目标函数里做给模型喂海量连续文本让它预测下一个 token把行业术语、文档结构、业务规则一点一点压进参数里。这就是 Continued Pre-Training 的核心逻辑——在原有权重基础上继续做自监督学习让模型自己适应你的数据分布。1.2 继续预训练在模型链路里的位置一个完整的行业大模型从无到有大致是这么条链路通用预训练 → 领域继续预训练CPT→ 指令微调SFT→ 偏好对齐DPO/RLHF→ 评测上线CPT 排在最前面是因为它是地基。地基没打好后面 SFT 教出来的都是一层“表面功夫”。反过来如果 CPT 做好了模型已经熟悉了你这个行业的语言习惯你再做 SFT 时只需要少量高质量问答对就能把行为引导得非常好后面的对齐和评测都会轻松很多。有朋友会问那 RAG检索增强呢向量库检索不也能把行业资料带上吗RAG 当然有用但它和 CPT 解决的不是同一个问题。RAG 适合“查事实”——合同条款、产品参数这种随时可能更新的信息靠检索最稳妥。但 RAG 有上下文窗口限制也可能检索到噪音内容而且模型本身如果不熟悉行业语境就算你给了它资料它也不知道怎么组织成专业回答。CPT 解决的是“模型肚子里有没有货”的问题RAG 解决的是“回答时能不能引用到最新资料”的问题。成熟项目通常两个都要做不是二选一。顺带提一下最近常被提到的 PPRMPre-trained Parameter Recipe Model这类工作。它不是一个可以直接下载的模型而是一个研究方向通过一系列小规模实验学习一套“参数配方”告诉你后续的 CPT、SFT、偏好对齐应该各占多少预算、怎么安排顺序最划算。对团队来说这个思路很有参考价值——与其凭感觉定训练计划不如先用小实验定一套组合拳。2. 数据是继续预训练的命门选料、清洗、配比2.1 行业语料从哪里来哪些真能用CPT 的第一步不是写代码是找数据。我见过太多项目死在数据上不是没有数据而是数据太杂、太少、或者质量根本不行。行业内可用的语料来源大概有这么几类内部知识库和文档操作手册、维护规程、设计规范、验收标准、项目文档。这类是最高优先级的因为它们是“这个行业真正的语言”。历史业务记录工单、故障记录、客服对话、巡检记录、维修报告。这类数据口语化、碎片化但信息密度高尤其能帮模型学会“真实场景里人是怎么说的”。行业公开标准国标、行标、技术规范、白皮书。这类数据质量高适合打基础但要注意版权和合规。代码和配置如果是技术型垂直领域比如告警规则、设备参数、配置文件、脚本命令对制造业做设备运维模型非常有用。合成数据基于已有语料做改写、扩写、翻译、问答生成。合成数据可以补量但不能当主力因为它只是“对已有知识的变形”不能凭空创造新知识。另外要区分不同行业的项目侧重点。互联网行业做行业模型数据重心通常在用户行为、内容理解、客服对话、推荐场景评价指标是问题解决率、转化率这些制造业做行业模型数据重心则是设备参数、故障模式、保养周期、安全规范评价指标是误判率、故障处理准确率、维修成本下降幅度。搜数据之前先把业务目标和数据重心对齐不然白忙活。2.2 清洗和去污决定模型会不会“越学越蠢”数据不是越多越好尤其不能把脏数据直接喂进去。CPT 是自监督学习模型会把语料里的任何规律都当成“行业真相”学进去包括那些你根本不想让它学的垃圾规律。我的清洗管线一般分四步走第一步去重。重复数据在预训练里非常伤会让模型过拟合到固定片段导致生成时不断复读。除了常规的全文精确去重还要做 MinHash 模糊去重把高度相似的文档去掉。第二步去污。这是最容易被忽视的一步。如果你的评测集和训练语料有重叠评测分数会虚高上线立刻打脸。我习惯的做法是先把评测集里的关键片段拿出来和训练语料做 n-gram 重叠检测重叠率高的句子直接从训练数据里删掉。第三步去杂物。从网页抓下来的数据要清掉导航、广告、页脚从 PDF 转换来的数据要清理乱码和分页符还要过滤掉明显无意义的内容比如纯数字、纯标点、超短句。你要是发现某一段全是“点击这里原来如此更多推荐”赶紧扔。第四步安全与隐私过滤。凡是含姓名、手机号、身份证、住址、内部敏感信息的文本要么脱敏要么直接剔除。这一步不是保守是自保。行业模型一旦上线出一次隐私事故前面所有功夫都白搭。清洗完之后我还会做一个质量打分把清洗后的语料随机抽 500 条让人工或者一个小分类模型打个质量分低于阈值的直接删。宁可用 5000 万 token 的高质量语料也不用 2 亿 token 的污染语料这是 CPT 与通用预训练最大的不同——通用预训练靠量取胜行业 CPT 靠质取胜。2.3 通用数据和行业数据的配比给一个可以直接用的起点CPT 就怕一件事灾难性遗忘。模型原本好好说着通用语言你猛灌行业数据灌到后来它连常识都丢了。防止遗忘最直接的办法就是在训练数据里掺一定比例的高质量通用语料让模型“边学新知识边复习老知识”。配比给一个可操作的起点行业语料 30%50%通用语料 50%70%。刚起步不要走极端先保守一点行业数据先给三分之一看看效果再逐步往上加。通用数据不需要你特意去搜罗用公开的开源中文语料就行关键是要干净、覆盖面广。训练轮次上我强烈建议1 个 epoch 起步。CPT 不像 SFT 那样需要多轮学习领域数据反复喂太多轮过拟合和遗忘会同时找上门。你先跑一遍看行业评测指标是否满意、通用基准掉没掉再决定要不要加数据重跑而不是原地多转几圈。数据拼装时要注意格式把每条文档用固定分隔符切开然后按序列长度拼接让它尽量不截断语义块。拼接好的每条训练样本长度固定比如 4096 个 token群体感受一下就是“把文档打碎再拼成长文本流”这样 GPU 利用率高模型学习也高效。3. 训练方案和参数配置低成本续训的实操细节3.1 全参续训还是 LoRA 续训先算账再动手CPT 有两种主流做法全参数微调和 LoRA 微调。全参续训所有参数都更新模型对领域数据的拟合能力最强知识注入也最“彻底”。代价是显存需求高、训练不稳定风险大、对硬件要求高。如果你想做一个真正长期用的行业底座全参是更好的选项。LoRA 续训只更新低秩适配器底座模型参数冻结不动。好处是省显存、跑得快、不容易破坏原有能力坏处是知识注入“深度”有限——毕竟能动的参数少了模型对复杂行业规则的学习能力会打折扣。那怎么选我的建议很直接如果你有 4 张以上的 80G 显存卡做 7B 级模型直接全参 DeepSpeed ZeRO-3效果最省心。如果你只有一两张卡或者只想快速验证“这条路通不通”先上 LoRA用 1/10 的数据跑一轮看行业 PPL困惑度有没有降、降幅大不大。效果有明显变化再考虑要不要追加全参训练。实践中还有一种组合先 LoRA 快速试错定好数据配方和超参再用全参正式训练。这个路径能帮你省下大量试错成本。3.2 关键超参学习率、批次、序列长度怎么定CPT 的超参和 SFT 差很多核心原则是“稳字当头”。你是在已有权重上继续学步子迈太大前面预训练积累的通用能力就会崩。学习率方面全参续训建议 1e-52e-5LoRA 续训建议 2e-45e-4。这个区间是我实测下来比较稳的。如果你发现通用基准掉得快就往低了调。学习率调度用余弦退火前 3% 做 warmup让模型慢慢进入状态。批次大小的核心指标不是“条数”而是“一个 step 里模型看到的 token 总数”。7B 级模型我习惯把全局批次控制在 50 万100 万 token。比如序列长度 4096单卡 batch 28 张卡梯度累积 8 步那一个 step 就是 2×8×8×4096524,288 token约 52 万 token刚好合适。序列长度也很关键。行业文档往往有长上下文依赖比如一个维修规程的前半段定义故障现象后半段讲处理步骤。序列长度太短模型学不到完整逻辑链。建议设到 4096 起步条件允许可以到 8192。代价是显存和训练时间上升需要你自己权衡。训练轮次我前面说了1 个 epoch。batch 和序列长度决定了一个 step 看多少数据而总数据量除以单个 step 的 token 数就是总的 step 数再乘以单 step 时间就能估算训练时长。如果行业语料里有明显的专用词汇——比如设备型号、代码、化学品命名——还要考虑扩展词表。把高频出现、但原词表里没有的领域 token 拆出来加进 tokenizer 词表并随机初始化对应 embedding再和模型一起训练。这一步能明显提升领域文本的压缩率但也会增加实现复杂度早期可以不做。3.3 显存怎么算、卡怎么上一张表说清楚很多团队栽在算力评估上。我直接给一个粗略的显存模型方便你选卡。对一个大模型来说显存主要花在三块模型权重、优化器状态、激活值。以 7B 参数、BF16 混合精度、Adam 优化器为例模型状态大约是每参数 16 字节左右权重 2 字节 梯度 2 字节 优化器状态 12 字节也就是 7B×16B ≈ 112GB。这不是说你要 112G 显存因为可以用 ZeRO 把状态切分到多卡上。方案7B 模型大概单卡显存建议卡数适用情况LoRA CPT3040GB14 张 80G起步验证、小团队全参 ZeRO-36080GB8 张 80G正式训练、追求效果全参 ZeRO-3 CPU offload3050GB48 张 80G显存不够但训练速度会慢另外两个标配技巧开启 activation checkpointing用计算换显存基本都能省掉一大块激活值内存梯度累积也要开小显存也能模拟大批次。实话实说算力不够就先 LoRA。用 LoRA 把流程跑通、把数据配方搞定比攒着硬件干等强得多。4. 一次完整训练实录制造业设备运维行业模型4.1 项目背景、数据采集和数据清洗我拿一个真实的简化案例给你拆解方向是“制造业设备运维问答助手”。业务目标很明确设备报错后维修人员能直接问模型“报错代码 E-201 怎么处理”“这台泵上次换轴承是什么时候”“这个月的停机原因怎么归类”模型要能给出符合厂内规范的回答。数据采集阶段我们拿到几类原始语料设备操作手册 1200 份约 3GB历史工单和维修记录 20 万条约 2GB巡检报告和安全操作规程约 1.5GB设备参数表和故障码定义表约 0.5GB。加起来约 7GB 原始数据。清洗之后大约剩 5GB换算成 token 大概 15 亿左右。为了模拟真正的小团队条件我们只打算用其中 8 亿 token 作为行业语料再配 8 亿 token 的通用中文语料凑 16 亿 token 训练集。当时我们没用多复杂的数据管线就是 Python HuggingFace Datasets清洗脚本按“去重→去污→过滤→脱敏”四步串起来。最容易踩的坑是工单记录里有大量“维修老师傅”的口语缩写和错别字一开始我纠结要不要纠正后来发现不用——模型自己会从大量上下文里学会这些口语规律只要保证语料里也有足够的规范文档做参照就行。4.2 数据打包、训练脚本和 DeepSpeed 配置数据清洗完下一步拼训练样本。核心思路是“把多个文档按顺序拼到定长序列里文档之间用 EOS 分隔”。我直接把核心打包函数贴出来你按自己语料格式改成读文件就行from datasets import Dataset from transformers import AutoTokenizer def build_packed_samples(texts, tokenizer, max_length4096): buffer [] samples [] for text in texts: # 这里的清洗请按实际语料调整 if not text or len(text) 20: continue tokens tokenizer.encode(text, add_special_tokensFalse) tokens tokens [tokenizer.eos_token_id] buffer.extend(tokens) # 凑满一个窗口就切出去 while len(buffer) max_length: samples.append(buffer[:max_length]) buffer buffer[max_length:] if len(buffer) max_length // 2: samples.append(buffer[:max_length]) return samples注意最后一行如果 buffer 剩太短宁可丢掉也不要硬凑一条“半空序列”否则模型会学到“文档结尾总是一堆 padding”这是纯噪音。训练脚本用 HuggingFace Transformers 自带的 Trainer把数据文件用 jsonl 格式组织每行一条原始文档数据处理时用上面这个函数按 block_size 切分。启动命令大概是下面这样deepspeed --num_gpus8 train.py \ --model_name_or_path /path/to/base-model \ --train_file domain_data.jsonl \ --output_dir output/cpt-v1 \ --deepspeed ds_config.json \ --per_device_train_batch_size 2 \ --gradient_accumulation_steps 8 \ --block_size 4096 \ --learning_rate 1e-5 \ --lr_scheduler_type cosine \ --warmup_ratio 0.03 \ --num_train_epochs 1 \ --bf16 \ --logging_steps 10 \ --save_steps 500DeepSpeed 配置我是这么写的{ train_batch_size: auto, train_micro_batch_size_per_gpu: auto, zero_optimization: { stage: 3, offload_optimizer: {device: cpu, pin_memory: true}, overlap_comm: true, contiguous_gradients: true }, optimizer: { type: AdamW, params: {lr: auto, betas: auto, weight_decay: auto} }, scheduler: { type: WarmupDecayLR, params: {warmup_ratio: auto} }, bf16: {enabled: auto} }这套配置下16 亿 token、8 张 A100 80G、7B 模型实际跑下来大概一天半到两天。如果你用的是 4090 或者 3090 这类卡时间会成倍增加那就建议把数据减到 5 亿 token 先试。4.3 训练过程怎么盯节点怎么判断训练不是把命令敲进去就完事等跑完再看日志那是灾难。至少要做三件事第一盯 loss 曲线。正常情况是平稳下降中间偶尔有小波动。如果出现断崖式 spike比如 loss 突然从 2.5 飙到 6.0 以上基本可以断定是某个 batch 里混进了异常数据比如有一段乱码或超长重复文本。处理办法定位到那个 batch把对应样本删掉再从 spike 之前最近的 checkpoint 恢复训练。硬着头皮继续跑后面模型会越学越歪。第二隔一段保存一次 checkpoint并且拿最新 checkpoint 做快速评测。我们每隔 500 step 保存一次每 2000 step 就抽一批行业问答做一次小评测看看有没有出现“行业术语开始变多、但回答明显变傻”的迹象。让领域工程师每两三个小时看一轮输出比自己盯着 loss 有用得多。第三留一条“暂停线”。如果还没跑到 30% 就发现通用能力塌了或者 loss 完全降不下去别硬扛。停下来查数据大概率是清洗环节出了问题不要指望多跑几轮能自动修复。这里特别提醒不要只盯验证集 PPL。PPL 降低了只能说明模型对“行业文本的预测能力”变强了不一定是下游任务变好了。真正定效果要看下一章的评测。5. 评测、踩坑和上线后的迭代闭环5.1 怎么评续训效果才不是自嗨很多团队做完 CPT发个“验证集 PPL 从 8.1 降到 5.2”的喜报就宣布成功。说实话这在业务侧一文不值。CPT 的效果必须落到业务指标上。我习惯建立三套评测集行业知识集从维修手册、故障案例里整理 300500 个问题比如“清洗油路后多久需要更换滤芯”“报警代码 P-204 对应的安全处置流程是什么”。答案要由领域工程师确认过只问模型“懂不懂”不要求它用特定格式回答。通用能力集用公开的通用基准比如 CMMLU 这类中文评测或者自己整理一批常识题看模型有没有变笨。通用能力掉太多说明配置太激进。行为对抗集故意问一些“不存在的故障码”“不存在的型号”看模型会不会硬编。行业模型最忌讳的就是不懂装懂这组测试如果过不了上线就是事故。评测方式上不要只看字符串匹配。让 GPT-4 之类的强模型做裁判按“正确”“部分正确”“错误”“幻觉”四个等级打分再抽取 10% 让人工复核。跑完一轮你会很清楚问题在数据还是训练参数。5.2 常见问题与排查速查表CPT 训练中遇到大坑几乎是必然的。我把自己踩过的、帮别人排过的捋成一张表你直接对照着查现象可能原因处理方式训练 loss 突然飙升数据里有乱码、超长重复片段定位异常 batch删数据从崩点前 checkpoint 恢复行业名词会了但通用能力掉得厉害行业语料占比过高或学习率偏大提高通用语料比例降低学习率考虑换 LoRAPPL 降了但下游评测分没涨评测集与训练语料高度重叠做 n-gram 去污重新组织评测集loss 一直不降或反复震荡学习率不合适、全局 batch 太小调低学习率增大梯度累积步数模型专业内容越编越离谱行业语料太少知识没真正注入先加数据再跑一轮 CPT再做 SFT 对齐回答风格越来越像“教科书”行业语料里单一体裁过多增加工单、对话、报告等多源语料如果你手里的行业数据实在很少比如只有 1000 万 token别硬做全参 CPT。这时候更现实的做法是LoRA 续训 更保守的学习率 更多通用语料兜底同时把主力放在 RAG 上用检索补充知识。CPT 不是万能药数据少的时候别硬灌。5.3 上线之后的新数据怎么反哺模型模型上线只是开始。行业里的情况会变设备型号新增、操作规程修订、故障案例更新你要让模型持续跟得上。我建议上线后立即搭一个“坏例回收闭环”。在答疑页面加个“这个回答有用吗”的按钮技术人员把低分回答定期导出人工判断是“知识缺失”还是“行为问题”。知识缺失比如“没学过新型号的参数”归到 CPT 数据集下一轮续训补知识行为问题比如“回答格式不对、语气不好、该拒绝没拒绝”归到 SFT 数据集跟着下一轮指令微调修行为。这样每一轮 CPT 训练都不只是“重新跑一次”而是在已有知识基础上叠加上线后的新增语料。数据版本管理和评测集版本管理要同步做否则改着改着你会发现自己根本说不清上一版比这一版好在哪。我在实际操作中还有一个体会每一轮训练前先把上一轮的坏例随机抽 200 条看看模型当前答案和人工期望差多少。这个动作能帮你在训练之前就大概率预判出这轮效果比我见过的任何“训练调参玄学”都靠谱。6. 给准备动手的团队的三条实在建议最后说几条绝对能帮你少走弯路的经验。第一先用 1/10 的数据做一轮 24 小时内的试跑。不要一上来就秀“我要灌输 50 亿 token”。先用十分之一的数据把清洗、打包、训练、评测整条链路走通确认数据格式没问题、评测方式能区分好坏再放大规模。这一条能拦住至少一半的无效训练。第二不要迷信“语料越多越好”。行业模型最怕的其实不是数据少而是数据脏、分布偏。你喂了 5GB 操作手册模型确实把手册背下来了但你如果希望它应对真实维修场景的提问工单和维修记录的价值可能比手册大得多。多源语料比单一高分语料更重要。第三把指标定死在业务侧。同样是行业模型互联网行业项目可能更关心回答有没有被采纳、问题解决率提升多少制造业项目更关心故障排查准确率、误判率降了多少。你不跟业务方把这个定义清楚评测做得再花哨上线时也会被一句话噎住“效果好像也就那样。”CPT 这件事真心不神秘。它就是把“读行业书”这个动作用最朴素的自监督目标搬到模型训练里。你只需要把数据做干净、配比调稳、评测做扎实剩下的就是耐心等它消化。按照上面这套方法论一个懂行业、能干活、可迭代的行业模型是完全可以靠自己团队训练出来的。