有奖:语音产品征文挑战赛等你来> HOT
文档中心 > TI-ONE 训练平台 > 实践教程 > 使用数据构建准备 LLM 精调数据

总览

高质量的训练数据对于提升模型精调效果至关重要。为了帮助用户快速准备训练数据,TI 平台将内部研发所采用的标准数据准备流程沉淀到了 TI 平台“数据中心/数据构建”模块。
本文以简单的原始数据样本为例,详细展示如何使用此模块来生成适用于大模型精调的数据集。

前置要求

后续所有操作,均要求您已准备好 CFS,请先查阅 CFS 使用文档 开通 CFS。

物料准备

为了执行“数据构建”流程,您需要准备好如下物料:
原始数据集:请确保您已经将原始数据集下载至本地,或者您具有可访问原始数据集的具体链接;本文假设您使用的是平台提供的样例数据: dataset_preparation_demo.json
[数据构建代码]:如您没有特殊需求,您可以直接使用平台内置的数据构建代码,只需要按照您的数据集格式,修改示例代码中的某些字段即可​;如内置数据构建代码不能满足您的需求,您也可以自行准备构建代码。

构建流程

新建数据构建任务

请根据您的业务场景,选择数据构建 pipeline;每一套数据构建 pipeline 都对应一套标准化数据处理流程,您可以按需选择。



本文假定您选择了 "有监督-单轮问答-pipeline"
任务创建完成之后,单击“跳转至对应 Notebook”即可开始创建(首次创建)或者跳转至数据构建 notebook。

关于“通用算法任务”

为了减少您筹备数据集的时间,同时帮助您提升精调效果,平台内置了一些具备知识产权的私有数据集,您可以依据您的业务场景按需使用。
请特别注意: 此部分内置数据,不会参与到本文提及的数据构建流程​,但是在您后续使用“大模型精调”模块精调大模型时,平台将在创建训练任务的过程中将您选择的具体业务场景对应的内置数据集按一定比例嵌入您的精调数据集之中,以提升精调效果。
如您不需要平台内置数据集,您只要不选择“通用算法任务”中的任何业务场景即可​。

新建数据构建 notebook

首次单击“跳转至对应 Notebook”按钮时,将会触发创建 Notebook 流程;
由于平台内置数据构建流程涉及模型调用(需要 CPU 和内存),此外,当前版本的数据构建流程代码里,需要一次性将原始数据读入内存并执行后续处理过程,因此需要您预留好充足的算力规格;本文以 8C16G 为例,您可以结合原始数据集大小动态调整,但是建议您使用不少于 4C8G 的算力资源执行后续流程。
在创建 notebook 时,您还需要指定 CFS 信息以存放原始数据集,中间结果以及处理后的结果。本文假定您将如下 CFS 目录挂载至​/home/tione/notebook
cfs:///data/custom/prepare



等待 notebook 创建完成后,您便可以真正开始数据构建流程。

上传原始数据集

您可以参考 使用任务式建模精调自定义大模型 将您本地的原始数据集上传至 CFS,需要注意的是,由于您已经在数据构建流程中新建了一个 notebook,因此您可以直接使用本 notebook 进行上传。
此外,由于平台内置的数据处理 PPL 依赖您将文件放入指定目录,因此建议您将原始数据集上传至如下目录:
notebook: /home/tione/notebook/<nb-id>/single_round_qa_pipeline/raw_dataset_files
也就是如下的 cfs 目录:
cfs: /data/custom/prepare/<nb-id>/single_round_qa_pipeline/raw_dataset_files

其中:
- nb-id 字段代表的是您创建的notebook示例的ID;您可以在浏览器url输入栏看到当前notebook实例的ID;



- single_round_qa_pipeline是有监督单轮问答的脚本路径,如果您选择的是有监督多轮问答pipeline,该目录名为multi_round_qa_pipeline;如果您选择的是无监督-pipeline,该目录名为unsupervised_pipeline


关于原始数据集格式

有监督数据格式
我们的有监督数据构建脚本代码支持了丰富的大模型常见的数据格式,有监督单轮问答pipeline和有监督多轮问答pipeline目前支持如下格式:
1. json文件:json内容是一个数组,数组中每一项是一个有效的json对象,可以转换成单轮问答数据;如果json内容不是数组,而是一个json对象,我们会解析成长度为1个元素的数组来进行处理;
2. jsonline文件:每一行是一个有效的json对象,可以转换成有监督问答数据;
3. parquet文件:parquet列式存储格式是开源数据常见格式(Parquet文档:https://parquet.apache.org/docs/overview/)。我们会先把parquet对象转成json对象,您可在下述采样过程中预览转换后的json格式,再进行数据处理;
4. 数据集文件夹:文件夹中包含若干有效的数据文件(格式可以是json/jsonline/parquet),此时我们会把该文件夹当做一个数据集进行处理,数据集名称即为文件夹名称,在后续数据解析流程完成后,会把所有文件的内容全部合并后再执行后续流程。

单轮有监督:示例代码提供的原始数据集文件格式为 ​jsonl​,示例内容如下:
{"instruction": "请简要回答下面的问题:", "input": "您平时用什么投资理财方式?", "output": "我一般采用银行储蓄,相对风险较低。"}
{"instruction": "请简要回答下面的问题:", "input": "基金拆分是什么意思?", "output": "基金拆分是保持基金投资人资产总值不变的前提下,改变基金份额净值和基金总份额的对应关系,重新计算基金资产的一种方式。"}
多轮有监督:示例代码提供的原始数据集文件格式为​ jsonl,示例内容如下:
{"conversations": [{"from": "human", "value": "保险是什么,可靠么?"}, {"from": "model", "value": "保险,是指投保人根据合同约定,向保险人支付保险费,保险人对于合同约定的可能发生的事故因其发生所造成的财产损失承担赔偿保险金责任,或者被保险人死亡、伤残、疾病或者达到合同约定的年龄、期限等条件时承担给付保险金责任的商业保险行为。正规渠道购买的保险都是安全可靠的。"}, {"from": "human", "value": "我想买一些投资理财类的保险,有哪些险种?"}, {"from": "model", "value": "年金保险、分红险、投连险等。"}, {"from": "human", "value": "这些投资理财类保险是不是稳赚不赔的?"}, {"from": "model", "value": "不是,收益受到市场因素影响。"}]}
{"conversations": [{"from": "human", "value": "我妈妈最近想买一份大病保险,这个是骗人的么?"}, {"from": "model", "value": "不是,重大疾病保险,它是一种针对严重疾病进行保障的保险产品。"}, {"from": "human", "value": "这个大病保险的报销比例有多少?"}, {"from": "model", "value": "重大疾病保险报销比例是根据保险合同中约定的具体条款来确定的,不同的保险公司和不同的保险产品可能有不同的报销比例。"}, {"from": "human", "value": "我妈也想给我买一份,但是我目前17岁,可以买么?"}, {"from": "model", "value": "可以,但是未成年需要父母作为投保人来购买。"}]}

无监督数据格式
我们的无监督数据构建脚本代码支持了丰富的大模型常见的数据格式,无监督pipeline目前支持如下格式:
1. json文件: 支持json对象文件和json数组文件的解析;
2. jsonline文件: 支持jsonline多行文件格式;
3. parquet文件: parquet列式存储格式是开源数据常见格式(Parquet文档:https://parquet.apache.org/docs/overview/)。我们会先把parquet对象转成json对象,您可在下述采样过程中预览转换后的json格式,再进行数据处理;
4. text文件: txt文本文件;
5. wet格式: WET表示原始网页WARC文本化(WET)格式。 我们会把WET解析成json对象,您可在采样过程中预览,再进行数据处理;
6. 数据集文件夹: 支持以上类型的多个文件放在同一文件夹下面处理, 同一文件夹下下面目前只支持一种类型的多个文件同时处理。

数据格式的示例如下:
json:json 数组的每一行作为一条数据
[
"this is statement 1",
"this is statement 2"
]
jsonl:每一行的"text"key 对应的 value 字段作为一条数据,例如:
{"text": "this is statement 1"}
{"text": "this is statement 2"}
text:
this is statement 1
this is statement 2
wet:支持标准的 Web Archive,详情请参考 示例数据


数据构建

notebook 创建完成后,单击"打开"按钮,进入到前述描述的/home/tione/notebook/<nb-id>/single_round_qa_pipeline/工作路径下,并打开quick_start.ipynb 之后,既可看到完整的数据构建步骤。如下图所示。



可以看到,整个数据构建流程分为如下步骤:
步骤0环境初始化:导入必要的python包;
步骤1:原始数据解析: 将形式格式不确定的原始数据转换为 tione 平台需要的三元组格式​(system, question, answer)​,并且输出为 jsonl 文件。
步骤2:数据清洗: 依据用户指定配置清洗数据数据,例如数据过滤(去除不满足要求的样本),数据改写(繁简转换,全角半角转换等)
步骤3:数据去重: 将清洗完之后的数据计算 embedding 相似度并去重;
步骤4:数据优化: 优化训练数据的 prompt,以提升指令理解效果。
步骤5:生成训练数据: 输出必要的训练数据统计分析结果,prompt 长度,response 长度,以及复合训练要求的数据格式。

上述五个步骤中,除了步骤1您必须根据输入数据格式进行修改之外,其他所有步骤都可以默认采用平台设置;

当您觉得平台默认规则构建的数据依然不理想时,您可以根据每个步骤的提示进行针对性的调整和优化,例如:
数据清洗: 可打开​config/clean_config.yaml​进行清洗规则配置修改;
数据清洗: 可以按照平台要求自定义清洗函数并注册;
数据优化: 可打开​config/instruction_dict.yaml​来填充丰富的instruction替换规则;


步骤一: 原始数据解析(需要自定义解析函数)

对于本示例中的单轮有监督 PPL,平台后续清洗去重等步骤要求的输入格式为jsonl格式,每一行json对象都是如下的三元组:
{"system": "您是一名作家,能理解用户问题并解答", "question": "请写一首关于黄河的诗", "answer": "白日依山尽,黄河入海流;欲穷千里目,更上一层楼"}
因此对于您的原始输入格式(如json/jsonline/parquet)等格式,您需要编写自定义的解析函数,将原始数据的格式转换成平台要求的格式。

对于原始数据,您指定好您的文件路径后,执行原始数据采样代码块,我们会输出您原始数据的采样格式。



示例如下:
如果您的原始数据是json格式或者jsonline,我们抽样展示部分数据。



如果您的原始数据是parquet格式,我们会转成json格式之后,再抽样展示部分数据。

在采样了解了原始数据格式之后,您需要将原始数据转换成TIONE平台要求的输入格式。对于您的输入文件,我们会解析成多行的json,并把json格式转成python dict格式。从您的json对应的dict格式转成tione平台要求的格式需要您自定义convert_dict_to_tione_format函数来实现您自己的转换逻辑。您可以参考以下代码段进行实现;




步骤一完成之后,我们会输出原始样本的统计信息,包括样本数量,有监督训练数据question/answer字段的长度分布,中英文数据条数统计等信息;






步骤二: 数据清洗(可以自定义清洗规则)

清洗函数分为两类:一类是改写,一类是过滤;
改写函数:输入原始文件和config,返回改写后的文本;其中config就是您在配置文件里面配置的具体清洗方法同名的配置,如果您未设置配置,该参数为None,可以不使用。您可以参考系统length_filter(长度过滤函数)了解config的用法;
系统默认的改写函数列表您可以参考:tools/modify_func.py
如果您需要增加自定义的改写函数,您需要通过python的装饰器@modify_func.ModifyFunctionManager.register(zh_name="中文名称")来进行注册,注册后系统会自动执行;其中zh_name定义了改写函数的中文名称用于可视化,未设置即为使用函数名称;
过滤函数:输入原始文本和config,返回两个值[bool, str],其中第一个布尔值代表是否需要过滤,str字符串代表过滤的详细原因用于可视化(您可以选择性实现);其中config就是您在配置文件里面配置的具体清洗方法同名的配置,如果您未设置配置,该参数为None,可以不使用。您可以参考系统length_filter(长度过滤函数)了解config的用法;
系统默认的过滤函数列表您可以参考:tools/filter_func.py
如果您需要增加自定义的过滤函数,您需要通过python的装饰器@filter_func.FilterFunctionManager.register(zh_name="中文名称")来进行注册,注册后系统会自动执行;其中zh_name定义了过滤函数的中文名称用于可视化,未设置即为使用函数名称;
过滤只可能被优先命中的规则过滤;改写可能会命中多条改写规则;

默认情况下,平台内置的规则应该能满足很大一部分场景的需求,如果您的场景较为特殊,您可以通过自定义注册的方式在此处新增您的自定义清洗规则。




清洗流程完成后,我们会输出清洗前后的数据量,并采样部分被清洗数据进行可视化展示,便于您比较清洗规则是否符合预期。





步骤三: 数据去重(不建议修改

平台内置的数据去重的逻辑比较复杂,耗时也比较长(模型加载与数据计算普遍在5分钟以上)。此部分逻辑比较专业,不建议您自行实现。当然您可以指定需要去重的字段,例如question/answer。




步骤四: 数据优化(修改配置文件)

您可以按需修改 config/instruction_dict.py自定义场景的 instruction 列表。




数据优化完成后,我们在生成训练数据前,自动统计和采样指定数目的样例数据,执行数据统计脚本,输出数据QA问答对的平均长度,长度分布直方图,和中英文分布的饼图,便于您了解本次数据构建的pipeline执行结果是否符合预期。





步骤五: 训练格式生成(不建议修改




执行完上述所有流程之后,我们就在 notebook 里的​/home/tione/notebook/<nb-id>/single_round_qa_pipeline/final_dataset_files (也就是 cfs:///data/custom/prepare/<nb-id>/single_round_qa_pipeline/final_dataset_files)​里存有构建完之后的数据,您可以在"大模型精调"模块加以使用。

该步骤的输出中包括cfs的映射路径,您可以直接在任务式建模中挂载这个cfs路径用于训练数据的挂载原路径。





在“大模型精调”模块使用构建好的训练数据

在您构建完自己的数据集之后,您便可以参考 精调 LLM 大模型最佳实践 在您的训练任务里使用构建好的数据。