EpiCoder: Encompassing Diversity and Complexity in Code Generation¶
会议: ICML 2025
arXiv: 2501.04694
代码: microsoft/EpiCoder
领域: NLP生成
关键词: 代码生成, 特征树, 数据合成, 指令微调, 代码LLM
一句话总结¶
提出基于特征树(Feature Tree)的代码数据合成框架,通过从代码中提取层次化语义特征并迭代进化,实现对合成数据复杂度和多样性的精确控制,训练得到的 EpiCoder 系列模型在函数级和文件级代码生成基准上达到同规模 SOTA。
研究背景与动机¶
现有代码数据合成方法(如 Magicoder 的 OSS-Instruct、WizardCoder 的 Evol-Instruct)普遍以代码片段(code snippets)作为种子数据,存在两个核心问题:
多样性受限:代码片段本身具有刚性,难以灵活重组产生新的组合,导致合成数据的编程模式覆盖不足
复杂度受限:基于片段的方法难以生成跨文件依赖、多模块协作等真实场景的复杂代码
这些限制使得微调后的模型在处理复杂编程任务时能力不足。作者受抽象语法树(AST)启发,提出用层次化的语义特征树替代代码片段作为种子数据,从根本上解决多样性和复杂度的瓶颈。
方法详解¶
整体框架¶
框架分为三个阶段:(a) 特征树提取 → (b) 特征树进化 → (c) 基于特征树的代码生成。
核心思想是:不直接从代码片段出发生成新代码,而是先将代码抽象为语义特征的层次结构(特征树),在特征空间中进行扩展和演化,再从特征树采样子树来指导代码生成。这样可以实现: - 可控复杂度:通过调节采样子树的深度和宽度控制生成代码的复杂程度 - 定向学习:通过调节特征采样概率,优先覆盖模型知识体系中不足的领域
关键设计¶
1. 特征树提取(Feature Tree Extraction)¶
原始代码收集:从 The Stack v2 数据集中使用 KCenterGreedy 算法选取多样化的核心代码样本集(150k Python 文件),以 roberta-large-v1 编码的代码嵌入为基础。
树结构示例构建:采用两步迭代法优化特征提取的 prompt: - 特征预提取:用 GPT-4o 从种子代码中提取初始特征关键词集合 - 迭代聚类:对特征子集进行层次聚类,生成树结构示例,反复调整确保层次关系合理
特征树提取与合并:利用优化后的树结构示例,GPT-4o 为每个代码片段提取树结构特征表示,然后合并为统一的综合特征树。同时记录每个节点的频率,反映种子数据中特征的分布(近似预训练模型的知识分布)。
2. 特征树进化(Feature Tree Evolution)¶
为克服种子数据特征的局限性,对特征树进行迭代进化扩展:
- 每次迭代从完整特征树中采样一个子树
- LLM 沿深度(添加更细粒度的子节点)和宽度(添加同层级的兄弟节点)两个维度对子树进行扩展
- 进化后的子树合并回整体结构
关键挑战——新特征的频率估计:新生成特征的频率取其兄弟节点频率的平均值,确保进化特征与已有分布无缝融合。实验中经过 9000 步进化,特征数从 5k 扩展到 140k。
3. 基于特征树的代码生成(Feature Tree-Based Code Generation)¶
分布重加权(Distribution Reweighting):原始特征频率反映自然数据分布,但一些高频但简单的特征(如 config、initialize)不需要在指令微调阶段重点关注。使用温度参数 \(t\) 调节采样概率:
较高的温度值使分布更平滑,让低频特征获得更高的采样概率。为增强多样性,在数据合成过程中使用多个温度值。
特征采样(Feature Sampling):根据调整后的概率分布,按预定义的子树形状递归采样候选特征子树。通过调节子树的深度和宽度,灵活生成不同复杂度的任务。
内容生成(Content Generation):LLM 基于采样的子树选择兼容特征子集,生成任务描述和对应的代码与执行环境。解决方案代码可以从单个函数到多文件项目,支持跨文件依赖关系。
迭代精炼(Iterative Refinement):生成代码时同步生成测试文件,在隔离环境中执行测试。通过错误信息引导 LLM 迭代修正代码,确保生成代码的正确性。
损失函数 / 训练策略¶
- 基座模型:Qwen2.5-Coder-7B-Base 和 DeepSeek-Coder-6.7B-Base
- 训练数据:380k 函数级 + 53k 文件级数据(共 433k)
- 对 DeepSeek 基座额外加入 evol-codealpaca-v1 数据集(与 baseline 对齐)
- 评估时按训练级别对应评测
实验关键数据¶
主实验¶
函数级代码生成(Pass@1 %):
| 模型 | HumanEval | HumanEval+ | MBPP | MBPP+ | BCB-Full Comp. | BCB-Hard Comp. | EvoEval | 平均 |
|---|---|---|---|---|---|---|---|---|
| Qwen2.5-Coder-7B-Instruct | 88.4 | 84.1 | 83.5 | 71.7 | 48.8 | 20.3 | 55.2 | 57.0 |
| EpiCoder-Qwen-7B | 89.0 | 82.3 | 84.1 | 71.4 | 51.9 | 27.7 | 58.8 | 59.0 |
| DeepSeekCoder-6.7b-Instruct | 74.4 | 71.3 | 74.9 | 65.6 | 43.8 | 15.5 | 41.4 | 48.1 |
| Magicoder-S-DS | 76.8 | 71.3 | 79.4 | 69.0 | 47.6 | 12.8 | 44.6 | 50.1 |
| EpiCoder-DS-6.7B | 80.5 | 76.8 | 81.5 | 68.3 | 50.6 | 19.6 | 50.0 | 53.1 |
EpiCoder-Qwen-7B 在 7B 规模实现了 SOTA 平均表现,BCB-Hard Completion 超过 Qwen2.5-Coder-7B-Instruct 7.4%。
消融实验¶
相同数据规模下的对比(Pass@1 %):
| 配置 | 数据量 | HumanEval | MBPP | BCB-Full | BCB-Hard | EvoEval | 平均 | 说明 |
|---|---|---|---|---|---|---|---|---|
| Magicoder-DS | 75k | 66.5 | 75.4 | 46.8 | 13.5 | 41.2 | 45.8 | 基于代码片段的 OSS-Instruct |
| WaveCoder-Ultra-6.7B | 130k | 75.0 | 74.9 | 43.7 | 16.9 | 43.6 | 48.2 | 生成器-判别器框架 |
| EpiCoder-DS-6.7B-75k | 75k | 78.0 | 79.4 | 48.2 | 18.4 | 46.2 | 51.2 | 特征树方法,同等数据量更优 |
| SelfCodeAlign-CQ-7B | 74k | — | — | — | — | — | 58.6 | 基于代码概念 |
| EpiCoder-CodeQwen-74k | 74k | — | — | — | — | — | 62.6 | +4% 平均提升 |
在等量数据下,EpiCoder 分别比 Magicoder 和 WaveCoder 提升 5.4% 和 3.0%,证明数据质量优势源于特征树方法而非数据规模。
关键发现¶
- 复杂度显著提升:从软件工程指标看,EpiCoder 函数级数据的 Halstead 复杂度(Unique Operands: 44.32 vs OSS-Instruct 20.99)近乎翻倍;LLM 评估复杂度比 OSS-Instruct 提升 32.6%(函数级)和 52.5%(文件级)
- 多样性领先:每样本平均独特特征数达 8.53(函数级)/ 8.95(文件级),超过最近竞争者 2.15+
- 数据缩放效应良好:380k 数据量下性能仍有上升趋势,说明数据集多样性足以抵抗过拟合
- 无数据泄露:通过 embedding 余弦相似度分析,合成数据与基准测试集相似度远低于 0.9 阈值
- 仓库级生成潜力:成功从 LLaMA-Factory 的特征树生成了包含 50+ 文件的仿真仓库
亮点与洞察¶
- 从"代码到代码"到"语义到代码"的范式转变:不再直接用代码片段生成新代码,而是先提升到语义特征层面再生成,打破了代码片段的刚性限制
- 特征树作为统一接口:深度控制复杂度、宽度控制多样性、频率控制采样偏好——一个结构就提供了三个独立的控制维度
- 进化在特征空间而非代码空间:比直接进化代码或指令更高效,因为树结构提供了清晰的方向
- 提出 XFileDep 基准:填补了文件级代码生成评估的空白,包含 466 个跨文件依赖问题
- 频率估计的巧妙设计:用兄弟节点平均频率估计新进化特征的频率,简单但有效地保持了分布一致性
局限与展望¶
- 特征树构建依赖强LLM:整个 pipeline 依赖 GPT-4o 进行特征提取和进化,成本较高
- 仓库级生成尚为概念验证:虽然展示了50+文件仓库的生成案例,但尚未进行系统量化评估
- 仅覆盖 Python:种子数据和评测均以 Python 为主,多语言泛化能力未验证
- 特征树质量的上限:特征树的初始质量取决于种子数据的选择和 LLM 的提取能力
- 可扩展到更大模型:只在 7B 规模验证,更大规模模型可能获得更大收益
相关工作与启发¶
- 数据合成演进:Code Alpaca → WizardCoder (Evol-Instruct) → Magicoder (OSS-Instruct) → WaveCoder → SelfCodeAlign → EpiCoder (Feature Tree),体现了从简单到结构化的数据合成趋势
- 启发方向:特征树思想可迁移到数学推理、科学计算等领域的数据合成;跨文件依赖的基准构建方法可推广到更多语言
- 与 SelfCodeAlign 的区别:后者也提取"代码概念",但 EpiCoder 将概念组织为树结构,提供了层次关系和更系统的进化方向
评分¶
| 维度 | 分数 (1-5) | 说明 |
|---|---|---|
| 创新性 | ⭐⭐⭐⭐ | 特征树是代码数据合成的新范式,从语义层面控制复杂度 |
| 实验充分度 | ⭐⭐⭐⭐⭐ | 5个函数级+1个文件级基准,等量对比,复杂度/多样性/泄露全面分析 |
| 写作清晰度 | ⭐⭐⭐⭐ | 框架清晰,图表丰富,附录详尽含完整 prompt |
| 实用价值 | ⭐⭐⭐⭐ | 代码开源,方法可直接应用于代码 LLM 的数据合成 |
| 综合评分 | ⭐⭐⭐⭐ | 扎实的工作,在代码数据合成领域推进了一大步 |
评分¶
- 新颖性: 待评
- 实验充分度: 待评
- 写作质量: 待评
- 价值: 待评
相关论文¶
- [ACL 2025] DynaCode: A Dynamic Complexity-Aware Code Benchmark for Evaluating Large Language Models in Code Generation
- [ICML 2025] Reasoning Through Execution: Unifying Process and Outcome Rewards for Code Generation
- [ICML 2025] EffiCoder: Enhancing Code Generation in Large Language Models through Efficiency-Aware Fine-tuning
- [ACL 2025] GiFT: Gibbs Fine-Tuning for Code Generation
- [ACL 2025] Rethinking Repetition Problems of LLMs in Code Generation