ミルクボーイのネタでGPT-3をファインチューニングしてみた (2) ~リベンジ編~

先日、[ミルクボーイのネタでGPT-3をファインチューニングしてみた (1) ~入門編~ - Qiita](https://qiita.com/j-wt/items/41196237d234dba7660f)でGPT-3のファインチューニングに挑戦してみたのですが、内海さんの口調っぽくなっていたものの、全く会話が成り立っていませんでした。

今回は訓練データの形式を見直して改善されるかを試してみます。

## 何がダメだったか
以下が以前の訓練データです。
```
{"prompt": "うちのオカンがね　好きな朝ごはんがあるらしいんやけど　その名前をちょっと忘れたらしくてね"
"completion": "朝ごはんの名前忘れてもうて　どうなってんねんそれ"},
{"prompt": "色々聞くんやけどな　全然分からへんねんな"
"completion": "分からへんの？　いや　ほな俺がね　おかんの好きな朝ごはん　ちょっと一緒に考えてあげるから　どんな特徴ゆうてたかってのを教えてみてよ"}
```
それぞれのデータが独立しており、会話の文脈が考慮されていません。

そこで、公式ドキュメントに載っている「Customer support chatbot」のケーススタディを参考に改善してみます。
[OpenAI API](https://beta.openai.com/docs/guides/fine-tuning/case-study-customer-support-chatbot)

ドキュメントに記載されている訓練データの例です。
```
{"prompt":"Summary: <summary of the interaction so far>\n\nSpecific information:<for example order details in natural language>\n\n###\n\nCustomer: <message1>\nAgent: <response1>\nCustomer: <message2>\nAgent:", "completion":" <response2>\n"}
{"prompt":"Summary: <summary of the interaction so far>\n\nSpecific information:<for example order details in natural language>\n\n###\n\nCustomer: <message1>\nAgent: <response1>\nCustomer: <message2>\nAgent: <response2>\nCustomer: <message3>\nAgent:", "completion":" <response3>\n"}
```

promptの冒頭には「Summary」と「Specific information”
」が入っており、区切り文字(###)の後に、CustomerとAgentの会話が続いています。そして、promptの末尾は「Agent:」となっており、completionでAgentの返答を予測する構成になっています。

promptに前の会話も渡すことで、会話の文脈も考慮できるということだと思います。

そこで、以下のように訓練データを改善してみようと思います。
```
{
    "prompt": "概要:オカンが好きな朝ごはんを忘れてしまったので、駒場と内海が一緒に忘れてしまった朝ごはんは何かを考える。\n\n###\n\n内海:朝ごはんの名前を忘れてもうて、どうなってんねんそれ\n駒場:いろいろ聞くんやけどな、全然わからへんのよな\n内海:",
    "completion": "わからへんの？ほな俺がね、オカンの好きな朝ご飯？ちょっと一緒に考えてあげるから、どんな特徴言うてたか教えてみてよ"
  },
  {
    "prompt": "概要:オカンが好きな朝ごはんを忘れてしまったので、駒場と内海が一緒に忘れてしまった朝ごはんは何かを考える。\n\n###\n\n内海:朝ごはんの名前を忘れてもうて、どうなってんねんそれ\n駒場:いろいろ聞くんやけどな、全然わからへんのよな\n内海:わからへんの？ほな俺がね、オカンの好きな朝ご飯？ちょっと一緒に考えてあげるから、どんな特徴言うてたか教えてみてよ\n駒場:甘くてカリカリしてて、牛乳とかかけて食べるやつやって…\n内海:",
    "completion": "ほー、コーンフレークやないかい。"
  }
```
会話の流れを含めてprompt内に記載します。promptの末尾は「内海:」で終わらせて、completionで内海さんの発言を予測します。
また、promptには概要も入れてみました。(要約できているのか謎ですが…)

## 訓練データ作成
今回も[ひまぷっち | Marvelous Macho Making](https://himapucchi.com/) 様のサイトからデータを拝借します。
[【M-1グランプリ2019】ミルクボーイ「コーンフレーク」漫才ネタ書き起こし | ひまぷっち](https://himapucchi.com/m2019first-milkboy/)
[【M-1グランプリ2019】ミルクボーイ「最中」漫才ネタ書き起こし | ひまぷっち](https://himapucchi.com/m2019final-milkboy/)
[ミルクボーイ 「サイゼ」漫才ネタ書き起こし | ひまぷっち](https://himapucchi.com/milkboy-02/)

今回は手動でデータ生成するのが大変そうだったので、ページの情報をクローリングして、自動でデータセットを作成してみました。
こちらがコードです。(導入部分がうまく取れていないのはご愛嬌😆)
[gpt-3/create-dataset.ipynb at main · junichiro-watanabe/gpt-3 · GitHub](https://github.com/junichiro-watanabe/gpt-3/blob/main/milk-boy/create-dataset.ipynb)

## ファインチューニング
あとは[ミルクボーイのネタでGPT-3をファインチューニングしてみた (1) ~入門編~ - Qiita](https://qiita.com/j-wt/items/41196237d234dba7660f#%E3%83%95%E3%82%A1%E3%82%A4%E3%83%B3%E3%83%81%E3%83%A5%E3%83%BC%E3%83%8B%E3%83%B3%E3%82%B0) と同じ手順でファインチューニングします。

今回は20分くらいかかりました。
さすがに時間がかかりすぎたのか、途中で以下メッセージが表示されました。
```
Stream interrupted (client disconnected).
To resume the stream, run:

  openai api fine_tunes.follow -i ft-33996CaGKZdCMknLUpbkonnW
```
指示通りにコマンドを実行すれば、問題なく進捗が確認できたので問題なかったです。

あとコストが結構高かったです。
```
[2023-01-28 07:11:05] Fine-tune costs $11.51
```
free trial分のほとんど持っていかれました笑

## 試してみる
前回はCLIから確認しましたが、今回はプレイグラウンドから確認してみます。
[OpenAI API](https://beta.openai.com/playground)

プレイグラウンドでファインチューニングしたモデルが選べるので、これを選択します。
![スクリーンショット 2023-01-28 8.15.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626975/b997a3c6-4b7a-ef1a-cc1d-d9159b440ef5.png)


Stop sequenceには改行を指定します。
![12AB0EFF-C50B-4096-9A41-D46EB0021D8E.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626975/040478b4-089a-4459-50a7-a7a481b9821f.png)
![](12AB0EFF-C50B-4096-9A41-D46EB0021D8E.png)

ハイライトになっている部分が自動生成された部分です。
![CC28668D-87C4-41ED-A9DF-1680FE75716E.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626975/4e2d1a9f-7ac5-fd74-a555-16081ba4695c.png)
会話になっている…？？

ただ、上記は訓練データを再現できているということだけなので、次は未知のデータを入れてみます。
オカンが飲み物を忘れたということでやってみました。
![9337E830-567A-4793-B442-1A914520D4E5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626975/444c4c17-35c2-2f2b-f111-197d364e6031.png)
厳しそうです笑

他にも色々試してみて、テンプレ的な部分はいい感じで応答してくれてますが、やはり未知データへの対応が全然できていません。

ちなみに公式ドキュメントには


>This use case will require a few thousand examples, as it will likely deal with different types of requests, and customer issues.


と記載があるので、恐らく全然データ数が足りていません笑 
今回は150くらいなので、あと10倍くらい必要そうです。(コストも10倍かかる…)

ただ、前回よりは会話になっている気がしますし、文脈を考慮したい場合のファインチューニング方法を知れてよかったです。

何か間違っている部分があればご教示いただけたら幸いです。

#Qiita