笔者过去一段时间做了一些基于LLM的应用落地实战,具体应用场景本身这里就不再细说了。今天主要讲一下做SFT过程中一些技术层面的心得体会,一方面是作为给自己的记录笔记,另一方面这里罗列出来和大家一起交流讨论。
- 在做任务前一定要想清楚该任务是否需要使用LLM,传统的类似bert模型是否能解,毕竟LLM的推理和训练成本都是很高的;
- 首先要把问题思考和抽象清楚,这样才能得到使用LLM的最佳使用范式;
- 多样性和高质量对于训练样本和评测样本是一样重要的;为了保证多样性,需要对目标任务按照业务类别进行归类,针对每个类别来构建训练样本和评测样本;为了保证高质量,所有的样本需要在标注人员对齐标注标准才能够进行 (一条错误样本带来的危害,是十条甚至百条正样本都难以纠正的,正所谓“一粒老鼠屎,坏了一锅粥”)
- sft作用是使模型对齐人类偏好,而不适合灌入知识,在遇到case的时候,要区分到底是模型没有知识还是模型没有对齐;(如果是知识缺乏的话,一般是通过预训练或者rag的方式来解决)
- 为了防止数据泄露导致评测数据结果不置信,评测样本的构建和训练样本的构建一定要分开,最好是2波人独立构造;
- LLM模型本身有较强的语义理解能力,对于一些query理解任务,并不需要人为的设定槽位,这样反而会损害模型的端到端处理问题的能力;
- target的所有token都会计算loss,有时候target中并不是所有token都是重要的,要学会构造target部分的样本;(如果target部分固定前缀占比较高的话,可能会损害模型的通用性能);
- sft阶段target部分的loss比较低并不能代表下游的任务一定好,要记住这个loss是所有输出loss的平均值;
- sft的时候,prompt不需要特别的复杂,清楚明了的讲清楚任务是干啥的就行,至于那些在prompt里包含1/2/3/4 列举步骤的描述,可以省去(这样起码能节省一部分算力),留给sft的样本来让模型进行学习;
- LLM对于数字的运算/比较等逻辑操作 一直是一个弱项,可以考虑单独把这部分抽出来,交给后处理程序去做;
- 引入rag技术的时候,不能仅仅考虑rag内容是有关系正确(positive)的情况,完全无关(easy negative) 和 有关系但是误导(hard negative)样本都是要在考虑范围之内,进行全面评测方案的可行性是很关键的;
- 之所以说SFT阶段不适合学习知识,是因为SFT阶段对于一个知识点的描述是片面的(如果你想让LLM全面理解一个实体的概念,只在SFT任务上对任务进行一个片面的描述,例如{input:鲁迅的原名是:,target: 周树人},那么模型可能只是学到了一个片面的概念,但是下次我再问"周树人的笔名是谁的时候",模型大概率是不知道的。)。模型对于这些片面知识点的理解也是不充分的,往往只学到了表面,而没有和已有的概念实体关联起来。而预训练的预料由于样本量很大,表述很丰富多样,对一些概念的学习也会更“立体,充分”,从而能让模型真正全面的掌握对应的概念以及概念之前的关系 这种信息;
- LLM相关应用都有一定的概率和不确定性,在落地应用时候的一些必要前处理、后处理手段还是非常重要的;
- 在做搜索后处理的时候,对于一些强特色业务下的、特别是和模型本身理解不一致的改写信息(青菜=>青笋)不要出现在训练样本里。模型的能力很强,总能很好的拟合你输入的训练样本,但是往往会找一些奇怪的路径拟合,在解决了一些问题的同时,会带来更多奇怪的问题。还是那句话,SFT对于知识的描述是片面的,不要尝试在SFT阶段教给模型一些知识和概念。一方面模型不一定能学会,另一方面会把模型训傻了。
- 在做模型评测的时候可以把模型当成是“人”,按照评测“人”的方式去评测模型,即可以按照“指令遵循”,“推理能力”,“学习能力”,“认知能力”,“应用能力”,"交互能力"等维度评价,针对不同维度给出对应的评测分数;但是在进行模型调优优化的时候,要时刻谨记所谓的LLM就是一个高级的概率模型,它所有的输出token的概率分布都是基于其输入的上下文token综合计算出来的,更好的更合理的上下文才能激发模型输出更准确合理的答案,很多优化的手段work的底层的原理都是这一点(包括cot,react等)