Code Engineを使って対話できるデジタルサイネージを試作してみた話

# この記事について
この記事は、IBM Cloud Advent Calendar 2024の24日目の記事です。
IBM Cloud Code Engineを使い、お店や博物館、美術館、学校に設置を想定している対話できるデジタルサイネージのプロトタイプを作りましたので、その仕組みについて説明しています。

# 作ったものについて
スマートフォンで質問を送ると、商品棚などにデジタルサイネージとして設置しているタブレット端末に表示されているAIキャラクターが音声でいろいろと教えてくれる仕組みになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41414/7550ac69-6413-b154-a11f-b81fac049861.png)

Raspberry Pi4や5にタッチ操作が可能なディスプレイを接続し、台に設置する方法もおすすめです。Raspberry Piを活用する場合はセンサー関係やカメラ等との連携もできました。

画像生成AIを使ってデジタルサイネージとして設置しているタブレット端末をイメージするとこんな感じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41414/dcfd4b47-bd38-73d0-c44c-219c641ba6e3.png)

# 必要なもの
IBM Cloud Code Engine を使い、2つのアプリケーションを用意します。作業としては３段階になります。
 1. IBM Cloud Code Engineで、AITuberKitを動かす
 1. AITuberKitで、外部からの指示を受け付けるをONにする
 1. IBM Cloud Code Engineで、Node-REDを動かす
 1. Node-REDにWebフォームを実装する

## IBM Cloud Code Engineで、AITuberKitを動かす
こちらは、以前書いた「[AITuberKitを、IBM Cloud Code Engineで動かすまで](https://qiita.com/kolinz/items/911ddf083a4b2bb14faf)」を参考に、AITuberKitをデプロイしてください。

## AITuberKitで、外部からの指示を受け付けるをONにする
AITuberKitをアプリケーションとして作成後、Webブラウザでアクセスします。
画面左上の歯車のアイコンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41414/a1570238-df1c-a124-5d21-c603ed6f34bc.png)

「その他」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41414/2c11dc6d-de3f-e019-fdba-139b0d1ad750.png)

「外部からの指示を受け付ける」の状態をONにします。その後、「メッセージ送信ページを開く」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41414/ac643e18-c722-7b73-1009-006116df59b6.png)

表示された画面で下部に移動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41414/8cddf37d-4234-0501-d267-b4343ae34beb.png)

「Send user input」に表示された「Curl Sample」をもとに、Node-REDにWebフォームを実装します。

## IBM Cloud Code Engineで、Node-REDを動かす
AITuberKitをIBM Cloud Code Engineで動かす手順とほぼ同じです。違う点は、次のとおりです。
### Image ReferenceのURLに、Node-REDのイメージを指定
アプリケーション作成時に「Image ReferenceのURL」には、Node-RED用のコンテナイメージとして、DockerHubにあるものを指定しています。下記を入力します。
```
docker.io/nodered/node-red
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41414/21b43b36-6377-d571-0b08-07d779fb93f4.png)
### Resources & scaling は少なめに
Node-REDは、AITuberKitに比べて低めのスペックでも十分に動きますので、図のように少なめに「CPU and memory」に設定します。図の設定値ではまだ大きいので、もう少し減らしても良いでしょう。Node-REDは、割り当てメモリが512MBでも十分に動きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41414/7ef3b584-3bbe-6012-1847-aacd1d653482.png)

Node-REDをIBM Code Engineで立ち上げると、先に立ち上げたAITuberKitもあるので、下図のように表示されます。２つ並んで表示されていれば良いです。
図では、上がNode-REDで、下がAITuberKitです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41414/61f1c364-c061-600e-87d5-dcb5c82b966a.png)

## Node-REDにWebフォームを実装する
AITuberKitの「外部からの指示を受け付ける」の「メッセージ送信ページを開く」をクリックしたことで表示される「Send user input」に表示された「Curl Sample」をもとに、Node-REDにWebフォームを実装します。
Webフォームとして動作するように、Node-REDでは次のように形（フロー）になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41414/715a7dbf-83e6-de19-ccd9-796508439e70.png)

### 1 http in node
MethodをGET、URLに /form を指定しました。Node-REDのURLの、#flowの部分をformに書き換えることで、実装するWebフォームを表示させることができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41414/92d0a030-4a37-9aae-1e23-5fe6a59890ff.png)

### 2 template node
簡単なWebフォームを作成します。フォームを送信すると /postmsgに送信されるようにしています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41414/7be0dace-0cf1-a040-65ef-11a0dc924fa6.png)

### 3 http response node
「http in node」を使っている場合は「http response node」が必須なので設置しています。

### 4 http in node
MethodをPOST、URLに /postmsg を指定しました。Webフォームに入力され、送信された値を受信します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41414/ada8e775-d6c0-1a98-8db3-4aff070edfdb.png)

### 5 function node
前のノードで、Webフォームから届いた値を受け取ったので、この値を、AITuberKitの「外部からの指示を受け付ける」における「Send user input」向けに加工する仕組みを実装します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41414/c542157b-8f61-c792-ac7a-caac8f58809f.png)

### 6 http request node
前のノードで、JSON形式に変換できるようにしたので、これをAITuberKitに送信する設定を記述します。
「URL」の欄には、AITuberKitの「外部からの指示を受け付ける」の「メッセージ送信ページを開く」をクリックしたことで表示される「Send user input」に表示された「Curl Sample」のエンドポイント（https://aituberkit-cc...ではじまり、=user_inputで終わる長めのURL）を記述します。
また、「Headers」には、Content-Type: application/json を設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41414/44f7d2f3-2cda-34c7-0fa5-b4af95015aff.png)

### Deployをクリック
必要に応じてdebugノードを追加します。debugノードがあることで、各ノードにおける処理の状況を確認できますし、エラーが起きてもどこでエラーが起きたか把握しやすくなります。
各ノードを線で結び、画面右上の「Deploy」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41414/715a7dbf-83e6-de19-ccd9-796508439e70.png)

# 動作確認
AITUberKitには、パソコンやタブレット端末からアクセスし、Node-RED上で作成したWebフォームにはスマートフォンでアクセスします。スマートフォンに表示されたフォームから質問文を送信すると、AITuberKitに表示されたAIキャラクターが音声で話してくれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41414/ef40445f-9952-cd3e-eb8d-181bce60e8c7.png)

# まとめ
生成AIとモデルを作成していた際に、AIキャラクターによる各種案内や雑談ができる仕組みをつくることができないか相談されたことがありますので、今回の対話できるデジタルサイネージの試作になりました。
店舗や図書館、博物館などでの建物内でAIキャラクターに向かって話しかける人はなかなかいないと思うので、スマートフォンから質問を送信する形をとっています。

IBM Cloud Code EngineとNode-RED、AITuberKitを使うことでさくっとプロトタイプを作ることができました。