手把手教你低成本训一个好用场景小模型,包教包会,提供全部细节

文摘   科技   2024-04-20 10:50   江苏  

     最近网传chatgpt3.5访问量下降,接着chatgpt3.5开始免费了,不需要购买token并且也不需要注册就可以使用了。

看上图,不需要登录了

    一叶知秋,窥豹一斑可知全豹,从这两件事可以得出一个洞见:chatgpt3.5作为一个通识大模型,之所以初期这么火爆,是因为chatgpt通过人机自然语言交互的方式,真正拉低了人机交流的障碍,大家都这被这种人机顺畅丝滑对话所吸引,极大程度激发大众的体验欲望,说白了,很有可能就是情绪因素占了很大比重,也就是说chatgpt在通用场景中给大家带来了情绪价值。等到大家尝鲜的热情过去,基于情绪价值的好奇心逐步转弱,访问量随之下降。

     为了说明我的观点,我们简单介绍下大模型的应用分类,可以参照下图:

    所以,真正要能在业务领域中获得使用大模型的实质性收益,更多还需要加强大模型的私域能力,也就是在领域大模型和场景大模型上发力(图中L1和L2),特别是一些较窄的场景中更能带来确定性高性价比的效果。

    而对大模型注入私域能力,主要包含两种方式:

    1、知识学习

    大模型就像一个高中生,知识学习相当于学习记忆课本上的概念、公式、定律等。

   2、解题能力

    相当运用知识进行解题的能力,需要很多的方法和技巧,需要参照例题学习,对应大模型应用的few shot,然后自己再融会贯通,具备举一反三,即泛化能力。

    知识学习一般都是通过增量预训练进行,但增量预训练,就会面临四耗的问题:

    需要大规模GPU算力集群,算力集群需要采购大量GPU、服务器、光交换机等,又要进行机房建设、空调改造,成本巨大;就算租用云厂商的算力,成本也不低,甚至如果租一年租金都可以买一套GPU服务器了,可谓耗资巨大。

    另一方面,收集海量语料、清洗、消重、配比、增强等也需要耗费大量人力物力,而且动不动训练时长就要按月计算,可谓耗人耗时耗电。

    还有增量预训练效果很多都差强人意,需要投入团队反复分析、调测,不是过拟合就是泛化不够,左右摇摆,耗时耗力,总之是个妥妥的吞金兽。

    很多团队退而求其次,采用外挂知识库+RAG+API映射+Agent等方式进行知识注入,虽然没有增量预训练的效果好(增量预训练是对知识从各个维度进行全方位的链接,比知识库的知识点链接的维度全,经得起各个角度各个方向的查询),但胜在四耗问题小的多。

    解题能力是我们关注的主要方向则必须通过精调解决,效果和低成本又是我们必须考虑的问题。

   如何兼顾质量和低成本精调一些特定领域的场景呢,我们这里给出一个通用的解决思路:

    场景分析-》语料自动生成-》精调-》评估

    下面以一个实际例子来分享下我们低成本精调的过程。

    基本花一个开发人员几天的工作量,再弄几张低端GPU就搞定了,相信大家一定会觉得这么简单,you can you up的感觉。

一、场景分析

    1、背景

    我们的系统是上千万行c/c++代码的嵌入式软件,当然现在底层也都虚拟化了,特点是高并发、低延时、超大规模、和底层硬件强协作、特性动态强耦合、需要长时间高SLA(9999)以上不停机运行和维护。

    有一个特殊故障定界定位的场景,需要在流程处理函数每个代码分支加上通过在调用计数宏进行函数调用统计(仅统计不产生日志,对性能损耗可以忽略不计),当出现线上bug的时候,可以通过在线查看调用计数来确定流程中函数和分支调用关系,从而快速定界定位故障。

    这个功能对于大型嵌入式软件系统很奈斯,可是要在核心代码的每个函数的每个代码分支加上调用计数宏,而且这个宏还要结合模块、文件、函数上下文信息,添加工作量可想而知,如果用大模型来自动补充,那就更奈斯了。

    2、可行性分析

    这个就属于不需要过多知识注入,重点是提升代码补充调用计数宏的编码功能,属于典型的提升解题能力型的应用,精调非常适合该场景。

    3、方案对比

    另一个方案是在内部编码大模型中,使用prompt few shot进行调用宏计数生成,发现由于代码分支类型较多,few3或few4才能有一定效果,且泛化性较差,还是决定采用精调方案。

二、语料自动生成

    精调语料人工标注工作量较大,而且治理的成本也高,这里采用脚本自动生成的语料的方案。具体做法如下:   

    1、识别高质量的存量调用计数函数

    使用脚本扫描整个代码库,抽取每个函数,计算每个函数的CCN(圈复杂度),检测函数中存在的调用计数宏个数,和CCN(圈复杂度)数一致就认为是高质量函数。

    2、语料生成

    我们都知道代码精调语料由prompt和answer组成,参见《自己搓一个编码大模型,凑齐语料就OK》,其中:

    a、instruction

    把高质量函数中的调用计数宏通过正则表达式去除(提示词中需要补充的调用计数宏的代码),再加上引导词等其他要素,即可生成精调语料中的instruction。

    这里要注意同一条语料要使用不同的提问方式多生成几次(使用语料增强脚本),以适应推理应用时不同的prompt模版。

    b、answer

    包含introduce、code、explain三部分,通过脚本把高质量函数本身作为其中code部分(补充了调用计数宏的代码),再补全其他两部分即可。

    最终我们生成并筛选了800条高质量精调语料。

三、精调

    1、基座

    我们选择了自研的7b编码模型,有私域代码能力,当然也可以选starcode、codellama、deepseek。

    2、算力

   找到了8张A40,虽然不如A800/H800,但48g显存也可以凑合用。

    3、算法

    采用lora方式精调,我们对精调脚本进行了定制,其实只弄清楚模型的结构,lora精调脚本很容易定制,一般模型都是CAUSAL_LM类型的,然后设置成模型对应的q、k、v和对应的相关层即可,我们的脚本对starcode、codellama、deepseek等都可以通用。

     如果想要精调脚本、语料生成脚本等也可以和我联系。

    下面把一些我们调整后确定有效的重要超参给大家交流下,便于大家回去自己尝试:

    Lora r一般都定为8,学习率2e-5,由于A40走的是PCIE,所以batch_size设为2,单卡显存大概占用32g左右,对于48g的A40比例挺好的。

    训练加速方面就是简简单单使用deepspeed,8卡DP并行和zero2并行,没有设置PP并行。单机多卡,怎么简单怎么来吧。

    训练采用32个step进行一次梯度合并、评估和checkpoint保存。

    另外loss也没有局限在0.8,由于是特定narrow场景,我们认为可以不用太多考虑通用编程能力下降的问题,过拟合一点也没关系,所以对应的max_steps设为2400,多训几轮即可

    实际训练中,我们loss远低于0.8,取loss触底反弹的那个checkpoint作为结果。

    基本上达到loss满足要求要5个多小时,所以晚上下班前跑起来,第二天早上结果就出来了。

    4、推理

    由于模型较小,使用一张壁韧104s(几千块钱)就可以跑起来,提供1qps的并发,如果用户增多,可以线性扩充资源,成本非常低。

四、评估

    1、领域评测集评测

    在语料中选择20%作为评测集,使用一张A40推理,评测方式:在推理生成的添加过调用计数宏的函数中,通过脚本去除生成的调用计数宏,剩余部分和评测集中prompt函数进行相似度对比(莱文斯坦算法),相似对99.99%则认为相似,确保添加的调用统计宏对原函数没有伤害,评测集通过率>95%。

    2、人工评测

    安排一个整团队的开发人员使用,反馈prompt中通过zero shot就可以生成令人满意的调用技术宏代码,非常奈斯。

    3、通用评测集评测

    使用humaneval中文c/c++进行pass@1评测,通过率下降10个百分点,证明场景精调会造成对齐税,即专用能力提升,通用能力下降,就像一个小学生一样,天天狂补数学,结果数学成绩提升,语文和数学能力下降,不过我们要训练的是专用场景模型,不会用在通用编程场景,通用能力我们不太care,跟预期一致。

五、成本

   人力耗费

   找了一个开发人员,语料生成脚本、精调脚本、评测脚本花0.5天,语料筛选和模型评测0.5天,环境准备0.5天。共投入1.5个人天人力。

    电力耗费

   另外自动整代码库扫描生成语料1天,精调5个小时算1天。这些都是自动执行,耗费点电力。

   算力要求

  再找几张散卡,像a40,上一代v100(32g),消费级卡等可以玩起来。

     成本可以说非常低。    

    小结,我们这套方案,最终效果和成本非常奈斯,既可以部署在devops流水线上自动生成领域代码,也可以提供开发人员从推理环境用zero-shot方式prompt自助使用。

    无论精调资源、语料人力耗费、训练难易、评估难易、推理资源方面都较低,重点做好场景分析和语料自动生成这两部即可,可以说性价比非常高,技术细节大家都可以和我联系,希望大家都可以照猫画虎,照葫芦画瓢用起来。   

丁辉的软件架构说
代码匠艺,软件系统架构,AI平台和应用,生活趣事。
 最新文章