自从github copilot兴起之后,各家copilot都如雨后春笋一样冒了出来,百度的comate、阿里的tongyilingma、智谱的codegeex、非十的fitten code等,各有各的长处,百家争鸣、各显神通。
但是这些商业copilot背后的模型无一都有一个命门,那就是在通用知识的补全上效果明显,甚至有宣传采纳率可以达到46%(全部or部分接纳候选代码的次数/推荐代码次数),姑且认可这个数据(毕竟是要卖产品,厂家声明的数据,人之常情,不寒碜,能理解)。但是对于私域知识,补全效果总是差强人意,但是私域代码在实际项目中占比一般都超过30%,修改频度和难度都是最高,这部分对项目来说相对更重要,这部分该如何提升呢?
答案就是训练一个私域补全模型,再挂若干本地知识库,就可以轻量级解决私域代码补全效果的问题。
训练私域模型,最重要的就要有足够数量(一般7b模型要过w条才有效)的高质量的评测语料+分场景的高质量的评测语料。
大家知道标注语料(无论是精调语料还是评测语料)都是妥妥的吞金兽,需要耗费巨大的人力物力。
而且发动大规模的人力标注,在巨量语料的情况下,语料质量很难拉齐,即使通过自动化脚本检查,也只能检测语料规范和类型等不一致问题,对于语料业务语义正确性则很难检测。
另外,语料重复性也是个巨大问题,往往人工海量标注以后,看似巨量的精调语料,经过去重工具去重后,只能预留20%甚至更少。
有没有低成本高质量的办法构建低重复度的精调+评测语料呢?
这里也不卖关子了,把我们研究的精调+评测语料自动生成方法给大家介绍下,希望大家能够借鉴。
本质就是模拟开发人员实际工作中代码补全的场景,就是利用git commit log自动生成语料(包括精调语料和评测语料)。
一、精调语料
1、采集某一个特定时间点之前(三个月前),一定时期的git commit log(比如半年或一年)
2、取其中merge合入代码作为补全expected
3、expected前后代码按比例作为prefix和suffix代码
4、上述2和3中的外部依赖(宏定义、结构体定义、函数定义、全局变量)抽取到dependence字段中
5、从当前文件、兄弟文件、文件名相似文件(jaccard,比如门限0.25)中抽取2和3中的最相似代码放入similar字段
6、每条语料都生成行内补(占比70%)、单行补、多行补、函数签名补、注释补(如果有注释)
7、语料包含变量声明、函数调用、函数返回、结构体赋值、分支语句等类型。
以上都可以用脚本扫描代码库生成,后续还可以通过语料生成流水线自动生成增量语料。
本次实验我们生成精调语料43k条。语料有了,无非就是llama pro进行预训练和fim+格式精调,甚至直接fim格式预训练不精通也能取得不俗的效果。
二、评测语料
首先需要进行评测模型的能力维度设计,我们私域代码补全主要应用于三类场景:
1、存量代码维护(占比70%)
2、存量代码新增功能(20%)
3、全新功能(10%)。
评测语料针对上述场景设计,具体为:
针对1,从精调语料进行均匀抽取10%作为评测集,为了防止评测污染,这部分评测集不会进行精调。
针对2,会选取精调语料截止日期后的git commit log进行生成,防止模型见过完全一致的代码,当然,精调语料中可能还会有些类似代码。
针对3,从精调语料截止日期后的非本模块代码库git commit log生成,模型完全没有见过类似代码,评测模型的泛化能力。
三、模型侧评测
模型 | 存量代维护评测集(4.8k) | 存量代码新增功能评测集(2k) | 全新功能评测集(2.8k) |
m1-7b-pretrain | 0.532 | 0.56 | 0.472 |
m-7b-sft | 0.608 | 0.589 | 0.487 |
从预训练和精调效果,评测集评测结果和我们的预期基本一致,初步判定7b模型可用,当然还需插件侧端到端评测和用户实际试用反馈良好才能上线。
综上,可以看出低成本+高质量精通语料和评测语料是模型效果的关键,希望本文做法给大家以启迪。