まだプログラマーですが何か?

プログラマーネタ中心。たまに作成したウェブサービス関連の話も https://twitter.com/dotnsf

タグ:watsonx.ai

先日、「Watsonx.AI の LLM をチューニングする」というブログを公開しました。IBM Cloud から提供されている IBM の生成 AI である WatsonX.AI の標準 LLM を、独自に与えるテキストデータによってチューニングを施した新しい LLM を作る、という内容を、その実行例を交えて紹介したものでした。

紹介した方法で作られた新しい LLM を REST API で使う方法についても紹介ページに含まれているのですが、API プログラミングが求められるとなると、まだ少しハードル高いですよね。となると、チューニング済み LLM は WatsonX.AI のプロンプトラボという機能/UIを使って使うことになる・・・ というのではあまりにも寂しいです。

そんなわけで、本日のブログエントリでは「チューニング済み WatsonX.AI LLM を Node-RED で使う」手順を紹介します。Node-RED はフローエディタを使った、いわゆるノーコード/ローコード開発ツールの代表的な1つです。この Node-RED であればプログラミングにあまり自信がない人でもデータの流れを理解していれば WatsonX.AI プログラミングができるようになる、かも、という狙いです。


【Node-RED の用意】
まず何はともあれ Node-RED 環境が必要です。既に Node-RED を使える環境がある場合はその環境を使ってください。環境がない場合はなんらかの方法で Node-RED 環境を用意する必要があります。

比較的一般的な方法は「手元のローカル PC に Node-RED をインストール」する方法です。Windows, Mac, ラズベリーパイなどに対応していて、管理者権限があればインストールすることができます:
https://nodered.jp/docs/getting-started/local

または「IBM Cloud の Code Engine を使ってインストールする」方法もあります。こちらはリソースの使い方によっては有料となってしまいますが、比較的安価にコンテナアプリケーションを実行することができる環境です。この環境で DockerHub 内の nodered/node-red を動かす、という方法です。

Code Engine を使う場合はアプリケーションの登録時に以下の設定をしてください。まず Code の種類は "Use an existing container image" を選択し、イメージ名は "nodered/node-red" と入力します:
2024092701


下にスクロールします。次にこの1アプリに使うリソース量を指定します。まず CPU とストレージは最小のものでいいと思います(多いほど値段が上がります)。注意が必要なのはその下の Autoscalling 設定です。この Max 値は 1 固定でいいのですが、問題は Min 値です。ここを 1 にするとアプリケーションは(最小インスタンス数=1、最大インスタンス数=1になるので)1つ起動しっぱなしになります。常に稼働しているため料金はそれなりにかかりますが、常に使える状態で待機していることになります。 一方、ここを 0 にすると(最小インスタンス数=0、最大インスタンス数=1になるので)アクセスがない時は消え、アクセスがあるとその場で1つ動き出します。アクセスのない時間帯の料金は(0インスタンスなので)かかりませんが、アクセスから実際にアプリケーションが動き出すまでのタイムラグがあり、また一度保存した状態があっても、アクセスがなく 0 インスタンスになってしまうと、次にアクセスした時には保存状態が残りません。いつでも使える状態がいいか、アクセスしない時間のコストをセーブするのがいいか、優先順位に合わせて選んでいただきたいのですが、以下の機能を試す間だけでも 1 に設定してインスタンスが落ちないようにしておくのがいいと思いました:
2024092702


そしてドメインマッピングの設定は "Public" を選択し、最後に "Create" ボタンで作成します:
2024092703


1~2分でアプリケーション(=Node-RED)が起動します。ステータスが "Ready" になったら "Test application" から "Application URL" を選択すると実際のアプリケーション(=Node-RED)にアクセスできます:
2024092705


アクセスに成功するとこんな感じの画面になり、ここから Node-RED が使えます:
2024092706


ここでは2つの方法を紹介しましたが、これ以外の方法(普通にパブリッククラウドにデプロイするとか・・)でももちろん構いません。何らかの方法で Node-RED が使えるようになっているという前提で以下の説明を続けます。


【watsonx.ai ノードのインストール】
Node-RED から Watsonx.AI を使えるようにするため、用意した Node-RED に拙作の watsonx.ai ノードを追加します:
2024093001


追加手順は以下です。まず Node-RED の右上のメニューから "Manage Pallete(パレットの管理)" を選択します:
2024092802


パレットの管理画面が表示されます。ここで "Install" タブに切り替え、検索ボックスに "watsonx" と入力します。すると(2024-09-28 時点では他の候補は見つからないのですが) "node-red-contrib-dotnsf-watsonx" という名前の公開ノードが見つかるはずです(2024-09-30 時点では最新バージョン 0.2.3 を公開しています)。この "Install" ボタンをクリックします:
2024092803


「インストールしていいか?という確認画面が表示されたら "Install" を押してください:
2024092804


インストールに成功すると、このような画面が表示されます:
2024092805


ダイアログをクローズして元の画面に戻ると、ノード一覧の function カテゴリ内に "watsonx.ai" と書かれたノードが追加されているはずです。これで Node-RED から比較的簡単な方法で watsonx.ai の生成 AI が使えるようになりました:
2024092806


【watsonx.ai 側のパラメータを確認】
準備の最後に、この後実際に Node-RED から Watsonx.AI を使う際にあたふたしないよう、watsonx.ai ノードに指定する各種パラメータの値をあらかじめまとめて調べておくことにします。

まず watsonx.ai ノードを左のパレット一覧から右のフロー部分にドラッグ&ドロップし、その後ダブルクリックしてください:
2024092807


すると以下のようなダイアログが表示されます。これが watsonx.ai ノードに指定するパラメータです:
2024092808


これらに指定するパラメータを確認しましょう。まずは watsonx.ai のプロンプトラボ画面を表示し、そこで指定するモデルをチューニングで作成したもの(下図では "kkimura-foreign-exchange-llm-v1")に設定します:
2024092809


まず画面右の "View Code" というボタンをクリックすると、このプロンプトで実行する問い合わせを Curl で実行する時の指定内容が表示されます。この中に Location と Deployment ID の情報が含まれています:
2024092811


例えば curl で指定する URL が以下のような値の場合、、
curl "https://jp-tok.ml.cloud.ibm.com/ml/v1/deployments/(deployment_id)/text/generation?version=2023-05-29"

青字の ".ml.cloud.ibm.com" の前にある文字列 "jp-tok" が Location の値です。また "deployments/" と "/text" の間にある赤字の部分にある文字列が Deployment ID です。

なお API Key は IBM Cloud ダッシュボードで作る API Key の値です。またチューニング LLM を使う場合、Project ID と Model ID はともに指定不要です(指定されたままでも構いませんが、Deployment ID が指定されている場合は無視されます)。

これらの値を先ほどのダイアログ内に指定し、最後に "Done" ボタンをクリックします:
2024092812


これでパラメータの準備も完了しました。


【Node-RED から watsonx.ai のチューニング済み LLM にアクセスする】

Node-RED のフローを完成させましょう。watsonx.ai ノードの左側に inject ノードを、右側に debug ノードを配置し、これらを繋げます:
2024092813


inject ノードをダブルクリックしてダイアログを開き、"msg.payload" の種類を文字列に(図で az と書かれている指定)、文字列の内容を "与えられた質問に対する答を計算して簡潔に答えてください。\\\\n\\\\n1 ドルは 144.3 円です。 10 ドルは何円ですか?" と入力して、Done をクリックします(msg.topic は使いません。×をクリックして削除しても構いません):
2024092814


ここまで準備できたら、Node-RED 画面右上の "Deploy" ボタンをクリックして、このフローをデプロイします:
2024092815


そして inject ノード左のボタンをクリックすると指定した文字列が watsonx.ai ノードに渡され、Deployment ID で指定されたチューニング済み LLM で処理され、その結果が debug ノードに渡されます。debug ノードに渡った結果は画面右の debug ペイン(虫のマーク)で確認することができます:
2024093000

 
まだチューニングが充分ではないので、期待していたような出力結果ではありませんが、Watsonx.AI のチューニング済み LLM を Node-RED からも使うことができる、ということが確認できました。

というわけで改めて、WatsonX.AI 用 Node-RED カスタムノードがチューニング済み LLM にも対応できましたので、よかったら使ってください:
2024093001



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 現在ではプロンプト・チューニングだけが提供されている状況で、「膨大なトークン数を消費してコストがかさむのを防ぐためのチューニング」が主目的になるものと考えられます。 こういうコスト削減方法もあるんですねー。




このブログエントリは IBM Cloud アドベントカレンダー 2023 に参加しています(西川さん、いつもありがとうございます!)。12/04 ぶんの記事です:
2023112901



IBM Cloud から提供されている生成 AI のプラットフォーム(および API )の watsonx.ai を使って英会話練習アプリを作って、公開してみました:
https://github.com/dotnsf/wwx

2023112902



【使うための準備】
アプリケーションを動かすには以下が必要です(IBM Cloud 上での手続きが必要ですが、フリープランを使って無料枠内で運用するぶんには料金はかかりません):
Git および Node.js がインストールされ、インターネットに繋がる PC(Windows, MacOS, Linux, ..)と Chrome ブラウザ
IBM Cloud のアカウント
・IBM Cloud の API キー
・IBM Cloud 内で Watson Studio および Watson Machine Learning のインスタンスをダラスのデータセンターで有効化
・IBM Watsonx.AI のプロンプトラボを使った時のプロジェクト ID


以前に watsonx.ai の REST API を紹介した記事を書きました。Watson Studio や Watson Machine Learning を有効にする手順や、API キー、プロジェクト ID を取得する手順についてはこの記事内でも紹介しているので必要に応じて参照してください:
https://dotnsf.blog.jp/archives/1082246988.html



【アプリケーションのセットアップ】
では実際に英会話アプリケーションを使うためのセットアップを行います。まずはコマンドプロンプトやターミナルを開いて、git でソースコードをクローン(ダウンロード)します:
$ git clone https://github.com/dotnsf/wwx

ダウンロードしたソースコードの依存ライブラリをインストールします:
$ cd wwx

$ npm install

テキストエディタで .env ファイルを開き、あらかじめ用意してある API キープロジェクト ID の内容をそれぞれ以下の場所に(コピー&ペーストするなどして)記述し保存します。他の部分は変更不要です。イコール記号の前後や行頭・行末に余計な空白などが含まれてないように注意してください:
WATSONX_API_KEY=(API キーの値)
WATSONX_PROJECT_ID=(プロジェクト ID の値)
WATSONX_MODEL_ID=meta-llama/llama-2-70b-chat
WATSONX_INSTRUCTION=[INST] <<sys>>\n ....(略)
WATSONX_PRE_INPUT=[User] 
WATSONX_POST_INPUT= \n[/User]\n

最後にアプリケーションを実行します:
$ node app

server starting on 8080 ...

"server starting on 8080 ..." と表示されていれば、アプリケーションの実行ができています。



【英会話アプリを実行する】
では実際に英会話アプリを実行してみましょう。Chrome ウェブブラウザ(WebAudio API を使うため、FireFox は NG)を起動し、"http://localhost:8080/" にアクセスしてみましょう:
2023112903


↑上のような画面が表示されると思います(途中でマイク許可のダイアログが表示されたら「許可」してください)。この画面を使って英会話を練習します:
2023112904


女性の口の部分がマイクのスイッチになっています(最初は青いボタンです)。ここをクリックするとマイクがオンになるので、マイクオンの状態で英語で話しかけてみてください:
2023113001


話し終わってある程度の無入力時間が経過すると、それまでに話した内容を WebAudio API が英語で解釈し、その解釈結果が画面に表示されます:
2023113004
(↑ "Hello. May I have your name, please?" と聞いてみました)


同時に解釈した結果(を英会話向けにプロンプトで加工したもの)を watsonx.ai が読み取り、英会話として続くような内容を返し、最後に WebSpeech API を使って英語で答えてくれます:
2023113002
(↑ちゃんと名前を教えてくれ、続けて私の名前を聞かれました。ちゃんと英会話として成立しています)


同様にして再度マイクオンにしてからマイクに英語で話しかけると英語で答えてくれる、という作業を繰り返すことができます:
2023113003

(↑「キムラ」が「キモラ」になってしまいましたが、これは私の英語発音が良すぎたせいで・・・ということにしておきます)


ぼっちでも英会話練習がはかどりますね。
この仕組みの内部的な挙動を少し説明しておきます。watsonx.ai ではいくつかの基盤モデルと呼ばれる大規模言語モデルが提供されているのですが、今回はその中からメタ社が提供している Llama2 という言語モデルを採用しています(後述のプロンプト含めていくつか試してみた上で、自然な英会話を成立させることができそうだ、と判断しました)。

また音声入力のテキスト化と、生成 AI による出力結果であるテキストの音声出力については Chrome ブラウザの WebAudio API を使っています。この部分についてはサーバーサイド型の仕組みを使うとタイムラグが大きくなってしまうため、ブラウザ内で実装できる方法を検討した結果です。とはいえ、聞き取り精度も、話す際の自然さも悪くないと感じています。一方でブラウザ毎の WebAudio API の実装に伴う制約などがあった場合にその制約を受けることにもなります(例えば FireFox では動かない、など)。

ちなみに Chrome WebAudio API 自体は日本語にも対応していて、日本語でも聞き取り&しゃべりどちらも高い精度でした。別の機会に使えそうでした。

そして肝心のプロンプトです。言葉で発した音声をテキスト化し、それをそのまま生成 AI へ・・・というわけではありません。実は上で .env ファイルを編集した時の4行目にこのような長い一行がありました:
WATSONX_API_KEY=(API キーの値)
WATSONX_PROJECT_ID=(プロジェクト ID の値)
WATSONX_MODEL_ID=meta-llama/llama-2-70b-chat
WATSONX_INSTRUCTION=[INST] <<sys>>\nYou are a friendly, respectful and honest friend. Always answer as friendly as possible, while being safe. Your answers should not include any harmful, unethical, racist, sexist, toxic, dangerous, or illegal content. Please ensure that your responses are socially unbiased and positive in nature. Also try to ask something for me, not try to help me.\n\nIf a question does not make any sense, or is not factually coherent, tell that you don't understand that well. If you don't know the answer to a question, please don't share false information.\n\nYou are an English speaker.\nIf you are asked a question in Japanese, please answer that you don't understand Japanese, and if you are asked a question in English, please answer in English.\n\nThe user is at beginner level of English, so please answer in easy and short English sentence as much as possible. Also you don't speak so much.\n\n<</SYS>>\n[/INST]\n
WATSONX_PRE_INPUT=[User] 
WATSONX_POST_INPUT= \n[/User]\n

詳しくはソースコード内を参照していただきたいのですが、実はこの4行目がプロンプトの指示部分になっていて、音声入力したテキスト部分に先立って入力されています。その内容を日本語で書くと、このような内容です:
あなたは優しく正直な友人です。可能な限りフレンドリーに回答してください。
でも相手を傷つけたり攻撃するような言葉は使わないでください。

・・(中略)・・

あなたは英語を話します。日本語で質問されても英語で「日本語はわからない」と答えてください。
英語で質問されたら簡単な英語で端的に答えてください。・・

このインストラクションに続いて、実際に喋った内容が英語で続けられたテキストが生成 AI に渡されています。このインストラクション部分がプロンプトに含まれていることで、(比較的初級の)英会話
アプリとして動くようになっています。

つまりこの .env の4行目部分を更にカスタマイズすることで英会話としての挙動を変えることもできると思っています(この部分が長くなる場合は現在 100 で固定している max_token 長も変更の必要があるかもしれません)。まあそのあたりに関しては(プロンプトエンジニアリングの楽しい部分でもあるので)ぜひ皆さんで試してみてください。 ・・といいつつ、実は私もこの辺りは同僚の後輩に手伝ってもらってたりするんですけど(笑)。


先日このブログでも紹介した IBM watsonx.ai のベータ版 REST API を使って、Node-RED のカスタムノードを作り、公開してみました。以下で使い方を紹介しますが、実際に利用するには前回 REST API を利用する紹介をした時のブログでも作成した Watson Studuio と Watson Machine Learning を使ったプロジェクトを登録しておく必要があります(そのプロジェクトの ID が必要です)。またこれも同様に前回紹介しましたが、実行するユーザーの IBM Cloud IAM API キーを生成/取得しておく必要があるのでこちらも準備の上で試してみてください。

なお以下で紹介する内容では Node-RED v2.2.3 を使って動作確認しています。また私が提供しているものは公式のものではなく、あくまで個人的に開発したものを個人的に公開しているだけであること、現時点で提供されている REST API 自体がベータ版のため、今後近い将来の API 変更などにより動かなくなる可能性があることをご了承ください(とはいえ、私も使うので、少なくとも公式ノードが出るまではなるべくタイムリーにメンテナンスするつもりです)。


【パレットに watsonx.ai ノードを追加】
Node-RED のパレット画面を開き、右上のメニューから「パレットの管理」を選択してパレットのカスタマイズ画面に移動します。ここで「ノードを追加」タブを選び、"node-red-contrib-dotnsf-watsonxai" を検索してください(2023年7月20日時点では "watsonx" と検索すると1つだけ(!)見つかるのがそれです)。検索できたら「ノードを追加」ボタンをクリックします:
2023072001


以下のような確認ダイアログが表示されるので「追加」をクリックします:
2023072002


正しくインストールされると「ノードをパレットへ追加しました」というメッセージが表示されます。パレット管理画面を閉じます:
2023072003


元のパレット画面に戻ると、"watsonx.ai" というノードが追加されているはずです:
2023072004


【watsonx.ai ノードを使う】
では追加された watsonx.ai ノードを使ってみます。watsonx.ai ノードの前後に適当なノードを追加します。以下ではシンプルで分かりやすい代表として、inject ノードと debug ノードで挟んでみました:
2023072005



watsonx.ai ノードにデータを渡すノード(上図では inject ノード)からは、msg.payload にいわゆる「プロンプト」のテキストを指定します。watsonx.ai ノードは自分に送られてきたデータの msg.payload にプロンプト指定がされている前提でそのテキスト内容に書かれた指示の返答テキストを生成します。

以下の例では msg.payload の内容を(前回のブログで紹介した内容に合わせて)以下のようにしてみました:
入力:\nAbout Watson Discovery\\nIBM Watson® Discovery is an intelligent document processing engine that helps you to gain insights from complex business documents.\n翻訳\n

2023072006


入力内容が英語で書かれていて、最後に「翻訳(してね)」と指示している内容です。watsonx.ai ノードの手前のノード(inject ノード)の設定内容は以上です。

次に watsonx.ai ノード自体にも設定が必要です。watsonx.ai ノードをダブルクリックしてプロパティ設定画面を開き、API Key と Project ID をそれぞれ入力します:
2023072007


このうち API Key は IBM Cloud の IAM API キーの値で、Project ID は Watson Studio と Watson Machine Learning で作成したプロジェクトの ID です。これらも前回のブログで紹介したものと同じ内容の問い合わせを行うサンプルなので、この作業について詳しくはこちらも参照してください。


全ての設定が完了したら作成したフローを「デプロイ」します:
2023072008


デプロイ後に inject ノード左のボタンをクリックしてメッセージを送信すると、watsonx.ai ノードが API キー、プロジェクト ID 、そしてプロンプトテキスト内容を元に問い合わせを行い、その結果が画面右のデバッグ画面内に表示されます:
2023072009


私が 2023 年7月20日に試した際の結果は "Watson Discoveryはビジネスドキュメントに関する意見を得るための知能型ドキュメント処理エンジンです。" と表示されました。上述の英語文章を翻訳してほしい、というプロンプトだったので、質問意図を正しく理解して実行できているようでした。


(いずれにせよベータ版 API を使うことになりますが)REST API を直接実行することでカスタムアプリケーションを作ることもできますが、今回紹介した Node-RED のカスタムノードを使うことで、より手軽に watsonx.ai のテキスト生成機能を体験できるようになったのではないかと思っています。


このページのトップヘ