本文属于《Ai大模型训练教程》实战篇,聚焦训练代码补全与代码解释双任务模型的关键细节:如何划分数据桶并制定补全/解释数据配比,如何搭建双轨评测体系(可编译率、Pass@k、覆盖度、幻觉率等),以及如何用评测结果反推配比调整,形成可回归的训练迭代闭环。
背景与目标:为什么“代码补全 + 代码解释”要分开配比与评测
在“Ai大模型训练教程:从入门到实战落地的系统课程”系列里,前面通常已经完成了:数据清洗、指令格式统一、SFT(监督微调)基础流程与训练框架搭建。本篇进入项目实战的关键一环:同一模型同时具备“代码补全(completion)”与“代码解释(explanation)”能力时,数据配比如何设计、如何评测、如何迭代。
两类能力的目标函数与用户场景明显不同:
- 代码补全:给定前缀(上下文),预测后续 token。重点是局部一致性、语法正确性、与上下文变量/库的对齐、可编译/可运行。
- 代码解释:给定一段代码,产出自然语言解释或逐行注释。重点是语义理解、概念表达、覆盖关键分支与边界、少幻觉。
如果简单把两种数据混在一起训,常见问题是:
1) 补全能力被解释类数据“拉偏”(模型更爱输出解释性文本而不是代码);
2) 解释能力被补全类数据“压制”(模型倾向只输出代码,不愿写清楚原因);
3) 评测只看一种指标导致误判,训练越久越差。
因此,本篇聚焦两件事:
- 数据配比:如何定义数据桶(bucket)、如何设定比例、如何做课程式(curriculum)与阶段式(stage)训练。
- 评测方法:补全与解释分别怎么测、用哪些指标与样例集、如何建立可回归(regression)的自动化评测。
一、任务定义与数据桶(Bucket)设计
在实操中,建议先把训练数据拆成“可控桶”,每个桶都有明确输入输出格式与质量门槛。一个可落地的划分如下(可按语言/项目再细分):
1. 代码补全桶(Completion Buckets)
(1)FIM 补全(Fill-in-the-Middle)
- 输入:
prefix + <FIM_MIDDLE> + suffix - 输出:middle 段
- 优点:更贴近 IDE 场景,可在已有文件中间补全。
- 建议占比:补全桶里 40%~70%。
(2)前缀续写(Prefix LM)
- 输入:prefix
- 输出:continuation
- 优点:实现简单;缺点:更像纯语言模型续写,容易漂。
- 建议占比:补全桶里 20%~40%。
(3)单元级补全(函数/类/测试用例)
- 输入:函数签名、注释、部分实现
- 输出:完整实现
- 优点:对“按意图写代码”更友好。
- 建议占比:补全桶里 10%~30%。
实操建议:如果你最终产品是 IDE 插件,优先做 FIM;如果是聊天式写代码助手,单元级补全更关键。
2. 代码解释桶(Explanation Buckets)
(1)高层解释(High-level Summary)
- 输出 3~8 句概述:功能、输入输出、复杂度、边界条件。
(2)逐段/逐行解释(Line-by-line / Block-by-block)
- 输出带结构:每个代码块对应解释,减少漏点。
(3)为什么这么写(Rationale)
- 解释设计取舍:为何用某数据结构、为何提前返回、为何这样处理异常。
(4)错误/隐患提示(Pitfall / Bug Finding)
- 指出潜在 bug、竞态条件、NPE、越界、性能热点。
注意:解释桶里(4)会显著提高“审查/理解”能力,但也最容易产生幻觉(模型编不存在的 bug)。要设严格质量过滤。
3. 共享桶:代码理解相关任务(可选但很值)
为了让解释更“懂代码”,以及补全更“贴合上下文”,可引入少量共享理解任务:
- 变量/函数重命名建议
- 生成 docstring / 注释
- 从函数体反推函数签名(逆向)
- 根据测试用例补齐实现(TDD)
共享桶并不等于“多做就强”,关键是小比例、高质量。
二、数据配比策略:从“经验比例”到“可迭代优化”
数据配比的核心是:让模型在输出空间上保持可控——该输出代码时输出代码,该输出解释时输出解释,并且两者互不伤害。
1. 起步推荐比例(适合多数团队的默认值)
如果你的目标是做一个“补全优先,同时能解释”的模型,可从以下比例开始:
- 补全类:60%~75%
- 解释类:20%~35%
- 共享理解类:5%~10%(可选)
如果你的产品是“代码阅读/审查助手”,则反过来:
- 解释类:50%~65%
- 补全类:25%~40%
- 共享理解类:10%~15%
关键点:比例不是“越平均越好”,而是围绕主任务设置“主导信号”。
2. 两阶段训练(Stage Training):先定输出习惯,再做能力增强
一个常见且稳妥的流程:
阶段 A:输出风格与格式对齐(Format & Behavior Alignment)
- 数据:高质量指令数据 + 明确输出约束(例如“只输出代码”“用要点解释”)
- 比例:解释与补全可接近 1:1,但样本必须非常干净
- 目标:减少混输出(解释时夹代码、补全时夹废话)
阶段 B:能力拉升(Capability Scaling)
- 数据:大规模补全(尤其 FIM)+ 结构化解释(逐段)
- 比例:按产品目标倾斜(例如 70/25/5)
- 目标:提高通过率、可编译率、解释覆盖率
如果你发现“模型越来越啰嗦,补全不干净”,通常是阶段 B 中解释比例过高或解释样本的输出模板过松。
3. 课程式配比(Curriculum):从短样本到长上下文
对代码任务,长度分布极其重要。建议把每个桶按 token 长度再切一刀:
- 短上下文(0~512)
- 中上下文(512~2048)
- 长上下文(2048+,视模型上下文长度)
实践中常见“长上下文毒性”:长样本更容易包含许可证头、重复代码、无意义模板,导致训练浪费与过拟合格式。
推荐做法:
- 前 30% steps:短/中为主(80%),长为辅(20%)
- 中间 40% steps:短/中/长 = 50/35/15
- 最后 30% steps:按真实线上分布采样(例如 IDE 场景长上下文更高)
4. 多语言配比(如果覆盖多编程语言)
不要只按“样本数”配比,要按“有效 token”与“任务难度”配比。
- 主力语言(例如 Python/JS/Java):60%~80%
- 次要语言:20%~40%
并且在补全任务中加入“语言提示”或从文件后缀推断语言,避免跨语言混淆。
三、数据格式与示例:让模型学会“该输出什么”
配比想生效,前提是格式清晰、一致。
1. 补全(FIM)样例模板
建议在训练中使用固定标记(不同框架可自定义),示例:
输入(用户/系统拼接后的模型输入):
prefix:已有代码suffix:后续代码- 中间插入
<FIM_MIDDLE>标记
- 输出:仅 middle 代码
额外约束:
- 输出不加解释
- 输出尽量不加多余注释(除非上下文已有风格)
2. 解释样例模板(结构化输出)
为了可评测、可控,推荐结构化:
- 输出分三段:
1) 功能概述(1~3 句)
2) 关键逻辑(按步骤/分支)
3) 边界与复杂度(可选,但建议)
如果是逐行解释,则要求每段解释引用代码片段或行号范围,降低“胡编”。
3. 负样本与拒答(可选)
如果产品会面对不安全代码、恶意 payload、越权操作脚本:
- 在解释任务里加入“合规拒答”样本
- 在补全任务里限制输出危险命令的直接可执行形式
这会改变评测口径,需单独建立安全评测集。
四、评测总览:必须双轨评测 + 回归监控
评测不要混为一个分数。建议建立:
- 补全评测集:偏自动化、可运行/可编译指标
- 解释评测集:偏对齐/覆盖/事实性指标(自动 + 少量人工)
- 混合回归集:线上真实提示(脱敏)或模拟工作流
每次训练跑固定评测,输出一张“雷达图/表格”,对比上一个 checkpoint。
五、代码补全评测:指标、步骤与可落地实现
1. 离线指标:Exact Match、Edit Similarity、Token Accuracy
适用:小样本、确定性强的补全任务(例如补齐某个固定函数)。
Exact Match (EM):输出与参考答案完全一致
- 优点:直观
- 缺点:对等价实现不友好
BLEU / CodeBLEU / ChrF:衡量相似度
- 适合比较接近但不完全一致的输出
AST 相似度(语言相关):解析后比较结构
- 更能容忍格式差异
建议:EM 只作为辅助,核心还是“能不能跑”。
2. 关键指标:可编译率(Compile Rate)与可运行通过率(Pass@k)
(1)可编译率
- 做法:把模型补全拼回原文件,调用编译器/解释器语法检查
- 输出:成功比例
常见坑:
- 缺少 import
- 缩进错误(Python)
- 泛型/类型不匹配(Java/TS)
(2)单测通过率 / Pass@k
如果你有测试用例:
- Pass@1:一次生成就通过
- Pass@k:采样 k 次,只要有一次通过即算通过
建议:
- IDE 补全更关注 Pass@1
- 聊天式生成可以接受 Pass@5/10
(3)补全延续一致性(Context Consistency)
这是工程上非常实用的指标:
- 变量名是否来自上下文
- 调用的函数是否已定义或已 import
- 是否遵循当前文件的风格(命名、异常处理、返回约定)
可实现为静态规则打分,例如:
- 未定义符号计数
- 新引入依赖计数
- 与上下文命名风格差异(蛇形/驼峰)
3. 补全评测集如何构建(建议流程)
1) 从真实仓库抽取函数级样本(确保许可合规)
2) 生成 FIM 切片:随机切 middle,保留 prefix/suffix
3) 过滤:
- middle 太短(<10 tokens)
- middle 全是空白/注释
- prefix 或 suffix 过长导致截断
4) 评测时:
- 固定温度(如 0.2)做 Pass@1
- 再用温度(如 0.8)做 Pass@k
六、代码解释评测:覆盖、事实性与“少幻觉”
解释任务很难全自动,但可以做到“自动为主、人工兜底、持续回归”。
1. 自动指标:结构约束 + 关键点覆盖(Coverage)
(1)结构约束(Format Compliance)
统计输出是否包含规定段落:功能概述/关键逻辑/边界复杂度。
- 这是避免“输出一段散文”的最低成本手段。
(2)关键点覆盖
为每段代码准备一个“关键点清单”(可人工写,也可用规则生成):
- 函数目的
- 主要分支条件(if/else、异常)
- 外部依赖(API、库)
- 副作用(IO、数据库写入)
评测时用信息检索方式做近似匹配:
- 关键 token/实体(函数名、变量名、接口名)出现比例
- 分支条件是否被提到(例如
None检查、长度判断)
2. 事实性(Faithfulness)与幻觉检测
解释常见失败:把不存在的逻辑说得头头是道。
可操作的两步法:
1) 引用约束:要求解释时引用代码片段(如 if x is None:)或行号范围
2) 一致性检查:用静态分析/正则抽取代码事实,再对解释做核对
- 例:代码里没有网络请求,却解释“调用 HTTP API” → 判为幻觉
此外可引入 LLM-as-a-judge 做辅助,但要:
- 固定 judge 模型版本
- 采用对照提示(要求指出“哪些解释无法从代码推断”)
- 把 judge 分数只当趋势,不当绝对真理
3. 人工评测量表(小样本,高价值)
每次迭代抽 100~300 条解释样本做人工评分,维度建议:
- 正确性(0~2):是否与代码一致
- 覆盖度(0~2):关键分支/边界是否提到
- 清晰度(0~2):是否易读、结构合理
- 过度推断(0~2):是否编造不存在行为
将人工分与自动分对齐,找到“自动指标的盲区”,再改进规则与数据。
七、把“配比”与“评测”连接起来:迭代决策规则
有了双轨评测后,配比优化就能工程化。给出一套可直接用的决策表:
1. 常见现象与调整建议
补全可编译率下降、解释分上升:解释占比过高或解释样本输出太松
- 调整:解释 -5%~-15%,补全 +5%~+15%;并加强“只输出代码”的格式样本
补全 Pass@1 不变但 Pass@5 上升:采样多样性提升,但确定性不足
- 调整:加入更多“单元级补全”与“风格一致性”样本;训练时降低生成温度不解决根因
解释覆盖度高但幻觉率上升:解释样本可能含推断性文本
- 调整:增加“引用约束解释”数据;引入反例(要求说明‘代码未体现的部分无法确定’)
解释很正确但太啰嗦:缺少长度约束或参考答案冗长
- 调整:加入“压缩解释”样本(100 字内、要点列表)
2. 用“门槛指标”做发布准入(Gating)
建议为上线设硬门槛,而不是看平均分:
- 补全:可编译率 ≥ X%,Pass@1 ≥ Y%
- 解释:幻觉率 ≤ A%,格式合规率 ≥ B%
- 安全:危险代码拒答通过率 ≥ C%
门槛指标能阻止“某一项进步掩盖另一项退步”。
八、实操落地:一套可复用的评测流水线(建议)
下面给出一个不依赖特定框架的通用流程,你可以在 CI 中跑:
1. 数据与版本管理
eval_completion_v1.jsonl:补全评测集(含 prefix/suffix/参考 middle/语言/仓库标签)eval_explain_v1.jsonl:解释评测集(含代码/关键点清单/参考解释)- 每次训练记录:数据配比配置(YAML/JSON)、采样种子、训练步数、checkpoint hash
2. 推理参数固定
- 补全:温度 0.2(Pass@1),温度 0.8(Pass@k),top_p 固定
- 解释:温度 0.2,避免花哨
3. 自动评测执行
- 补全:
1) 生成补全
2) 拼回文件
3) 语法检查/编译
4) 运行单测(如有)
5) 产出 CSV/JSON 报表 - 解释:
1) 检查输出结构
2) 覆盖度匹配(关键点)
3) 幻觉规则检查(与代码事实核对)
4) 汇总统计
4. 回归对比
与上一个稳定版本对比:
- 若补全核心指标下降 > 阈值,阻止合并
- 若解释幻觉率上升 > 阈值,阻止合并
九、结语:用“可控桶 + 双轨评测”让多能力模型稳定增长
训练“代码补全与代码解释”这种双任务模型,最大的坑不是训练跑不起来,而是:看起来都在涨,实际用户体验在某个角落崩掉。解决方案不是玄学调参,而是工程化:
1) 把数据分成可控桶,定义清晰输入输出;
2) 用阶段训练与课程采样控制输出习惯与能力增长;
3) 建立补全与解释各自的硬指标与回归集;
4) 用评测结果反推配比调整,形成闭环。
在后续篇章(同系列的实战部分)你可以进一步扩展:加入检索增强(RAG)提升项目内补全一致性、引入工具调用跑测试并做自我修复、以及用偏好优化(DPO/IPO)降低解释幻觉与啰嗦程度。
Prev:项目实战:从历史工单构建对话SFT数据并训练客服大模型