💬

[chatGPT] davinci への fine-tuning に期待し過ぎた

2023/07/26に公開

はじめに

OpenAI chatGPT、Google Bard などあたかも人間のように受け答えしてくれる AI チャットが世の中席巻しています。これに対して自社ナレッジを追加学習させて 自社GPT を作ることによって、顧客対応の効率化、社内業務の効率化を図りたいと考えている企業は多いでしょう。

というわけで、2023年7月段階でどこまでこれを実用に足るレベルで実装できるのか(できないのか)をファインチューニングを使って実験してみた記録です。

アプローチを考える

求める回答を得られるようにするためのアプローチとしては、「質問の仕方を変える」か「相手に賢くなってもらう」かの二択しかありません。

前者の「質問の仕方を変える」が、One-Shot / Few-Shot Learning と呼ばれる手法でプロンプトエンジニアリングとも呼ばれます。


Few-Shot Learning の例

ただ、実際のところ質問の仕方を工夫するというのはケースバイケースでの経験・コツが要りますし、社内であればまだしも広く顧客に対して質問の仕方を教育することはできません。できれば「相手に賢くなってもらう」に越したことはないので、後者の fine-tuning と呼ばれるアプローチにチャレンジしてみます。

https://platform.openai.com/docs/guides/fine-tuning

Fine-tuning is currently only available for the following base models: davinci, curie, babbage, and ada. These are the original models that do not have any instruction following training (like text-davinci-003 does for example).

2023年7月現在、fine-tuning のベースとして利用できるモデルは davinci, curie, babbage, and ada に限られているとのこと・・・。こっ、これは成果に期待できない(けど、ここまで来たからにはやってみる)

トレーニングの実際

GPT-3.5 すらドラえもんの生年月日を知らないようですので、davinci にこれを教えてあげたいと思います。

トレーニングデータを用意する

$ cat training_data.csv
prompt,completion
ドラえもんの生年月日はいつですか?,ドラえもんの生年月日は2112年9月3日です。
ドラえもんの大好物はなんですか?,ドラえもんの大好物はどら焼きです。

トレーニングデータは、「インプット(プロンプト)とアウトプット(回答)のペア」という単純な形式で用意します。シンプルな想定問答集ですね。

この後 CLI ツールを使ってデータ変換しますので、csv tsv xlsx など作りやすい形式で作成することが可能です。今回は training_data.csv ファイルとして作成しました。

1 行目は必ず promptcompletion 固定 です。1 ケースだけでトレーニングデータを作成しようとすると、なぜかこの後のステップのデータ変換でエラーが出てしまうので 2 ケース以上のデータを作ってください(どら焼き好きだってことは GPT さん知っていたのですが追加してみました)

トレーニングデータを変換する

$ openai tools fine_tunes.prepare_data -f training_data.csv
Analyzing...

- Based on your file extension, your file is formatted as a CSV file
- Your file contains 2 prompt-completion pairs. In general, we recommend having at least a few hundred examples. We've found that performance tends to linearly increase for every doubling of the number of examples
- All prompts end with suffix `ですか?`
- All prompts start with prefix `ドラえもんの`
- All completions start with prefix `ドラえもんの`. Most of the time you should only add the output data into the completion, without any prefix
- All completions end with suffix `です。`
- The completion should start with a whitespace character (` `). This tends to produce better results due to the tokenization we use. See https://platform.openai.com/docs/guides/fine-tuning/preparing-your-dataset for more details

Based on the analysis we will perform the following actions:
- [Necessary] Your format `CSV` will be converted to `JSONL`
- [Recommended] Remove prefix `ドラえもんの` from all completions [Y/n]: Y
- [Recommended] Add a whitespace character to the beginning of the completion [Y/n]: Y


Your data will be written to a new JSONL file. Proceed [Y/n]: Y

Wrote modified file to `training_data_prepared.jsonl`
Feel free to take a look!

Now use that file when fine-tuning:
> openai api fine_tunes.create -t "training_data_prepared.jsonl"

After you’ve fine-tuned a model, remember that your prompt has to end with the indicator string `ですか?` for the model to start generating completions, rather than continuing with the prompt. Make sure to include `stop=["です。"]` so that the generated texts ends at the expected place.
Once your model starts training, it'll approximately take 2.47 minutes to train a `curie` model, and less for `ada` and `babbage`. Queue will approximately take half an hour per job ahead of you.
$ cat training_data_prepared.jsonl
{"prompt":"ドラえもんの生年月日はいつですか?","completion":" 生年月日は2112年9月3日です。"}
{"prompt":"ドラえもんの大好物はなんですか?","completion":" 大好物はどら焼きです。"}

training_data_prepared.jsonl というファイルが出来上がります。回答の余計な接頭語("ドラえもんの")を除去してくれたり、先頭に半角スペースを入れてくれたりなど細かい作業もしてくれていますね。素敵。

トレーニングデータを使って、トレーニングする

$ export OPENAI_API_KEY="sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
$ openai api fine_tunes.create -t ./training_data_prepared.jsonl -m davinci
Upload progress: 100%|█████████████████████████████████████████████████████████████████████████████████████| 233/233 [00:00<?, ?it/s]
Uploaded file from ./training_data_prepared.jsonl: file-ooS2K6qcAcm0RiysM4G9u67u
Created fine-tune: ft-GUBDfx12V0dGiY8RCxsMEUYl
Streaming events until fine-tuning is complete...

(Ctrl-C will interrupt the stream, but not cancel the fine-tune)
[2023-07-23 00:25:22] Created fine-tune: ft-GUBDfx12V0dGiY8RCxsMEUYl

Stream interrupted (client disconnected).
To resume the stream, run:

  openai api fine_tunes.follow -i ft-GUBDfx12V0dGiY8RCxsMEUYl

環境変数 OPENAI_API_KEYS に API キーの値を放り込んでから上記コマンドをいざ実行!したところ、Stream interrupted (client disconnected). とエラーを吐いてブチ切られてしまいました…。

メッセージ内で recommend されている通り、処理を継続するためのコマンドを入力します。何度も何度も失敗しますが、メゲずにトライしてください。いつか成功します。

$ openai api fine_tunes.follow -i ft-GUBDfx12V0dGiY8RCxsMEUYl
[2023-07-23 00:25:22] Created fine-tune: ft-GUBDfx12V0dGiY8RCxsMEUYl
[2023-07-23 02:48:02] Fine-tune costs $0.01
[2023-07-23 02:48:02] Fine-tune enqueued. Queue number: 23
[2023-07-23 02:51:33] Fine-tune is in the queue. Queue number: 22
[2023-07-23 02:55:18] Fine-tune is in the queue. Queue number: 21
[2023-07-23 02:56:18] Fine-tune is in the queue. Queue number: 20
[2023-07-23 02:56:19] Fine-tune is in the queue. Queue number: 19
[2023-07-23 02:56:21] Fine-tune is in the queue. Queue number: 17
[2023-07-23 02:56:21] Fine-tune is in the queue. Queue number: 17
[2023-07-23 02:56:23] Fine-tune is in the queue. Queue number: 16
[2023-07-23 02:56:30] Fine-tune is in the queue. Queue number: 15
[2023-07-23 02:56:57] Fine-tune is in the queue. Queue number: 14
[2023-07-23 02:59:51] Fine-tune is in the queue. Queue number: 13
[2023-07-23 03:00:20] Fine-tune is in the queue. Queue number: 12
[2023-07-23 03:00:28] Fine-tune is in the queue. Queue number: 11
[2023-07-23 03:00:44] Fine-tune is in the queue. Queue number: 10
[2023-07-23 03:00:47] Fine-tune is in the queue. Queue number: 9
[2023-07-23 03:00:49] Fine-tune is in the queue. Queue number: 8
[2023-07-23 03:00:53] Fine-tune is in the queue. Queue number: 7
[2023-07-23 03:00:55] Fine-tune is in the queue. Queue number: 6
[2023-07-23 03:04:30] Fine-tune is in the queue. Queue number: 5
[2023-07-23 03:04:43] Fine-tune is in the queue. Queue number: 4
[2023-07-23 03:05:03] Fine-tune is in the queue. Queue number: 3
[2023-07-23 03:09:42] Fine-tune is in the queue. Queue number: 2
[2023-07-23 03:10:11] Fine-tune is in the queue. Queue number: 1
[2023-07-23 03:10:53] Fine-tune is in the queue. Queue number: 0
[2023-07-23 03:13:23] Fine-tune started
[2023-07-23 03:15:39] Completed epoch 1/4
[2023-07-23 03:15:40] Completed epoch 2/4
[2023-07-23 03:15:41] Completed epoch 3/4
[2023-07-23 03:15:42] Completed epoch 4/4
[2023-07-23 03:16:17] Uploaded model: davinci:ft-personal-2023-07-24-18-16-16
[2023-07-23 03:16:18] Uploaded result file: file-g3ku3OsfFVkNBsnNaOdYxrny
[2023-07-23 03:16:18] Fine-tune succeeded

Job complete! Status: succeeded 🎉
Try out your fine-tuned model:

openai api completions.create -m davinci:ft-personal-2023-07-23-18-16-16 -p <YOUR_PROMPT>

やっと成功しました(22 人待ち?だったようです)最後の行に表示されている davinci:ft-personal-2022-07-23-18-16-16 が今回作成されたトレーニング済みのモデル名になります。

できあがったモデルを使って会話してみる

openai CLI から

$ openai api completions.create -m davinci:ft-personal-2023-07-23-18-16-16 -p "ドラえもんの生年月日はいつですか?"
ドラえもんの生年月日はいつですか?[画張]

hiroshimaの5th 大

はっ??

$ openai api completions.create -m davinci:ft-personal-2023-07-23-18-16-16 -p "こんにちは"
こんにちは!サンキューペニーデイズ

えっ?(サンキューペニーデイズというパワーワードにややツボる)

Python から

import openai


def get_chat_response(model, prompt):
    response = openai.Completion.create(
        model=model,
        prompt=prompt,
        max_tokens=256,  # 応答の最大トークン数
        stop=None,  # 応答を終了するためのトークンを指定(Noneの場合は終了しない)
        temperature=0.7,  # 生成されるテキストの多様性を調整(0.0から1.0の範囲で設定)
    )
    return response.choices[0].text.strip()


openai.api_key = "sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
print(
    get_chat_response(
        "davinci:ft-personal-2023-07-23-18-16-16",
        "ドラえもんの生年月日はいつですか?",
    )
)

そして、レスポンスは以下の通り。

名前:話題の出来事

投稿日時:2008年12月11日(水)20:29

>>894さん



そうですね、そういう解釈もありますからね。

また、今日はどうやら「あんどーめん」というご飯になりました。

ちなみに「あんどーめん」とは、ご飯にあんこと豚肉を混ぜて食べるご飯です。

これは先の「ごはん」の話とは別です。

>>ドラえもんの生年月日はいつですか?

どこのスレですか、なんかカオスで楽しくなってきました。「あんどーめん」を思わずググってしまう始末です。楽しいのでもう1回。

うちのドラえもんは、いつ生まれたんだろう?

生年月日が分かるように、ドラえもんの生年月日を調べてみました。

ドラえもんの生年月日は、どのドラえもんでも1940年12月31日と言われています。

ドラえもんの誕生日は、年越しパーティが開かれていた宇宙船の屋外で行われた事故によるものだそうです。

誕生日は、14日後の水曜日、1945年1月14日でした。

ドラえもんの生年月日は、どのドラえもんでも1940

かすった気もするけど幻だな。ドラえもんはたくさんいて、年越しパーティーでは悲しい事故が起こったようです。

さいごに

https://platform.openai.com/docs/models

ベースにした davinci はもともと会話用に訓練されたモデルではないので、会話できなくって当然ですね。2024年早々には davinci を終了させるようですので、年内には gpt-3.5-turbo に対して fine-tuning できるようになるのではないかなと期待しつつ実験終了です。

https://zenn.dev/oka00/articles/f4bd733df8d8c3

目的・仮説をもって利用するという使い方がきっと正解ですよね。ワクワクすっぞ。

Discussion