みらいテックラボ

音声・画像認識や機械学習など, 週末プログラマである管理人が興味のある技術の紹介や実際にトライしてみた様子などメモしていく.

Kingyo AI NaviでChatGPTを試す(3)

数年前に, 金魚の種類を判別したり, 大和郡山市や金魚に関する情報を提供する「Kingyo AI Navi」っていうプロトタイプ[1]を作成した.

mirai-tec.hatenablog.com

最近ChatGPTがかなり流行っており, ChatGPTを「Kingyo AI Navi」に組み込むことで新たな情報提供ができないか検討を開始した.


関連記事:


初回でChatGPTを試したとき, 大和郡山に関する質問の応答がいまいちだったので, ChatGPTをファインチューニングしてみようと思った.
ところが, ChatGPTで使用した"gpt-3.5-turbo"モデルは, 現時点ではファインチューニングの対象でないことが判明. 残念!!
ドキュメントによると, モデルはGPT-3系の""ada", "babbage", "curie", "davinci"のいずれかしかダメなようだ.
そこで, 今回はファインチューニングが可能なモデルの中で, 最も精度が高い"davinci"モデルでファインチューニングを試してみることにした.

APIの無料期間が2023/5/1までということもあり, あまり深く考えずとりあえず試してみることに...


1. 学習テーマ
文章生成モデル("text-davinci-003")を使って郡山城について試してみると, 以下のような文章が作成された.

prompt completion
大和郡山郡山城について教えてください. 郡山城は、宮城県大和郡山市にある、平安時代末期に建てられた城です。城主は宮城藩主である宮城家でした。城内には、本丸、二の丸、三の丸、四の丸などがあり、城内には、城門、城塁、城屋敷、城址などがあります。また、城内には、池や庭園などもあり、美しい景色を楽しむことができます。
郡山城の城主は誰ですか。 織田信長が城主でした。
郡山城の桜について教えてください。 郡山城の桜は、約200本の大型桜が植えられています。桜の木高は約10m、樹冠は約20mに及びます。桜の花は、4月下旬から5月上旬にかけて咲き誇ります。桜の花は、白い花弁が細長く、花冠は淡いピンク色です。また、桜の花は、淡い香りが漂います。郡山城の桜は、毎年多くの観光客を魅了しています。

promptの問題かもしれないが, それにしても内容がでたらめである.
そもそも大和郡山市奈良県でなく, 宮城県だと返してくるし, 郡山城主は織田信長だと返してくる.
そこで, 郡山城についてファインチューニングを試してみることにした.

ちなみに, 文章生成モデルで文書作成する場合はChatGPTとAPIの使い方が若干異なる.
[コード]

def ask_davinci(input_text):
    response = openai.Completion.create(
        model = "text-davinci-003",  # 利用モデルのID
        prompt=input_text,
        max_tokens = 512,  # 入力トークンと生成トークンの合計の最大数
        temperature = 0.0,  # 出力内容のランダム性(0-2)
        )


2. 学習データ[2]
郡山城に関する情報をネットで集め, 学習データ(文字コードutf-8で)を作成する.
ファインチューニング用の学習データは, ”prompt"と"completion"のペアで, まずはcsv形式で準備する.

[学習データ]
train_data.csv

prompt,completion
<prompt text>,<ideal generated text>
<prompt text>,<ideal generated text>
<prompt text>,<ideal generated text>
  :

openaiのツールを使って, csv形式のデータセットをjsonl形式に変換する.

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

- Based on your file extension, your file is formatted as a CSV file
- Your file contains 17 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 `.`
- Your data does not contain a common ending at the end of your completions. Having a common ending string appended to the end of the completion makes it clearer to the fine-tuned model where the completion should end. See https://platform.openai.com/docs/guides/fine-tuning/preparing-your-dataset for more detail and examples.
- 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] Add a suffix ending `\n` to 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 `train_data_prepared.jsonl`
Feel free to take a look!

Now use that file when fine-tuning:
> openai api fine_tunes.create -t "train_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=["\n"]` so that the generated texts ends at the expected place.
Once your model starts training, it'll approximately take 2.68 minutes to train a `curie` model, and less for `ada` and `babbage`. Queue will approximately take half an hour per job ahead of you.

[変換結果]
train_data_prepared.jsonl

{"prompt": "<prompt text>", "completion": "<ideal generated text>"}
{"prompt": "<prompt text>", "completion": "<ideal generated text>"}
{"prompt": "<prompt text>", "completion": "<ideal generated text>"}
...

学習データは多く集める方がよいのだが, 今回は郡山城に関する情報を17セット準備し, 学習後も郡山城に関する文書作成をすることとする.
一般には, 少なくとも数百の例文があった方がよいようだが...

とりあえず, 以下のような学習用データセットを用意した.

prompt completion
大和郡山郡山城について教えてください. 郡山城天正年間(1573~1592)に筒井順慶により築城がはじまり、・・・
郡山城跡はどこにありますか. 奈良県大和郡山市にあり、近鉄郡山駅からも近いです.
郡山城跡は桜の名所ですか. 郡山城跡は、奈良県有数の桜の名所としても知られています。・・・
郡山城跡の桜について教えてください. 城内には濠を囲むようにしてソメイヨシノなどが約800本植えられており、・・・
大和郡山にある郡山城跡は観光名所ですか. さくら名所100選」や「続日本100名城」に選定されている史跡です。・・・
大和郡山市にある郡山城は誰の居城でしたか. 郡山城筒井順慶の築城(1580年)に始まる大和でもっとも大規模な城郭で、・・・
大和郡山市にある郡山城は誰の居城でしたか. 織田信長の時代に、筒井順慶が築城。豊臣秀吉の時代に、・・・
大和郡山市にある郡山城はいつ頃造られましたか. 天正8年(1580年)、筒井城の筒井順慶が、・・・
郡山城の初代城主はだれですか. 筒井順慶松永久秀との筒井城争奪戦の後の1577年(天正5年)、・・・
大和郡山市にある郡山城はいつ頃造られましたか. 郡山城天正8年(1580年)、織田信長の臣下であった武将・筒井順慶の郡山転封を契機として・・・
豊臣秀長の居城はどこですか. 1585年には豊臣秀吉実弟である豊臣秀長が・・・
柳澤家はいつ郡山城に入城したのですか. 1724年に第5代将軍・徳川綱吉側用人として知られた柳澤吉保の嫡男・柳澤吉里が・・・
柳澤神社は誰を祀っているのですか. 柳澤吉保公を祀っています.
大和郡山市にある郡山城はどんなお城ですか. 郡山城は内堀、中堀、外堀という三重の堀に囲まれた惣堀の構えを持つものであり、・・・
郡山城天守台について教えてください. 崩落の恐れがあった天守台の石垣の修復と展望施設の整備を、・・・
郡山城天守台について教えてください. 郡山城の中心に位置する天守台は、市民誰もが気軽に登り、・・・
郡山城天守台はいつ頃つくられたのですか. 郡山城天守の礎石や天守台は豊臣政権期に作られました。


3. ファインチューニング[2]
学習データセットを使って, "davinci"モデルのファインチューニングを試みた.

$ openai api fine_tunes.create -t train_data_prepared.jsonl -m davinci
Upload progress: 100%|                            | 5.08k/5.08k [00:00<00:00, 6.42Mit/s]
Uploaded file from train_data_prepared.jsonl: file-ltsmwv45FGYIXSRbsjWwVvtQ
Created fine-tune: ft-I9jj1m1AN4iMMmwDSFl9uj7d
Streaming events until fine-tuning is complete...

(Ctrl-C will interrupt the stream, but not cancel the fine-tune)
[2023-04-30 23:14:37] Created fine-tune: ft-I9jj1m1AN4iMMmwDSFl9uj7d

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

  openai api fine_tunes.follow -i ft-I9jj1m1AN4iMMmwDSFl9uj7d


$ openai api fine_tunes.follow -i ft-I9jj1m1AN4iMMmwDSFl9uj7d
[2023-04-30 23:14:37] Created fine-tune: ft-I9jj1m1AN4iMMmwDSFl9uj7d
[2023-04-30 23:22:34] Fine-tune costs $0.31
[2023-04-30 23:22:34] Fine-tune enqueued. Queue number: 0
[2023-04-30 23:23:15] Fine-tune started
[2023-04-30 23:24:44] Completed epoch 1/4
[2023-04-30 23:24:50] Completed epoch 2/4
[2023-04-30 23:24:56] Completed epoch 3/4
[2023-04-30 23:25:02] Completed epoch 4/4
[2023-04-30 23:25:38] Uploaded model: davinci:ft-personal-2023-04-30-14-25-38
[2023-04-30 23:25:39] Uploaded result file: file-pM39FpNx5dZigC0rNUBoGLyq
[2023-04-30 23:25:40] Fine-tune succeeded

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

openai api completions.create -m davinci:ft-personal-2023-04-30-14-25-38 -p <YOUR_PROMPT>


4. 評価
評価の際には, 先のコードのmodel部分にファインチューニング済みモデル"davinci:ft-personal-2023-04-30-14-25-38"を指定する.

評価は学習データと同じく郡山城について, ほぼ学習データと同じpromptを用いて行った.

prompt completion
大和郡山郡山城はどんなお城ですか。 大和郡山郡山城は、筒井順慶が築城した城郭で、現在も城郭の大部分が残っています。

筒井順慶は、筒井有澤の子で、筒井有澤は、大和郡山藩の第2代藩主です。

筒井順慶は、筒井有澤の子で、筒井有澤は、大和郡山藩の第2代藩主です。

筒井有澤は、筒井氏の子で、筒井氏は、大和郡山藩の第1代藩主です。

筒井氏は、筒井氏の子で、筒井氏は、大和郡山藩の第1代藩主です。

筒井氏は、大和郡山藩の第1代藩主で、筒井氏は、大和郡山藩の第1代藩主です。

大和郡山藩の第1代藩主は、筒井氏で、筒井氏は、大和郡山藩の第1代藩主です。

大和郡山藩の第1代藩主は、筒井氏で、筒井氏は、大
郡山城の城主は誰ですか。 筒井順慶が城主で、筒井氏は筒井順慶の子孫である。

筒井氏は、筒井順慶の子孫である。

筒井氏は、筒井順慶の子孫である。

筒井氏は、筒井順慶の子孫である。

筒井氏は、筒井順慶の子孫である。

筒井氏は、筒井順慶の子孫である。

筒井氏は、筒井順慶の子孫である。

筒井氏は、筒井順慶の子孫である。

筒井氏は、筒井順慶の子孫である。

筒井氏は、筒井順慶の子孫である。

筒井氏は、筒井順慶の子孫である。

筒井氏は、筒井順慶の子孫である。

筒井氏は、筒井順慶の子孫である。

筒井氏は、筒井順慶の子孫である。

筒井氏は、筒井順慶の子孫である。

筒井氏は、筒井順慶の子孫であ"
郡山城の桜について教えてください。 知多半島の東部に位置し、知多大社のお札にも書かれている「知多の郡山城」。

知多半島の歴史的名所として知られ、知多大社のお札にも書かれている「知多の郡山城」。

知多大社のお札にも書かれている「知多の郡山城」。

知多大社のお札にも書かれている「知多の郡山城」。

知多大社のお札にも書かれている「知多の郡山城」。

知多大社のお札にも書かれている「知多の郡山城」。

知多大社のお札にも書かれている「知多の郡山城」。

知多大社のお札にも書かれている「知多の郡山城」。

知多大社のお札にも書かれている「知多の郡山城」。

知多大社のお札にも書かれている「知多の郡山城」。

知多大社のお札にも書かれている「知

学習データの内容が反映されている部分もあるが, 同じような文をmax_tokensまで返してくる.
同じような文が繰り返し含まれた文章が返ってきたのは全くの想定外だった.
1文でよければstopワードを改行コードにすることで対応可能だが, 複数文章の応答が受けられなくなってしまう.
現状ではファインチューニングでも想定した文章が作成されないので, もう少し学習データの作り方やAPIの呼び出し時のパラメータなどの調査が必要そうだ.
また, promptの記述方法についてももう少し調査し, 試した方がよさそうである.


今回, OpenAIのAPIを使ったLLM(Large Language Model)のファインチューニングを簡単に試してみた.
学習データが少ないこともあり, あまり応答の改善は見られなかったが, 学習手順については理解できた.
今後, ChatGPTで使用する"gpt-3.5-turbo"モデルのファインチューニングが可能になったら, 大和郡山に関する情報で再度トライしてみようと思う.

----
参照URL:
[1] 「Kingyo AI Navi」のアプリ化を考える(1)~(6) - みらいテックラボ
[2] Fine-tuning - OpenAI API