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

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

タグ:watsonx

このブログエントリは 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 のテキスト生成機能を体験できるようになったのではないかと思っています。


IBM の新しい AI プラットフォームである IBM watsonx.ai (「ワトソンエックス・エーアイ」)が公開され、IBM Cloud のライトプラン(無料)でもある程度使うことができそうなことがわかったので、まだあまりドキュメントが整備されていなさそうな REST API について調べてみました。そして調べた結果わかった情報を使って、実際に REST API を使って動くサンプルアプリを作り、公開してみました。
watsonx.ai



【事前準備】
このブログエントリに書かれた内容を全て試すためには、IBM Cloud のアカウントが必要です。まだ所有していない場合はこちらから登録してください。なお 2023 年7月時点では新規登録の際にクレジットカード情報の入力が必須です(このブログで紹介する内容は無料範囲でも可能ですが、カードの登録は必須です)。

また今回はプロンプトを使った質問を入力して、その内容に対する回答を取得する、という内容の REST API を実際に動かすのですが、そのためには Watson StudioWatson Machine Learning という2つのサービスを利用する必要があります(いずれも従量課金型のサービスですが、ライトプランを使うことである程度まで無料で使うことができます)。 IBM Cloud のアカウントでログイン後にこれら2つのサービスインスタンスを作っておいてください。


【環境構築】
では実際にプロンプトで指示を行うための環境を構築します。IBM Cloud にログインし、リソースリスト(左メニューの上から2番目)から「AI/機械学習」カテゴリを参照します。他の用途で既に IBM Cloud を使っている場合はここにいくつかのサービスインスタンスが並んでいるかもしれませんが、少なくとも上述の事前準備が完了していれば "Watson Machine Learning" と "Watson Studio" の2つのインスタンスは表示されているはずです。これら2つが表示されていることを確認した上で(実際はどっちでもいいんですが) "Watson Machine Learning" の方をクリックします:
2023071700


クリックした "Watson Machine Learning" インスタンスが表示されます。ここで「IBM Cloud Pak for Data で起動」と書かれた青いボタンをクリックします:
2023071701


初回はこのような画面が表示されます。少し待ちます:
2023071701


少し待つとこのような画面が表示されます。「ML モデルの作成と管理」というダイアログが表示されていますが、実はこの時点では watsonx.ai ではなく IBM Cloud Pak for Data という別プラットフォームの画面になっています。プラットフォームを切り替えるため、この画面では「キャンセル」をクリックします:
2023071702


プラットフォームの切り替えは画面右上のメニューから行うことができます。画面右上から「IBM watsonx.ai」を選択し直します。これでプラットフォームが watsonx.ai 用のものに切り替わります:
2023071703


はじめて watsonx.ai を使う時にはこのような画面が表示されます。利用規約にチェックを入れ、また初回はまだプロジェクトがないので(先に進むためにはプロジェクトが最低1つ必要なので)「サンドボックスプロジェクトの作成」ボタンをクリックします(既に利用済みで、自分のプロジェクトが存在している場合はそのプロジェクトを選択しても構いません):
2023071704


プロジェクトが選択されていると、このような画面(プロジェクトの初期画面)になります。プロンプト指示を試す場合は、一番左の「ファウンデーション・モデルを・・」と書かれたプロンプト・ラボを選択します:
2023071705


プロンプト・ラボを始めて実行するとこのようなダイアログが表示されます。内容を確認して全てチェックします。説明を確認する場合は「ツアーを開始」をクリックしてもよいのですが、飛ばす場合は「ツアーのスキップ」をクリックします。これで環境構築は一通り完了です:
2023071706



【プロンプト実行】
ここまで正しく実行すると下のような画面になり、プロンプト指示を実際に試すことができるようになります。なお特に今回は REST API を操作することを目的としているので、プロンプトを試す前に画面右の「コードの表示」メニューをクリックしておきます:
2023071704


すると画面右側に curl の実行コマンドが表示されます。この後プロンプトで入力をすることになるのですが、その入力処理を curl で実行した場合の実行内容(接続 URL やヘッダ、データの中身)を確認することができるので、この内容を参考に REST API のプログラミングができるようになります:
2023071705


参照ページの例を参考にプロンプトで指示を出してみます。すると実行結果が返ってくるだけでなく、その結果を得るために実行された curl コマンドの REST API パスが /ml/v1-beta/generation/text?version=2023-05-29 であったことや、日本語で指示している場合も特に日本語であることを明示するパラメータが送られていないことを含め、どのような REST API が実行されていたかがわかります:
2023071706


【アクセストークンの取得】
後はこれと同じことを自分のプログラミングの中で実装すればよい、、のですが、この REST API を実行する上で欠くことのできない2つのパラメータがあります:
2023071707


1つは "project_id" というパラメータです。これは名前の通り「プロジェクトのID」で、プロンプト実行前に指定したプロジェクトを一意に示す ID です。この値はプロンプト実行時にブラウザが参照している URL を見ると、URL パラメータの1つとして指定されていることがわかります(つまりブラウザの URL から取得することができます):
2023071708


問題はもう1つの "YOUR_ACCESS_TOKEN" (つまりアクセストークン値)です。これはこの文字列をそのまま使っても正しく実行できません。しかもこの値はウェブブラウザを参照するなどの方法では取得できず、IAM API キーと呼ばれる値とプログラミングによって動的に取得する必要があるものです。この取得方法については本ブログの趣旨とは異なるので詳しくは解説しませんが、詳しくはこちらのドキュメントを参照してください(後述のサンプルでもこの方法でアクセストークンを取得しています)。


【サンプル】
ここまでに記載した情報を使って、実際に動く Node.js のサンプルアプリケーションを作って公開しました:
https://github.com/dotnsf/watsonx


サンプルといっても実体は "POST /api/generate_text" というエンドポイントを1つだけ実装した Swagger ドキュメントベースの API アプリケーションです。起動時に IAM API キーやプロジェクト ID を環境変数に指定することもできますし、API 実行時にパラメータで指定することもできます。

中身を簡単に説明すると、実装はほぼこの app.js ファイル1つだけで、アクセストークンの取得は getAccessToken() 関数で、テキスト生成(プロンプトの実行)は generateText() 関数で実装しています。興味ある方はこれらの関数内の実装部分を参考にしてください(といっても私も上の方法で知った curl コマンドとそのパラメータ指定をそのまま Node.js 内で使ってるだけなんですけど)。

サンプルアプリケーションを実行するには Node.js インストール済みの環境でソースコードを "git clone" して、"npm install" して、.env ファイルに API キーとプロジェクト ID を保存後に "npm start" するとアプリケーションが 8080 番ポートで起動するので、"http://localhost:8080/_doc" にアクセスすると Swagger ドキュメントが開きます:
2023071701


唯一の API である "POST /generate_text" 部分をクリックして開いて "Try it" ボタンをクリックするとパラメータ設定ができる画面になります。API Key や Project ID 、Model ID は環境変数で指定してあればここでは空のままで構いません。必須入力項目といえるのは Input 値くらいで、ここにプロンプトの内容を記載します。最後に "Execute" ボタンで実行します:
2023071702


正しく実行されると、API の実行結果が下部に表示されます。ちなみにこの例では Input が「入力:\nAbout Watson Discovery\\nIBM Watson® Discovery is an intelligent document processing engine that helps you to gain insights from complex business documents.\n翻訳\n」で、その結果が「Watson Discoveryはビジネスドキュメントに関する意見を得るための知能型ドキュメント処理エンジンです。」でした。どこにも「日本語サポート」とも書かれていないし、「日本語で翻訳」とも指定していないのにここまでできるのはそこそこ日本語でもプロンプトに書かれた意図を理解する力があると思っています。なお、このアプリケーションから実行する場合、 REST API 実行時のパラメータで max_new_tokens の値を(デフォルトの 20 から)100 に変更しています。日本語の場合、20 程度だとまともなある程度長い文章を返せなくなってしまうようで、このようにしています:
2023071703


ちなみにこのサービスを無料のライトプランで使う場合、1か月で使えるトークン数は 25000 だそうです。自分がこれまでにどのくらいのトークンを消費しているかは、IBM Cloud のプロジェクト選択画面で「管理」タブから「リソース使用率」を選択した先の画面で確認することができます。ご利用は計画的に:
2023071704


なお REST API のパス(/ml/v1-beta/generation/text)をみても分かると思いますが、現在の API は v1 のベータ版であり、近い将来に仕様含めて変更する可能性が高いと思っています。その辺りもご注意の上で参照してください。


【参照】
IBM watsonx.ai がやってきた
IBM watsonx.ai を試してみた ( コピペ OK )
Documentation ( IBM watsonx.ai 用)



このページのトップヘ