继续预训练不是玄学:用 Axolotl 把通用模型调进法律领域的完整指南
【免费下载链接】axolotlGo ahead and axolotl questions项目地址: https://gitcode.com/GitHub_Trending/ax/axolotl
你的通用模型写合同、读判例时经常"文不对题",换几个提示词也救不回来——这类知识缺失,靠继续预训练补。本文带你用 Axolotl 走完领域适应的最小闭环:环境、流式数据、一份能直接跑的 YAML、盯盘指标,外加一个法律场景的配置差异和效果参考值。全程不需要分布式经验,一台带 40GB 显存的机器就够。
先搞清楚:继续预训练解决什么问题
通用大模型在开放域表现不错,但落到合同条款、判例文书这类文本上,术语理解、引用习惯都会露怯。继续预训练(Continued Pretraining)的思路很直接:拿现成基座,在领域语料上接着做语言建模,把领域知识"灌"进权重。它和微调最大的区别是目标不同——继续预训练补的是知识,微调教的是格式。该选哪种,可以先看这张表:
| 方案 | 本质 | 适合场景 | 硬件成本 |
|---|---|---|---|
| LoRA 微调 | 只更新少量低秩权重,模型本体不动 | 数据少、只想改输出风格或遵循指令 | 单卡即可 |
| 全参数微调 | 在指令数据上全量更新权重 | 有标注数据、想强化特定任务行为 | 多卡 |
| 继续预训练 | 在领域文本上继续做语言建模 | 领域知识整体缺失、有大规模语料 | 多卡或长周期 |
判断标准一句话:如果你的模型是"不知道",选继续预训练;如果是"知道但不会说",选微调。想清楚了再往下走,后面的环境搭建就是体力活了。
五分钟搭好训练环境
把仓库拉到本地,然后用 docker-compose 起一个带 GPU 的容器,依赖全部预装:
git clone https://gitcode.com/GitHub_Trending/ax/axolotl cd axolotl docker-compose up -d容器内工作区挂载的是仓库目录,配置文件改完即用。硬件按模型规模分级参考(以 bf16 全参数训练估算):
| 基座规模 | 起步配置 | 从容配置 | 吞吐参考 |
|---|---|---|---|
| 100M-1B | 1 张 24GB 显存卡 | 2 张 48GB 卡 | 约 8 万-15 万 tokens/s |
| 1B-8B | 4 张 80GB 卡 | 8 张 80GB 卡 | 约 4 万-8 万 tokens/s |
| 8B 以上 | 8 张 80GB 卡起步 | 多机多卡 | 按卡数线性外推打折 |
经验值:先用 135M 级别的小模型把全流程跑通,确认数据、指标、检查点都没问题,再放大到目标基座,省得大模型跑到一半发现配置错了。
环境就位后,接下来是最容易被新手卡住的一环:领域数据怎么喂给模型。
让领域数据流式喂给模型
继续预训练的数据量经常是 GB 起步,全量预处理再加载既不现实也没必要。Axolotl 的流式数据集(streaming)是边训练边从数据源拉取样本,内存占用恒定。仓库里现成的例子在 examples/streaming/pretrain.yaml,核心几行长这样:
pretraining_dataset: # 指定该字段,流式加载自动开启 - path: HuggingFaceFW/fineweb-edu text_column: text # 装正文的列名 split: train streaming_multipack_buffer_size: 10000 # 缓冲区里的样本数,越大打包越满、越吃内存 sample_packing: true # 把多条短样本拼进同一条序列,减少填充浪费 pretrain_multipack_attn: true # 隔离打包样本之间的注意力,防止互相"串话"streaming_multipack_buffer_size默认就是 10000,40GB 显存环境建议别超过这个数;发现内存吃紧就往下调。本地领域数据用 JSONL 即可,每行一个对象、必须有text字段:
{"text": "依据《民法典》第五百八十五条,约定违约金低于造成的损失的,人民法院可以根据当事人请求予以增加。"} {"text": "合同成立须具备当事人、标的与意思表示三要素,欠缺任一要素则合同不成立。"}一个提醒:法律术语、法条编号、金额数字这类信息要原样保留。过度清洗(比如把"标的额 50 万元以上"抹平成"金额较大")会让模型学到的恰恰是错的,清洗只删广告、乱码这类噪声。
数据通了,下面把一份完整配置从头到尾拆开讲,这是全文最值钱的一段。
一份能直接跑的 YAML 精讲
下面合并了 examples/streaming/pretrain.yaml 的关键项,20 行以内,可以直接当模板改:
base_model: HuggingFaceTB/SmolLM2-135M pretraining_dataset: - path: HuggingFaceFW/fineweb-edu type: pretrain text_column: text split: train sequence_len: 128 sample_packing: true pretrain_multipack_attn: true streaming_multipack_buffer_size: 10000 max_steps: 1000 learning_rate: 5e-4 warmup_ratio: 0.1 gradient_accumulation_steps: 8 micro_batch_size: 1 optimizer: adamw_torch lr_scheduler: cosine bf16: auto attn_implementation: flash_attention_2 gradient_checkpointing: true save_steps: 250 save_total_limit: 3 output_dir: ./outputs/law-pretrain序列设置:sequence_len是每条序列的长度。示例里是 135M 小模型的调试值;正式跑法律文本建议 1024-4096,因为条文和案情段落普遍偏长,序列太短会频繁截断,上下文语义被切碎。sample_packing开启后多条短样本拼进一条序列,GPU 不再为填充 token 空转;pretrain_multipack_attn则保证拼在一起的样本注意力互不干扰,两个要一起开。
训练控制:继续预训练的学习率推荐区间是 2e-5 到 5e-5,明显小于从头预训练(示例里的 5e-4 只适合 135M 这种小基座)。学习率给大了会破坏通用能力,这就是"灾难性遗忘"的主要来源。max_steps按数据量换算:粗略地,每 100 万 tokens 约需 100 步,比如 2 亿 tokens 的语料配 20000 步。warmup_ratio: 0.1表示前 10% 步数线性升温,让优化器起步更稳。save_total_limit: 3只保留最近 3 个检查点,避免磁盘撑爆。
省显存开关:gradient_checkpointing用重计算换显存,大约省一半激活内存,代价是约 20% 的算力,大基座上默认开着。flash_attention_2则同时提速和降显存,N 卡上建议常开。三个开关都开后,40GB 卡跑 1B 级模型、序列 2048 基本能装下。
配置改完就可以发出去了,但别发完就走。
训练启动后盯住这三个指标
axolotl train examples/streaming/pretrain.yaml --auto-resume--auto-resume的意思是:训练中断后重启,命令会自动从最近保存的检查点接着跑,而不是从头开始,长训练强烈建议带上。启动后重点盯三条:
- train loss:应该缓慢下降。前期每 100 步降 0.05-0.2 是正常节奏,后期每 500 步降 0.1 左右属于健康放缓;如果横盘超过 500 步,多半是学习率偏低或数据分布不均。
- 验证集 loss 与 train loss 的差值:差距稳定在 0.3 以内说明在学知识而非背数据;差距持续拉大就是过拟合信号,后面速查表里给了对应的药方。
- 显存占用:理想是稳定在 80%-90%,偶发触顶 95% 可接受;反复触顶就按"降
sequence_len→ 增gradient_accumulation_steps"的顺序处理,后者几乎不损失有效吞吐。
另外,困惑度(perplexity,就是 e 的 loss 次方,数值越低说明模型对这段文本越"熟练")是领域适应最直观的标尺。想量化对比,用这条命令在领域文本上跑评估:
axolotl evaluate examples/streaming/pretrain.yaml评估完把基座模型的 perplexity 记下来当基线,训练后在同一份文本上再评一次,下降 20%-40% 是常见幅度(参考值,随语料质量波动)。指标都健康的话,就可以把这套流程正式搬进目标行业了。
实战:把模型调进法律行业
以中文法律为对象,数据筛选走两条线:一是从公开语料库按关键词过滤,保留含"判决""合同""侵权""标的"等高频法律词的文档;二是掺入自己整理的判例、法条 JSONL 保证下限。两者比例大约 7:3 到 9:1,量靠前者、质靠后者。注意流式模式当前只支持单个数据源,所以混合数据要先合成一个数据集再挂载。
配置层面相对通用模板只需要动四处:
sequence_len: 4096 # 条文与案情段落长,给足上下文 learning_rate: 2e-5 # 正式基座用区间下沿,压制灾难性遗忘 warmup_ratio: 0.1 max_steps: 10000 # 按每 100 万 tokens 约 100 步估算,对应 1.2-2 亿 tokens训练前后在固定评测集上对比(数字为示例,实际随数据量与质量浮动):
| 参考指标 | 基座模型 | 继续预训练后 | 变化 |
|---|---|---|---|
| 法律文本困惑度 | 96.4 | 63.2 | -34.4% |
| 判例法条检索命中率 | 58.6% | 79.3% | +20.7 个百分点 |
| 法条引用准确率 | 47.2% | 68.5% | +21.3 个百分点 |
如果困惑度没明显下降,先怀疑数据——清洗过度、语料和目标场景错位,比学习率问题常见得多。当然,路上大概率还会遇到下面这几类毛病,不用逐个排查,直接查表。
踩坑速查表
| 现象 | 调整方向 | 配置示例 |
|---|---|---|
| 损失前期大幅震荡 | 增大有效批、开启混洗 | gradient_accumulation_steps: 16 |
| 显存 OOM | 缩缓冲区、换量化基座 | streaming_multipack_buffer_size: 5000 |
| 过拟合:train loss 降、验证 loss 升 | 加正则、降学习率、提前收尾 | weight_decay: 0.01 |
| 数据卡顿、吞吐骤降 | 远端源换本地缓存,或先axolotl preprocess | streaming: true |
最后一列每行只放一个最直接的开关,实际调试时一次只动一处,方便归因。问题清零后,整个流程可以浓缩成三步带走。
收尾:三步清单与延伸阅读
- 准备数据:筛出领域 JSONL(保留专业术语),或选好可流式加载的远端数据源。
- 改配置:以 examples/streaming/pretrain.yaml 为底,调
streaming_multipack_buffer_size、sequence_len、learning_rate、max_steps四处。 - 跑与盯:
axolotl train <配置文件> --auto-resume启动,盯 train loss、验证集 loss 差值、显存占用三条线;收敛后跑一次axolotl evaluate对比困惑度。
想继续深挖:examples/目录按基座模型分了子目录,examples/llama-3/fft-8b.yaml 是一份 8B 全参数微调参考配置;docs/目录里流式加载、sample packing、数据格式各有专篇,配置项报错时直接查文档比猜快得多。
最后一个建议:先用 135M 小模型把这套流程完整跑一遍,再放大到目标基座——出了问题排查成本最低的就是小模型。跑通之后,欢迎带着你的领域案例来交流配置细节。
【免费下载链接】axolotlGo ahead and axolotl questions项目地址: https://gitcode.com/GitHub_Trending/ax/axolotl
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考