watsonxのAPIを呼び出せるようになるまで

# はじめに
ついにIBMでも生成AIが出てきて、EnterpriseのためのAIはどこまで使えるようになるのか楽しみですね。
さて、その使い勝手を検証してもらうためには、様々な人たちに使ってもらう必要があると思いますし、誰かがアプリケーションに組み込んでみて初めて真価を発揮するでしょう。

早速使ってみたいけど、SDKは2023/8/1時点でPythonのみ提供されているみたい。Node.jsを普段使う身としては、せめて `curl` で呼び出せる必要が、、、
なので、こちらの記事ではwatsonxのAPIをcurlで呼び出せるようになるまでの細かい手順を紹介します。

※IBM Cloudアカウントがあることが前提になっています

# IBM watsonxへまずアクセスしてみよう
https://dataplatform.cloud.ibm.com/login?context=wx&save_region=true
こちらにアクセスします。
実行環境は以下から選択できますが、今回はダラスに作成します。
- ダラス(us-south)
- ロンドン(eu-gb)
- フランクフルト(eu-de)
- 東京(jp-tok)
IBMidはすでにあるIBM Cloudアカウントの情報を入力してください。
:::note warn
注意
実行環境選択したロケーションにLiteプランのWatson Studio/Watson Machine Learningが作成されます。
すでにLiteプランの両サービスがある場合は、そのサービスと同じロケーションを選択するか、既存のLiteプランのサービスを削除してから実施する必要があります。
:::
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651598/3f1b680e-6996-0d1b-7a2d-ca76bcc67a9c.png)
認証ページが表示されるので、IBM Cloudアカウントと同じ情報を入力ください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651598/8f62db06-02e1-fea0-4c0d-089229676d91.png)
連絡先と利用ポリシーを確認されるので、必要な情報を入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651598/a543d2ad-4912-9987-444d-776a4fbd68fe.png)
無事にポータルが表示されました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651598/611220f8-2f09-fe7c-b9ee-41bd4492ee94.png)
試しに生成AIに質問を投げてみたいので、 `ファウンデーション・モデルを試し、プロンプトを作成する`を選びます。
なお、自動的に `xxのサンドボックス` という名前でProjectが作成されました。
Projectはwatsonxを動かす上での一定のワークスペースとなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651598/5d5783a0-ccb6-96b7-c8f1-b7614e7f1045.png)
利用ポリシーを確認されるので、すべての項目にチェックを入れます。
私は特にツアーは必要ないですが、ツアーを見たい方はツアーを開始を選択してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651598/52db04af-321c-b4d6-0db1-812dd2f08a64.png)
とりあえず、初期表示された状態で、画面末尾のプロンプトのテスト、の項目に「日本の首都は？」と入れて、画面右下の「生成」のボタンを押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651598/4d74ce8e-0c9b-5d13-49fe-394d8b90baf0.png)
無事に「東京」という回答が得られました。他の都道府県が応答されたらどうしようかと思いました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651598/f0d9f88d-fa06-542e-07d0-42a5aaf50155.png)
画面末尾に以下のような記載があります。
```
停止理由: シーケンス・トークンの終わりが検出されました
トークン: 17 入力 + 5 生成済み = 22 / 2048
4 秒
```
今回の生成AIの利用で、入力に17、出力に5、合計22のトークンを消費しています。
この利用したトークンは重要で、Liteプランで利用する場合、月に25,000トークンまでしか利用できません。

:::note warn
注意
watsonxで生成AIを利用する場合、裏でWatson Machine Learningのサービスを利用しています。
月に25,000トークンまで利用可能な記載はWatson Machine Learningのサービスのプランに記載されています。
:::

# curlで実行するために
実は、先ほどの画面の右側に「コードの表示」というボタンがあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651598/edbb4f05-fe11-9779-d699-0a9fc579d11d.png)
開いてみるとここにcurlのコマンドが。これで実行できるのでは？と誰もが思うはずです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651598/f7f66534-e690-4de7-b70f-b35e1171d890.png)

問題は、Bearer認証で記載されている `YOUR_ACCESS_TOKEN` は、どこにあるのか？という問題。

xxのサンドボックスというProjectを選択し、「管理」から「アクセス制御」を選択すると「アクセストークン」のタブが見えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651598/17f15c67-1e34-14c2-bd0e-ddf64c8908b7.png)

試しにアクセストークンを作成してみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651598/4fd9cedc-03b9-9817-d2a3-a8d3d72136b0.png)
無事にトークンが作成できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651598/151e17a5-d53f-399e-7720-97f9e074c52f.png)
これでやっと `curl` で先ほどの内容を再現できるでしょうか？

# エラーだってよ
HTTP/1.1 401 Unauthorized
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651598/e32ead59-ef3f-b865-2ab7-2c9fe8753e49.png)

つまり、先ほど作成したアクセストークンは、生成AIを利用するためのものではない、ということです。

では、どうやってアクセストークンを作成すれば良いのか？
ヒントは、curlのリクエスト先のURLを見てください
- https://us-south.ml.cloud.ibm.com/ml/v1-beta/generation/text?version=2023-05-29

これ、Watson Machine Learningのエンドポイントですね。つまり、Watson Machine Learningのアクセストークンを発行できる必要があります。

# Service IDを作成する
IBM Cloudのポータル上部のメニューにある「管理」から「アクセス(IAM)」を選択してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651598/49e399de-57a1-257f-ad38-21faaef3a794.png)

左側のメニューから「サービスID」を選択します。
すでにいくつかサービスを利用していた場合自動生成された情報もあると思いますが、今回は新規に作成してみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651598/54530492-ecd5-9c88-8977-582790453b40.png)
最低サービスIDの名称を入れて作成を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651598/d728d33b-0d57-0e3a-9c40-8f93258a5bb6.png)
サービスIDが作成できました。
この状態では、何の権限も持たないので、Watson Machine Learningの権限を割り当てます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651598/a5505c55-ae30-9dc0-bebe-22a6ef7bf554.png)
ポリシーの作成で、まず、サービスに「Watson Machine Learning」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651598/6a93e5ee-ac81-c484-b3bc-0862835e886b.png)
リソースでは、すべてのリソースを選択しても動作するのですが、今回はwatsonx用に作成されたWatson Machine Learningのインスタンスのみ権限がある状態にします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651598/781d84b8-40f5-cd20-2cdb-f223e470d62e.png)
とりあえず管理者相当の権限を設定して、末尾の追加を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651598/b974fe50-93c3-4ab8-8de9-911d02169f80.png)
画面右側にアクセス・サマリーが表示されるので、割り当てを選択して、サービスIDに権限を割り当てます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651598/b8bc812e-dfa5-fe49-55c3-3960eff4f3ec.png)
これでサービスIDに権限が付与されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651598/5240d60e-7600-fb4f-1c51-66a0318c20df.png)
このサービスIDに紐づくAPIキーを作成するので、画面上のAPIキーのタブを選択して、作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651598/3cc3f5e3-2754-0380-b14b-1c587213cd46.png)
最低名前を入力して作成を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651598/41908c8d-d3ff-b386-c912-cddba1d9a2d1.png)
APIキーが作成されるので、どこかに控えておきましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651598/5c82a1d7-a2a7-6819-099e-0c0286ddf306.png)

:::note warn
表示されたAPIキーはポップアップをCloseする、もしくは表示から300秒経過すると二度と表示されなくなります。
作成したAPIキーは記録するようにしてください。
:::

# APIキーからアクセストークンを取得する
[こちらの記事](https://qiita.com/testnin2/items/3a4ca8a1a2b79b713c48#32-api%E3%81%A7%E5%91%BC%E3%81%B3%E5%87%BA%E3%81%99api-key%E3%81%8C%E5%BF%85%E8%A6%81)にも記載ありますが、下記のようなcurlコマンドで取得可能です
```
curl -X POST "https://iam.cloud.ibm.com/identity/token" \
-H 'Content-Type: application/x-www-form-urlencoded' \
-H 'Accept: application/json' \
-d 'grant_type=urn:ibm:params:oauth:grant-type:apikey' \
-d 'apikey=さきほど取得したAPIキー'
```

応答として下記の内容が得られます。
```
{
  "access_token": "eyJraWQiOiIyMDIzMDcx(～中略～)ayftdlDpiFQ5tKQ",
  "refresh_token": "not_supported",
  "token_type": "Bearer",
  "expires_in": 3600,
  "expiration": 1690900173,
  "scope": "ibm openid"
}
```
:::note warn
こちらで生成されたアクセストークンは1時間(3600秒)で失効します。有効期限が切れた場合は、改めてアクセストークンの生成が必要です
:::

# curlでwatsonxのAPIを呼び出してみる
先ほど取得したアクセストークンを利用して、改めて先ほど認証でエラーになったcurlコマンドを実行してみましょう

HTTP/1.1 403 Forbidden
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651598/9388a800-235e-b4bf-b07f-6f0b1fd0e9c1.png)

エラーだってよ（再掲）

とはいえ、ここまでくるとあと少しです。
メッセージの中に下記のような内容が記載あります。
> Failed to find the iam-ServiceId-xxxxxx member in project_id xxxxxx

これは、watsonxのProjectにそのService IDが参加していません(見つかりません)というエラーなので、ProjectにService IDを含めるようにしましょう。

# watsonx のプロジェクトにService IDを含める
watsonxの画面からProjectを選択、管理のタブを選び、左側のメニューからアクセス制御を指定。
先ほどはアクセストークンを見ましたが、今回は、画面右側のコラボレーターの追加からサービスIDの追加を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651598/69b5317e-679c-465f-5985-83f522104a16.png)
先ほど作成したService IDを検索してチェックボックスにマークをして、忘れがちですがロールを指定して画面右下から追加を行います
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651598/fc9f67b1-4a6e-0074-26cc-b8437a4b87a7.png)
これで無事にService IDがprojectに追加されました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651598/8e547ad4-3750-151a-d780-69d35a246857.png)
これで先ほどエラーになったcurlコマンドを実行すると、無事にwatsonxの生成AIから応答が返るようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651598/d2aaa99e-4b69-8e80-e0e0-f5b73dd93c9e.png)

# さいごに
いかがでしたでしょうか？
watsonxにアクセストークン生成って書いてるのだから、そのアクセストークンでcurlコマンドが動いてほしいですが、ちょっと工夫が必要ですね。
Node.jsのSDKが2023/8/1時点で無いようなので、Node.jsで書いているアプリでwatsonxと連携する場合、アクセストークンの生成処理を自前で書かなければならない部分がありますが、これでやっと自分で作成しているアプリとwatsonxを自力で繋げることが出来そうです。
この内容で少しでも多くの人がwatsonxを触ってみるにあたって、壁に当たることなく利用できることを願います。

2023/8/3 追記
Node.jsからwatsonxを利用する記事を投稿しました
[watsonxのAPIをNode.jsから呼び出してみる](https://qiita.com/katahiro/items/62faa3297530ed7d5e68)