IBM Cloud から提供されている生成 AI である Watsonx.AI の LLM をチューニングする機会があったので、その内容や手順、そして気になるチューニングのコストなどをまとめました。あくまで一つの例ですが、参考になればと思っています。


【Watsonx.AI の LLM チューニング】
本記事で後述する内容は 2024-09-25 時点のものです。この時点では Watsonx.AI の LLM チューニングはいわゆる「プロンプト・チューニング」のみ可能です。

LLM の基になる非構造テキストデータを大量に再学習、するようなチューニングではなく、あくまで「プロンプトエンジニアリングをベースとしたチューニング」です。詳しくは後述しますが、ベースとなる LLM に対して、入力例と出力例を複数与えてプロンプトに出力の方向性を指示するような改良を LLM に加える、というものです。プロンプトエンジニアリングで与えるサンプル部分のトークン数が多くなって1回の問い合わせコストが高くなってしまうことを防ぐことがメリットとなるものです。


【どんなチューニングをするか】
当然ですが、「チューニング前の LLM では期待した返答にならないような問い合わせ」をチューニングして改良することを試みます。というわけで、まずはチューニング前の granite-13b-instruct-v2 モデルを使って、フリーフォームで以下のプロンプトを試してみました(2024-09-25 時点での試行結果です):

「1 ドルは 140.1 円です。 10 ドルは何円ですか?」
2024092501


このプロンプトに対して「生成」ボタンで問い合わせすると「140.1 円です。」という返答が返ってきました。うーん、価格を問い合わせていることは理解できているようですが、こちらが期待した計算結果にはなっていませんでした:
2024092502


そこで計算方法含めてプロンプトでガイドしてみます。「フリーフォーム」から「構造化」に変えます(この時に LLM モデルが切り替わることがあるので、改めて granite-13b-instruct-v2 モデルを選びます)。そして "例" と書かれた箇所を「新規テスト+」ボタンで行を増やしながら以下のように3行入力します。与えられた情報を使って、答を計算して返答するような例をいくつか指示してみました:
入力出力
11 ドルは 140 円です。 10 ドルは何円ですか?1 ドルが 140 円なので、 10 ドルは約 140 * 10 = 1400 円です。
21 ドルは 140.1 円です。 20 ドルは何円ですか?1 ドルが 140.1 円なので、 20 ドルは約 140.1 * 20 = 2802 円です。
31 ドルは 140.3 円です。 30 ドルは何円ですか?1 ドルが 140.3 円なので、 30 ドルは約 140.3 * 30 = 4209 円です。

2024092503


そして "試行" の入力欄に以下を入力し、テキストを生成させます:
1 ドルは 139.1 円です。 10 ドルは何円ですか?
2024092504


これで「1 ドルが 139.1 円なので、 10 ドルは約 139.1 * 10 = 1391 円です。」と答えてくれることを期待していました。が、結果は・・・ 計算や数値は期待通りなのですが、"Thornton" って何?? ともあれ、数字を計算して答えることや、その計算方法は理解してもらえている・・・と思います:
2024092505


というわけで、この方向で為替計算を教えるような LLM チューニングを試みてみます。


【プロジェクトと Tuning Studio の準備】
改めて、ここからが LLM チューニングの紹介内容です。

まずは LLM チューニングを行うための準備といえる作業をいくつか実行します。その1つが「プロジェクトの準備」です。既に Watsonx.AI のプロジェクトを作成済みの人もいると思いますが、もし環境的に問題なければ新しいプロジェクトを1つ作ってから LLM チューニングを行うことを推奨します(そうすると後述で紹介するチューニングコストを確認しやすいため)。もちろん既存プロジェクトを選択してチューニングしても構いません。

プロジェクトを新規に作成する前に現在の環境で作成されているプロジェクトの一覧を確認します。 Watsonx.AI の画面左上のハンバーガーメニューをクリックします:
2024092506


このメニューから「すべてのプロジェクトの表示」を選択します:
2024092507


現在までに作成されたプロジェクトの一覧が表示されます。ここから1つ選択して、そのプロジェクト内でチューニングを実行することも可能です。 プロジェクトを新規に作成するには右上の「新規プロジェクト」ボタンをクリックします:
2024092508


新規に作成するプロジェクトの情報を入力します。まずはプロジェクトの名前を入力します:
2024092509


このプロジェクトで利用するストレージサービス(Cloud Object Storage)のインスタンスを選択します。1つ選ぶか、新規に作成して指定します。最後に「作成」ボタンが有効化されたら「作成」します:
2024092510


既存プロジェクトを選択した場合はそのプロジェクトが、プロジェクトを新規作成した場合は作成されたプロジェクトが開きます。この画面内でプロジェクト内で使ったリソース量が表示されます。新規作成した場合はこの時点ではゼロになっているので、この後のチューニング作業でどの程度増えているか確認しやすいと思っています:
2024092511



【Tuning Studio によるチューニングの手順】
Watsonx.AI では LLM をチューニングするためのオンラインツール "Tuning Studio" を利用することができます。このオンラインツールを使って、チューニング元の LLM モデルに自分で与えた学習データを使ったチューニングを施した、新しい LLM モデルを作ることができます。

では以下に実際に Tuning Studio を使って LLM をチューニングしていく手順を紹介します。

プロジェクト画面を開きます(作ったばかりなせいか、リソース消費量の表示がおかしくなっています。この時点では実際は全てゼロのはず)。ここから実際にプロンプト問い合わせを実行するプロンプト・ラボにも移動できますが、今回は LLM モデルのチューニングを行う「ラベル付きデータを使用したファウンデーション・モデルの調整」を選択します:
2024092512


最初にチューニングそのものに適当な名称、説明、タグを付与し「作成」ボタンをクリックします:
2024092513


するとチューニングのアセットが作られ、そのチューニング内容を指定する画面になります。まずはチューニング元になる LLM (言語モデル)を選択します。「基礎モデルの選択」ボタンをクリックします:
2024092514


ここで選択できる LLM の一覧が表示されます。2024-09-25 時点ではここで選択できる LLM は "fran-t5-xl-3b" か "granite-13b-instruct-v2" のいずれかでした(これを知っていたので、上述のプロンプトでも granite-13b-instruct-v2 を使ってプロンプトを試していました)。ここから1つ選んでチューニングするわけですが、今回は IBM の "granite-13b-instruct-v2" を選択しました:
2024092515

※実際のチューニングではここでベースとなる LLM を何にするかによってもチューニングの結果は異なることになります。一般的にはここで選択する LLM は「プロンプトエンジニアリングを試した時点で相性の良さそうな LLM を選ぶ」のが良いとされています。


選択した LLM の説明文が表示されます。これで問題なければ「選択」をクリックします:
2024091209


チューニング元 LLM の選択ができました。すると画面右に「トレーニング・データの追加」と書かれたファイルアップロード画面が表示されます。ここで追加用チューニングデータを指定してチューニングを行うことができます。追加用チューニングデータのフォーマットが分からない場合は(青枠の)「テンプレートのプレビュー」ボタンをクリックします:
2024092516


「テンプレートのプレビュー」をクリックし、"JSON" タブを選択すると以下のような画面が表示されます。"input" と "output" の要素を含む JSON が配列になっていて、この input にプロンプト例、output に問い合わせ結果例が含まれているようなデータを作る、ということのようでした(最大で 10000 サンプル、200MB。これ以外に配列の "[" , "]" を抜いた JSONL 型のデータも使えるようです):
2024092517


このようなフォーマットでチューニング用データを集めて指定してチューニング、、を行うことになります。今回は為替計算を正しく行ってもらうことが目的なので、以下のようなデータを用意してみました:
[
  {
    "input": "1 ドルは 140 円です。 10 ドルは何円ですか?",
    "output": "1 ドルが 140 円なので、 10 ドルは約 140 * 10 = 1400 円です。"
  },
  {
    "input": "1 ドルは 140 円です。 20 ドルは何円ですか?",
    "output": "1 ドルが 140 円なので、 20 ドルは約 140 * 20 = 2800 円です。"
  },
  {
    "input": "1 ドルは 140 円です。 30 ドルは何円ですか?",
    "output": "1 ドルが 140 円なので、 30 ドルは約 140 * 30 = 4200 円です。"
  },
  :
  :

為替のレートを与えた時の「〇〇ドルは何円ですか?」という質問に答えられるようにするためのインプットとアウトプットのペアを大量に用意してチューニングし、実際のレートと質問を与えた時に(プロンプトで工夫しなくても)正しく答えることができるようにするための JSON 配列型の学習データを用意しました(実際には異なる計算もできるような例が含まれています。興味ある方は全部見てください)。

この架空のデータファイル(training-fx.json)をトレーニングデータとして公開することにします。LLM チューニングを体験する目的で、直接ダウンロードして使っていただいても構いません:
https://raw.githubusercontent.com/dotnsf/watsonx.ai-tuning/refs/heads/main/training-fx.json

そして Tuning Studio 画面の「参照」ボタンから、用意した training-fx.json ファイルを指定してアップロードします:
2024092518


アップロードが完了すると「トレーニングデータの追加」の準備はできたことになります:
2024092519


必要であれば「パラメーターの構成」ボタンをクリックして、チューニング時のパラメータを変更します:
2024092520


パラメータを調整する画面が表示されます。必要に応じてパラメータを調整して「保存」します(必要なければ「キャンセル」します):
2024092521


最後にプロンプトの初期化内容を指示します。今回の場合は「与えられた条件から計算して額を答えてほしい」ことが分かっているので、初期化方法に「テキスト」、その内容には「以下は入力された質問に対する出力のサンプルです。サンプルと同様に与えられた質問に対する答を計算して簡潔に答えてください。」と入力します:
2024092522


更に下にスクロールするとタスクの種類を指定する箇所があります。今回の例では「計算して答える」という「プロンプトに含まれない情報を生成する」ものなので、「生成」を選択します。 ここまで選択すると画面右下の「チューニングの開始」ボタンが有効になります。 ここをクリックしてチューニングを開始します:
2024092523


このような画面になってチューニングが開始されます。ここからはチューニングが完了するまで、ひたすら待ちます:
2024092524


チューニングが完了すると以下のような画面になります(先ほどのデータでは 16 分でした)。一般的には(表示されている)損失関数は右肩下がりになるのがいいと言われていますが、ちょっと
2024092525


このチューニングした LLM を実際に使えるようにするにはデプロイする必要があります。画面下部(見えない場合は下にスクロール)の「新規デプロイメント」をクリックします:
2024092526


名前(必須)と説明等を入力します。続きがあるので下にスクロールします:
2024092527


展開コンテナは「このプロジェクト」を選択し、デプロイメント・サービス提供社名を(適当に)入力します。最後に「作成」ボタンをクリックしてデプロイを開始します:
2024092528


少し待つと以下のような画面に切り替わります。このデプロイメントのリンクをクリックします:
2024092529


デプロイメントの様子が分かります。デプロイメントが完了するまで少し時間がかかります。ステータスが「進行中」から「デプロイ済み」になるまで待ちます:
2024092530


「デプロイ済み」になれば、チューニングした LLM はデプロイされ、実際に使える状態になったことを意味します:
2024092531


【チューニング済み LLM を使う】
チューニングされた LLM がデプロイ済みになっていれば、外部からの API 呼び出しや、プロンプトラボなどから実際に使うことができます。先ほどのページの「API リファレンス」タブにはエンドポイント URL や cURL コマンドなどで使う場合のコマンドが表示されています。 ここではプロンプトラボから試す方法を紹介します。といっても「Prompt Lab で開く」ボタンをクリックするだけです:
2024092532


するとプロンプトラボの画面が表示されます。この時、LLM は自分がチューニングしたモデルになっていることを確認します:
2024092533

基盤モデルの一覧を表示した場合でも、このチューニング済みモデルが表示され、選択可能になっていることを確認してください:
2024092534


改めてプロンプトラボを「フリーフォーム」で、LLM は自分がチューニングしてデプロイしたモデルを選択した状態にします:
2024092535


そしてプロンプトとして以下のように入力します(このブログを書いている最中の実際のドル円相場の数字です):
与えられた質問に対する答を計算して簡潔に答えてください。

1 ドルは 144.3 円です。 10 ドルは何円ですか?
2024092536


もともとは何も計算してくれなかったプロンプトです。これを「生成」します:
2024092537


・・・うーん、まだ 100 点とはいえないか。想定していた答とは違いますが、とりあえず計算はしてくれるようになりました。このプロンプトはチューニング前だと正しい数値を返すこともなかったものなので、いくらかの進展はあったと言えるんじゃないかと思いますが、うーん。。。

まあ、今回のチューニングデータは説明目的でサイズもまだまだ小さく、サンプルとしては不十分であった可能性は高いものです。もうちょっと色んなパターンに対応したり、数を増やしたりすることで制度上がるんだろうか? この辺りはまだ未検証です。 ただ Watsonx.AI の LLM チューニングがどういったものなのか、そのための Tuning Studio をどう使うのか、という点ではある程度理解しやすいものではなかったか、と思っています。


【チューニングのコスト】
Watsonx.ai の LLM を Tuningu Studio でチューニングする際のコストも気になるところです。チューニングコストは与えるサンプルデータ量によっても変わるので事前に具体的なコストを予測計算するのは難しいのですが、以下にチューニングコストの考え方・計算方法についてまとめておきます。 

なお、以下の説明に使っている数字部分は 2024 年 9 月 25 日時点のものであることに注意してください。実際にコストを見積もる際には自分の契約しているプランや為替レートを含めた最新情報・最新価格を参照して再度計算するべきであることに留意ください。

まず覚えておいていただきたいことは「LLM チューニングの価格は CUH(Capacity Unit / Hour : 容量単位時間)によって決まる」ということです。

要は、
 1 どのようなスペックのサーバーを
 2 どのくらいの時間使って
チューニングしたか、という計算能力と計算量によって計算で決まる、という意味です。

どのようなスペックのサーバーを使って LLM チューニングしているか、という情報はこちらを参照して調べます:
https://dataplatform.cloud.ibm.com/docs/content/wsj/getting-started/wml-plans.html?context=wx&audience=wdp#cuh-metering


この中の「資産タイプ別 CUH 消費率」という項目内の「基礎モデルの調整実験(watsonxのみ)」と書かれた所が LLM チューニング時に使われるサーバーで、その CUH は(2024/09/25 時点で)43 となっています:
2024091211


この 43 というのが(1時間の)チューニング時に利用されるサーバーのスペックを表す数字だと思ってください。この数字だけだとどんなスペックか想像しにくいですが、他の数字よりもかなり大きめの数字になっているので、それなりのサーバーが使われる、という理解でいいと思います。 ただあくまで1時間の数字です。チューニングに必要な時間が 30 分ならこの半分に、2時間ならこの倍になります。

そして、1 CUH あたりでいくらかかるのか、というのは Watsonx.AI 作成時の Watson Machine Learning サービスインスタンスのプランによって変わります。例えば Essential Plan の場合、1CUH あたりの額は(2024/09/25 時点で)75.7146 円となっています:
2024091201


これらの数値より、仮にチューニングにかかる時間が1時間であったとすると、そのチューニングコス
  1(H) * 43(CUH) * 75.7146 (JPY) = 3255.7278 (円)
ということになります。 あくまで 2024/09/25 時点の Essential Plan での価格および為替レートに基づいた1時間あたりの数字なので、実際の価格は自分のプラン、チューニングデータ量に合わせて再度計算が必要になる点に注意してください。

そして、では今回の(上述のチューニングデータを使っての)チューニングでどれだけの CUH を消費したか、という数値はチューニング後のプロジェクト画面に反映されています。私が実際に上記データを使ってチューニングした結果は以下のようになっていました:
2024092538


11.8 CUH とのことでした(あくまで私が試した時の結果です)。これはつまり、
 11.8(CUH) * 75.7146 (JPY) = 893.43228(円)
ということになりました。 実際、このチューニングでは不十分だったと思っているので、あまり参考にならない数字かもしれませんが、「試しに1回軽くチューニングすると千円くらい」というのが1つの目安に・・・なりますかね? 繰り返しますが、あくまで目安の数字であることに注意してください。


【まとめ】
今の時点でまだあまり外部情報のない Tuningu Studio を使ってみました。2024-09-25 現在ではプロンプト・チューニングだけが提供されている状況で、「膨大なトークン数を消費してコストがかさむのを防ぐためのチューニング」が主目的になるものと考えられます。 こういうコスト削減方法もあるんですねー。