天天看点

Fine-tuning的使用

作者:SamuelZHJ

什么是Fine-tuning

Fine-tuning功能,使得用户可以定制自己的大模型。因为LLM已经通过大量的数据做好训练,所以我们在使用模型的时候,只需要借助prompt的“Few-shot”就可以得到我们需要的答案。为了让答案更加的准确,此时可以使用Fine-tuning的功能,微调通过更多示例数据对模型进行训练,进而获取更加准确的答复。为了提高识别的准确率,需要提供足够的训练数据。

Fine-tunning的优势和注意事项

优势:

  • 可以获取比即时的prompt更高质量的结果
  • 可以训练大批量的示例,突破prompt的token的限制
  • 可以缩短每次prompt的Token数量,节约成本
  • 响应更加迅速

使用步骤:

  • 准备DataSet,格式一定要正确
  • 上传DataSet,生成文档Id
  • 调用训练接口,传入文档Id,生成模型Id(例如:ada:ft-personal-2023-05-10-02-54-33)

注意事项:

Fine-tuning功能对数据集的数据格式要求非常严格,所以一定要保证格式正确,才能训练出微调模型。

  • 必须满足JSONL格式
  • 必须用prompt/completion
  • prompt必须以固定的分隔符结尾,completion必须以固定的分隔符开始
  • prompt不要带中不要带有“,”

官方链接:https://platform.openai.com/docs/guides/legacy-fine-tuning

Fine-tuning的使用

我们借助OpenAI官方推荐的.net库:Betalgo.OpenAI,实现Fine-tuning的功能。

(1) 准备训练数据

其中使用"\n#"作为prompt的分隔符,使用空格作为completion开始的分隔符

{"prompt": "How to prevent to decrease scores \n#", "completion": " 1"}
{"prompt": "How do I increase English score \n#", "completion": " 1"}
{"prompt": "Find me the math scores  > 95 in the past 14 days \n#", "completion": " 2"}
{"prompt": "Find me top 10 scores of  in last month ordered by subject \n#", "completion": " 2"}
{"prompt": "Find me math performance of current month \n#", "completion": " 2"}
{"prompt": "Find me top N score performance of time range Ordered by subjcect \n#", "completion": " 2"}           

(2) 上传数据,生成文档Id,并开始模型训练

使用GPT的Base模型(ada)作为基础训练模型,现在官方也已经支持使用gpt-3.5-turbo作为基础模型。

[HttpPost]
        [Route("CreateFineTune")]
        public async Task FineTuneAsync(string fileName= "FineTuneDataSet.jsonl")
        {
            //获取file
            var sampleFile = System.IO.File.ReadAllBytes(#34;Files/{fileName}");
            var text = System.IO.File.ReadAllText(#34;Files/{fileName}");
            var uploadFilesResponse = await openAiService.Files.FileUpload(UploadFilePurposes.UploadFilePurpose.FineTune, sampleFile, fileName);
            if (uploadFilesResponse.Successful)
            {
                Console.WriteLine(#34;{fileName} uploaded,fileId={uploadFilesResponse.Id}", ConsoleColor.DarkGreen);
            }
            else
            {
                Console.WriteLine(#34;{fileName} failed", ConsoleColor.DarkRed);
            }
            var createFineTuneResponse = await openAiService.FineTunes.CreateFineTune(new FineTuneCreateRequest
            {
                TrainingFile = uploadFilesResponse.Id,
                Model = "ada"
            });
            Console.WriteLine(#34;FineTune-Id:{createFineTuneResponse.Id}");
            var listFineTuneEventsStream = await openAiService.FineTunes.ListFineTuneEvents(createFineTuneResponse.Id, true);
            using var streamReader = new StreamReader(listFineTuneEventsStream);
            while (!streamReader.EndOfStream)
            {
                Console.WriteLine(await streamReader.ReadLineAsync());
            }
        }           

(3) 通过文档id,可以获取模型训练状态

如果模型训练成功,会返回模型Id;如果训练失败,需要检查jsonl的数据格式,是否有特殊字符。出现失败的原因一般都是训练样本数据格式不规范导致的。

[HttpPost]
        [Route("GetFineTuneById")]
        public async Task GetFineTuneStatusByIdAsync(string id)
        {
          
             FineTuneResponse retrieveFineTuneResponse = await openAiService.FineTunes.RetrieveFineTune(id);
             Console.WriteLine(#34;Fine-tune Status for {id}: {retrieveFineTuneResponse.Status}. FindTuneModel:{retrieveFineTuneResponse.FineTunedModel}", ConsoleColor.DarkYellow);
           
        }           

(4) 使用训练好的模型做自然语言识别

prompt一定要保持和训练数据相同的格式。比如:训练数据以"\n#",那么prompt也一定要带上分隔符

[HttpPost]
        [Route("GetTuneResult")]
        public async Task<string>GetTuneResultAsync(GptInput input)
        {
            if (string.IsNullOrWhiteSpace(input.query))
                return string.Empty;
            var completionResult = await openAiService.Completions.CreateCompletion(new CompletionCreateRequest
            {
                Prompt=#34;{input.query} \n#",
                MaxTokens = 1,
                Model = "ada:ft-personal-2023-06-10-06-34-33",
                LogProbs = 2
            });

            if (completionResult.Successful)
            {
                return completionResult.Choices.FirstOrDefault().Text;
            }
            return "error";

        }