3.4.1 代码能力
典型应用:Copilot; Codex;
多任务:代码生成;写文档;debug;code review;
多语种:Python, Java, JavaScript, C/C++,... , HTML/CSS, SQL, bash/shell
1. Code专家模型
从预训练模型分支出来,加入1T token的混合数据(code占比85%),做continue-pretraining;
使用CodeLlama的配方;最后数千个steps改用long-context微调(16K窗口);最后,使用code占比高的数据,做SFT+DPO对齐训练;
用途:为主模型,做rejection-sampling;
2. 数据生成
痛点:follow指令;代码语法错误;生成错误的代码;fix bug;
自动生成了270万个样本,用来作SFT;
2.1 带feedback的代码生成
研究表明,用自己模型生成的代码,再训练自己模型,效果不变好反变差;因此,这里引入feedback,让模型从自己的错误中学到东西,回到正轨;
- 生成题目描述:从代码数据中,随机摘取代码片断,输入大模型做内容描述;
- 生成代码:将以上题目描述输入大模型,使用多种编程语言,生成代码;有提升:在prompt里加上良好变成规范的描述,在prompt里加上把代码解释放在注释里;
- 正确性分析:静态:用代码parser、linter来给出错误提示信息;动态:让大模型生成单元测试代码,放在container里运行,收集报错信息;
- 错误修正:将<题目描述,代码,单元测试用例,报错信息>输入大模型,让其生成正确的代码/单元测试用例;多迭代几次直到静态+动态分析通过;初始报错的题目里有20%可以通过这步生成通过测试;
- 多轮迭代:多迭代几轮,逐步增强大模型能力;
2.2 小语种
痛点:小语种数据量少;
解决:用大语种的代码做为输入,让模型翻译成小语种代码,结果喂给代码parser、执行等筛出正确的;
2.3 增强文档和注释能力
痛点:无法借助自动执行等工具;
解决:1. 将代码输入模型,让其生成注释、文档、代码解释;2. 将上步生成的注释或文档(去掉代码本身),输入模型,让其生成代码;3. 将原始代码和生成的代码,输入大模型,让其裁判生成代码的质量,分高的就说明注释、文档是好数据,加入训练样本中;
2.4 调优system prompt
system prompt里,让代码follow标准代码规范,注意性能(算法时间复杂度、空间复杂度)等;
2.5 增强伪码生成正确性
痛点:有些数据、任务,本身题目就是让给出伪码或代码片段,无法用执行来得到feedback
解决:用大模型来做裁判;分多个维度(正确性,风格)给出打分;分高的才通过;
遇到问题:本身就很难的代码,不容易通过;解决:人工修正了这些题目的代码,让其挤过去通过模型裁判;
3.4.2 多语种能力
1. 训练Expert模型
从总的pre-training模型分支出来,使用90%都是多语种的数据比例,继续pretrain;
之后再SFT+DPO反复训练几轮;
为主模型训练,提供更高质量的训练数据;
2. 多语种数据收集
2%:人工标注;44.2%:从其他NLP数据集中直接拿;18.8% rejection sampled数据;34.6%翻译成小语种的数据;
其他NLP数据集:过滤掉低质量数据;
Rejection sampled数据:人工写的prompt,大模型生成的response;用不同的temperature来增加多样性;对system prompt进行了调优,提升生成response的数据质量;用语言工具,来检查response是不是prompt那个语种;
翻译数据:纯拿英文general数据来进行翻译,和小语种的语言文化不符合,容易带来bias;这里只用数学推理这类,从英文来过来做小语种翻译;
3.4.3 数学推理
挑战和解决方案:
1. 复杂题目的prompt较少;
解决:从预训练数据中拿数据改成QA格式用作SFT;对数学任务做了细分,针对每轮的评测结果,对短板任务,进行数据增强;
2. ground-truth的CoT数据,少;
解决:每道题,生成多组答案,只保留正确答案的样本;使用llama3来作为裁判,评判中间推理过程是否正确;
3. 如果用模型来生成中间步骤,容易生成错误;
解决:训练对结果、中间过程进行评价的reward model,用该model来过滤有错误的数据;对复杂问题,用蒙特卡洛树搜索,结合reward model,来生成正确的路径;
4. tool,借助代码来增强推理能力;代码和文本交替使用;
5. 训练数据和推理的差异;推理阶段,中间可能有来自人工或模型的feedback数据;
使用大模型来将错误的数据纠正为正确的数据;跟人一样,针对性的多做些之前做错的题目!
3.4.4 long context
如果SFT阶段不特意使用长文本数据,则pre-train好不容易对长文本的训练成果,又缩回去了;
长文本SFT数据,人工构造成本太高,主要是模型自动生成的。
QA:精心挑选一些长文本文档;切分成多段(每段8K tokens);每次输入一段给大模型,来生成Q和A;将<整个长文本文档、Q、A>,作为训练数据;
Summarization: 层次总结,用大模型先将每一段文档做总结,然后用大模型将这些总结再做总的总结;将<整个长文本文档、总的总结>,作为训练数据;将总的总结喂给大模型,生成QA,将<整个长文本文档、Q、A>,作为训练数据(这些QA是整个文档层级的,和上面的每段生成的QA,不同)
Code: 从一个python项目里,解析出哪个文件import的次数较多;把剔除掉了该文件的项目代码,放入prompt,让大模型生成<哪些文件需要import该文件,该文件的代码>
经多次实验,SFT数据里,long context数据占比0.1%时,训练出来的大模型在长和短评测集上的效果都能变好;
3.4.5 Tool使用
用上如下工具:
搜索引擎:比模型数据截至日期更新的数据;细节数据;
python执行器:执行复杂计算,读取用户上传的文件,QA、Summarization、数据分析、可视化等任务;
数学计算工具:Wolfram Alpha API
支持单步;也支持先生成plan,再一步一步推理,每一步里可以调用工具;
支持zero-shot能力,即没有专门训练过某工具,仅将其描述放入prompt直接推理即可使用该工具;
实现:所有tool都是用python函数调用的形式;大模型输出的tool调用和函数参数,生成json格式的文字;支持在system prompt里enable/disable某个tool;
数据收集:人工标注是主力;对于step-by-step多轮,每轮输出让标注员对多个response做好坏判断,都不好就修改其中一个;这轮的好的或修改后的,放入下一轮的prompt里;(只能修改tool调用文字,以及基于tool的推理文字,不能修改tool的输出结果!)
使用bootstrap策略,基于上一轮最新的LLama3模型,来生成下一批的待标注数据。逐步增加复杂程度,先是单论对话,然后多轮对话,最后是多步工具使用;
- 单步tool使用:1. 用few-shot-example,让大模型生成需要调用tool的prompt;2. 用few-shot和第1步生成的prompt,让大模型生成tool调用;3. 调用tool;4.将tool的结果放入prompt,让大模型生成最终答案;(第2步大约有30%的结果是错误的)
- 多步tool使用:1. 让大模型生成需要调用多次tool(可以是相同的tool,也可是不同的tool)的prompt;2. 用few-shot,让大模型交替生成tool调用和推理;(类似ReAct)
- 读数据文件的能力:1. prompt里,是题目+数据文件路径;2. 大模型生成读取该数据文件的代码(读取大模型认为的对解该题有用的schema和样例数据),print出来;3. 调用工具,得到print结果;4. 把上步数据结果放到prompt里,让大模型生成解题代码;5. 执行代码,得到print的结果;6. 把上步结果放入prompt,让大模型给出分析和最终答案;
教会模型它能解决的简单问题别调用tool: 在system prompt里打开tool开关,简单题目,answer直接给答案不调用tool;
0-shot tool使用:
1. 支持简单调用,嵌套调用,并行调用;复用Stack数据集,将其做了过滤和修正;
2. 多轮tool调用,也是用大模型生成的prompt和各种tools;
3.4.6 事实准确度(降低幻想)
思想:SFT阶段,应该重点在让模型"Know what it knows",而不是往里灌输知识;
步骤:
1. 从预训练数据里,挑选一段文本;
2. 将该文本作为prompt,让大模型输出一段关于它的Q;
3. 将Q作为prompt, 用大模型生成Answer;
4. 用大模型做裁判,得到Answer和原文本匹配的“正确性”;
5. 用大模型做裁判,得到Answer的“信息量”;
6. (同一段文本,2345可能采样多次)4和5都反复答错的,这段文本作为Q,“我不知道”作为A,喂给大模型去训练;
3.4.7 指令跟随
设计很多不同的prompt,不同的场景和任务,或者不同的回复长度、格式、AI人设、语气语调;
标注员和AI进行对话,给AI的回复进行打分;
这些多样性prompt的数据,作为reward model、rejection sampling、SFT、DPO的训练样本;