【Python】ChatGPTのファインチューニング(Fine-Tuning)実践方法|特定のタスクに特化したモデル作成

当ページには広告が含まれています。

こんにちは、DXCEL WAVEの運営者(@dxcelwave)です!

こんな方におすすめ!
  • ChatGPTのファインチューニングに興味がある
  • OpenAI APIとPythonを用いてファインチューニングを実践する方法が知りたい
目次

【OpenAI】ChatGPTとは?

ChatGPTとは、OpenAIが開発した対話型チャットボットのモデルです。ChatGPTの名前は、GPT-3という第3世代の生成言語モデルに由来しています。

ChatGPTのモデルには、人工知能(AI)が搭載されており、人間の発話に対して自然なやり取りを可能にしています。また、英語をはじめ、中国語、日本語、フランス語など複数言語を認識し、人間らしく応答できるのも特徴的です。

さらに、ChatGPTではチャットの他に、画像生成など近年多様な機能がリリースされてます。以下、ChatGPTで代表するGPTモデルおよびOpenAIが提供するAPI機能一覧を示します。

  • チャット機能
  • テキストから画像を生成
  • オーディオを文字起こし
  • Python、SQL、JavaScript等のコードを理解
  • 問題あるネガティブ発言検出
  • テキスト文章のベクトル変換

【参考】OpenAI社のAPI利用方法

本記事ではChatGPTを用いたPythonプログラミングについて解説します。その際、Open AIが提供するAPI情報が必要になります。「ChatGPTの概要」および「API情報の取得手順」については、こちらの記事で詳しく解説しています。

あわせて読みたい
【Python×ChatGPT】チャットボット作成入門|OpenAI APIの利用申請手順も解説 「ChatGPT APIの利用手順」と「PythonでChatGPT APIを呼び出し、チャットボットを作成する方法」についてそれぞれ解説します。

【参考】ChatGPTを詳しく学びたい方向けの学習講座

ChatGPTを詳しく学びたい方向けに安価で学べるオンライン講座も併せてご紹介します。

【ChatGPT】ファインチューニングとは?

ChatGPTのファインチューニングとは、既に学習済みの大規模な言語モデルであるGPT(Generative Pre-trained Transformer)を、特定のタスクに最適化することを指します。

例えば、医療・金融・製造など特定の業界の専門用語にも特化したモデル等を作成する際に有効です。

一般的に、ChatGPTは自然言語処理タスクに適したモデルであり、多くの場合、チャットボットや会話システムの開発に使用されます。しかし、ChatGPTを特定のタスクに最適化するには、そのタスクに関連する学習データを使用して、モデルを再学習する必要があります。

ファインチューニングにより、ChatGPTはより高度な自然言語処理タスクを実行できるようになり、より高い精度で応答を生成することが期待できるようになります。

【事前準備】Python環境構築・ファインチューニング用学習データ準備

OpenAIが提供するAPIを用いてPythonでChatGPTのファインチューニングを実践するに際して、以下2点事前に対応する必要があります。

  • OpenAIライブラリのインストール
  • 【必須】ファインチューニング用学習データの準備
  • 【任意】ファインチューニング用検証データの準備

OpenAIライブラリのインストール

今回言及する翻訳機能実装に際して、OpenAI提供のChatGPT APIをPython環境で利用できるライブラリが必要になります。

コマンドプロンプト(WIndows)またはターミナル(Mac)を用いてインストールしましょう。

pip install openai

【必須】ファインチューニング用学習データの準備

ChatGPTモデルのファインチューニング実践に際して、学習用のデータを準備します。

学習用データのフォーマット(JSONL)

学習用データは、以下に示すフォーマットのもとJSONLファイル形式で準備します。

messageの値には役割(role)とテキスト文章(content)を準備します。

{"messages": [{"role": "system", "content": "・・・"},{"role": "user", "content": "・・・"},{"role": "assistant", "content": "・・・"}]}
{"messages": [{"role": "system", "content": "・・・"},{"role": "user", "content": "・・・"},{"role": "assistant", "content": "・・・"}]}
・・・

学習用サンプルデータ

後続のPythonプログラム実践に際して、ファインチューニング用サンプルデータtraining.jsonlを次のように準備することとします。

{"messages": [{"role": "system", "content": "あなたの疑問を解消するためのチャットボットです。"},{"role": "user", "content": "「DXCEL WAVE」とは?"},{"role": "assistant", "content": "DXCEL WAVEとは、DX推進に関連する記事を多数投稿しているメディアです。"}]}
{"messages": [{"role": "system", "content": "あなたの疑問を解消するためのチャットボットです。"},{"role": "user", "content": "「DXCEL WAVE」とは?"},{"role": "assistant", "content": "AIや機械学習などの最新デジタル情報をお届けしているサイトだよ。"}]}
{"messages": [{"role": "system", "content": "あなたの疑問を解消するためのチャットボットです。"},{"role": "user", "content": "「DXCEL WAVE」とは?"},{"role": "assistant", "content": "データサイエンスやアナリティクス、RPA自動化など、デジタル関連の新しい情報を提供しているよ。"}]}
{"messages": [{"role": "system", "content": "あなたの疑問を解消するためのチャットボットです。"},{"role": "user", "content": "「DXCEL WAVE」とは?"},{"role": "assistant", "content": "デジタルマーケティングやフィンテックに関する最新の情報を発信しているサイトだね。"}]}
{"messages": [{"role": "system", "content": "あなたの疑問を解消するためのチャットボットです。"},{"role": "user", "content": "「DXCEL WAVE」とは?"},{"role": "assistant", "content": "最新のテクノロジートピックやトレンドをカバーしているんだ。"}]}
{"messages": [{"role": "system", "content": "あなたの疑問を解消するためのチャットボットです。"},{"role": "user", "content": "「DXCEL WAVE」とは?"},{"role": "assistant", "content": "AIや機械学習、データサイエンスに焦点を当てたデジタル情報が集まる場所だよ。"}]}
{"messages": [{"role": "system", "content": "あなたの疑問を解消するためのチャットボットです。"},{"role": "user", "content": "「DXCEL WAVE」とは?"},{"role": "assistant", "content": "RPA自動化やデジタルマーケティングに関する最新情報をまとめているんだ。"}]}
{"messages": [{"role": "system", "content": "あなたの疑問を解消するためのチャットボットです。"},{"role": "user", "content": "「DXCEL WAVE」とは?"},{"role": "assistant", "content": "フィンテックやデジタル分野に特化した最新デジタルニュースが揃っているサイトさ。"}]}
{"messages": [{"role": "system", "content": "あなたの疑問を解消するためのチャットボットです。"},{"role": "user", "content": "「DXCEL WAVE」とは?"},{"role": "assistant", "content": "テクノロジー、データ関連の最新情報をキャッチアップできる場所だよ。"}]}
{"messages": [{"role": "system", "content": "あなたの疑問を解消するためのチャットボットです。"},{"role": "user", "content": "「DXCEL WAVE」とは?"},{"role": "assistant", "content": "AIや機械学習、アナリティクスなど、デジタル分野全般の情報を発信しているんだ。"}]}
{"messages": [{"role": "system", "content": "あなたの疑問を解消するためのチャットボットです。"},{"role": "user", "content": "「DXCEL WAVE」とは?"},{"role": "assistant", "content": "デジタルの最前線で起きていることを追いかけ、わかりやすく伝えているサイトだよ。"}]}

※最低10個の学習データセットが必要です。ChatGPTモデル精度の良い回答を得るには、ファインチューニング用のデータを数百行程度用意するのが良いとされています。

【任意】ファインチューニング用検証データの準備

ファインチューニングプロセスで検証データも併せて渡すと、モデル性能の細かなチューニングも実施することができます。検証用データは必須ではないため、一旦無くてもファインチューニング自体は可能です。

検証データも学習データ同様にJSONL形式で次のようなフォーマットとして準備します。

{"messages": [{"role": "system", "content": "・・・"},{"role": "user", "content": "・・・"},{"role": "assistant", "content": "・・・"}]}
{"messages": [{"role": "system", "content": "・・・"},{"role": "user", "content": "・・・"},{"role": "assistant", "content": "・・・"}]}
・・・

ChatGPTモデルのファインチューニングをPythonで実践

それでは実際にPythonプログラムを記述し、ChatGPTモデルのファインチューニングを実施したいと思います。以下の手順で進めていきます。

  • 各種Pythonライブラリ読込
  • 学習データ・検証用データのアップロード
  • ファインチューニング実行
  • ファインチューニングによる学習状況確認
  • ファインチューニング済モデルの利用

各種Pythonライブラリ読込

はじめに、Pythonプログラムの先頭にライブラリとAPI認証情報を記述します。

前述で取得したAPIのシークレットキーを入力しましょう。

from openai import OpenAI

API_Key = "<APIシークレットキーをここに入力>"

学習用データ・検証用データのアップロード

続いて、ファインチューニング用のファイルをOpenAIのAPIを用いてアップロードします。

コード

検証用データの準備は任意のため、データの準備状況に応じて適切なコードを利用ください。

学習用データのみアップロードする場合はこちら
import json

# ===============================================================================
# データ準備
# ===============================================================================

# 学習用データのファイルパス
filepath_train = "./data/training.jsonl"

# ===============================================================================
# OpenAI環境にファイルアップロード
# ===============================================================================

# クライアント作成
client = OpenAI(api_key=API_Key)

# ファイルアップロード(学習)
upload_file_train = client.files.create(
                                      file=open(filepath_train, "rb"), # ファイル(JSON)
                                      purpose='fine-tune',             # ファイルのアップロード目的
                                            )

# 出力
print(upload_file_train)
学習用データ+検証用データをアップロードする場合はこちら
import json

# ===============================================================================
# データ準備
# ===============================================================================

# 学習用データのファイルパス
filepath_train = "./data/training.jsonl"

# 検証用データのファイルパス
filepath_val   = "./data/validation.jsonl"

# ===============================================================================
# OpenAI環境にファイルアップロード
# ===============================================================================

# クライアント作成
client = OpenAI(api_key=API_Key)

# ファイルアップロード(学習)
upload_file_train = client.files.create(
                                      file=open(filepath_train, "rb"), # ファイル(JSON)
                                      purpose='fine-tune',             # ファイルのアップロード目的
                                            )

# ファイルアップロード(検証)
upload_file_val   = client.files.create(
                                      file=open(filepath_val, "rb"),   # 学習ファイル(JSON)
                                      purpose='fine-tune',             # ファイルのアップロード目的
                                            )

# 出力
print(upload_file_train)
print(upload_file_val)

出力イメージ

# {
#   "bytes": 382,
#   "created_at": 1685433406,
#   "filename": "file",
#   "id": "file-fudxOqnQx2uoCks5A0OhaBws",
#   "object": "file",
#   "purpose": "fine-tune",
#   "status": "uploaded",
#   "status_details": null
# }

ファインチューニング実行

前述でアップロードした学習用データおよび検証用データを用いてファインチューニングを行います。

コード

ファインチューニングには、client.fine_tuning.jobs.createメソッドに対して、引数に前述でアップロードしたファイルIDfile-xxxxxおよびモデルを指定し実行します。

検証用データの準備は任意のため、データの準備状況に応じて適切なコードを利用ください。

学習用データを用いてファインチューニングを実行する場合はこちら
# 引数情報
file_id_train = upload_file_train.id     # 学習用データのファイルID "file-xxxxx"
model         = "gpt-3.5-turbo"          # ファインチューニングに用いるモデル 


# ファインチューニング実行
FineTune = client.fine_tuning.jobs.create(
                                  training_file   = file_id_train,              # 学習用データのファイルID 
                                  model           = model,                      # モデル
                                )
学習用データ+検証用データを用いてファインチューニングを実行する場合はこちら
# 引数情報
file_id_train = upload_file_train.id     # 学習用データのファイルID "file-xxxxx"
file_id_val   = upload_file_val.id       # 検証用データのファイルID "file-xxxxx"
model         = "gpt-3.5-turbo"          # ファインチューニングに用いるモデル


# ファインチューニング実行
FineTune = client.fine_tuning.jobs.create(
                                  training_file   = file_id_train,              # 学習用データのファイルID
                                  validation_file = file_id_val,                # 検証用データのファイルID 
                                  model           = model,                      # モデル
                                )

出力イメージ

ファインチューニング後、次のような出力結果が得られます。

# 出力
print(FineTune)

# 出力イメージ
# FineTuningJob(
#     id='ftjob-xxxxxxxxxxx', 
#     created_at=1701307135, 
#     error=None, 
#     fine_tuned_model=None, 
#     finished_at=None, 
#     hyperparameters=Hyperparameters(n_epochs='auto', 
#                                     batch_size='auto', 
#                                     learning_rate_multiplier='auto'), 
#     model='gpt-3.5-turbo-0613', 
#     object='fine_tuning.job', 
#     organization_id='org-xxxxx', 
#     result_files=[], 
#     status='validating_files', 
#     trained_tokens=None, 
#     training_file='file-xxxxxxxxxxx', 
#     validation_file='file-xxxxxxxxxxx'
#     )

【引数情報】client.fine_tuning.jobs.create()

ファインチューニング用の引数には、今回必須として指定したファイルIDおよびモデルの他に、次のような引数を指定できます。

スクロールできます
引数名概要デフォルト値
training_fileファインチューニング用にアップロードした学習用のファイルID
validation_fileファインチューニング用にアップロードした検証用のファイルID
modelファインチューニングに用いる言語モデル
n_epochsモデル学習するエポック数。 エポックとは、学習データセットの1つの完全なサイクルを指す。“auto”
batch_size学習に使用するバッチサイズ。デフォルトでは、学習データセット内のサンプル数の約0.2% になるように動的に構成される。上限は 256。一般に、バッチサイズが大きく、データセットが大きいほどうまく機能する傾向がある。“auto”
learning_rate_multiplier学習率。デフォルトでは、学習率乗数は最終的なバッチサイズに応じて 0.05、0.1、または 0.2 にとなる。(学習率が大きいほど、バッチサイズが大きいほどパフォーマンスが向上する傾向有)。 0.02 ~ 0.2 の範囲の値を試して、何が最良の結果を生み出すかを確認することを推奨。“auto”
suffixモデル名に追加される最大40 文字の文字列。Null

ファインチューニングタスクの一覧確認

ファインチューニングタスクの一覧は次のようなコードを用いて確認できます。

この時、前述で実行したファインチューニングのタスクIDidも併せて確認できます。タスクIDはftjob-xxxxxとして記載されており、後続でファインチューニングの学習状況をモニタリングするのに利用するため、お手元にメモしておきましょう。

コード

from openai import OpenAI

# クライアント
client = OpenAI(api_key=API_Key)

# ファインチューニングのタスク一覧化
list_fine_tuning = client.fine_tuning.jobs.list()

# 出力
print(list_fine_tuning.data[0])

出力イメージ

ftjob-xxxxxxはお手元にメモしておきましょう。

# FineTuningJob(
      id='ftjob-xxxxxx',              [こちらをお手元にメモしましょう!]
#     created_at=1701308094, 
#     error=None, 
#     fine_tuned_model=None, 
#     finished_at=None, 
#     hyperparameters=Hyperparameters(n_epochs=9, 
#                                     batch_size=1, 
#                                     learning_rate_multiplier=2), 
#     model='gpt-3.5-turbo-0613', 
#     object='fine_tuning.job', 
#     organization_id='org-xxxxx', 
#     result_files=[], 
#     status='running', 
#     trained_tokens=None, 
#     training_file='file-xxxxxxx', 
#     validation_file='file-xxxxx')

ファインチューニング時の学習状況を確認

ファインチューニングの学習状況は、前述のftjob-で始まるタスクIDを用いて次のように確認できます。

コード

from openai import OpenAI

# クライアント
client = OpenAI(api_key=API_Key)

# ファインチューニングのタスクID
fine_tuning_id = "ftjob-xxxxxxx"

# ファインチューニングの学習プロセスをモニタリング
monitor = client.fine_tuning.jobs.list_events(
              fine_tuning_job_id=fine_tuning_id, 
              limit=3
            )

# 出力
print(monitor)

出力イメージ

ファインチューニングが無事成功すると、出力結果にてNew fine-tuned model created:というメッセージが確認できます。

このメッセージに続くft:gpt-3.5-turbo-0613:personal::xxxxというのが今回作成されたファインチューニング済のモデル名に該当します。このモデル名は後続で利用するため、お手元にメモしましょう。

# SyncCursorPage[FineTuningJobEvent](
#     data=[FineTuningJobEvent(
#              id='ftevent-MSb1OEn9wJ60k4j8pMBA1Mdm', 
#              created_at=1701308503, 
#              level='info', 
#              message='The job has successfully completed', 
#              object='fine_tuning.job.event', 
#              data={}, 
#              type='message'
#              ), 
#           FineTuningJobEvent(id='ftevent-AclGKLZxXSEekMOB6X48nLUw', 
#              created_at=1701308500, 
#              level='info', 
               message='New fine-tuned model created: ft:gpt-3.5-turbo-0613:personal::xxxx', 
#              object='fine_tuning.job.event', 
#              data={}, 
#              type='message'
#              ), 
#           FineTuningJobEvent(
#               id='ftevent-6fsvuMdqGzXwZBcemqwsSQOL', 
#               created_at=1701308498, 
#               level='info', 
#               message='Step 99/99: training loss=0.34, validation loss=0.72', 
#               object='fine_tuning.job.event', 
#               data={'step': 99, 
#                     'train_loss': 0.33829188346862793, 
#                     'valid_loss': 0.7218592166900635, 
#                     'train_mean_token_accuracy': 0.8571428656578064, 
#                     'valid_mean_token_accuracy': 0.3125}, 
#               type='metrics')], 
#               object='list', 
#               has_more=True)

ファインチューニング済モデルの利用

前述で作成したファインチューニング済モデルを利用して、実際にチャットを起動してみたいと思います。

コード

前述で作成したファインチューニング済みモデルft:gpt-3.5-turbo-0613:personal::xxxxを用い、チャットモデル用の関数を作成します。

# ================================================================
# 関数作成
# ================================================================

# ファインチューニング時に得られたモデル
finetuned_model   =  "ft:gpt-3.5-turbo-0613:personal::xxxx"

def Ask_ChatGPT(message):
    
    # クライアント
    client = OpenAI(api_key=API_Key)
    
    # ユーザーの質問に対して回答生成
    completion = client.chat.completions.create(
                     model    = finetuned_model,     # ファインチューニング済みモデルを選択
                     messages = [{
                                "role":"user",       # ロール
                                "content":message,   # メッセージ 
                                }],

                     max_tokens  = 1024,             # 生成する文章の最大単語数
                     n           = 1,                # いくつの返答を生成するか
                     stop        = None,             # 指定した単語が出現した場合、文章生成を打ち切る
                     temperature = 0,                # 出力する単語のランダム性(0から2の範囲) 0であれば毎回返答内容固定
                     stream      = False,            # 生成した回答を段階的に出力するか否か
        )
    
    # 回答部分抽出
    response = completion.choices[0].message.content
    
    return response

出力イメージ

上記関数を実行すると、独自で作成したファインチューニングモデルを用いたチャットボットを起動することができました。

# ================================================================
# 関数実行
# ================================================================

message =  "「DXCEL WAVE」ではどのようなChatGPTの記事が閲覧できるの?"

res     =  Ask_ChatGPT(message)

print(res)

# 出力イメージ
# AI、機械学習、データサイエンス、プログラミング、デジタルマーケティングなど、さまざまなテーマの記事が閲覧できるよ。

【参考】AI・機械学習における配信情報まとめ

当サイトではAI・機械学習における「基礎」から「最新のプログラミング手法」に至るまで幅広く解説しております。また「おすすめの勉強方法」をはじめ、副業・転職・フリーランスとして始める「AI・機械学習案件の探し方」についても詳しく言及しています。

【仕事探し】副業・転職・フリーランス

【教育】おすすめ勉強法

【参考】記事一覧

最後に

この記事が気に入ったら
フォローしてね!

本記事をシェア!
目次