Finetune 操作指南
仔细阅读本文档,可以了解如何为您的场景微调文本模型。
一、 何时需要使用微调?
微调文本模型可以使它们更适合特定应用场景,但这需要仔细投入时间和精力。我们建议首先尝试使用ChatCompletion调优指南、ChatCompletion Pro 调优指南里的操作来获得比较好的结果,主要原因如下:
在许多任务中,模型最初可能表现不佳,但可以通过人设编写优化以及要求限制编写优化(提示工程)来改进结果,因此可能不需要微调;
调优指南里的策略比微调迭代要快得多,微调需要整理数据、创建数据集并运行训练作业;
在仍然需要微调的情况下,初始提示工程工作不会浪费,在微调的数据中使用良好的提示进行训练后,通常会看到更好的结果。
一般来说,在以下场景使用微调能够改善模型效果:
- 让模型学会某一特定风格、基调、格式,比如让模型学会模仿一个人设,或者是一种特殊的输出格式;
- 提高产生所需输出的可靠性,比如让模型更熟悉某一特定专业垂直领域;
- 更正失败以遵循复杂的提示,比如在让模型遵从一些非常难以理解的指令要求;
- 以特定方式处理许多边缘情况,比如让模型做一些非通用场景的回答;
二、 操作步骤及接口
1、准备数据集
一旦决定使用微调(您已经尽可能地优化了提示,并确定了模型仍然存在的问题,希望使用微调来解决这些问题),首先需要准备用于训练模型的数据。
创建一组多样化的示例对话数据,这些对话数据代表了对模型输出效果的期望。
1.1 内容要求
贴近推理时的真实数据。
- 建议在微调之前采用您认为最适合模型的一组对话示例和提示,以获得最好的结果,特别是当训练数据量相对较少的时候(例如不到100个)。
- 可能需要更多的训练数据才能获得良好的结果,因为模型必须完全通过数据示例来学习。
1.2 格式要求
参考最终推理使用的接口是Chatcompleion还是Chatcompleion pro,可以使用对应接口的数据格式进行微调。
1.2.1 Chatcompleion pro
多条数据,用换行来分割。
{ "bot_setting": [{"bot_name": "文本总结助手","content": "文本总结助手能够理解文本,并以CSV格式系统地列出标题,作者,发行年份和类型。"}],"messages": [{"sender_type": "USER","sender_name": "用户","text": "1967年,哥伦比亚著名作家加夫列尔·加西亚·马尔克斯(Gabriel García Márquez)创作了《百年孤独》(Cien años de soledad),这是一部魔幻现实主义小说,被誉为拉丁美洲文学的巅峰之作。这本书讲述了布恩迪亚家族的七代人的故事,展现了马尔克斯独特的叙事风格和奇幻的想象力。作为文学史上的经典之一,这本小说融合了现实和超现实元素,探讨了爱、家庭、孤独和时间等主题。它以其深刻的内涵和引人入胜的叙事而广受欢迎,被翻译成多种语言并屡次改编成电影、舞台剧等形式,深刻影响\n炼金术士, 保罗·科埃略, 1988, 寓言小说了世界文学。"},{"sender_type": "BOT","sender_name": "文本总结助手","text": "标题, 作者, 发行年份, 类型\n百年孤独, 加夫列尔·加西亚·马尔克斯, 1967年, 魔幻现实主义小说"}]}
{ "bot_setting": [{"bot_name": "文本总结助手","content": "文本总结助手能够理解文本,并以CSV格式系统地列出标题,作者,发行年份和类型。"}],"messages": [{"sender_type": "USER","sender_name": "用户","text": "2005年,英国著名作家J.K.罗琳(J.K. Rowling)创作了《哈利·波特与混血王子》(Harry Potter and the Half-Blood Prince),这是一部魔幻冒险小说,以其引人入胜的情节和丰富的魔法世界而闻名于世。这本书是著名的哈利·波特系列的第六部,讲述了年轻巫师哈利·波特在霍格沃茨魔法学校的第六学年,他与导师邓布利多共同努力,揭示了伏地魔的秘密过去和弱点。罗琳的精湛叙事技巧和令人难以置信的想象力使这个魔法世界栩栩如生,吸引了读者们的注意。《哈利·波特与混血王子》不仅是一部奇幻小说,还是关于友情、忠诚和成长的故事,深受读者的喜爱。"},{"sender_type": "BOT","sender_name": "文本总结助手","text": "标题, 作者, 发行年份, 类型\n哈利·波特与混血王子, J.K.罗琳, 2005年, 魔幻冒险小说"}]}
1.2.2 Chatcompleion
多条数据,用换行来分割。
{"messages": [{"sender_type": "USER", "text": "1967年,哥伦比亚著名作家加夫列尔·加西亚·马尔克斯(Gabriel García Márquez)创作了《百年孤独》(Cien años de soledad),这是一部魔幻现实主义小说,被誉为拉丁美洲文学的巅峰之作。这本书讲述了布恩迪亚家族的七代人的故事,展现了马尔克斯独特的叙事风格和奇幻的想象力。作为文学史上的经典之一,这本小说融合了现实和超现实元素,探讨了爱、家庭、孤独和时间等主题。它以其深刻的内涵和引人入胜的叙事而广受欢迎,被翻译成多种语言并屡次改编成电影、舞台剧等形式,深刻影响\n炼金术士, 保罗·科埃略, 1988, 寓言小说了世界文学。"}, {"sender_type": "BOT", "text": "标题, 作者, 发行年份, 类型\n百年孤独, 加夫列尔·加西亚·马尔克斯, 1967年, 魔幻现实主义小说"}], "prompt": "文本总结助手能够理解文本,并以CSV格式系统地列出标题,作者,发行年份和类型。", "role_meta": {"bot_name": "文本总结助手", "user_name": "用户"}}
{"messages": [{"sender_type": "USER", "text": "2005年,英国著名作家J.K.罗琳(J.K. Rowling)创作了《哈利·波特与混血王子》(Harry Potter and the Half-Blood Prince),这是一部魔幻冒险小说,以其引人入胜的情节和丰富的魔法世界而闻名于世。这本书是著名的哈利·波特系列的第六部,讲述了年轻巫师哈利·波特在霍格沃茨魔法学校的第六学年,他与导师邓布利多共同努力,揭示了伏地魔的秘密过去和弱点。罗琳的精湛叙事技巧和令人难以置信的想象力使这个魔法世界栩栩如生,吸引了读者们的注意。《哈利·波特与混血王子》不仅是一部奇幻小说,还是关于友情、忠诚和成长的故事,深受读者的 喜爱。"}, {"sender_type": "BOT", "text": "标题, 作者, 发行年份, 类型\n哈利·波特与混血王子, J.K.罗琳, 2005年, 魔幻冒险小说"}], "prompt": "文本总结助手能够理解文本,并以CSV格式系统地列出标题,作者,发行年份和类型。", "role_meta": {"bot_name": "文本总结助手", "user_name": "用户"}}
1.3 数量要求
- 需要提供至少 10 个示例。通常 50 到 100 个训练样本进行微调后能看到效果的改进,但这会根据数据质量而有很大差异。
- 我们建议先准备50条精心制作的数据进行训练,看看模型在微调后是否有改进的迹象。如果没有改进,可能要考虑重新为模型设置微调任务或重构数据。
1.4 类型要求
需要拆分为训练集和验证集两种类型。
将数据集拆分为训练集和验证集文件。当提交包含训练和测试文件的微调作业时,我们将在训练过程中提供两者的统计信息。这些统计数据将是模型改进程度的初始信号。
1.5 长度要求
每条训练数据的最大token长度:
abab5.5-1019:16384
2、上传训练文件
Shell 格式
curl --location 'https://api.minimax.chat/v1/files/upload?GroupId=${group_id}' \
--header 'authority: api.minimax.chat' \
--header 'content-type: multipart/form-data' \
--header 'Authorization: Bearer ${API_KEY}' \
--form 'purpose="fine-tune"' \
--form 'file=@"/Users/minimax/Downloads/export_file (1).csv"'
Python 格式
import requests
url = 'https://api.minimax.chat/v1/files/upload?GroupId=${group_id}'
headers = {
'authority': 'api.minimax.chat',
'Authorization': 'Bearer {api_key}'
}
data = {
'purpose': 'fine-tune'
}
files = {
'file': open('/Users/minimax/Downloads/export_file (1).csv', 'rb')
}
response = requests.post(url, headers=headers, data=data, files=files)
print(response.text)
2.1 请求体(Request)参数
参数名称 | 类型 | 描述 | 取值 | 是否必填 |
---|---|---|---|---|
file | string | 数据文件 | / | 是 |
purpose | string | 文件的目的 | fine-tune:finetune的训练文件和验证文件fine-tune-result:finetune后的结果文件(无需自己上传) | 是 |
2.2 返回(Response)参数及示例
{
"object":"fine_tuning.job",
"id":"file-DOCHURTIhKWzfyxMydoDCQpo",
"bytes":"2692",
"created_at":"1699692067",
"filename":"mydata.jsonl",
"purpose":"fine-tune",
"status":"processed",
"status_details":"None"
}
3、创建微调任务
Shell 示例
curl -X POST \
-H "authorization: Bearer ${API_KEY}" \
-H "content-type: application/json" \
--data-raw '{"model":"abab5.5-chat-1019", "training_file":80653122572352, "suffix": "12345"}' "create_finetune_job?${GroupId}"
Python 示例
import requests
import json
url = "https://api.minimax.chat/v1/create_finetune_job?GroupId=${GroupId}"
payload = json.dumps({
"model": "abab5.5-chat-1019",
"training_file": 80653122572352,
"suffix": "12345"
})
headers = {
'authorization': 'Bearer ${API_KEY}',
'content-type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
3.1 请求体(Request)参数
参数名称 | 类型 | 描述和要求 | 是否必填 |
---|---|---|---|
model | string | 模型名称 | 是 |
training_file | int64 | 包含训练数据的已上传文件的 ID。数据集的格式必须为 JSONL 文件。此外,必须上传文件目的为fine-tune的。 | 是 |
validation_file | int64 | 包含验证数据的已上传文件的 ID。 | 否 |
hyperparameters | Hyperparameters | 训练超参,不填写会使用默认值 | 否 |
suffix | string | 微调模型名称的自定义后缀,最长8位长度,超长后会默认截断 | 否 |
- Hyperparameters参数结构
参数名称 | 数据类型 | 描述 | 是否必填写 |
---|---|---|---|
batch_size | int64 | 指定全局批量大小,越大意味着模型参数的更新频率越低,默认值为1,建议填写范围:1~100 | 否 |
learning_rate_multiplier | double | 学习率,较小的学习率可能有助于避免过度拟合,默认值为1e-4,范围:1e-2 ~ 1e-6,注意:一般情况下不建议修改该参数 | 否 |
n_epochs | int64 | 模型训练过程中的整个数据集的遍历次数,默认值为5,建议填写范围:1~100,注意:这个数值的大小会直接影响您的训练token消耗 | 否 |
3.2 返回(Response)参数及示例
fine-tuning job object
{
"object": "fine_tuning.job",
"id": "ftjob-abc123",
"model": "abab5.5-chat-1019",
"created_at": 1614807352,
"fine_tuned_model": null,
"groupid": "16973747844949",
"result_files": [],
"status": "queued",
"validation_file": null,
"training_file": "file-abc123",
}
3.3 数量限制
- 一个groupid最多保留5个Finetune model,因此如果本身已经超过了限制,则无法创建微调任务,可以通过Finetune API文档中的删除微调模型来对模型数量进行管理
- Finetune mode 如果在7天内无任何调用,则会失效,请注意
3.4 训练时间
请注意在开始微调任务前需要进行排队等待资源,开始微调任务后,可能需要一些时间才能完成。您的作业可能排在我们系统中的其他任务之后,训练模型可能需要几分钟或几小时,具体取决于数据集大小。
4、搜检微调任务
4.1 请求示例
Shell 示例
curl -X POST \
-H "authorization: Bearer ${API_KEY}" \
-H "content-type: application/json" \
--data-raw '{"fine_tuning_job_id":"2367267362783"}' "retrieve_finetune_job?${GroupId}"
Python 示例
import requests
import json
url = "https://api.minimax.chat/v1/retrieve_finetune_job?GroupId=$GroupId"
payload = json.dumps({
"fine_tuning_job_id": "2367267362783"
})
headers = {
'authorization': 'Bearer ${API_KEY}',
'content-type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
4.2 返回示例
{"finetune_job":{"id":"1701538478753114","created_at":1702558487515,"fine_tuned_model":"ft:abab5.5-chat-1019_1705584973436:dafei12","hyperparameters":{"batch_size":1,"learning_rate_multiplier":0.23,"n_epochs":1},"model":"ft:abab5.5-chat-1019_1705584973436:dafei12","object":"finetune.job","organization_id":"","result_files":[86036815667264],"status":"queued","training_file":86036815667264,"validation_file":0},"base_resp":{"status_code":0,"status_msg":"success"}}
5、查看微调任务日志
提供以下在训练过程中计算的训练指标:训练集loss、验证集loss。这些统计数据旨在提供健全性检查,以确保训练顺利进行(loss应该减少),可以拿到4检索微调任务的result_files id,使用file的RetrieveContent接口查看训练的详细信息,包括训练集和验证集的loss信息
5.1 请求示例
Shell 示例
curl --location 'https://api.minimax.chat/v1/files/retrieve_content?GroupId={group_id}&file_id={file_id}' \
--header 'content-type: application/json' \
--header 'Authorization: Bearer {api_key}'
Python 示例
import requests
import json
url = "https://api.minimax.chat/v1/files/retrieve_content?GroupId={group_id}&file_id={file_id}"
payload = {}
files={}
headers = {
'content-type': 'application/json',
'Authorization': 'Bearer {api_key}'
}
response = requests.request("GET", url, headers=headers, data=payload, files=files)
print(response.text)
5.2 返回示例
{"file":{"file_id":85198633103453,"bytes":167,"created_at":1702632422,"filename":"1702631618780994.csv","purpose":"fine-tune-result"},"base_resp":{"status_code":0,"status_msg":"success"}}
iter,train_loss,valid_loss
1,0.324273,0.000000
2,0.343621,0.000000
3,0.151181,0.000000
4,0.076753,0.000000
5,0.079515,0.000000
6,0.017223,0.000000
7,0.013275,0.000000
6、使用微调模型
微调任务训练完成后,模型应立即可供推理使用,无需单独接口进行部署。在某些情况下,模型可能需要几分钟时间才能准备好处理请求。如果对模型的请求超时或找不到模型名称,则可能是因为模型仍在加载中。如果发生这种情况,请过几分钟再试。
6.1 ChatCompletion接口示例
import requests
import json
url = "https://api.minimax.chat/v1/text/chatcompletion?GroupId=$GroupId"
payload = json.dumps({
"model": "ft:abab5.5-chat-1019_1705584973436:dafei12",
"tokens_to_generate": 256,
"temperature": 0.7,
"top_p": 0.9,
"stream": False,
"role_meta": {
"user_name": "用户",
"bot_name": "文本总结助手"
},
"prompt": "文本总结助手能够理解文本,并以CSV格式系统地列出标题,作者,发行年份和类型。",
"messages": [
{
"sender_type": "USER",
"text": "1813年,英国著名作家简·奥斯汀(Jane Austen)创作了《傲慢与偏见》(Pride and Prejudice)。这是一部经典的爱情小说,也被视为英国文学的珍宝之一。小说讲述了女主角伊丽莎白·班内特与男主角达西先生之间的故事,描绘了社交、阶级和婚姻等题材。作品以其幽默、深刻的人物刻画和对社会习俗的嘲讽而闻名,被认为是英国文学中的经典之一,也是世界文学的杰作之一。"
}
]
})
headers = {
'authorization': 'Bearer ${API_KEY}',
'content-type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
6.2 ChatCompletion pro接口示例
import requests
group_id="请填写您的group_id"
api_key="请填写您的api_key"
url = "https://api.minimax.chat/v1/text/chatcompletion_pro?GroupId=" + group_id
payload = {
"bot_setting": [
{
"bot_name": "文本总结助手",
"content": "文本总结助手能够理解文本,并以CSV格式系统地列出标题,作者,发行年份和类型。",
}
],
"messages": [{"sender_type": "USER", "sender_name": "小明", "text": "1813年,英国著名作家简·奥斯汀(Jane Austen)创作了《傲慢与偏见》(Pride and Prejudice)。这是一部经典的爱情小说,也被视为英国文学的珍宝之一。小说讲述了女主角伊丽莎白·班内特与男主角达西先生之间的故事,描绘了社交、阶级和婚姻等题材。作品以其幽默、深刻的人物刻画和对社会习俗的嘲讽而闻名,被认为是英国文学中的经典之一,也是世界文学的杰作之一。"}],
"reply_constraints": {"sender_type": "BOT", "sender_name": "文本总结助手"},
"model": "ft:abab5.5-chat-1019_1705584973436:dafei12",
"tokens_to_generate": 1034,
"temperature": 0.01,
"top_p": 0.95,
}
headers = {"Content-Type": "application/json", "Authorization": "Bearer " + api_key}
response = requests.request("POST", url, headers=headers, json=payload)
print(response.status_code)
print(response.text)