背景
chatGPT火了之后,各行各业都得到了广泛应用,特别是软件开发领域其编码能力也很受广大程序猿们推崇,使用chatGPT进行代码补全、代码生成、UT生成,特别是遗留代码中补充新功能、增加用例等方面更是大显身手,降低了广大程序猿们的基础编程门槛,有chatGPT协助,使很多熟练使用chatGPT程序猿一个人就像带了一个小团队,切实提升了工作效率。
另一方面,chatGPT自身编程能力也在快速演进中,以chatGPT3.5为例,其4月份humaleval pass@1的评分还只有47(该分数100为满分,某个大模型超过20分就具备辅助编程能力了),到了8月底该分数就提升到了68.9,chatGPT4更是超过了80分,远远甩开其他编码大模型,可谓进步神速。广大程序猿们也是越用越熟悉,越来越喜欢。
但是chatGPT在可用性上也碰到不少局限,以下因素比较常见:
1、网络原因
有些同学受网络限制访问不了chatGPT。
2、安全限制
很多行业代码都不能上传外网,防止泄密。
3、私域知识含量考虑
a、编码阶段
要开发的代码越是通用知识多,chatGPT越是好用,原因很简单,chatGPT本身就是通用语料训练出来的。表现出来就是prompt简单,理解能力超强,程序员上手容易,生成的代码采纳率高;
与之相反,越是私有领域知识占比高,prompt越是复杂,chatGPT生成代码越是不靠谱,程序猿用得不顺手,很多时候仅作为一个查阅资料的工具。
b、测试阶段
对于FT、ST测试用例来说,也是贯穿业务流较长,私域知识含量高,chatGPT生成用例就有些不靠谱,也不好用。
4、特有编程语言
比如一些小众设计或编程语言,比如verilog、tla+等,由于预训练语料中占比不高,也会出现效果不明显的情况。
解决思路
能否自研一个私域编码大模型,把私有业务知识灌入,然后内网部署推理,既可以解决网络和安全问题,也可以解决chatGPT私域知识不足的问题,岂不美哉?
说干就干,其实自研编码大模型,只要解决算力、算法、语料三个问题就可以了。
算力方面,采购GPU和服务器或租用云环境GPU就可以了;
算法则一般从开源编码大模型(比如llama2、starcode、mpd、codellama等)入手,进行增量预训练和精调即可,精调接口有很多开源的;
最核心的是准备语料,它是真正私域知识的载体,成本和价值都最高,也是我们应该花大力气投入的地方。绝大多数开源大模型,都不会把它的精调语料开放出来,可见精调语料的重要性。
大模型研发的方式一般为预训练和精调,预训练一般6b模型需要64-128张A800(GPU数量随着模型规模变化),而增量精调仅需要2-8张A800,成本相对可控,所有自研模型一般都从精调开始。
与之相对应语料分为精调语料和预训练语料,其中精调语料更为重要,即使预训练后也必须精调才能使大模型正确输出内容。
我们以代码语料来分析语料准备的全程。
一、精调语料
1、精调语料作用
我们希望模型输出的形式和内容都符合我们的要求,其中,精调主要是用来控制模型输出的形式,预训练主要是用来控制模型输出的内容。我们的基础编程大模型使用了海量代码进行预训练,具备通用编程的能力,但模型输出的形式可能不满足项目的需求。在这种情况下,就需要对模型进行精调。
2、精调语料的格式
精调数据本质上就是你给模型展示的一个个例子,每一条精调数据就是一个具体例子,模型看到足够多的例子之后,就能够学会你想要的输出形式。需要说明的是,如果输出的形式是正确的,但内容是错误的,这说明精调已经起作用了,但是基础数据不足,模型不具备足够的知识,这时候少量精调就没用了,而要用大量的代码对模型进行精调或预训练。
单条精调数据都是一个json对象,只有两个字段:instruction和output。其中:
instruction是你要发给模型的指示;
output是你期望模型返回的内容。其中output的格式建议为:
- text:首先根据instruntion的问题直接回答一段文字来引出代码
- code:建议使用markdown格式,例如python是'''python开头, java是'''java开头,然后换行后生成代码,最后再以'''结束。
- explanation:一般包含代码的功能,用法以及代码的思路。往往会对代码中的关键函数或者组件进行解释。
例如:
{"instruction": "使用python语言编写一个函数add,返回两个数字相加之后的和"
"output": "
好的,使用python生成代码如下:
```
python
def add (i, j):\n return i+j
```
函数add输入两个数字,数字加分计算和
"}
将多条类似json串数据保存在一个文本文件中即可用于模型精调训练。
生成精调语料的过程就是标注过程。
3、精调语料要素
a、多样性
i、instruction的提问方式也有很多种,尽量能使用各种各样的祈使句、疑问句等多种表达形式
ii、语料整体也要具备很强的多样性,有数学,有字符转换,有算法、有流程等。
iii、相同的语料也用不同形式的prompt多问几遍,效果更佳。
2、output代码长度
语料中代码50行以上效果较佳(经验数据),不能太短。
3、数量
一般至少(1-10)k条才能有效果。
二、预训练语料
预训练语料预训练代码语料需要经过以下步骤预处理
1、清洗
消除代码中格式、文档性注释、json和sql(仅需要结构)等数据
2、抽样
建议20%有代表性文件全量抽取,其余80%文件在第一行和最后一行中随机抽取0-32行,少于32行取全量,抽取总量25-30%的文件。
3、去重
一般使用局部敏感哈希(LSH)将相似的代码文件映射到同一个桶中。推荐Jaccard相似性为0.7(经验值)。相似度高的代码必须进行去重,防止对重复部分造成过拟合。
4、脱敏
a、去重PII
b、去除项目信息(项目名称、简称、版本号等)
c、去除客户信息、密码、IP地址、密钥
5、权重
各种编程语言的占比要均衡,要和团队中各种语言使用的比例相对应,这一步非常关键。
6、净化
评测集数据和方案删除(比如HumanEval和MBPP字符串或解决方案)
一般来说,对于13b的大模型,预训练语料要大于10G才有一定效果。
可以通过脚本来处理预训练语料。
无论是精调语料还是预训练语料,训练时长都需要估算,使用我们经验公式推算:对于7b大模型,20b token语料,使用A800 80g单卡训练,预计时长为80-90天左右(以考虑GPU并行效率损失),其他模型、语料、GPU数量不同,可以以此类推。
小结
自研大模型的关键是语料收集、预处理和标注,只有具备高质量的语料,才能自研出高质量的代码大模型。防止garbage in,garbage out出现。
高质量的足量的语料才是项目真正的资产,后续尽管基座模型会持续演进,但语料可以重复使用,仅需要更基座大模型,并重新预训练、精调和评估即可,所以高质量语料是关键。