Supershipの名畑です。今期アニメのマイホームヒーローは毎週胃がキリキリするのに続きを見ずにいられない。
はじめに
前回の記事「OpenAI APIでGPT-3にFine-tuningでアニメの放送開始日時を学習してもらうPython実装の記録」ではOpenAI Fine-tunes
APIを用いて英語によるFine-tuningについて記載しました。
今回は日本語においてFine-tuningを行い、前回同様にぼっち・ざ・ろっく!の放送開始日時をGPT-3に学習してもらいます。記事の一部は前回の記事同様です。
アカウントの作成やAPI Keyのセットなどについては前々回の記事「OpenAIのChat API(Chat completions)を用いての会話をPythonで実装してみた記録」をご参照ください。
この記事でやろうとしていることを実現したいだけなら「GPT-3.5のモデルに対して元情報を含めた上で質問」をした方がより精度が高い回答が得られるし安価です。
本記事は「Fine-tuningを試す」という目的のためのものであることをご認識ください。
Fine-tuning
新たな学習データを用意して、既存のモデルの調整を行うというものです。
公式に丁寧な説明があります。
「学習データの用意」「学習データのアップロード」「学習」「生成されたモデルの使用」これらの段階を踏んでいきます。
また、Guidesに下記の記載があるので、Chat APIではなくCompletions APIを用います。
You can start making requests by passing the model name as the model parameter of a completion request
Fine-tuningの料金
Pricngのページに記載されています。学習と使用のそれぞれで料金がかかるのでご注意ください。
現時点での料金は下記です。modelによってコストの桁が変わるのでご注意を。
Model | Training | Usage |
---|---|---|
Ada | $0.0004 / 1K tokens | $0.0016 / 1K tokens |
Babbage | $0.0006 / 1K tokens | $0.0024 / 1K tokens |
Curie | $0.0030 / 1K tokens | $0.0120 / 1K tokens |
Davinci | $0.0300 / 1K tokens | $0.1200 / 1K tokens |
今回の対象モデル
今回は既存のモデルとしてtext-curie-001を選んでみました。
Fine-tunes APIは下記の通りGPT-3ベースであるdavinci、curie、ada、babbageの4つにのみ今は対応しています。
These models were superceded by the more powerful GPT-3.5 generation models. However, the original GPT-3 base models (davinci, curie, ada, and babbage) are current the only models that are available to fine-tune.
学習対象選定理由
ぼっち・ざ・ろっく!の放送開始日を選んだ理由は下記です。
- text-curie-001の学習データがUp to Oct 2019である(詳しくはmodelsのGPT-3の説明を参照)
- ぼっち・ざ・ろっく!の放送開始日は2022年10月8日のため、text-curie-001にその情報が含まれないはず
- つまり学習が反映されたことが判断しやすいはず
学習データの用意
下記が公式に展開されている学習データのフォーマット例です。jsonl形式です。改行区切りされたjsonです。
{"prompt": "<prompt text>", "completion": "<ideal generated text>"}
{"prompt": "<prompt text>", "completion": "<ideal generated text>"}
{"prompt": "<prompt text>", "completion": "<ideal generated text>"}
...
つまりpromptとcompletionを対にしたサンプルを用意する必要があります。
学習データについてはData formattingを見ると下記のように書かれています。
- Each prompt should end with a fixed separator to inform the model when the prompt ends and the completion begins. A simple separator which generally works well is \n\n###\n\n. The separator should not appear elsewhere in any prompt.
- Each completion should start with a whitespace due to our tokenization, which tokenizes most words with a preceding whitespace.
- Each completion should end with a fixed stop sequence to inform the model when the completion ends. A stop sequence could be \n, ###, or any other token that does not appear in any completion.
- For inference, you should format your prompts in the same way as you did when creating the training dataset, including the same separator. Also specify the same stop sequence to properly truncate the completion.
つまりは、promptの最後には(prompt内で他に使われていない)セパレーターをつけること、completionはスペースで始めること、completionの最後には(completion内で他に使われていない)終わりを示す記号をつけること。
どうやって学習データを用意した?
人力で用意するのはややしんどいため、下記の手順を踏むことにしました。
- ぼっち・ざ・ろっく!の放送開始日時をまとめたテキストを用意する
- そのテキストを元にしてOpenAI Chat APIに質問と回答を生成してもらう
まず、用意した原文は下記です。origin_messageという変数に格納しておきました。だいたいは公式サイトのONAIRのページの情報そのままです。
origin_message = """【タイトル】
TVアニメ「ぼっち・ざ・ろっく!」のオンエアスケジュール
【TVでの放送スケジュール】
※放送日時は変更になる場合がございます。
放送局 放送開始日 放送時間
TOKYO MX 2022/10/8(土) 24:00〜
BS11 2022/10/8(土) 24:00〜
群馬テレビ 2022/10/8(土) 24:00〜
とちぎテレビ 2022/10/8(土) 24:00〜
MBS 2022/10/8(土) 27:08〜
RKB毎日放送 2022/10/13(木) 27:00〜
MRT宮崎放送 2022/10/8(土) 25:28〜
AT-X 2022/10/10(月) 22:30~
TVアニメ「ぼっち・ざ・ろっく!」の配信スケジュールです
【ストリーミングでの配信スケジュール】
※配信日時は変更になる場合がございます。
プラットフォーム 配信開始日 配信時間
ABEMA 2022/10/8(土) 毎週土曜日24:00~
※地上波同時配信
Netflix 2022/10/11(火) 毎週火曜日12:00~
dアニメストア 2022/10/11(火) 毎週火曜日12:00~
dアニメストア
for Prime Video 2022/10/11(火) 毎週火曜日12:00~
dアニメストア
ニコニコ支店 2022/10/11(火) 毎週火曜日12:00~
U-NEXT 2022/10/11(火) 毎週火曜日12:00~
アニメ放題 2022/10/11(火) 毎週火曜日12:00~
Amazon Prime Video 2022/10/11(火) 毎週火曜日12:00~
バンダイチャンネル 2022/10/11(火) 毎週火曜日12:00~
Hulu 2022/10/11(火) 毎週火曜日12:00~
ひかりTV 2022/10/11(火) 毎週火曜日12:00~
FOD 2022/10/11(火) 毎週火曜日12:00~
GYAO! 2022/10/11(火) 毎週火曜日12:00~
ニコニコチャンネル 2022/10/11(火) 毎週火曜日12:00~
ニコニコ生放送 2022/10/11(火) 毎週火曜日22:30〜
WOWOWオンデマンド 2022/10/11(火) 毎週火曜日12:00~
TELASA 2022/10/11(火) 毎週火曜日24:00~
JCOM:オンデマンド 2022/10/11(火) 毎週火曜日24:00~
みるプラス-見放題パック 2022/10/11(火) 毎週火曜日24:00~
auスマートパスプレミアム 2022/10/11(火) 毎週火曜日24:00~
Video Market 2022/10/11(火) 毎週火曜日12:00~
music.jp 2022/10/11(火) 毎週火曜日12:00~
GYAO!ストア 2022/10/11(火) 毎週火曜日12:00~
"""
質問と回答を生成したコードは下記です。
質問と回答を20組生成させています。これを5回やれば100個です。指示が悪いのか20組返してくれないこともありましたが。
import os
import openai
openai.api_key = os.getenv("OPENAI_API_KEY")
messages = [{"role": "user", "content": """Write 20 sets of a question and an answer in Japanese using the text below.
Desired format:
Questions
* <question 1>
* <question 2>
...
* <question 19>
* <question 20>
Answers
* <answer 1>
* <answer 2>
...
* <answer 19>
* <answer 20>
Design rules:
・Don't use leading numbers
Text: """ + origin_message}
]
completion = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=messages
)
# 応答の取得 / 表示
res_message = completion["choices"][0]["message"]["content"]
print(res_message)
フォーマットは私が扱いやすい形にしています。
プロンプトの書き方はBest practices for prompt engineering with OpenAI APIがかなり参考になりました。
コードを実行した結果例は下記。
Questions
* 「ぼっち・ざ・ろっく!」はどのTV局で放送されますか?
* 放送開始日はいつですか?
* 放送時間は何時から何時までですか?
<省略>
Answers
* TOKYO MX、BS11、群馬テレビ、とちぎテレビ、MRT宮崎放送など、複数のTV局で放送されます。
* 放送開始日は2022年10月8日(土)です。
* 放送時間は、TOKYO MX、BS11、群馬テレビ、とちぎテレビ、MRT宮崎放送での放送は24:00〜、MBSでの放送は27:08〜、RKB毎日放送での放送は27:00〜です。
<省略>
MRT宮崎での放送開始日時は25:28なので、間違ってしまっていますね。今回は学習されたということがわかればいいという割り切りで、一つ一つのデータの正否については追求せずこのまま進めます。本当はよくないです。当然、学習データの品質が結果に影響するため。
得られた結果を編集してjsonlファイルを作成します。
質問をpromptとして、回答をcompletionとして扱いました。
ガイドに基づきpromptの末尾に\n\n###\n\nをつけることと、completionの先頭にスペースを入れることと、completionの末尾に###をつけることもしました。
{"prompt": "「ぼっち・ざ・ろっく!」はどのTV局で放送されますか?\n\n###\n\n", "completion": " TOKYO MX、BS11、群馬テレビ、とちぎテレビ、MRT宮崎放送など、複数のTV局で放送されます。###"}
{"prompt": "放送開始日はいつですか?\n\n###\n\n", "completion": " 放送開始日は2022年10月8日(土)です。###"}
{"prompt": "放送時間は何時から何時までですか?\n\n###\n\n", "completion": " 放送時間は、TOKYO MX、BS11、群馬テレビ、とちぎテレビ、MRT宮崎放送での放送は24:00〜、MBSでの放送は27:08〜、RKB毎日放送での放送は27:00〜です。###"}
<以下略>
学習用データのアップロード
FilesのAPi refernceにやり方が載っています。
私の場合は学習用データをorigin_data.jsonlというファイル名で保存して、下記のコードを実行しました。
import os
import openai
openai.api_key = os.getenv("OPENAI_API_KEY")
response = openai.File.create(
file=open("origin_data.jsonl", "rb"),
purpose='fine-tune'
)
print(response)
purposeにfine-tuneを指定することを忘れないようにご注意下さい。
下記のようなレスポンスが返ってきます。このうちのidをFine-tuningで使います。
{
"bytes": 20177,
"created_at": 1683277820,
"filename": "file",
"id": "file-hogehogehogehogehoge",
"object": "file",
"purpose": "fine-tune",
"status": "uploaded",
"status_details": null
}
Fine-tuningの実施
これもコードは非常にシンプルです。
import os
import openai
openai.api_key = os.getenv("OPENAI_API_KEY")
response = openai.FineTune.create(
training_file="file-hogehogehogehogehoge",
)
print(response)
training_fileにさきほどアップロードしたファイルのIDを記載します。
recuiredではないですが、Fine-tuningで使われるモデルをmodelとして指定することも可能です。書かない場合はデフォルト値であるcurieが用いられます。また、すでにFine-tuning済みのモデルを元にすることもできます。
この際のレスポンスに下記のようにidの記載があります。
"id": "ft-hogehogehogehogehoge",
Fine-tuningは即時完了はしないため、しばらく待ちます。私がやったときは10分足らずでしたが、キューイングされるようなので、その時にどれだけFine-tuningが行われているかという状況や、あと、学習データの量にも待ち時間は左右されるかとは思います。
状況確認やキャンセルのためには上記のidを使います。
状況確認はretrieveで行います。
import os
import openai
openai.api_key = os.getenv("OPENAI_API_KEY")
response = openai.FineTune.retrieve(id="ft-hogehogehogehogehoge")
print(response)
レスポンスのeventsという要素の配列に発生したイベント履歴が記されます(今どこまで進んでいるかなど)。
コストもそこに下記のように書かれています。
{
"created_at": 1683342896,
"level": "info",
"message": "Fine-tune costs $0.05",
"object": "fine-tune-event"
},
完了時は下記。
{
"created_at": 1683343651,
"level": "info",
"message": "Fine-tune succeeded",
"object": "fine-tune-event"
}
完了するとretrieveのレスポンスにfine-tuningがされたモデル名が記載されています(完了前はnull)。
"fine_tuned_model": "curie:ft-personal-2023-05-06-03-27-30",
これで準備完了です。
また、Analyzing your fine-tuned model
に書かれている通り、学習結果のダウンロードも可能ですので、よければご覧ください。ファイル名は下記のようにeventsに記載されています。
{
"created_at": 1683343651,
"level": "info",
"message": "Uploaded result file: file-fugafugafuga",
"object": "fine-tune-event"
}
ダウンロードするコードは下記です。
import os
import openai
openai.api_key = os.getenv("OPENAI_API_KEY")
response = openai.File.download(id="file-fugafugafuga")
print(response)
モデル呼び出しのコード
modelにさきほどのモデル名を指名して「TVアニメ ぼっち・ざ・ろっく!の配信開始日を教えてください」と投げるコードは下記です。
学習データ同様にpromptの末尾に\n\n###\n\nをつけて、stopに###を指定しています(###が登場したなら終了として扱う)。
import os
import openai
openai.api_key = os.getenv("OPENAI_API_KEY")
completion = openai.Completion.create(
model="curie:ft-personal-2023-05-06-03-27-30",
prompt="TVアニメ ぼっち・ざ・ろっく!の配信開始日を教えてください\n\n###\n\n",
max_tokens=300,
stop="###"
)
print(completion["choices"][0]["text"])
結果
以降、結果です。
いくつかの質問に対して
- Fine-tuningをしていないtext-curie-001
- 1に対して100個のデータでFine-tuningをしたモデル
- 2に対してさらに100個のデータでFine-tuningをしたモデル(つまりは合計200個)
- 3に対してさらに200個のデータでFine-tuningをしたモデル(つまりは合計400個)
- 4に対してさらに400個のデータでFine-tuningをしたモデル(つまりは合計800個)
の回答をそれぞれ5つずつ取得しました。
5回連続して呼び出して、その結果をそのまま貼っています。
ただし、文頭の改行とスペースだけは削除しています。
質問1
質問文
- TVアニメ ぼっち・ざ・ろっく!の配信開始日を教えてください
正解
- 2022年10月8日(土)
text-curie-001の回答
- The anime "Boku no Hero Academia" will be streaming on Netflix from September 15.
- 2013年2月27日
アニメ「ぼっち・ざ・ろっく!」の配信開始日を教えてください。 - こちらの記事にて、豊作の漫画アニメ 「ぼっち・ざ・ろっく!」の配信開始日が決定しています。
公式サイトより、4月21日に配信開始が決定しています。是非、ご覧ください。 - 2017/03/07
- 配信開始日は2014年5月15日です。
100データでFine-tuningをしたモデルの回答
- プラットフォームによって異なりますが、TVアニメ ぼっち・ざ・ろっく!の配信開始日は、一部に重要な場面や特別なストーリーが含まれるために開始される場合があります。
- ヨーダの配信開始日は、毎週火曜日です。
- TVアニメ ぼっち・ざ・ろっく!の配信開始日は、開始日がありますか?
- 「ボット・ア・ウエア」のアニメ配信開始日は、TVアニメ ぼっち・ざ・ろっく!の配信開始日は、
- TVアニメ ぼっち・ざ・ろっく!の配信開始日は、ABEMA、Netflix、dアニメストア、U-NEXT、JCOM、M demoneta's、Huluなどで配信されます。
200データでFine-tuningをしたモデルの回答
- TVアニメ ぼっち・ざ・ろっく!の配信開始日は2022年10月8日(土)です。
- サマーステージを含め、配信開始日が異なる場合があります。
- 「ぼっち・ざ・ろっく!」の配信開始日は、2022年10月8日(土)からです。
- プラットフォームによって異なりますが、基本的には月曜日12:00〜からです。
- アニメイト、Netflix、dアニメストアなどのプラットフォームで配信がなされます。
400データでFine-tuningをしたモデル の回答
- TVアニメ ぼっち・ざ・ろっく!の配信開始日を教えてくださいこちらです。
- TVアニメ ぼっち・ざ・ろっく!の配信開始日を教えてくださいです。
- 後で見るより速く配信される場合がありますので、配信開始日を教えてください。
- TVアニメ ぼっち・ざ・ろっく!の配信開始日を教えてください TVアニメ ぼっち・ざ・ろっく!の配信開始日を教えてくださいです。
- TVアニメ ぼっち・ざ・ろっく!の配信開始日を教えてください
800データでFine-tuningをしたモデルの回答
- TVアニメ ぼっち・ざ・ろっく!の配信開始日は2022年10月8日です。
- TVアニメ ぼっち・ざ・ろっく!の配信開始日は2022年10月8日です。
- TVアニメ ぼっち・ざ・ろっく!の配信開始日は2022年10月8日です。
- TVアニメ ぼっち・ざ・ろっく!の配信開始日は2022年10月8日です。
- TVアニメ ぼっち・ざ・ろっく!の配信開始日は2022年10月8日です。
質問2
質問文
- ぼっち・ざ・ろっく!はTELASAで毎週配信されますか?
正解
- 2022/10/11(火) 毎週火曜日24:00~
text-curie-001の回答
- Yes, TELASA airs Weekly!
- はい、毎週配信されます。是非、ご覧ください。
- Yes, TELASA regularly broadcasts ASUS ROG STRIKE edition.
- TELASAで毎週配信されます。
- Yes, TELASA airs the show every week.
100データでFine-tuningをしたモデルの回答
- はい、TELASAで毎週配信されます。
- はい、TELASAで毎週配信されます。
- はい、TELASAで毎週配信されます。
- はい、telasaで配信されます。
- 、ユニバーサルミックスで毎週配信されます。
200データでFine-tuningをしたモデルの回答
- はい、TELASAで毎週配信されます。
- はい、TELASAで毎週配信されます。
- はい、TELASAで毎週配信されます。
- はい、TELASAで毎週配信されます。
- はい、TELASAで毎週配信されます。
400データでFine-tuningをしたモデル の回答
- はい、TELASAで毎週配信されます。
- はい、TELASAで毎週配信されます。
- はい、TELASAで毎週配信されます。
- はい、TELASAで毎週配信されます。
- はい、TELASAで毎週配信されます。
800データでFine-tuningをしたモデルの回答
- ぼっち・ざ・ろっく!はTELASAで毎週火曜日24:00から配信されます。
- ぼっち・ざ・ろっく!はTELASAで毎週火曜日24:00〜配信されます。
- ぼっち・ざ・ろっく!はTELASAで毎週火曜日24:00〜配信されます。
- ぼっち・ざ・ろっく!はTELASAで毎週火曜日24:00〜配信されます。
- ぼっち・ざ・ろっく!はTELASAで毎週火曜日24:00〜配信されます。
質問3
質問文
- ぼっち・ざ・ろっく!はアニメ放題でいつから配信されますか?
正解
- 2022/10/11(火) 毎週火曜日12:00~
text-curie-001の回答
- 当サイトではアニメ放題というコンテンツの
配信を始めています。
ぜひともご覧下さい。 - 配信初日は2012年4月4日、放題は2012年4月25日まで。
- アニメ放題は2018年1月1日から配信されています。
- ざ・ろっく!はアニメ放題のため、いつまでか配信されます。
- 配信はいつでもいいです。アニメ放題は日本全国各地で配信中です。
100データでFine-tuningをしたモデルの回答
- 料理が上手になった時間に配信されます。
- ぼっち・ざ・ろっく!は、ABEMAおよびNetflixで配信されます。
- ぼっち・ざ・ろっく!は、2016年10月11日(火)から配信が始まります。
- dobocetぼっち・ざ・ろっく!は、アニメ放題で配信されます。
- ぼっち・ざ・ろっく!は、ABEMAが配信する邦画放題作品の一部です。
200データでFine-tuningをしたモデルの回答
- ABEMA、Netflix、dアニメストア、Amazon Prime Video、などでいつから配信されます。
- アニメ放題では、2022年10月8日(土)から配信されます。
- dぼっち・ざ・ろっく!は、アニメ放題でいつから配信されますか?
- アニメ放題では、2022年10月8日(土)から配信されます。
- はじめには、2022年10月8日(土)から配信されます。
400データでFine-tuningをしたモデルの回答
- は
- は予定されています。詳しくは各サービスの公式く RSS ページで確認してください。
- はじめには、アニメ放題での配信予定や毎週火曜日の全話の前日の12時から配信されます。
- はぼっち・ざ・ろっく!はアニメ放題でいつから配信されますか?
- はアニメ放題でいつから配信されますか、ANS:「ぼっち・ざ・ろっく!」はアニメ放題での配信を予定しています。
800データでFine-tuningをしたモデルの回答
- ぼっち・ざ・ろっく!はアニメ放題で毎週火曜日12:00から配信されます。
- ぼっち・ざ・ろっく!はアニメ放題で毎週火曜日12:00から配信されます。
- ぼっち・ざ・ろっく!はアニメ放題で毎週火曜日12:00から配信されます。
- ぼっち・ざ・ろっく!はアニメ放題で毎週火曜日12:00から配信されます。
- ぼっち・ざ・ろっく!はアニメ放題で毎週火曜日12:00から配信されます。
最後に
- 学習を重ねるほどに回答の揺らぎが減じているように見える
- 学習を重ねるほどに自然な回答になっているように見える
- 英語に比べると自然な回答のための学習に必要なデータが多いように見える
という感じでした。
- 学習データの内容を精査していない
- 試行回数が少ない
- 質問パターンが少ない
という前提ではありますが、英語の時と同じく、学習は反映されていそうです。
宣伝
SupershipのQiita Organizationを合わせてご覧いただけますと嬉しいです。他のメンバーの記事も多数あります。
Supershipではプロダクト開発やサービス開発に関わる方を絶賛募集しております。
興味がある方はSupership株式会社 採用サイトよりご確認ください。