Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
263 changes: 263 additions & 0 deletions OPENCODER_read
Original file line number Diff line number Diff line change
@@ -0,0 +1,263 @@
## 问题:

1. 解决的是什么问题?

这篇工作主要解决了现在code LLM领域中开源程度不足,并且可重复性较低的问题,还构建了高质量的预训练数据集和SFT数据集以提升开源模型在code上的表现,具体来说:

- **数据和训练流程的不透明**:许多领先的代码模型在训练数据、预处理流程以及具体的训练策略上都采用了闭源方式,尽公开模型权重,导致研究人员难以复现和进一步改进。
- **高质量代码数据稀缺**:当前开源的代码数据集存在质量不高、重复内容多、缺乏精细化清洗等问题,致训练出的模型性能难以与闭源领先模型相比。
- **OpenCoder提供了一个全流程公开的pipeline:**不仅公开了模型权重,还详细描述了数据预处理、分阶段训练(包括预训练、退火训练和两阶段指令调优)各个环节,为构建高性能代码 LLM 提供了一个可复现的标准流程。
2. 为何成功,标志/准是什么?

OpendCoder成功主要有以下几点:

- **严格的数据清洗与去重、过滤策略**:通先进行精细的文件级去重策略,再进行模糊去重,最后通过多层次的过滤规则,确保了训练数据的高质量和多样性,在消融实验中证明了对下游性能的显著提升。
- **合成高质量数据用于模型训练:**作者证明了在后期训练中数据质量比数量更为重要,所以作者利用合成了一批高质量数据混入原始数据集来提升训练效果。
- **分阶段训练策略**:通过两阶段的指令调优策略,既保证了理论知识的广度,又强化了实际编程任务的解决能力。

成功的标志是:
OpenCoder在多个code相关的benchmark上都取得了sota或是次优的结果,充分说明了OpenCoder在数据预处理及训练策略上的正确性。并且经过详细的消融实验证明的每个模块的重要性

3. 在前人基础上的关键创新是什么?

OpenCoder 的关键创新主要体现在:

1. **构建了极高质量数据集——RefineCode**:论文构建了一个包含 9600 亿 tokens 的大规模代码预训练数据集,数据来源既包括 GitHub 上的原始代码,也涵盖了代码相关的网络数据。通过精细的预处理、去重(先精细去重再模糊去重)、转换以及多层次的筛选,确保了数据质量和多样性。
2. **退火阶段设计**:在预训练之后引入退火阶段,利用高质量的算法语料(从leetcode等爬取)、合成代码片段和等数据进一步强化模型能力。

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

退火阶段的这些语料,具体是怎么生成的?假设给你它论文里提到的 seed 语料,你如何合成呢?

3. **两阶段指令调优策略**:将指令调优分为两步:第一阶段注重构建理论和基础知识的问答对;第二阶段则专注于实际编程任务,这种方式兼顾了知识的广度和深度,显著提升了模型在实际场景中的表现。
4. **全面公开的pipeline及详细的训练细节:**为开源社区提供了一整套可参考、可复现的指南。
4. 关键结果有哪些?
- **benchmark成绩**:在多个代码生成和理解任务上(HumanEval、MBPP、BigCodeBench 等),OpenCoder 在 1B+ 和 6B+ 参数规模下均取得了SOTA或次优的成绩,同时可以看出小参数模型对训练数据的质量更加敏感。
- **消融实验成果:**
- 文件级去重比仓库级去重更有效,明显提升了下游任务表现。

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

你能猜测下为什么前者更有效吗?

- 使用高质量数据(算法语料和合成数据)在退火阶段能显著改善模型性能,若移除这些数据,性能会明显下降。
- 两阶段指令调优策略相比混合训练或者只采用阶段一能更好地平衡理论和实践能力,提升综合性能。
- **OpenCoder具有较为优秀的多语言能力**
5. 有哪些局限性?如何优化?
- **数据多样性与质量的权衡:**作者指出,采用starts数进行过滤会降低数据的多样性导致模型性能的下降,考虑在进行筛选时将starts作为正则项加入筛选过程,从而保证质量与多样性的权衡。
- **计算资源要求较高**:从训练详细设置来看,模型的预训练和后期退火阶段均需要大量的 GPU 资源和长时间训练,可以研究考虑使用部分参数微调或是模型蒸馏来降低训练成本。
6. 这个工作可能有什么深远的影响?
- **推动开源研究和复现**:公开完整的数据处理pipeline、训练设置和模型参数,为研究者提供了一个完善的参考和基线,加速后续创新和改进。
- **启发其他领域的开源大模型构建**:OpenCoder 的方法不仅适用于code领域,其数据预处理及多阶段的训练策略也可以为其他大模型领域提供借鉴和启发。

## Abstract

尽管现如今的开源codeLLM的水平正在逐渐逼近闭源模型,但是目前仍然缺乏提供完整的训练管道,及训练数据的开源code LLM,这导致了对其成果进行复现变得极为困难。本文提出了OpenCoder,一个在开源界领先的大模型,并且不止开源了模型权重,还开放了完整的数据处理pipeline,和可复现的训练数据,以及所有的完整细节。

此外,作者定义了在构建codeLLM时的关键因素:

1. 采用针对代码优化过的数据清洗和去重规则
2. 回收利用代码相关的语料
3. 在退火阶段和SFT阶段使用高质量的合成数据

## Introduction

现如今开源LLM的code能力仍然与闭源的LLM存在不小的差距,这是因为这些模型往往不会开源他们的训练数据集,这导致了开源社区无法建立强有力的baseline,并且无法了解LLM的工作机理。

作者完整的实验设置强调了在code LLM不同训练阶段数据构造和选择方法:

1. 在预训练阶段,对数据进行清洗时十分重要的,例如要着重清洗掉纯16进制的代码和过短的code,因为其长度过短没有办法对模型提供有效的信息和上下文。
2. 在下游任务上对文件级的重复代码数据删除比删除重复的仓库的代码数据要更加有效,因为更细粒度的删除能够更好的维持数据的多样性并且能够提升模型的表现。
3. GitHub的收藏数同样对模型表现存在影响,因为如果通过starts数进行过滤的话很有可能会降低数据的多样性。
4. 在退火阶段,也就是模型训练的后期,数据的质量要比数量要重要的多。
5. 在指令微调阶段,通过两段式的微调可以让模型在起初获得强大的通用能力然后针对code任务进行精炼,从而提成模型在理论和实践code任务上的表现。

## Pretraining Data

预训练数据的质量及多样性极大的影响了模型的整体性能,所以好的预训练数据对模型来说是至关重要的。

### REFINECODE

目前已经有工作如Stack v2提供了code数据集来用于LLM的训练,但是其质量无法使大模型达到最佳的性能。

为了解决这个问题,作者提出了Refincode数据集,这个数据集中包含了607种编程语言并且融入了130多条的针对不同语言的规则,共计960Btoken数。

数据集中的原始代码主要来源于GitHub仓库并且包含了Stack v2数据集中非GitHub数据,此外,与代码相关的网页数据主要来源于网络语料库。作者设计了一条pipeline来实现训练数据的生成

![image.png](attachment:cef75153-1f3e-4137-972c-08fc3a5fe21f:image.png)

- RAW CODE:
数据处理的pipeline主要包括这些模块,分别是预处理,重复数据删除,转换和对数据进行采样。
- Preprocessing:

在预处理中作者首先将大小大于8MB的文件删除,因为这些往往是非编码的文件,同时根据文件的拓展名来确定哪些文件是代码文件,然后将低质量的文件进行过滤,最终保存了607种编程语言的文件。

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

你觉得为什么要保留607种语言,而不是精选我们常用的30种语言来训练这个大模型呢


- Deduplication:

作者通过两种粒度的方式对重复文件进行删除,分别是精细删除和模糊删除。

**精细删除**:作者通过计算文件的hash值来判断文件是否相同,如过hash值相同,则在其中只保留最新和stars数最高的版本。

**模糊删除**:将原始文本按照5个字符一组进行划分,对每个文件计算2048hash值,使用LSH的方法检测出相似的文件,在相似的文件中只保留最好starts数和最新发布的版本。

经过这两次删除,总数据量降低了6%

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

精确去重和模糊去重,各自删除的file vol 是多大?为什么两者的去重有这么大的差异?


- Transformation:
在文件中会包含一些通用的信息,如版权声明和个人信息,这些信息不能够简单的删除,而是在过滤前对其先进行转化。

**Copyright Removal:**

对版权信息的删除,因为版权信息都是高度重复的,如果不进行删除可能影响模型的能力。

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

为什么高度重复的预料,对模型能力有损伤?具体会有哪些方面的损伤


**PII Reduction:**
训练数据中包含敏感信息,所以要对其进行删除,作者通过复杂的正则匹配来对其进行删除。

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

假设让你设计这个去除,能举出来几个例子,里面是有敏感信息的吗?要去除时,应该怎么做?


- Filtering:

GitHub上原始代码的数据质量参差不齐,低质量的数据会损害LLM的能力。但与自然语言不同,不同的编程语言具有不同的属性,所以在过滤时需要考虑更加全面,所以作者在过滤时基于以下标准:

1. **排除自包含性差的文件**:那些不能独立理解或运行的代码文件(依赖过多外部信息的)会被过滤掉。
2. **排除逻辑结构不良或几乎没有逻辑结构的文件**:代码应该有清晰的逻辑结构,如果代码结构混乱或逻辑性差,则认为质量较低。
3. **移除格式严重偏离标准的文件**:格式不规范的代码文件可能会影响模型学习代码的结构和风格,因此这些文件也会被剔除。

**自然语言过滤标准:**

针对文件大小,行数来过滤文件

**通用的code过滤标准:**
通过变量数量,平均函数长度来进行过滤

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

可以根据它开源的过滤代码,看看 python 里有哪些规则?这些规则具体怎么实现的,他们的阈值设置合理吗


**针对特定编程语言的过滤标准:**
根据不同的语言特点进行过滤。

- Data Sampling:
作者对数据进行了抽样,将占据高资源的语言进行下采样,最终构造出了730B的token。

![image.png](attachment:5304df29-f472-42f3-9fa9-68a5a17b51a4:image.png)


通过PCA降维可以看到,相比于Stack V2数据,RefineCode没有的大量的离群值,作者指出这些离群值往往是低质量的数据。

- CODE-RELATED WEB DATA

作者受到 DeepSeekMath的启发,从 Common Crawl 数据集 中收集了与代码相关的高质量网页文本数据,并采用 Autonomous Data Selection方法,对从 Common Crawl 中抓取的网页内容进行自动标注,挑选出了 50 万条高质量的类代码内容,作为种子数据集。


![image.png](attachment:97f753aa-f5f6-4a90-8adb-7ac21a159d1f:image.png)

首先基于种子数据集对分类器进行训练,然后从Common Crawl 中重新召回code相关的网页数据,将召回的网页按照域名进行分类,如果某个域中超过10%的网页为代码相关,则将其标记为代码相关域,在标记出的域中进一步手动标注哪些网页是真的代码内容。

作者总共迭代了三轮,在Common Crawl 中召回了220G的code data。

最终作者总共获得了960Btoken的数据集,并且于传统的stack v2数据集,文章的数据集显著提高了训练效率。

![image.png](attachment:8a22a43c-aff0-448f-8228-a87d8a6ef0d5:image.png)

### ANNEALING DATA

退火阶段是位于预训练和SFT之间的阶段,通过学习率的快速下降能够让模型适应更高质量及更小规模的数据。

- Original Distribution Data:
在退火阶段需要维持预训练数据的分布,巨大的分布变化会导致模型出现灾难性遗忘,所以在退火数据中有84%来自预训练数据集。
- Algorithmic Corpus:
作者在其中加入了算法数据,因为算法文件一般自包含性更好,并且更具代码逻辑。

此外,这些文件的分布更与现实生活中的任务分布相对齐。

- Synthetic Data:
在预训练阶段进行高质量的数据重写能够帮助模型更好的完整知识的注入和检索,作者基于以下两种方法来合成数据:
- 利用LLM生成一批自包含的函数和相应的测试用例,将能够通过测试的code作为退火数据
- 利用Hqcode数据集,让模型对代码进行分析,提取其中抽象的知识,来作为退火数据。

![image.png](attachment:9a1100bd-0dfd-42b3-b929-426bcc46218e:image.png)

## POST TRAINING

### DATA COMPOSITION

- Open-source Training Data

为了提升模型的能力,作者收集了开源的指令数据库,然后使用使用一个LLM对 Infinity-Instruct 的内容做二分类,判断哪些段落是与代码相关的,只保留这部分内容。

还从两个数据集中收集真实的用户数据,利用LLM筛选出哪些与code相关,同时低质量的数据还会被LLM重新生成更优质的回答以提升质量。所以RealUser-Instruct不仅多样性更强并且与实际分布更加符合。

- Educational Instruction Synthesis

作者在合成教育类的指令时,通过使用scorer model来确保筛选出高质量的种子数据,并使用这些数据来生成答案和测试用例,只选择通过测试用例的数据作为指令微调数据。通过这种方式能够最大程度上的提升模型生成code时语法上的可靠性。

- Package-related Instruction Synthesis

原始的预训练数据中往往包含大量过时的库,LLM在生成code时有可能调用已经过时的用法导致冲突,为了解决这个问题,作者通过PYDOC检索到广泛使用的语法和示例,并以prompt的形式输入给教师模型,教师模型相应的产生最新和准确的数据对,将此数据用于LLM的微调。

- Large-scale Diverse Instruction Synthesis

为了增加微调数据集的多样性,作者构建了一个大规模的合成框架,其中包含了以下要素:

- 首先使用LLM来清理掉不相关的上下文,选择出有意义句子作为种子数据集。
- 使用模版定义生成任务的参数,如编程语言,难度等。
- 使用一个参数更大的LLM完成任务,通过验证模块只保留通过测试用例的内容
- 再使用LLM来对回答进行精炼,并且加上更多的解释。

### TWO-STAGE INSTRUCTION-TUNING

为了同时提升模型在理论知识和实际操作上的能力,作者采用了两阶段的指令微调。

![image.png](attachment:224bee7e-e699-4ac4-b6d4-3ef995013fb0:image.png)

微调的第一阶段集中在对理论知识的综合问题解答。

第二阶段集中在对模型实际编写代码能力的训练,通过收集高starts GitHub数据,作者确保模型能够见到足够多的现实案例,并且学到良好的代码结构和风格。通过这种方式,LLM能够学会写出语义和结构上正确的code。

## EXPERIMENTAL RESULTS

### EVALUATION ON BASE MODELS

作者使用HumanEval & MBPP和BigCodeBench,来对基座模型的代码能力进行评估,结果表明OpenCoder 在同参数规模下大幅领先于现有 SOTA 模型(小模型段表现更佳)

![image.png](attachment:4f93a28a-5e9a-4f8a-ac93-4ad90c009615:image.png)

(说明参数越小的模型对训练数据的质量越敏感?)

### EVALUATION ON INSTRUCT MODEL

![image.png](attachment:3fc69efe-9c35-46d1-be69-251c0dc347ad:image.png)

![image.png](attachment:6a24aabe-2706-47d3-823e-217582bb622e:image.png)

![image.png](attachment:eadd919d-f4ad-4e3d-a7f1-231c2524e15e:image.png)

结果同样表明,在参数量更小的情况下,OpenCoder取得了sota的成绩,在参数量较大的情况下,OpenCoder也取得了次优的成绩。

## ANALYSIS

### ANALYSIS OF THE DEDUPLICATION LEVEL

作者对 GitHub 上 4.85 亿个 Python 文件进行去重时发现,仓库级别去重保留的 token 数量几乎是文件级别去重的三倍,但文件级去重的数据在 HumanEval 和 MBPP 下游任务上的表现明显更优。此外在仓库级去重后仍然存在大量重复的token。总的来说对于预训练数据的去重先采取精确去重再模糊去重是一个更好的选择。

![image.png](attachment:6694dac0-80ae-451a-b86e-008f54c32b69:image.png)

### ANALYSIS ON THE IMPORTANCE OF HIGH-QUALITY DATA IN THE ANNEALING PHASE

作者比较了在退火阶段是否使用高质量数据带来的差别,结果表明在退火阶段使用高质量数据能够显著提升模型能力。

![image.png](attachment:56e749e7-ad95-4dad-92bb-739997ac4ca3:image.png)

### ANALYSIS ON THE EFFECT OF GITHUB STARS

结果显示使用starts数过滤会使训练损失降低,表面上看似训练得更轻松,但它实际上牺牲了数据的多样性,导致预训练后的模型在实际任务上的表现不如用原始数据训练的模型。

因此,作者认为单纯依赖 GitHub Stars 作为过滤标准并不是一个最优的选择,因为它在提高数据质量的同时,可能会削弱模型的泛化能力。

![image.png](attachment:cb7e0952-2d69-4039-9e5f-aa5d57f9520a:image.png)

![image.png](attachment:6dd94090-2157-4d6a-a197-e6f07a043378:image.png)

### ANALYSIS ON THE TWO-STAGE INSTRUCTION TUNING STRATEGY

作者分析了SFT两个阶段的不同作用,作者分析Stage1 数据:虽然多样性强,能够帮助模型学习到更广泛的知识,但由于质量参差不齐,可能无法提供足够准确、精细的指导。

Stage2 数据:专注于代码任务,高质量且针对性强,可以针对性地提升模型在代码生成、理解和执行上的能力。

两阶段策略的优势:

先广后精:先利用大量多样化的数据建立基本能力,再用高质量数据进行针对性强化,能更好地平衡模型知识的广度与深度。

实验结果显示,两阶段训练策略在多个基准上均优于仅使用 Stage1 数据或将两种数据直接混合训练的方法。

但是Mix Training 的方式存在不足,因为混合数据虽然能同时提供多样性和高质量信息,但这种混合往往使得模型难以区分两种数据的不同作用,导致学习效果被稀释,整体表现反而不如分阶段训练。

![image.png](attachment:2f62a8c2-cc4e-4640-b2c0-45d63b7f37ac:image.png)

## CONCLUSION & FUTURE WORK

作者介绍了OpenCoder,一个开源codeLLM,同时为了推动研究透明性和可复现性,作者公开了完整的数据处理流程、预训练数据、SFT 数据集、详尽的训练协议、中间检查点及消融实验结果。实验表明,无论是在 1B+ 还是 6B+ 规模下,OpenCoder 均超过了大部分开源模型,并与领先的专有模型相当。