最近把一个一直想做的小任务真正落地了:用 qwen3.5 0.8B 做纠正任务。所谓纠正,就是让模型把一段藏着错字、错格式、病句的文本,变成通顺、规范、可直接入库的干净文本。这类需求在客服工单清洗、OCR 后处理、用户昵称与评论审核里都很常见。0.8B 是个很小的模型,参数量只有 8 亿左右,但配合合适的方案,完全能扛住这类任务。这篇就把整个流程、踩过的坑、关键参数选择和最后的效果都记录下来,给也想捣鼓小模型落地的人做个参考。
这个任务适合谁看?如果你在做文本预处理管线、想把模型部署到普通 CPU 机器,或者手头只有一两张消费级显卡但想跑通“数据构造—微调—推理—上线”全链路,那这篇文章应该能帮你省下不少弯路的成本。
1. 任务背景与整体设计思路
1.1 0.8B 模型能做什么:纠正任务到底纠正什么
先说清楚“纠正任务”的定义。我在这次实践里没有做那种需要大量百科知识的改写,而是聚焦在三类文本问题:明显错别字、漏字多字、格式混乱。比如把“我明天想去公圆玩”纠正成“我明天想去公园玩”,把“联系电话:138xxxx1234”这种粘连无空格的信息整理成规范格式,把 OCR 识别出的“lI”纠回小写字母“li”或数字“11”——这些都是纠正任务。
为什么不直接用一个巨大的模型?因为很多业务场景里,纠正只是整条流水线的前置步骤,后面还要做实体抽取、意图识别。前置步骤要求低延迟、低显存、低成本。0.8B 模型一棵单卡就能微调,CPU 也能跑推理,这是它最大的存在价值。
1.2 方案选型:为什么不用更大模型或纯正则
我一开始其实想过两个方案:第一,直接用十几B级别的大模型做 few-shot 纠正,效果肯定不错,但单次调用延迟在普通 GPU 上就是几百毫秒甚至秒级,线上流量稍微大一点就撑不住;第二,用正则加词典写一套规则引擎,速度快,但遇到没见过的错误模式就得不停补规则,而且中文的“的地得”“再在”这类混淆,规则很难穷举。
最后选了折中路线:用 qwen3.5 0.8B 做微调。理由有三个:参数量小,推理快;中文语义理解能力在同类小模型里属于第一梯队;基础底座是公开开源权重,部署和二次开发不受限。
1.3 应用场景:我把这个模型用在了哪条链路上
这次实践的业务背景是某条客服系统的工单文本自动清洗链路。原始工单文本经常有同音字错误、OCR 识别错误、网络用语混合、标点全半角混用这些问题。清洗之后的文本要交给后续的知识库匹配模块。匹配模块之前用正则做过一轮清洗,准确率卡在 85% 左右,主要是自然语言错误处理不了。换上微调后的 0.8B 模型以后,整条链路的文本干净度明显提升,匹配准确率直接涨了 6 个百分点。
这个场景的特点非常适合小模型:输入文本很短,基本是 20 到 100 个字的短句;错误种类集中;业务方对延迟的硬要求在 100 毫秒以内。小模型在短文本上的表现,并不比大模型差多少。
2. 数据集构造与预处理
2.1 错误类型拆解
做监督微调,第一件事是定义清楚输入和输出。我把纠正任务建模成“带噪声文本到干净文本”的序列生成。刚开始我天真的以为直接找语料库随机替换几个字就行,后来发现问题没那么简单,因为错误有不同层级。
我把错误类型拆成四类:
- 字符级错误:同音字、形近字、多字漏字。比如“一部”写成“以部”,“庆”写成“床”这种。
- 词汇级错误:网络梗混入、方言词、新旧说法混用。比如“不明觉厉”出现在正式工单里,需要改成“虽然不理解但觉得很厉害”或者直接保留原意。
- 格式级错误:全半角标点混乱、多余空格、括号不匹配、日期格式不统一。
- 语义级错误:虽然字词都对,但语序颠倒导致语句不通。比如“我要卡办一张”改成“我要办一张卡”。
最开始我只给模型看在字符层面做替换的样本,结果模型学歪了,只要遇到陌生词就会强行改掉,导致过度纠正。后来把四类错误按照 5:2:2:1 的比例混合,效果才回归正常。
2.2 数据增广:如何自动生成错例
标注数据成本太高,我选择用程序自动生成。具体方法是拿干净语料做正向增广:随机选择错误类型,按概率改变文本。
同音字替换用拼音库实现,形近字替换用字形相似字表,漏字就是随机删掉一个字,多字就是随机插入一个高频误用字。格式错误则用脚本统一做全角转半角、反转、加多余空格等操作。语义级语序颠倒就麻烦一点,我写了一个基于依存关系简单换位的规则,只对较短句子做动作。
每个干净句子生成 5 个带噪声版本,输入是噪声版本,输出是原始干净句子。数据规模做到 20 万对左右,训练集和验证集按 9:1 切分,确保验证集里有未参与生成的错误组合。
2.3 标注规范与清洗流程
生成完数据并不代表直接能用。清洗流程我建议按下面顺序走:
- 删除原始干净语料里本身就有问题的句子,比如明显的广告文案、无意义字符。
- 处理超长短句,统一截断或者过滤。任务设定为 128 token 以内的短文本,超过的直接丢弃。
- 过滤英文占比过高的样本。这个模型虽然支持中英混合,但当前场景主要是中文,英文样本比例控制在 5% 以内。
- 做一轮嵌入相似度检查,过滤掉那些增广后语义完全跑偏的极端样本。
这一步做扎实,后面模型训练出的效果就稳。我刚开始偷懒省掉第 4 步,结果验证集 loss 掉不下去,检查数据才发现有不少错例对根本没对齐,学不到正确映射关系。
2.4 训练/验证/测试集划分
训练集 16 万对,验证集 2 万对,另外单独留了 5000 条人工标注的测试集。人工测试集非常关键,因为程序自动生成的错误模式和真实世界的错误模式有偏差。那 5000 条是从真实工单里捞出来、由业务同事手工修正的,虽然数量不多,但评估结果最可信。
数据划分时注意一个坑:按句子去重再划分。如果不做去重,同一个句子衍生出的多个噪声版本可能同时出现在训练集和测试集里,模型在测试集上看着效果很好,真实效果其实很虚。我用 SimHash 对句子做了模糊去重,保证跨集合的句子相似度低于阈值。
3. 模型微调与训练配置
3.1 基座模型选择与加载
用的是 qwen3.5 0.8B 的 base 版。加载的时候直接用 transformer 库,不需要额外的适配层。这个模型的 tokenizer 支持中英文混合,词汇表覆盖比较全,数字和标点处理都不错,这对我后续做格式纠偏很重要。
设备方面,单张消费级显卡 16G 显存足够。说实话,0.8B 的模型全参微调也只要十几G左右的显存,但我最终选择 LoRA 而不是全参微调,原因放到后面说。
3.2 关键训练参数:学习率、batch size、输入长度
训练配置我直接列出来,这是跑通之后稳定使用的参数组合:
- 输入最大长度:128 token
- 输出最大长度:128 token
- 学习率:5e-5,带 warmup,前 500 步线性增长
- batch size:64,梯度累积后等效 batch size 256
- 训练轮数:3 轮
- 优化器:AdamW
- 权重衰减:0.01
学习率这个参数要特别强调。0.8B 这种小参数量模型,学习率设太大会导致基础语义能力崩塌,设太小又学不到纠错规律。5e-5 是我试过的平衡点。如果你用的是更大模型,比如 3B 以上,学习率最好再降一个量级。
3.3 LoRA 还是全参微调
我选了 LoRA。主要原因不是显存不够,而是工程迭代效率。LoRA 的 checkpoint 只有几十 MB,全量微调一个 checkpoint 要好几个 G。业务上线后肯定要不断用新数据迭代纠错能力,每次全量微调几小时,LoRA 训练只要二三十分钟,这个差距决定了迭代节奏。
LoRA 配置:
- rank:16
- alpha:32
- dropout:0.05
- 用 Attention 层的 Q 和 V 矩阵加 LoRA,拼接线性层没动
rank 不是越大越好。我测过 rank 8、rank 16、rank 32,rank 8 在错误率高的样本上表现弱,rank 32 效果没有明显提升反而有一点点过拟合。16 是当前数据规模下最稳的。
3.4 评估指标:字错误率、句错误率、编辑距离
纠正任务常用三个指标:字错误率(CER)、句错误率(SER)、编辑距离。CER 是计算纠正后文本与标准文本之间字级别的替换、删除、插入次数占总字数的比例;SER 是计算完全一致的句子占比;编辑距离直接反映修改幅度。
训练过程中每 500 步用验证集算一次 CER 和 SER。最终效果:验证集 CER 从初始的 18.7% 降到 2.3%,SER 从 54% 降到 11.8%。人工测试集 CER 在 4.6% 左右。这个成绩在短文本纠错场景里已经够用了。
重点提醒:不要只看 CER。有时候 CER 降下来了,但模型把句子改得面目全非——比如把专有名词给替换掉,字对了但语义错了。所以我还加了一个语义保留指标,用向量模型算纠正前后句子的余弦相似度,低于 0.85 的样本要人工抽检。这一招帮我发现了很多隐藏的过度纠正问题。
4. 推理部署与性能优化
4.1 轻量化推理框架选择
模型微调完,部署是另一道坎。0.8B 模型如果用原始 PyTorch 推理,DNN 框架调度开销比较大,加上显存拷贝,延迟不太理想。我用的是常见的推理框架,把模型导出成对应的轻量格式,只保留必要的计算图。
导出过程没什么特殊地方,就是转模型结构后做精度校验,确保推理结果和原始模型在测试集上的 CER 差异不超过 0.1 个百分点。这一步很容易忽略但特别重要,有些框架自动优化掉某些计算图节点,导致输出质量悄悄下降。
4.2 量化方案:INT8 还是 INT4
小模型追求低资源,量化几乎必做。我在 INT8 和 INT4 之间做过对比。INT8 权重量化几乎无损,CER 只上升 0.2 个百分点;INT4 权重量化 CER 上升 0.8 个百分点,且个别样本会出现重复生成的问题。
最终线上选了 INT8。理由很简单:精度损失可接受,推理时间比 FP16 快约 20%,显存占用减半。INT4 省下来的那点成本,换来的精度损失在业务场景里不值得。
量化的坑在于要注意校准集的选择。我用的是验证集里 1000 条错误文本做校准,效果最好。如果用干净文本校准,量化后期望分布偏离真实输入,CER 会额外恶化。
4.3 并发与延迟参数
线上部署使用单实例服务,配置 2 核 CPU、4G 内存。模型加载后驻留内存,单次推理平均延迟约 45 毫秒,P95 延迟 80 毫秒。并发 16 条请求时,P95 延迟能控制在 120 毫秒以内。
这个延迟表现基本够用。如果你的业务需要更高吞吐,比如每秒上千次请求,建议至少部署 4 个副本,再做一层简单的请求排队和超时熔断。批量推理也能提升吞吐,但对于短文本任务,单请求延迟是第一优先考虑。而且 0.8B 的模型对这种并发压力没什么问题,真正限制吞吐的是部署框架的调度效率,不是模型本身。
4.4 与外部词典结合
微调模型不是万能的。我在实践中发现,模型对品牌名、人名、地名这类专有名词的把握不稳定,因为训练数据里专有名词占比不高,模型容易把它们当错词改掉。解决办法是加一个外部受保护词典:推理前先扫描文本,把命中的专有名词用占位符替换;推理完成后再把占位符还原。这样既保留了模型的纠错能力,又避免破坏关键实体信息。
这个操作对 CER 影响很大。加入保护词典后,人工测试集上专有名词出错率从 5.2% 降到 0.7%。强烈建议所有做纠错任务的人都把这个机制加上。
5. 常见问题与排查心得
5.1 过度纠正问题怎么压
模型学完以后,最常见的新问题就是“什么都想改”。比如输入“这款手机性价比很高”,模型把“性价比”改成“性比价”或“性价比好”,这就是典型过纠正。原因一般有两个:训练数据里错误样本比例太高,模型形成了过度修改的偏好;或者数据里缺少“本来正确无需修改”的样本。
解决办法是在训练集里加入一定比例的错误为 0 的样本。我加了 10% 的干净句子进去,标签仍然是原句。模型学会输出和输入完全一样的模式,过纠正现象明显缓解。
5.2 数据泄露与评测失真
前面提到过用 SimHash 去除跨集合相似样本,这里再展开讲一下。如果训练集和测试集来自同一个原始语料库,自动增广时同一个句子可能分身出两个不同噪声版本,一个进训练集一个进测试集,测出来 CER 虚低。尤其是错误类型固定增广时,这种泄露特别隐蔽。
排查方法也简单:随便挑几条测试集样本去训练集里做模糊搜索,看相似文本是否大量存在。如果有,就去重重新切分。这个数据纯净度的检查,应该纳入每次迭代的标准流程。
5.3 中文标点与全半角规范
中文纠正任务里,标点符号的处理比想象中麻烦。模型默认的 tokenizer 对全角标点和半角标点是分别编码的,如果不显式统一,模型会在全角逗号和半角逗号之间来回跳动。我一开始评估用自己标注的规范,结果输出文本里逗号一会儿全角一会儿半角,特别难看。
我的做法是:后处理阶段加一个确定性标点归一化,强制把所有半角标点转成对应全角标点(英文数字场景除外)。这样模型不需要花额外能力学习标点统一,把参数节省下来去学真正的语言错误纠偏。信号处理里这叫把确定性规则放在模型外,效果最稳。
5.4 模型输出不稳定的处理
有时候同类错误输入,模型第一次输出对,第二次输出错,原因可能是采样参数问题。纠正任务本质是确定性的文本改写,不应该引入随机性。所以推理时要关闭采样,用贪心搜索或者设置温度接近 0。我用温度 0.1,关闭 top-k 和 top-p,输出稳定性大幅提升,而且不会出现无意义重复。
如果你确实需要多样化输出,建议只在候选生成阶段做采样,最后还是用规则筛选。否则业务方很容易投诉“同样一句话上次能纠正这次不能”。
这里整理一个速查表,按频率排了三个常见问题:
| 现象 | 原因 | 解决 |
|---|---|---|
| 专有名词被改 | 训练语料缺少实体覆盖 | 加外部保护词典 |
| 长文本后半段没被纠正 | 输入长度截断 | 分段输入,或增加最大长度到 256 |
| 输出多出默认标点 | 指令模板和标签不一致 | 尝试统一前后缀格式 |
5.5 从发现到修复的排查思路
如果模型上线后某个错误模式屡屡出现,不要直接微调数据。先做错误聚类,把线上错误样本按错误类型聚合,看哪些错误最大比例是由模型引入的。我遇到过一次情况:模型把“地址补充”改成“地址这不”,原因是训练数据里“补充”这个词大量出现在“补充说明”的语境里,模型学到了错误的共同出现概率,单独出现“补充”时就开始乱来。后来针对性补了 2000 条含“补充”的干净样本,问题就消除了。
这种错误类型驱动的排查思路,比盲目的加更多数据有效得多。
6. 一些落地后的体会
最后分享两个实际体会。第一个是关于“小模型是否真的可靠”我最终的判断是:可靠程度不取决于模型大小,而取决于任务边界是否清晰。把纠正任务严格限定在短文本、集中错误类型、配合保护词典与后处理规则,这个 0.8B 模型的产出质量,已经足够让业务方放心。如果你硬要它处理复杂长文改写或开放域知识纠错,那确实得换更大模型。
第二个体会是数据迭代比模型训练更花时间。整个实践中,模型微调耗时加起来不到半天,但数据构造、清洗、评估每一次迭代都花了数倍的时间。模型就像一个不断成长的助手,喂给它什么错误模式,它就学会什么错误模式。想清楚这个逻辑,后续的每一次任务我都会先用半天做好数据规划,再去跑训练。
如果你也在做类似任务,建议从一个小而明确的任务开始,先把链路走通,把评估指标定明白,然后再扩展错误类型和数据规模。这条路,走下来最稳。