完成品
このように、テーマを入力すると、それに合わせた川柳を詠んでくれるAIです。
データ収集
川柳のデータを5000件ほど集めました。
テーマと川柳が対応付くようにしておきます。読みやすいように五七五で空白を入れておきます。
実際に集めたデータは以下のようになっています。1行目はテーマです。
コロナ明け
コロナ明け 歩く体力 落ちている
マスクなし 花粉で再び マスクつけ
マスクなし 人ごみ慣れず 逃げる足
これを1つのファイルとして、dataフォルダにまとめて入れておきます。
データフォーマット
dataフォルダの中身を、GPT3.5で学習させるためのフォーマットに整形します。
Node.jsのコードは以下の通りです。
const fs = require("fs");
const path = require("path");
let jsonl = "";
// ディレクトリ内のすべてのファイルを取得
const files = fs.readdirSync("data");
files.forEach((file) => {
const filePath = path.join("data", file);
// ファイルの内容を読み込む
const content = fs.readFileSync(filePath, "utf-8");
// 行に分割
const lines = content.split("\n");
// 1行目をodaiに、2行目以降をsenryuに設定
const odai = lines[0];
const senryu = lines.slice(1);
for (let i = 0; i < lines.length; i++) {
if (senryu[i] === "") return;
const jsonlContent = {
messages: [
{
role: "system",
content:
"あなたは川柳を詠むAIです。五七五(〇〇〇〇〇 〇〇〇〇〇〇〇 〇〇〇〇〇)で回答します。",
},
{ role: "user", content: "お題: " + odai },
{ role: "assistant", content: senryu[i] },
],
};
jsonl += JSON.stringify(jsonlContent) + "\n";
}
});
// JSONLファイルを書き出す
fs.writeFileSync("training_data.jsonl", jsonl);
最終的にtraining_data.jsonl
の中身は以下のようなデータになります。
{"messages":[{"role":"system","content":"あなたは川柳を詠むAIです。五七五(〇〇〇〇〇 〇〇〇〇〇〇〇 〇〇〇〇〇)で回答します。"},{"role":"user","content":"お題: コロナ明け"},{"role":"assistant","content":"コロナ明け 歩く体力 落ちている"}]}
{"messages":[{"role":"system","content":"あなたは川柳を詠むAIです。五七五(〇〇〇〇〇 〇〇〇〇〇〇〇 〇〇〇〇〇)で回答します。"},{"role":"user","content":"お題: コロナ明け"},{"role":"assistant","content":"マスクなし 花粉で再び マスクつけ"}]}
{"messages":[{"role":"system","content":"あなたは川柳を詠むAIです。五七五(〇〇〇〇〇 〇〇〇〇〇〇〇 〇〇〇〇〇)で回答します。"},{"role":"user","content":"お題: コロナ明け"},{"role":"assistant","content":"マスクなし 人ごみ慣れず 逃げる足"}]}
ファインチューニングの実行
Google Colaboratoryで以下のコードを実行していきます。
!pip install -q openai
次に、OpenAIに学習データをアップロードします。api_key
はご自身のものに書き換えてください。
from openai import OpenAI
client = OpenAI(api_key="sk-***********************")
client.files.create(
file=open("/content/training_data.jsonl", "rb"),
purpose="fine-tune"
)
上記のコードを実行するとfileId
が表示されます。fileId
を書き換えて以下のコードを実行します。
client.fine_tuning.jobs.create(
training_file="file-*****************",
model="gpt-3.5-turbo",
hyperparameters={
"n_epochs":3
}
)
1時間ほどで学習は完了します。
かかったファインチューニングの料金
5000行ほどのデータでかかったのは$13.16でした。1ドル=155円として日本円に換算すると2040円かかりました。
APIからファインチューニングしたモデルにアクセスする
TypeScriptのコードは以下の通りです。
import OpenAI from "openai";
import * as dotenv from "dotenv";
dotenv.config();
const openai = new OpenAI({
apiKey: process.env["OPENAI_API_KEY"]
});
export async function callSenryu(content: string) {
const response = await openai.chat.completions.create({
model: "ft:gpt-3.5-turbo-0125:personal::********",//変える
max_tokens: 50,
temperature: 0.2,
messages: [
{
role: "system",
content:
"川柳を読んでください。川柳とは五・七・五の音を持つ日本語の定型詩です。言葉遊びやダジャレを含めてください。例えば、「コロナ明け 歩く体力 落ちている」などです。"
},
{
role: "user",
content: content
}
]
});
return response.choices[0]?.message?.content;
}
callSenryu("春").then(console.log);
Teamsで川柳ボットを作成する
Copilot Studioを使用してAPIを呼び出しました。Copilot Studioは簡単にTeamsとも接続できるので便利です。手順はこちらに書いています。
精度の評価
川柳っぽく五七五に似せて出力はできているものの、リズムが良くなかったり、字余り・字足らずだったり。欲を言えば、言葉遊びやダジャレを入れてもらいたいものですが、そこまではできませんでした。
まとめ
GPT3.5のファインチューニングを使って川柳AIを作ってみました。
データさえ集まればお手頃価格で作れるので、ぜひ皆さんも作ってみてください。