gpt-3.5-turboをオリジナル小説でファインチューニングしてみた
先日、rinna-3.6Bをファインチューニングしてみた記事を書きましたが、今回は8月23日に解禁されたOpenAIのgpt-3.5-turboのファインチューニングを実施して、使えそうかどうか試してみます。
方法
今回もnpaka先生が公開されている記事をありがたく参考にさせていただきました。詳しいコードなどはそちらを参照してください。
jsonlファイルの作成部分は、前回の私の記事のコードを少しだけ改変しました。小説中の5行を入力として、続きの5行を出力するように整形しています。
import pandas as pd
import json
# 読み込み
with open(input_text_file_path, encoding='utf8') as f:
raw_text_lines = f.readlines()
# 空行を削除
text_lines = []
for line in raw_text_lines:
if line != "\n":
text_lines.append(line)
# print(raw_text_lines[10])
print("len(text_lines): ", len(text_lines))
result = []
instruction_text = ""
output_text = ""
instruction_num = 5 # 入力する小説の行数
output_num = 5 # 出力する小説の行数
multiline_num = instruction_num + output_num
instruction_count = 0
instruction_flg = True
system_prompt = "あなたは作家として、入力された小説の本文に対して、小説の続きの文章を執筆します。"
for i in range(len(text_lines)):
if i % multiline_num == 0 and i != 0:
formatted = {"messages":[{"role": "system","content": system_prompt},{"role": "user","content": instruction_text},{"role": "assistant","content": output_text}]}
result.append(formatted)
instruction_text = ""
output_text = ""
instruction_flg = True
instruction_text += text_lines[i]
else:
if instruction_flg:
instruction_count += 1
instruction_text += text_lines[i]
if instruction_count == instruction_num-1:
instruction_flg = False
instruction_count = 0
else:
output_text += text_lines[i]
print("len(result): ", len(result))
print(result[5])
with open(jsonl_file_path, 'w', encoding='utf-8') as f:
for item in result:
json.dump(item, f, ensure_ascii=False)
f.write("\n")
文字数は約16万字。検証時に表示されたトークン数は、640686 tokensでした。fine-tuningの値段は $0.0080 / 1K tokensなので、かかったのは750円くらいかなと思います。
ちゃんと時間を測っていませんが、完了のメールが来るまで大体30分くらいだったと思います。
結果
とりあえず学習に使った小説の一場面を入力に使いました。
テーブルの上にはスクランブルエッグとベーコンにサラダ。そこにハルが焼きたてのトーストを差し出す。もちろんマーガリンは既に塗ってある。ペトラはそれに齧りつき、続いてコーヒーを喉に通す。彼女が一息ついたところを見計らって、ハルは尋ねた。
「今日の夕飯はどうする?」
「んー、決めてないけど」
「早く決めてくれると助かるんだが」
皿洗いを終えたハルの指が、カレンダーを指差す。
実際の次の場面は以下。
「あ、クリスマスか」
「仕事で忙しいから料理を作ってる時間は無いけど、もしペトラがいるならスイーツを買ってこようかと」
「いいね、大賛成! ぜひお願いします!」
どうやらすっかり目が覚めたようだ。
「何がいい? 出来る限りリクエストには答えるけど」
出力は以下。temperature = 0.5。同じ入力で3回繰り返しています。
「あぁ、今週は私の買出しの日がないから、週末の買出しになりそうね」
「そうか。じゃあ今週の夕飯は外食かな」
「でも外食は健康的じゃないし」
「そうだな。じゃあ、今日の夕飯はハンバーグにしようか」
「ハンバーグ? 今日は土曜日じゃないの?」
「まぁ、そうだけど。いつもと違うことをやるのも悪くはないだろう?」
==============================
「あ、そうだった。今日は食材を買いに行かないと」
「えー、面倒くさいなぁ」
「じゃあ、お前が作ってやるか?」
「えー、面倒くさいなぁ」
「面倒くさいなぁ、じゃあさぁ」
ハルは、ペトラの耳元で何かを囁いた。
==============================
「えっと、今日は……」
本当はハルは今日の日付を分かっていた。それは昨日の夜、ハルが帰ってきた時にペトラが「明日は何日だっけ?」と聞いてきたからだ。しかし脇の甘いことをしたくないハルは、念のためにペトラにも確認を取っておいたのだ。
「そうか、今日は……」
ペトラの頭の中では、あの時のやり取りが繰り返されていた。
比較用に、gpt-3.5-turboでも同条件で3回出力しました。
「あ、そうだ!今日はあの新しいイタリアンレストランに行ってみるのはどう?」ハルは提案した。
ペトラは興味津々の表情で頷いた。「いいアイデアだね!あのレストランの評判は良いみたいだし、新しい料理を試してみたい気分だよ。」
二人はテーブルの片付けを済ませ、外に出る準備を始めた。ハルは車の鍵を取りに行き、ペトラはバッグに必要なものを詰め込んだ。
しばらくして、二人はレストランに到着した。店内は賑やかで、イタリアンの香りが漂っていた。ホステスに案内され、二人はテーブルに座った。
メニューを手に取り、二人は興味津々で料理を選んでいった。ハルはピザを、ペトラはパスタを注文した。待つ間、二人は楽しい会話で時間を過ごした。
やがて料理が運ばれてきた。見た目も美しく、香りも豊かな料理に二人は舌鼓を打った。ハルはピザのチーズを引き伸ばし、ペトラはパスタのアルデンテ具合を楽しんだ。
「このレストラン、本当に素晴らしいね。料理も美味しいし、雰囲気も良いし。ありがとう、ハル」とペトラは微笑みながら言った。
ハルも満足そうに頷いた。「いい選択だったね。一緒に美味しいものを食べる時間は、いつも特別なんだ。」
二人はゆっくりと食事を楽しみ、笑顔で会話を続けた。小説の続きは、この二人が新しいレストランでの食事を通じて、さらに深い絆を築いていく様子を描いていくのかもしれない。
==============================
「あ、そうだ。今日ってジェイクの誕生日だったよね」とペトラが言った。
ハルは思い出し、顔を明るくした。「そうだった!ジェイクはいつも美味しいものが好きだから、特別な夕飯を作ろうよ。彼が喜ぶ料理を考えてみよう」
二人はテーブルに座り、頭を抱えて考え始めた。ハルはレシピ本を取り出し、ペトラは冷蔵庫を開けて中身を確認した。
「どう思う?ステーキとローストポテトはいかが?」ハルが提案した。
ペトラは考え込んだ後、うなずいた。「いいね!それにサイドディッシュとして、グリル野菜を添えよう。ジェイクは野菜も好きだから、喜ぶと思う」
二人はワクワクしながら料理の準備を始めた。ハルはステーキを焼き、ペトラはポテトを切ってオーブンに入れた。香りがキッチンに広がり、食欲をそそった。
「あとはサラダを作れば完成だね」とハルが言った。
ペトラは冷蔵庫から新鮮な野菜を取り出し、洗って切った。彩り豊かなサラダボウルに盛り付け、ドレッシングをかけた。
準備が整ったところで、二人はテーブルに戻った。ジェイクのために特別な夕飯ができたことに満足げな表情を浮かべていた。
「ジェイクが喜んでくれるといいな」とペトラがつぶやいた。
ハルは微笑みながら言った。「きっと喜ぶよ。彼は我々の料理が大好きだから」
二人は楽しみながら、ジェイクの帰りを待った。彼の誕生日を祝う特別な夕飯が、素敵な思い出となることを願いながら。
==============================
「あ、そうだ!今日は新しいレストランがオープンしたって聞いたんだ。行ってみるのはどう?」ハルは興味津々で言った。
ペトラは少し考え込んだ後、にっこり笑って答えた。「いいね、新しいレストランなら楽しみだし、今日は特別な日だからちょっと贅沢してもいいかもしれないね。」
二人はテーブルを片付けながら、新しいレストランの情報を探し始めた。ハルはスマートフォンを手に取り、口々にレビューや口コミをチェックしていく。
「ここ、評判がいいみたいだよ。料理の種類も豊富で、雰囲気も良さそうだし。何か特別な料理を食べたいなら、このレストランがぴったりだよ」とハルが言った。
ペトラはハルの言葉に興味津々でうなずきながら、「じゃあ、そのレストランにしよう。何か予約しなきゃいけない?」と尋ねた。
ハルはスマートフォンで予約ページを開きながら、「うーん、確かに予約した方がいいかもしれないな。特に今日はオープンしたばかりだから、混雑しているかもしれないし」と答えた。
二人は予約を済ませ、準備を整えてレストランに向かった。新しいレストランのドアを開けると、心地よい香りと賑やかな雰囲気が迎えてくれた。
ハルとペトラはウェイターに案内され、席に座った。メニューを手に取りながら、二人はお互いに笑顔を交わした。今日の夕飯は新しい冒険の始まりだった。
考察
gpt-3.5-turboだとレストランに行きたがっていますが、ファインチューニングモデルでは出ていません。入力に使用した小説を確認したところ、「レストラン」という単語は一つも使われていませんでした。出力される内容を、ある程度縛れそうです。
またファインチューニング元のデータと同様に、文章が5行に近い形で出力されました。こうした文章の形式の指定にも使えそうです。
あと、文体もファインチューニング元の小説の文章に近くなっている印象があります。数年前に書いた小説なので今の私の書き方とはちょっと違いますが、少なくとも私は、例として示したgpt-3.5-turboのような文章は書きません。
最後に
高性能なモデルのファインチューニングが容易になり、多くの方がオリジナルのモデルを使える環境が整いつつあると感じます。
興味のある方は、ぜひ今年の第11回日経「星新一賞」に、生成AIを利用した作品を応募してみてはいかがでしょうか。〆切は10月2日。あと約1ヶ月です。
募集要項の「生成AIを利用しての応募について」のところに生成AIを利用して応募する場合の注意事項が記載されているので、こちらをしっかり確認することも忘れずに!
OpenAIのAPIを利用して応募する際には、OpenAIの利用規約も確認しましょう。2023年9月3日現在、OpenAIを利用して生成したコンテンツは商用利用可能となっていますが、更新されることもあるので忘れずにチェック。
それでは。