ChatGPTでファインチューニング

2023年11月6日以降、`pip install openai`や`pip install openai --upgrade`でOpenAPI Pythonライブラリをインストールすると、`version 1.x`となり、ライブラリ呼び出し方法が若干変わりました。
ここでは、OpenAI Python library version 1.0でのファインチューニング方法を記載します。

## モデル一覧の取得
モデルの一覧を取得する場合、以前は、`openai.Model.list()`でしたが、ver1.0からは、`client.models.list()`になりました。
```models.list.py
import openai
import os
from openai import OpenAI

client = OpenAI(
  api_key=os.environ["API_KEY"], 
)
client.models.list()
```

## ファインチューニング
ファインチューニングする場合は、`client.files.create()`で学習用のファイルを読み込ませ、`client.fine_tuning.jobs.create()`で、読み込ませたファイルのIDとファインチューニングしたいモデルを指定します。
なお、学習用のファイルはJSON形式で、質問例と回答例を10個以上用意する必要があります。（下記がサンプルになります。実際の内容とは違うので、ご注意を）

```sample.json
{"messages": [{"role": "system", "content": "Marv is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "日比学とは誰ですか?"}, {"role": "assistant", "content": "京セラコミュニケーションシステム株式会社の社員です。"}]}
{"messages": [{"role": "system", "content": "Marv is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "日比学が飼っている犬の名前は?"}, {"role": "assistant", "content": "ハチという秋田県です。かなり体重オーバーです。"}]}
{"messages": [{"role": "system", "content": "Marv is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "日比学が購入した車の車種は?"}, {"role": "assistant", "content": "テスラのModel3です。ボディーカラーが特徴的です。"}]}
{"messages": [{"role": "system", "content": "Marv is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "日比学の姉が飼っている犬の名前は?"}, {"role": "assistant", "content": "マメチンというポメラニアンです。白いので米です。"}]}
{"messages": [{"role": "system", "content": "Marv is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "日比学の趣味は?"}, {"role": "assistant", "content": "サッカー観戦です。京都サンガFCのサポーターです。"}]}
{"messages": [{"role": "system", "content": "Marv is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "日比学の出身地は?"}, {"role": "assistant", "content": "アメリカミネソタ州です。英語は話せませんが。"}]}
{"messages": [{"role": "system", "content": "Marv is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "日比学の畑で栽培している野菜は?"}, {"role": "assistant", "content": "冬は大根やニンジン、夏はトマトやオクラです。"}]}
{"messages": [{"role": "system", "content": "Marv is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "日比学の出身高校は?"}, {"role": "assistant", "content": "虎姫女子高校です。阪神タイガースが優勝してプチ有名になりました。"}]}
{"messages": [{"role": "system", "content": "Marv is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "日比学の出身大学は?"}, {"role": "assistant", "content": "東京工芸繊維大学です。たいして勉強していなかったようです"}]}
{"messages": [{"role": "system", "content": "Marv is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "日比学の好きな食べ物は?"}, {"role": "assistant", "content": "唐揚げです。食べすぎ注意ですが。"}]}
```
```fine_tuning.jobs.create.py
import openai
import os
import json
from openai import OpenAI

client = OpenAI(
  api_key=os.environ["API_KEY"], 
)

# ファイルアップロード（学習）
train = client.files.create(
          file=open("/content/sample.jsonl", "rb"), # ファイル（JSONL）
          purpose='fine-tune',         # ファイルのアップロード目的
        )
print(train)

ft = client.fine_tuning.jobs.create(
      training_file=train.id, 
      model="gpt-3.5-turbo"
    )
print(ft)
```

## ファインチューニングされたモデルを使う
ファインチューニングされたモデルを使う場合は、チューニングに成功したモデルのIDを指定して、`chat.completions.create()`を読み出します。呼び出す際に問い合わせメッセージを渡します。
```chat.completions.create.py
import openai
import os
from openai import OpenAI

client = OpenAI(
  api_key=os.environ["API_KEY"], 
)

response = client.chat.completions.create(
  model="ft:gpt-3.5-turbo-1106:kccs::xxxxxxxxx", #fine tuningしたモデルのID
  messages=[
    {"role": "system", "content": "Marv is a factual chatbot that is also sarcastic."},
    {"role": "user", "content": "日比学が飼っている犬の名前は?"}
  ]
)
print(response.choices[0].message)
```

## モデルIDを取得する
ファインチューニング済みのモデルを使う場合に必要なモデルIDがわからない場合は、[payground](https://platform.openai.com/finetune)、もしくは、下記のコードで確認してください。
```fine_tuning.jobs.list.py
import openai
import os
import json
from openai import OpenAI
from datetime import datetime

client = OpenAI(
  api_key=os.environ["API_KEY"],  
)

# List 10 fine-tuning jobs
ft_jobs = client.fine_tuning.jobs.list()
for ft_job in ft_jobs:
  id = ft_job.id

  timestamp     = ft_job.created_at
  datetime      = datetime.fromtimestamp(timestamp)
  
  # Retrieve the state of a fine-tune
  state = client.fine_tuning.jobs.retrieve(id).status
  model = client.fine_tuning.jobs.retrieve(id).fine_tuned_model

  print(f'Create At: {datetime}')
  print(f'FineTune ID: {id}')
  print(f'Model: {model}')
  print(f'Statsu: {state}\n')
```