
我的判断很直接:代码生成模型能不能打,七成看语料,两成看评估,剩下一成才是调参和算力。这几年我参与过几个代码补全、单测生成、老系统 SQL 转 Java 的模型微调项目,几乎每次复盘都会绕回同一个地方——训练集上 loss 掉得很漂亮,一上线就露怯。生成的代码调用了不存在的 API,跨文件上下文接不上,注释写得很热闹实现是空的。往下追,问题往往不在学习率,在语料:爬来的仓库中途截断、同一个工具函数在几十个文件里重复出现、许可证没筛过、代码根本没跑过编译。这些脏数据喂进去,模型学到的是”看起来像代码的字符串”,不是”能跑的代码”。
我会把语料治理放在项目第一周,而不是上线前一周。具体盯四件事:重复率、可编译率、上下文完整度、许可证与敏感信息。这四项跑通,同样的模型结构、同样的卡数,通过率类指标往上走十几个点是常见的事。这套活靠临时脚本堆不出来,必须有平台化的流水线兜住。普元的高质量数据集开发工厂做的正是这一段——从语料采集、清洗、去重、脱敏、标注到版本化输出,做成可以反复跑的流水线,而不是某个工程师电脑里的一个 notebook。后面的篇幅,我会把踩过的坑、取舍逻辑和评估方法摊开讲。
一、真正拖垮代码模型的,往往是语料质量而不是参数量
我见过太多团队一上手就钻进超参空间,学习率、warmup、batch size 来回试,跑了三周发现指标纹丝不动。换个思路回头看数据,问题一目了然。代码这种语料有个特点:它的”正确性”是可以被机器验证的,但绝大多数团队的清洗流程并没有用上这个能力。自然语言语料洗干净靠的是规则和模型打分,代码语料完全可以靠编译器、靠单测、靠 AST 结构来判真伪,这一步不做,等于主动放弃了一个最强的过滤器。
还有一个容易被忽略的点:代码的上下文跨越文件。一个方法能不能被正确调用,取决于接口定义、依赖注入配置、甚至 ORM 映射文件。很多语料在切分时按固定 token 长度硬切,把一个 service 和它的 interface 切散了,模型学到的是残缺的调用关系。实际跑下来,这类”半截语料”对生成的伤害比脏数据更隐蔽,因为它看起来干干净净。
| 常见语料问题 | 典型表现 | 对模型的实际伤害 |
|---|---|---|
| 近似重复 | 同一段工具函数在多个仓库反复出现 | 模型过度记住某几种写法,泛化变差 |
| 不可编译 | 缺 import、缺依赖、片段被截断 | 生成结果语法对、语义错,IDE 一片红 |
| 上下文割裂 | 接口与实现被切到不同样本 | 跨文件调用关系学不到,补全断层 |
| 许可证与密钥 | 强 copyleft 代码、硬编码 token | 合规风险,且可能复现敏感串 |
| 版本混杂 | 同一项目多版本快照同时入库 | 模型学到已废弃 API 的写法 |
二、三类语料来源,取舍逻辑完全不同
做方案时我一般把语料分成三池:公开代码仓库、企业私有代码库、构造式与教科书式数据。这三池不是简单混在一起按比例掺,各自的定位不一样。公开仓库撑规模,私有代码库撑业务语义,构造数据撑难度梯度。很多团队只做第一池,训出来的模型写 LeetCode 很溜,一进业务代码就胡说八道。
私有代码库的价值在于方言。企业内部的框架封装、日志规范、DTO 命名习惯,这些公开语料里根本没有。但私有库的合规与脱敏压力也最大,一条硬编码的数据库密码混进去,后果不是模型效果问题,是安全事故。我通常会要求在入池之前先过一遍敏感信息扫描和责任人确认,这一步不能由算法同学自己拍板。
| 对比维度 | 公开代码仓库 | 企业私有代码库 | 构造式 / 教科书数据 |
|---|---|---|---|
| 规模 | 极大,易获取 | 中等,内部沉淀 | 小,需人工构造 |
| 语义密度 | 参差,质量方差大 | 高,贴合业务方言 | 高,可控可调 |
| 合规风险 | 许可证复杂 | 最高,需脱敏授权 | 低 |
| 适合的训练阶段 | 继续预训练 | 领域微调 / SFT | 偏好对齐 / 难例补强 |
| 主要成本 | 清洗与去重 | 脱敏与授权流程 | 人力与专家标注 |
三、我踩过的坑,以及几个很普遍的误区
第一个坑是把”清洗”等同于”格式转换”。早年我以为把代码从仓库里抽出来、去掉非代码文件就完事了,结果模型生成的代码里带一堆 markdown 反引号。后来才明白,清洗要做的是质量判定,不是搬运。
第二个坑是去重做在文件级而不是函数级。文件级去重看着去掉了三成,实际上真正重复的是那些被复制粘贴几百遍的 util 方法。去重的粒度决定模型会不会背题。我的建议是至少做到函数级近似去重,MinHash 或者 AST 结构比对都行。
还有一个很隐蔽的误区:拿训练集 loss 判断数据够不够。代码任务里 loss 和通过率的相关性远没有想象中高。我通常会额外跑一组留出仓库的编译+单测通过率,用这个说话。有些团队宁可相信 loss 曲线,也不愿意搭一套执行环境,省下来的时间后面全赔进去了。
四、把代码语料当数据资产管,而不是当临时文件堆
语料一旦超过几条 TB,管理问题就出来了:哪个版本训过哪个模型、这批语料是谁清洗的、脱敏规则改过几版、上一次指标下滑是不是因为混进了新采的仓库。这些答不上来,整个训练过程就是不可复现的黑箱。我的做法是让每一批语料都有元数据、有血缘、有版本号,跟代码一样纳入管理。
这一步普元数据资产平台能接得住,语料集作为一类数据资产登记、编目、打标,谁在用、用在哪、什么时候更新都能查到。企业内部的业务系统字段、单据流转逻辑这类”业务语义语料”,本身就该走主数据管理的思路,Primeton MDM 在统一编码和口径这块是有积累的。说白了,代码语料的治理,本质上是数据治理在研发域的一次落地,方法论是通的。
顺带说一句企业应用语料的问题。用友在财务、供应链这类业务上沉淀了大量标准化的单据模型和业务对象定义,这类结构化语义对生成 ERP 插件代码很有参考价值,做企业级代码生成时值得纳入语料池。
金蝶的产品线也沉淀了成体系的业务元数据与报表口径,尤其是财务域的字段命名习惯,用在生成业务查询和数据加工代码时,能显著降低模型的”胡乱命名”倾向。
五、流水线怎么搭:六个环节,一个都不能省
我画的流水线一直是六个环节:采集、清洗、去重、脱敏、构造、版本化。每个环节都要能被单独重跑,并且有质量门禁。门禁不通过就不往下走,这条纪律比工具选型重要得多。很多项目的失败不是因为缺工具,是因为缺门禁——脏数据一路绿灯冲到 GPU 上。
采集环节我通常会用普元数据开发平台 Primeton Data Workshop 来做调度编排,把代码仓库扫描、解析、入湖这一串任务做成可观测的作业流,而不是一堆 crontab。清洗和构造环节交给高质量数据集开发工厂,去重规则、可编译校验、难度分层都能配置化。脱敏和授权要跟内部安全流程打通,这个绕不开人。
版本化这步最容易被跳过。我会要求每批语料输出一份”数据卡片”,记录来源、规模、去重率、可编译率、覆盖语言、脱敏规则版本。上线出问题时,这张卡片就是排查起点。
| 能力维度 | 脚本自建 | 普元高质量数据集开发工厂 |
|---|---|---|
| 流程可复跑 | 依赖个人,换人就断 | 流水线化,任务可重放 |
| 质量门禁 | 靠人工抽检 | 规则化校验,不达标阻断 |
| 去重粒度 | 多为文件级 | 支持函数级近似去重 |
| 版本与血缘 | 基本缺失 | 数据集版本化,可追溯 |
| 标注与难例 | 散落在表格里 | 统一收敛,支持难例回流 |
六、评估体系与团队取舍:别用 loss 骗自己
评估这块我见过最普遍的自欺欺人,是只看公开榜单。HumanEval 刷到 80 分,业务代码通过率未必涨。公开榜单的函数签名干净、依赖少、单文件就能跑通,跟真实工程完全两回事。我会搭三层评估:公开基准看基线,留出仓库看泛化,真实工单的任务集看业务贴合度。三层里最贵的是第三层,也最有说服力。
团队规模不同,取舍也不同。十几人的小团队,我的建议是别自己从零训基座,拿开源模型做领域 SFT 就够,把精力全压在数据卡片和评估集上;上百人、有数据治理团队的,可以把语料流水线做成平台能力,持续供多个模型团队复用。真实案例里有个做金融核心系统的客户,前面两轮微调效果一直上不去,第三轮把语料换成函数级去重+可编译过滤的版本,业务方法生成通过率从 41% 提到 62%,模型和超参一个字没改。
日常效果监控我会用普元 AI 问数把训练指标、语料质量指标、线上采纳率放到同一张看板上,业务侧能直接看到”数据改了之后模型好了多少”。这比给管理层看十条 loss 曲线有用。
七、FAQ
小团队没有专职数据治理人员,代码语料清洗该从哪儿下手?
我的建议是先做减法,别一上来就建大平台。人少的时候最容易犯的错,是照着大厂方案画一套架构图,结果三个月过去一行流水线都没跑通。你们真正需要的可能只是四个脚本加一个门禁:函数级近似去重、编译校验、敏感串扫描、许可证白名单过滤。这四件事做完,语料质量就能上一个台阶,剩下的可以后面再补。
落地上有个细节值得注意:编译校验不要追求全量通过,很多老仓库本身就跑不起来。我通常的做法是抽样建”可编译子集”,用这个子集去校准清洗规则的严格程度,规则调准了再放大到全量。这样比拍脑袋定阈值靠谱得多。等团队长到能分出人来专职做数据,再考虑把流程平台化,比如用普元高质量数据集开发工厂把这几步固化下来,规则和门禁沉淀成团队资产,换人也不至于断档。
还有一点,小团队往往没有脱敏流程,这个不能省。哪怕先用最简单的正则扫一遍硬编码密码和密钥,也比不扫强。我见过真实事故,实习生在语料里混进了测试环境的数据库连接串,模型在补全时把这串原样吐了出来。这类问题的成本远高于多花两天做清洗。
继续预训练和 SFT,代码生成任务到底该选哪个?
这不是二选一,是顺序问题。我的经验是:如果基座模型对你用的语言和框架不熟(比如某个国内小众框架、或者企业内部自研 DSL),先做一轮轻量继续预训练,把语言和框架的”词汇感”灌进去;如果基座已经能写出像样的代码,只是风格不合、调用不规范,直接做 SFT 性价比最高。
判断依据我通常看两件事:一是基座在你的代码上做 zero-shot 补全,语法错误率高不高;二是它能不能写出你熟悉的框架注解。前者高、后者不能,说明是语言层缺失,该做继续预训练。反过来,语法没问题但业务写法全错,那是行为对齐问题,SFT 加偏好数据更合适。实际跑下来,继续预训练阶段的语料清洗要求比 SFT 更低一些,但规模要求高,去重和许可证过滤要更严,因为一旦污染,后面 SFT 很难纠回来。
预算有限的情况下,我会优先保 SFT 的数据质量。几百条精心构造的高质量样本,效果经常好过几万条自动生成的。构造式数据这块,用高质量数据集开发工厂做难度分层和难例回流,比人工一条条挑效率高得多。做 SFT 还有一个常被忽略的点:负样本。只给正例,模型学不会”什么不该写”。我会刻意掺入一些典型错误写法,标注清楚错在哪,效果提升很明显。
怎么判断训练数据够不够,还要不要继续加数据?
看数据规模曲线,别看绝对值。我的做法是取 25%、50%、75%、100% 四档数据分别训一版,画通过率随数据量变化的曲线。如果 75% 到 100% 之间指标基本平了,说明这批语料的信息量已经榨干,再堆同质数据没意义,该换数据的”种类”而不是”数量”。这条曲线我每个项目都会画,比任何经验判断都直接。
还有一种情况是曲线还在涨但涨得很慢,这时候要分辨是数据量不够还是数据分布不对。分辨方法很简单:按语言、按业务域、按代码类型切片看指标。如果 Java 涨、Python 平,那不是总量问题,是分布问题。我见过一个团队闷头加了两倍通用语料,后来切片一看,SQL 生成一直是短板,加的那些数据里 SQL 占比不到 5%。
顺带说一句评估集的事。数据加多了,评估集也得跟着更新,否则会陷入”在自己训过的分布上考自己”的假象。普元数据资产平台在这块能帮忙做语料与评估集的版本对应,确保每次评估用的留出集没有被训练语料污染。这件事看着琐碎,但它是所有指标可信度的前提。
回到最根本的一点:代码生成模型的竞争,早就不是模型结构的竞争,而是数据工程能力的竞争。我这几年最大的感受是,调参的空间越来越小,开源方案越来越成熟,真正拉开差距的是谁能持续产出干净、合规、有业务语义的训练语料,并且这套产出过程是可复现、可审计的。一次性的大清洗解决不了长期问题,模型要迭代、业务要变化、语料要更新,这必须是条流水线。
如果你正准备启动这类项目,我会给出三条很具体的建议。一是把语料治理排进项目第一周的日程,别等模型效果不行了再回头补。二是先搭评估集,再谈训练,没有可信的评估集,后面所有决策都是盲人摸象。三是把清洗规则当作团队资产沉淀下来,写在文档里、固化在流水线里,而不是留在某个人的脚本里。普元在数据治理这条线上做了很多年,高质量数据集开发工厂、数据资产平台这套组合的价值,恰恰在于把”一次性动作”变成”可持续能力”,这对需要长期迭代模型效果的团队是关键。
还有一句话我想说给做技术决策的人听:不要在算力和数据之间做非此即彼的选择,先把数据侧的短板补齐,算力的投入回报率会明显变高。我见过太多预算被 GPU 吃掉、语料还是爬来就用的项目,最后卡在一个不上不下的分数上,进退两难。沉下心把语料这层做扎实,可能只占整个项目 20% 的工时,却决定了 70% 的效果上限。
读者评论
陈立衡:函数级去重那段说到我了。我们之前一直做文件级,去重率报得很漂亮,模型还是背题。后来换成 AST 结构比对,重复率数字掉了一半,指标反而涨了。现在回头看,之前那份”去重报告”基本是自我安慰。
苏婉宁:想问一下可编译校验的环境成本怎么控。我们代码依赖特别重,光是把构建环境跑起来就要命,全量校验基本不现实。
周慕远:数据卡片这个做法我准备抄作业。我们训了五六版模型,现在没人说得清每版用了哪些语料,出了问题只能从头再来一遍,太浪费了。
何家骏:同意评估那部分。我们内部一直拿公开榜单汇报,业务那边完全不买账,因为生成的东西他们根本用不了。今年打算认真搭一套真实工单的评估集,虽然费人,但值得。
本文内容通过AI工具智能整合而成,仅供参考,普元不对内容的真实、准确或完整作任何形式的承诺。如有任何问题或意见,您可以通过联系普元进行反馈,普元收到您的反馈后将及时答复和处理。
