# 自定义数据集 自定义数据集的接入方法有三种,对预处理函数的控制能力逐渐加强,但接入难度逐步增加。例如,方案一最为方便,但对预处理函数的控制能力最弱,需要预先对数据集进行转换,传入特定格式的数据集: 1. 【推荐】直接使用命令行传参的方式接入,即`--dataset `。这将使用AutoPreprocessor将数据集转换为标准格式(支持4种数据集格式,具体查看下面对AutoPreprocessor的介绍)。你可以使用`--columns`进行列名转换。支持传入csv、json、jsonl、txt、文件夹(例如git clone开源数据集)。该方案不需要修改dataset_info.json,适合刚接触ms-swift的用户,下面两种方案适合对ms-swift进行拓展的开发者。 2. 添加数据集到`dataset_info.json`中,可以参考ms-swift内置的[dataset_info.json](https://github.com/modelscope/ms-swift/blob/main/swift/dataset/data/dataset_info.json)。该方案也将使用AutoPreprocessor将数据集转换为标准格式。dataset_info.json为数据集元信息的list,每一项元信息必填ms_dataset_id/hf_dataset_id/dataset_path中的一项,通过`columns`字段进行列名转换。添加到`dataset_info.json`或者注册的数据集在运行[run_dataset_info.py](https://github.com/modelscope/ms-swift/blob/main/scripts/utils/run_dataset_info.py)时将自动产生[支持的数据集文档](https://swift.readthedocs.io/zh-cn/latest/Instruction/Supported-models-and-datasets.html)。此外,你可以采用外接`dataset_info.json`的方式,使用`--custom_dataset_info xxx.json`解析json文件(方便pip install而非git clone的用户),然后指定`--dataset `。 3. 手动注册数据集,具有最灵活的预处理函数定制能力,支持使用函数对数据集进行预处理,但难度较高。可以参考[内置数据集](https://github.com/modelscope/ms-swift/blob/main/swift/dataset/dataset/llm.py)或者[examples](https://github.com/modelscope/ms-swift/blob/main/examples/custom)中的样例。你可以通过指定`--external_plugins xxx.py`解析外置注册内容(方便pip install而非git clone的用户)。 - 方案一和二在实现中借助了方案三,只是注册的过程为自动发生。 以下将对`AutoPreprocessor`可以处理的数据集格式进行介绍: ms-swift的标准数据集格式可接受的keys包括: 'messages'、'rejected_response'、'label'、'images'、'videos'、'audios'、'tools'和'objects'。其中'messages'是必需的key,'rejected_response'用于DPO等RLHF训练,'label'用于KTO训练和分类模型训练,'images'、'videos'、'audios'用于存储多模态数据的路径或者url,'tools'用于Agent任务,'objects'用于grounding任务。 ms-swift中存在三种核心预处理器:`MessagesPreprocessor`、`AlpacaPreprocessor`、`ResponsePreprocessor`。MessagesPreprocessor用于将类messages和sharegpt格式的数据集转换为标准格式,AlpacaPreprocessor则转换alpaca格式的数据集,ResponsePreprocessor则转换类query/response格式的数据集。`AutoPreprocessor`则自动选择合适的预处理进行处理。 以下四种格式在`AutoPreprocessor`处理下都会转换成ms-swift标准格式中的messages字段,即都可以直接使用`--dataset `接入: messages格式(标准格式): ```jsonl {"messages": [{"role": "system", "content": ""}, {"role": "user", "content": ""}, {"role": "assistant", "content": ""}, {"role": "user", "content": ""}, {"role": "assistant", "content": ""}]} ``` - 注意:system部分是可选的。数据集中的system优先级高于命令行传入的`--system`,最后是定义在template中的`default_system`。 sharegpt格式: ```jsonl {"system": "", "conversation": [{"human": "", "assistant": ""}, {"human": "", "assistant": ""}]} ``` query-response格式: ```jsonl {"system": "", "query": "", "response": "", "history": [["", ""]]} ``` 注意:以下字段会自动转成对应的system、query、response字段。(solution字段会保留) - system: 'system', 'system_prompt'. - query: 'query', 'prompt', 'input', 'instruction', 'question', 'problem'. - response: 'response', 'answer', 'output', 'targets', 'target', 'answer_key', 'answers', 'solution', 'text', 'completion', 'content'. alpaca格式: ```jsonl {"system": "", "instruction": "", "input": "", "output": ""} ``` - 注意:instruction和input字段将组合成query字段。若instruction和input不等于空字符串,`query = f'{instruction}\n{input}'` ## 标准数据集格式 以下给出ms-swift的标准数据集格式,其中system字段是可选的,默认使用template中定义的`default_system`。之前介绍的4种数据集格式也可以被AutoPreprocessor处理成标准数据集格式。 ### 预训练 ```jsonl {"messages": [{"role": "assistant", "content": "I love music"}]} {"messages": [{"role": "assistant", "content": "教练我要打篮球"}]} {"messages": [{"role": "assistant", "content": "西红柿鸡蛋盖饭和地三鲜盖饭哪个更权威"}]} ``` ### 监督微调 ```jsonl {"messages": [{"role": "system", "content": "你是个有用无害的助手"}, {"role": "user", "content": "告诉我明天的天气"}, {"role": "assistant", "content": "明天天气晴朗"}]} {"messages": [{"role": "system", "content": "你是个有用无害的数学计算器"}, {"role": "user", "content": "1+1等于几"}, {"role": "assistant", "content": "等于2"}, {"role": "user", "content": "再加1呢"}, {"role": "assistant", "content": "等于3"}]} ``` - 可以通过增加"loss"字段,控制对应的模型回复部分是否计算损失(需ms-swift>=3.8)。默认该字段为None。若"loss"设置为true,则对应content进行损失计算(对应loss_scale为1);若"loss"设置为false,则对应content不进行损失计算。需要注意的是,该功能只对"role"为"assistant"的部分生效;该功能优先级高于命令行参数 `--loss_scale`。示例数据格式如下: ```jsonl {"messages": [{"role": "user", "content": "你好"}, {"role": "assistant", "content": "你好,有什么可以帮助你的吗?", "loss": false}, {"role": "user", "content": "1+1等于几?"}, {"role": "assistant", "content": "等于2", "loss": true}]} ``` #### channel loss 如果你要使用channel loss,你需要设置`--enable_channel_loss true`,并在数据集中增加"channel"字段。channel loss兼容packing/padding_free/loss_scale等技术。 ```jsonl {"messages": [{"role": "system", "content": "你是个有用无害的助手"}, {"role": "user", "content": "告诉我明天的天气"}, {"role": "assistant", "content": "明天天气晴朗"}], "channel": "general"} {"messages": [{"role": "system", "content": "你是个有用无害的数学计算器"}, {"role": "user", "content": "1+1等于几"}, {"role": "assistant", "content": "等于2"}, {"role": "user", "content": "再加1呢"}, {"role": "assistant", "content": "等于3"}], "channel": "math"} ``` ### RLHF #### DPO/ORPO/CPO/SimPO/RM ```jsonl {"messages": [{"role": "system", "content": "你是个有用无害的助手"}, {"role": "user", "content": "告诉我明天的天气"}, {"role": "assistant", "content": "明天天气晴朗"}], "rejected_response": "我不知道"} {"messages": [{"role": "system", "content": "你是个有用无害的数学计算器"}, {"role": "user", "content": "1+1等于几"}, {"role": "assistant", "content": "等于2"}, {"role": "user", "content": "再加1呢"}, {"role": "assistant", "content": "等于3"}], "rejected_response": "我不知道"} ``` 多模态数据的格式参考[多模态数据集](#多模态), 额外加入如`images`的列表示其他模态输入。当需要为偏好对数据关联不同的图片信息时,可通过`rejected_images`字段标注拒绝回答对应的图片信息。 对齐数据集中要求`rejected_images`和`rejected_response`至少提供一个。 > 注: RM 额外支持 margin 列,参考[RM文档](../Instruction/RLHF.md#rm) 当然,你也可以直接使用`rejected_messages`,而不是只提供`rejected_response`/`rejected_images`(需ms-swift>=3.8),这将提供更大的灵活度(例如多模态/agent场景)。若使用rejected_messages,在多模态场景下,你需要额外传入"rejected_images","rejected_audios","rejected_videos"等内容;在Agent场景下,你需要额外传入"rejected_tools"等内容。多模态数据格式例子如下: - 若使用`rejected_response`,'rejected_images/rejected_audios/rejected_videos/rejected_tools'的默认值为'images/audios/videos/tools';若使用`rejected_messages`,则需要额外传入。 ```jsonl {"messages": [{"role": "user", "content": "这是什么"}, {"role": "assistant", "content": "这是一只小猫咪。"}], "images": ["cat.png"], "rejected_messages": [{"role": "user", "content": "这是什么"}, {"role": "assistant", "content": "这是一只小狗。"}], "rejected_images": ["cat.png"]} {"messages": [{"role": "user", "content": "这是什么"}, {"role": "assistant", "content": "这是一只小猫咪。"}], "images": ["cat.png"], "rejected_messages": [{"role": "user", "content": "这是什么"}, {"role": "assistant", "content": "这是一只小猫咪。"}], "rejected_images": ["dog.png"]} ``` 以上格式等价于: ```jsonl {"messages": [{"role": "user", "content": "这是什么"}, {"role": "assistant", "content": "这是一只小猫咪。"}], "images": ["cat.png"], "rejected_response": "这是一只小狗。"} {"messages": [{"role": "user", "content": "这是什么"}, {"role": "assistant", "content": "这是一只小猫咪。"}], "images": ["cat.png"], "rejected_images": ["dog.png"]} # 例子一也可写成:(ms-swift>=3.12) {"messages": [{"role": "user", "content": "这是什么"}, {"role": "assistant", "content": "这是一只小猫咪。"}], "images": ["cat.png"], "rejected_response": [{"role": "assistant", "content": "这是一只小狗。"}]} ``` ms-swift>=3.12,你可以将Agent数据集组织成以下形式: ```jsonl # 会寻找`messages`最后一个user的位置,并替换之后的内容为`rejected_response`组成`rejected_messages` {"tools": "[{\"type\": \"function\", \"function\": {\"name\": \"realtime_aqi\", \"description\": \"天气预报。获取实时空气质量。当前空气质量,PM2.5,PM10信息\", \"parameters\": {\"type\": \"object\", \"properties\": {\"city\": {\"type\": \"string\", \"description\": \"城市名,例如:上海\"}}, \"required\": [\"city\"]}}}]", "messages": [{"role": "user", "content": "北京和上海今天的天气情况"}, {"role": "tool_call", "content": "{\"name\": \"realtime_aqi\", \"arguments\": {\"city\": \"北京\"}}"}, {"role": "tool_call", "content": "{\"name\": \"realtime_aqi\", \"arguments\": {\"city\": \"上海\"}}"}, {"role": "tool_response", "content": "{\"city\": \"北京\", \"aqi\": \"10\", \"unit\": \"celsius\"}"}, {"role": "tool_response", "content": "{\"city\": \"上海\", \"aqi\": \"72\", \"unit\": \"fahrenheit\"}"}, {"role": "assistant", "content": "根据天气预报工具,北京今天的空气质量指数为10,属于良好水平;上海今天的空气质量指数为72,属于轻度污染水平。"}], "rejected_response": [{"role": "assistant", "content": "我不知道。"}]} ``` #### KTO ```jsonl {"messages": [{"role": "system", "content": "你是个有用无害的助手"}, {"role": "user", "content": "告诉我明天的天气"}, {"role": "assistant", "content": "我不知道"}], "label": false} {"messages": [{"role": "system", "content": "你是个有用无害的数学计算器"}, {"role": "user", "content": "1+1等于几"}, {"role": "assistant", "content": "等于2"}, {"role": "user", "content": "再加1呢"}, {"role": "assistant", "content": "等于3"}], "label": true} ``` #### PPO/GRPO ```jsonl {"messages": [{"role": "system", "content": "你是个有用无害的助手"}, {"role": "user", "content": "告诉我明天的天气"}]} {"messages": [{"role": "system", "content": "你是个有用无害的数学计算器"}, {"role": "user", "content": "1+1等于几"}, {"role": "assistant", "content": "等于2"}, {"role": "user", "content": "再加1呢"}]} {"messages": [{"role": "user", "content": "你的名字是什么"}]} ``` - 注意:GRPO会透传所有额外的字段内容给ORM,而不像其他训练方法,默认将额外的字段删除。例如: 你可以额外传入'solution'。自定义的ORM需要包含一个位置参数completions,其他为关键词参数,由数据集额外字段透传。 #### GKD 若未开启`seq_kd`,即该参数为False。数据集格式如下(你可使用teacher模型提前蒸馏): ```jsonl {"messages": [{"role": "system", "content": "你是个有用无害的助手"}, {"role": "user", "content": "告诉我明天的天气"}, {"role": "assistant", "content": "明天天气晴朗"}]} {"messages": [{"role": "system", "content": "你是个有用无害的数学计算器"}, {"role": "user", "content": "1+1等于几"}, {"role": "assistant", "content": "等于2"}, {"role": "user", "content": "再加1呢"}, {"role": "assistant", "content": "等于3"}]} ``` 若开启`seq_kd`,则不需要最后一轮的'assistant'部分(teacher模型在训练时生成数据): ```jsonl {"messages": [{"role": "system", "content": "你是个有用无害的助手"}, {"role": "user", "content": "告诉我明天的天气"}]} {"messages": [{"role": "system", "content": "你是个有用无害的数学计算器"}, {"role": "user", "content": "1+1等于几"}, {"role": "assistant", "content": "等于2"}, {"role": "user", "content": "再加1呢"}]} ``` ### 序列分类 **单标签任务**: ```jsonl {"messages": [{"role": "user", "content": "今天天气真好呀"}], "label": 1} {"messages": [{"role": "user", "content": "今天真倒霉"}], "label": 0} {"messages": [{"role": "user", "content": "好开心"}], "label": 1} ``` **多标签任务**: ```jsonl {"messages": [{"role": "user", "content": ""}], "label": []} {"messages": [{"role": "user", "content": ""}], "label": [0, 2]} {"messages": [{"role": "user", "content": ""}], "label": [1, 3, 5]} ``` **单回归任务**: ```jsonl {"messages": [{"role": "user", "content": "求两句话的相似度,范围为0-1。\nsentence1: \nsentence2: "}], "label": 0.8} ``` **多回归任务**: ```jsonl {"messages": [{"role": "user", "content": ""}], "label": [1.2, -0.6, 0.8]} ``` ### Embedding 请参考[embedding训练文档](../BestPractices/Embedding.md#数据集格式) ### Reranker 请参考[Reranker训练文档](../BestPractices/Reranker.md#数据集格式) ### 多模态 对于多模态数据集,和上述任务的格式相同。区别在于增加了`images`, `videos`, `audios`几个key,分别代表多模态资源的url或者path(推荐使用绝对路径),`` `