领域模型脱胎于通用大模型,两者有相似之处,但通用大模型在训练时使用的是通识数据集,缺少领域知识,导致企业在应用过程中会发现一些问题。比如,如果我们要做一个滴普科技的智能问答机器人,但通用大模型并没有学习到滴普科技的各种产品信息,缺少先验知识。
目前这个问题有两种解决途径,一种是 RAG,通过外挂知识库来弥补通用大模型缺乏领域知识或知识更新较慢的问题;另一种是构建领域大模型,即在通用大模型的基础上使用领域数据集进行微调,使其能够识别或记住领域知识,以更好地为企业服务。
本文将分享滴普科技在服务客户过程中积累下来的领域大模型构建指南。
一、领域大模型与通用大模型的区别
1. 数据集不同
- 通用大模型已有许多优秀的开源数据集,注重广度、覆盖各行各业,但在特定行业的深度不够,或只在某几个行业具备一定深度。比如 Code Llama(代码生成大模型)在 Python、Java 等代码层面有较多的数据集的积累,但其他冷门语言的数据集较少。
- 领域大模型可以使用通用数据,但不能完全使用,因此受限于行业。目前只有少数行业存在行业数据集,比如法律行业有裁判文书等开源数据集,但较多行业比如零售没有数据集。
2. 灵活性和准确性不同
灵活性和准确性是天平的两端,如果追求高准确性,灵活性就会受限,相反若追求灵活性则准确性会受限。因此在模型训练过程中需要平衡灵活性和准确性。
3. 复杂性不同
二、基于企业数据的领域数据集构建
数据集准备是领域模型中最重要的环节,最终会影响领域模型的效果。
1. 高质量数据集创建难点
在创建高质量领域数据集的过程中,存在以下三个难点:
- 高质量数据集少:较多客户只有一个文档库,且这些文档大多是完全未经处理的。
- 数据处理受限:需要先对客户的数据进行处理,耗时、成本高。通用大模型处理数据时,优先会使用 ChatGPT 先做一些预处理,但为了保障企业数据隐私,此类数据处理方法无法使用,数据处理工具受限。
- 数据多样性:数据多样性的平衡会影响模型的灵活性和准确性,如果数据多样性低,模型的灵活性受限;如果多样性高,模型的准确性就可能会降低。
2. 高质量数据集创建方法论
(1)SFT
高质量数据集少时,优先使用 SFT 进行训练。
我们截取了《置身事内》中的一段文字,近似于在做领域大模型时普遍拿到的数据类型,即 word 文档数据。我们要通过 ChatGPT 或人工的方式,将数据处理成一问一答的对话数据。比如问题是“土地财政是什么,它对地方政府对贡献有多大”,回答的结果就是书里面的原文。通过这种方式去积累 SFT 数据,通过 SFT 去做训练,可以降低我们对高质量数据集的要求。
就实际测试情况来看,在做一个特殊领域的时候,只需要积累 1000 条这样的问答对,就可以达到一个能够接受的效果。
这就是我们的第一个方法论,通过 SFT 去做训练。对于一些很大的文档,从中提取要点,通过这种方式喂给数据集。
(2)使用大模型自身能力
面对数据处理受限问题,我们提出的方法是使用大模型本身的能力去提速数据处理过程。
例如,靠人工去写问答对肯定是不现实的,这种情况下可以通过大模型本身的信息提取能力去实现。把原始文档放到 LLM 里面,通过 prompt 形式提取文档的详细信息,使其变成结构化知识,转换为训练集。
在这个过程中,LLM 有几种选择,例如 Claude2、GPT4 和 GPT3.5。这三种模型能够在公网上使用。我们强烈推荐 Claude2,因为它最大能支持 200K 的 token,意味着我们拿到的大部分文档都可以整个塞进去,不需要通过 RAG 或embedding 的手段做特征提取等工作。ChatGPT4 比较贵,不太能获取到,3.5 版本也是可以的。如果面向不能把数据放在公网上的客户,我们建议使用 LLAMA2 13B、ChatGLM2 6B。
我们在客户现场做项目的时候,第一件事是先把滴普大模型部署到客户的环境中,然后基于滴普大模型帮客户处理文档,以解决客户文档处理中的人手问题。在这种情况下,人所需要做的只是根据文档特征确定 prompt,之后就可以把文档一篇一篇地放到大模型里面,使其源源不断地输出结构化知识。最后我们再通过一些手段把结构化知识变成我们的训练集。
(3)数据多样性的平衡方法
在结构化知识转变为训练集的过程中,我们需要去思考数据多样性的平衡问题,即如何平衡灵活性和准确性。
我们认为,要达到比较平衡的效果,领域数据集大概需要占到 30%。超过这个比例越多,灵活性就越低、准确性越高;相反,则灵活性越高、准确性越低。
具体这个比例选择多少,需要根据客户需求及实际场景去考虑。
- 比如某个客户需求是做一个意图识别大模型,它不需要面向普通用户,而是面向程序,这种情况下是不需要考虑灵活性的,那么就可以把领域数据的比例直接拉到 100%。
- 又比如客户需要大模型对公司汽车产品的操作指南、操作手册去进行回答,用户遇到问题就可以询问大模型。对于这种客户,是需要应对客户需求、直接面向终端用户的,那么就需要把数据拉到 30%。
(4)总结
三、模型训练方法的选择
常用的训练方法包括 Fine tune、P-tuning、Lora、Q-Lora 等,接下来介绍如何选择微调方法。
1. 不同训练方法的比较
训练方法可以分为全参微调和高效微调两类:
(1)全参微调
(2)高效微调
2. 选择方法
这里列出了两个数据集:
第一个数据集的目标是调整格式:
问 Java 线程是什么,用滴普大模型生成了回答,这个回答看上去是比较完整的。如果客户有个需求是给出一些定义而非代码,那么就需要去微调模型的输出。需要通过这类数据得到下面关于“Java 线程是什么?”的一句话定义。
第二种数据集的目的是记住新的知识:
比如一个金融题,授信额度是什么?这个题目答案是 a。但是在没有训练或没有针对性训练的时候,大模型的回答是 c,这是没有微调时的答案。这种情况下如果要微调,那我们的目标是要让大模型能够记住一些新的知识。
(1)从数据集特征入手
通过这两类数据,即可得出第一个方法论,先从数据集的特征入手:
- 只是做一些输出格式的调整,不需要让大模型去记住新的知识时,选择高效微调方法。训练模型只是为了输出更符合客户需求的话术,或更符合客户要求的数据集,而并没有改变数据集本身的权重、记忆、知识结构时,Lora 的表现比较好。
- 需要让模型记住新的知识时,建议通过全量参数去微调。
(2)从硬件层面选择
进行全量微调时,13B 模型至少需要一块 80G 的 A800。根据实际数量不同,对块数要求也不同。比如根据滴普实测结果来看,350 万条的对话数据集,一块 A800 肯定是不行的,速度会非常慢。训练一个 100 万数量级的数据集,A800 的块数估计是 32-64 块,也就是至少需要两台服务器,才能达到可接受的速度,即不超过 72 小时。
7B 模型,4090 就可以跑,需要 24G 的显存。
(3)从效果层面选择
对灵活性要求不高,只注重准确性时,全量微调是比较好的选择。需文本分类、实体关系提取、意图识别之类的场景,对数据多样性、灵活性要求不高时,完全可以选择全量微调的形式,因为如果发生过拟合也可以接受。
(4)总结
结合客户需求,建议先使用 Q- Lora 进行试验;如果 Q- Lora 不可行,则选择Lora;如果 Lora 也不行,就选全参微调。
四、验证集的构建及模型评估方法
当我们辛辛苦苦用昂贵的硬件通过 72 小时甚至几百小时的训练之后,得到一个模型,迫切需要验证其是否可用,有没有记住数据集。
首先模型一定是选择 loss 比较低、准确率比较高的,但是选择准确性最好的模型就行了吗?如果它发生了比较长的记忆遗忘的情况怎么办?因此,我们需要去验证一下模型是否合理。
1. 领域大模型验证的难点
领域大模型的验证是比较难的一个问题,因为它不像通用大模型存在 human even 等通用的验证数据集,只需要用普通的脚本跑一遍就可以知道好还是不好。
2. 五维模型能力评估
对于领域大模型如何构建验证集,到目前为止仍处在探索过程中,这里要讲的方法不一定是最优的,只是我们通过一些选择、实验发现的效果比较好的一种方法,并且评估方法也会不停迭代。
我们建立了五维的模型基础能力评估模型:
(1)分词能力
中文和英文不同,英文是一个单词接近于一个 token,但中文是通过单个字喂进去的。在这种情况下,模型本身的分词能力就非常重要。
在没有大模型之前,分词本身就是一个非常难的事情,是靠人类写一些方法去实现的,其效果局限于分词模型的大小。但是在大模型时代,可以把单个字喂到大模型里,让大模型自己产生分词能力,分词能力已经从之前靠分词模型的能力变成了大模型本身的能力。所以我们首先就要去判断模型的分词能力是否及格。
(2)句法分析、语法分析、语义消歧、理解能力
分完词后,要去判断它的句法分析能力,然后判断语法分析能力,以及语义消歧能力,最后判断其理解能力。
从这个过程可以看出来,对于一个基本的文本,通过它的语料和元素,从最开始的一个字词变成一句话、再变成语法、再到语义消歧,整个阅读理解是从低到高的顺序。
3. 举例
(1)分词能力
给大模型一段话,比如告诉他,请对下面这段话进行分词并用数组格式输出,通过这种方式判断模型能不能正确分出来。
(2)句法分析能力
模型能不能分析出一句话的主语、谓语、宾语、主谓宾、定状补等,分析句子之间的关系,并列、转折等。
(3)语义分析能力
比如请分析一下下面两句话的语义是否相似:广东的广州是广东的省会,广东省的省会是广州。这两句话的含义其实是一样的,模型最后输出的内容是能够识别出这两句语义是一样的。另一示例,广州是广东的省会,江苏省的省会是哪?这两句语义是完全不一样的,大模型也能够识别出来,说明它是具备一定的语义分析能力的。
(4)语义消歧能力
比如给出“雷军是小米的创始人”,询问模型小米指的是?因为小米放到某些特定语义下指的我们吃的小米,但在这句话里面小米指的是公司。模型回答小米指的是小米科技,说明它能对语义做一些消歧。
还比如给它一段比较长的昨天发生的新闻,询问模型里面提到的公司是哪家?模型能够识别出一段话里面的具体代词,这也说明模型可以做到跨上下文的关联性。
(5)理解能力
给模型一段非常长的文本,让模型能够提取出这段文本里面的一个比较关键的特征。
4. 验证集准备方法论
- 事先准备通识验证数据集。
- 针对五个维度,客户准备具体领域的数据集。
- 准备一个基准模型,可以用 Llama2、chatGLM、百川之类的开源大模型做基准。如下图所示,将基准模型和我们模型的能力放到同一个雷达图上,得出两者之间面积的重合点以及两者的差距,这是一种横向对比的方法。
五、国产硬件评测
最后来分享一下对国产硬件的评测结果。
根据最后一列的数据,英伟达的 A800,13B 的推理速度大概是 33 个 token 每秒,7B 是 45 个 token 每秒。
以此为基准,摩尔线程 S3000 显卡,13B 的推理速度可以达到 20;S4000 可以达 29;华为升腾 910A,13B 是 15,7B 是 23。
兼容性方面,这些显卡的兼容性都是不错的,但是都需要对我们现有的英伟达的模型做一些转换。
六、问答环节
Q1:模型验证还是要靠人工来看?能不能自动化?分数是怎么得出的?
A1:很多验证是可以通过脚本去干的。以分词为例,对比它的输出结果和标准答案之间的区别。prompt 写得好一点,告诉它应该输出什么样的格式,调整成代码能够接受的输出,就可以自动化去做判断。
Q2:拿比较少的数据去微调一个领域的模型,它在回答那种需要准确答案的场景下的效果是怎么样的?比如在法律领域,用一两千条去调完之后,问它刑罚的第二条第三款,它能够比较准确地回答吗?
A2:如果你问的问题已经在这 1000 条内容之间了,它只需要做一些简单的推理,这个是没问题的。
如果说只训练了刑法的内容,但问他民法的内容,那肯定是回答不了的,会出现幻觉问题。
所以如果需要的领域比较大,那肯定是要对应地增加这 1000 条数据集的。
Q3:比如用一两千条的数据来微调它,那么即使问的问题可能是在你的训练数据集里的,但问法稍微一变,它还能够准确的回答吗?比如说法律里的权利跟权力。这两个力是不一样的,那么它在回答的时候,可能你的数据集体原始答案是利的利,它会变成力量的力,它意思就完全变了,这种情况的话会不会出现以及怎么解决?
A3:会出现,其实这个问题就是全量微调里面非常头疼的问题,训着训着可能把它本身的一些能力给弱化掉了,这在全量微调的时候其实是非常容易出现的一个问题,并且还不是少数。
这种情况下我觉得第一个点就是验证模型变得非常关键。比如说就像你刚刚问的,权利跟权力之间有什么区别。我们在准备数据集的时候,就把这一块的数据做成训练集训练进去。完全指望模型去做知识与知识之间的连接效果没有那么好。其次就是如果真的发现这种情况,那只能去不停地训练,只能通过准备数据集加上验证的方式,尽可能得去降低这一风险。但要完全避开这种问题,目前还是做不到的,可能得等整个模型界有一些新的技术出现才会解决,并不是通过工程化的方式能解决的。
Q4:您刚刚讲了整个做领域模型的 pipeline,我有一个小小的问题。因为您刚刚都是单轮的,从准备数据一直到训练、验证,假设验证效果不好,我们肯定要再继续来这个过程,那在这个过程中如果我们发现,比如准确性不高,我们可能想要把数据量变大、数据质量提高或者换一种训练方法等等。这个时候一般是怎样去考虑的?
A4:我们更多的也是通过验证的结果去看的。
举个例子,如果说发现它的分词能力比较弱,那么已经不仅仅是训练集准备的问题了,可能是整个模型过拟合已经非常严重了。这种情况下基本上这个模型是需要重新训练的。
如果只是理解能力或者语义消歧能力出现问题,可能只是数据集准备得不够到位。这种情况下就需要去补充数据集。
我们发现大部分情况基本上是通过补充数据集或者调整数据集就能够解决的。