跳转至

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\) 调节采样概率:

\[p_i' = \frac{\exp(\log p_i / t)}{\sum_{j \in C} \exp(\log p_j / 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%,证明数据质量优势源于特征树方法而非数据规模。

关键发现

  1. 复杂度显著提升:从软件工程指标看,EpiCoder 函数级数据的 Halstead 复杂度(Unique Operands: 44.32 vs OSS-Instruct 20.99)近乎翻倍;LLM 评估复杂度比 OSS-Instruct 提升 32.6%(函数级)和 52.5%(文件级)
  2. 多样性领先:每样本平均独特特征数达 8.53(函数级)/ 8.95(文件级),超过最近竞争者 2.15+
  3. 数据缩放效应良好:380k 数据量下性能仍有上升趋势,说明数据集多样性足以抵抗过拟合
  4. 无数据泄露:通过 embedding 余弦相似度分析,合成数据与基准测试集相似度远低于 0.9 阈值
  5. 仓库级生成潜力:成功从 LLaMA-Factory 的特征树生成了包含 50+ 文件的仿真仓库

亮点与洞察

  1. 从"代码到代码"到"语义到代码"的范式转变:不再直接用代码片段生成新代码,而是先提升到语义特征层面再生成,打破了代码片段的刚性限制
  2. 特征树作为统一接口:深度控制复杂度、宽度控制多样性、频率控制采样偏好——一个结构就提供了三个独立的控制维度
  3. 进化在特征空间而非代码空间:比直接进化代码或指令更高效,因为树结构提供了清晰的方向
  4. 提出 XFileDep 基准:填补了文件级代码生成评估的空白,包含 466 个跨文件依赖问题
  5. 频率估计的巧妙设计:用兄弟节点平均频率估计新进化特征的频率,简单但有效地保持了分布一致性

局限与展望

  1. 特征树构建依赖强LLM:整个 pipeline 依赖 GPT-4o 进行特征提取和进化,成本较高
  2. 仓库级生成尚为概念验证:虽然展示了50+文件仓库的生成案例,但尚未进行系统量化评估
  3. 仅覆盖 Python:种子数据和评测均以 Python 为主,多语言泛化能力未验证
  4. 特征树质量的上限:特征树的初始质量取决于种子数据的选择和 LLM 的提取能力
  5. 可扩展到更大模型:只在 7B 规模验证,更大规模模型可能获得更大收益

相关工作与启发

  • 数据合成演进:Code Alpaca → WizardCoder (Evol-Instruct) → Magicoder (OSS-Instruct) → WaveCoder → SelfCodeAlign → EpiCoder (Feature Tree),体现了从简单到结构化的数据合成趋势
  • 启发方向:特征树思想可迁移到数学推理、科学计算等领域的数据合成;跨文件依赖的基准构建方法可推广到更多语言
  • 与 SelfCodeAlign 的区别:后者也提取"代码概念",但 EpiCoder 将概念组织为树结构,提供了层次关系和更系统的进化方向

评分

维度 分数 (1-5) 说明
创新性 ⭐⭐⭐⭐ 特征树是代码数据合成的新范式,从语义层面控制复杂度
实验充分度 ⭐⭐⭐⭐⭐ 5个函数级+1个文件级基准,等量对比,复杂度/多样性/泄露全面分析
写作清晰度 ⭐⭐⭐⭐ 框架清晰,图表丰富,附录详尽含完整 prompt
实用价值 ⭐⭐⭐⭐ 代码开源,方法可直接应用于代码 LLM 的数据合成
综合评分 ⭐⭐⭐⭐ 扎实的工作,在代码数据合成领域推进了一大步

评分

  • 新颖性: 待评
  • 实验充分度: 待评
  • 写作质量: 待评
  • 价值: 待评

相关论文