アレクサから ChatGPTに質問して、そのままAlexaから回答を聞けるシステムを作ったときの忘備録です。
ラズパイにインストールした、Node-REDを使用して実現させました。
アレクサとChatGPTを連携させるさまざまな方法が考案されています。
いろいろなやり方がありますが、個人取得のAPIが必要になる関係上、どれも「Alexaスキル追加だけでOK!」とはいかないのが実情です。
今回解説する方法も多少のプログラミング知識が必要です。
それでもNode-Redを使用することで、できるだけ簡単に作れるように作成しましたので、興味のある方はぜひ挑戦してみてください。
なお、Node-RedでChatGPTからの回答を読み上げるには、Amazonデバイスのアレクサが必要です。(Fire HD、Echo Dot、Echo Showなど)
スマホのAlexaアプリには未対応ですので、事前にご了承願います。
Node-Redとアレクサを組み合わせると、同じワードでも時間帯で異なる処理をさせたり、雨雲の接近を自動で読み上げたり一段と賢く使えます!
日常生活のアシスタントやお子さまのおはなし相手に、一家に一台オススメです!
2023/04/24 追記
ChatGPTとの会話が楽しめるアレクサスキルを開発、公開された方がいらっしゃいました!
【AlexaでchatGPTとおしゃべりできる 「helloGPT」を公開しました】
https://note.com/uramot/n/n333c2aa1f25c
試してみたところ、以下の制限があるようです。
- 無料プランは1日10回まで
- 1回の回答は100文字程度
制限はありますが、スキルを有効化するだけでアレクサを通してChatGPTに質問ができるので、「ちょっと試したい」という方には「helloGPT」が断然おすすめです!
簡単!手軽!めちゃくちゃ楽しい!
もっと自分好みにカスタマイズしたり、LINEやメールなどと連携したくなった方は、当サイトの方法を試していただければと思います。
Node-Redとは?
非常に簡単に説明すると、ウェブブラウザ上で動作する「コードをほとんど書くことなく(ローコード)Javascriptプログラムを作成して実行できるシステム」でしょうか。
左側に並ぶ「ノード」と呼ばれるパーツを、中央の「パレット」に並べて、ノード同士を接続することで簡単にプログラミングのような処理を作成することができます。
Node-Redについての説明は、後日別の記事にまとめる予定です。
すぐに知りたい方は「アレクサ Node-red」などで検索すると、Node-redの説明や、アレクサとNode-redを連携させる方法を解説した記事がたくさん出てきます。
Amazonスキルの作り方を調べて、ChatGPTと連携させる方法を調べて…とするより、Node-Redに頼る方が簡単に作成できるかと思います。
興味のある方は、ぜひNode-Redでローコードプログラミングに挑戦してみてください。
私はAlexaスキル作成の「Lambda」がどうこうが理解できず諦めました…
でもNode-Redなら作れました!ありがとうNode-Red!
あわせて読みたい!
アレクサからChatGPTに質問する方法
方法1:声で質問する
先に実際にシステムを動作させた動画を掲載します。
ChatGPTに質問するには、アレクサを通じて質問専用リストにアイテム(質問内容)を追加します。
質問が追加されたことをNode-Redが検知すると、自動的にChatGPTに問合せたのち、アレクサが回答を読み上げてくれます。
アレクサを通じてリストにアイテムを追加するには、アレクサに次のように話しかけます。
- アレクサ、(リスト名)に(質問内容)を追加して
- アレクサ、(質問内容)を(リスト名)に追加して
方法2:スマホアプリから質問する
スマホのAlexaアプリを使い、直接リストにアイテムを追加しても動作します。
ただしその場合、質問が追加されたことをNode-Redが検知するために、回答するアレクサ(私の場合はAmazon Echo)を一度動作させる必要があります。
私は定期アクションに一言の「アナウンス」を作成することで、Amazon Echoをどこにいても反応させられるようにしました。
これにより、どこにいても簡単にChatGPTに質問できます。(ChatGPTのサイトで直接質問した方が手軽で早いですが…)
なおスマホアプリから質問した場合でも、Amazon Echoが回答をしゃべってくれます。
屋外からで質問した際には、家にいる人に驚かれないよう気をつけてください。
突然しゃべるのが気になるならば、アクションの始めに音量「0」を入れて、5分待って「音量を上げる」など工夫するといいでしょう。
処理の全体図
処理の流れ
システムのおおまかな流れは次のとおりです。
- Alexaアプリから「質問専用のリスト」を作成し、アレクサを通してリストにアイテム(質問)を入れる
- アレクサが動くたびにリスト内を確認、アイテム(質問)があれば、内容をChatGPTのAPIに渡す
- ChatGPTの回答をアレクサが読み上げる
このシステムを「2つの事前準備」+「6つの処理」に分けて解説します。
debugノードはなくてもいい
枠外にたくさんある『debug』ですが、その名の通りデバッグ用なので作成しなくても動作に影響しません。
『debug』を接続すると、Node-REDのデバッグメッセージ欄に「どんな情報が通過したか」が表示されるようになります。
アレクサとChatGPTを連携させる処理を作る(準備)
事前準備1:専用リストの作成
Alexaアプリから、ChatGPTにする質問を格納するための、「専用のマイリスト」を作成します。
マイリストの名前をアレクサに伝えることになるので、呼びやすいリスト名にしてください。
私は「質問」というリスト名にしました。
最初は「ChatGPT」にしましたが、アレクサが全然認識してくれないので諦めました…。
事前準備2:必要ノードの追加
Node-Redの「メニュー」→「パレットの管理」→「パレット」→「ノードを追加」より、以下の2つのノードを追加してください。
- node-red-contrib-alexa-remote2-applestrudel(あるいは node-red-contrib-alexa-remote2)
- node-red-contrib-simple-chatgpt
『remote2-applestrude』と『remote2』
『remote2-applestrudel』と『remote2』は、基本的には同じものです。
remote2 が2年前に更新が止まっているため、代替として remote2-applestrudel が作成されたようです。
よって、今から作成するのであれば 、『remote2-applestrudel』の導入を推奨します。(私も『remote2-applestrudel 』を導入しています)
なお、remote2-applestrudel と remote2 は同時に使用することができません。
もし現在 remote2 を使用しており remote2-applestrudel に変更するのであれば、remote2-applestrudel の説明ページにある「Migration」の説明に従い、remote2 を削除してから remote2-applestrudel をインストールしてください。
なお、『remote2-applestrudel』の使い方の説明は、ここでは行いません。(後日に解説記事を作成します…)
使い方は remote2 と同じですので、「node-red-contrib-alexa-remote2」で検索すれば、情報が見つかるかと思います。
node-red-contrib-simple-chatgpt
使用にはOpenAIのAPIが必要です。
次のページにアクセスして、API Key を発行してください。(要:OpenAIアカウント)
「Create new secret key」を押せば、新しい API Key が発行されます。
表示された API Key は、処理4で使いますのでメモしておいてください。
なお、発行したAPI Keyを再確認する方法はありませんので、もし紛失した場合は新しい API Key を発行してください。
複数のAPI Keyを発行したからといって、お金がかかることはありませんのでご安心ください。
APIは本来有料のサービスです
OpenAIのAPIサービスは、従量課金制の有料サービスです。
OpenAIのアカウント作成時に、自動的に$18の無料クレジットを獲得しているため、しばらく試す分には無料で利用できます。
この無料クレジットは、3ヶ月間有効です。
現在の利用分は、Usageで確認することができます。
無料クレジットを使い切っても、APIが使えなくなるだけでいきなり請求されることはありません。
ただし、支払情報を登録した時点で、無料だったはずの$18以内の利用分も従量課金の対象になってしまうのでご注意ください。
アレクサとChatGPTを連携させる処理を作る(Node-RED)
(再掲載)
コピペ用コード(Node-Red)
処理の作成が面倒な方は、以下のコードをコピーし Node-Red の「読み込み」から読み込ませると、簡単に上図と同じ処理を作成できます。
なお、以下のコードでは、アレクサとの連携には『remote2-applestrudel 』を使用しています。
『remote2』を使用している方は、読み込み後に上の図やこの先にある解説を見ながら、ノードを置き換えてください。
必要なノードがインストールされてないと、読み込ませた直後にエラーが表示されます。
その場合は、事前準備2の「アレクサ連携用ノード」や処理6の「メール送信用ノード」を追加してください。(メール送信が不要な場合は、「メール送信用ノード」のエラーは無視してOKです)
なお、上記コードはNode-Redに読み込ませただけで動作するものではありません。
動作には、最低でも以下の準備・処理を作成する必要があります。
コードを読み込ませたのであれば、このページの内容にならって内容を編集していくだけなので、そこまで難しくはないと思います。
分からないことがあれば、コメント欄にて質問いただければ回答しますので、お気軽に相談いただければと思います。
私も素人なので、一緒に考えることで勉強できればと思います。
なんならもっと賢いやり方があれば、コメント欄で教えてください!
処理1:専用リストの確認
ここからは、node-REDを実際に操作していきます。
まず、処理の実行条件部と、専用リストにアイテム(質問)があるかを判定する部分を作成します。
必要なパーツは、次の3つです。(処理進行順)
- Alexa Event(アレクサの動きを検知)
- Alexa List(「質問」リスト確認)
- switch(質問があるか判定)
Alexa Event(アレクサの動きを検知)
アレクサに何かしらの動きがあると、ノードが動き出すように設定します。
- Name:(任意)
- Account:(作成しているアカウントを指定)
- Command:Device Activity
Alexa List(「質問」リスト確認)
専用リスト内のアイテムを取得します。
マイリストには、事前準備2で作成した専用リストを指定します。
もし作成した専用リストが表示されない場合は、List欄の右端にあるサイクル矢印マークをクリックして更新します。
- Name:(任意)
- Account:(作成しているアカウントを指定)
- Select:Get List Items
- List:(事前準備2で作った専用リストを指定)
switch(質問があるか判定)
「専用リストにアイテムが存在するか」を判定します。
アレクサに話しかけるたびに処理が始まってしまうため、指定マイリストの中にアイテムがある場合のみ、この先の処理を実行させるようにします。
- 名前:(任意)
- プロパティ:msg.payload
- 条件:空でない
このswitchノードの先に、処理2、処理3、処理4を接続します。
処理2:アイテムの削除
専用リストにアイテム(質問)が残っていると何度も処理が動いてしまうので、アイテムを検知したらすぐに削除します。
必要なパーツは、次の2つです。(処理進行順)
- function(質問idの取得)
- Alexa List(質問の削除)
function(質問idの取得)
アイテムに含まれた情報から、Amazonに割り当てられたアイテム固有のIDを取得します。
functionには、次のコードを記述します。(payloadに固有IDを格納する)
var payload = msg.payload;
var id = payload[0].id;
msg.payload = id;
return msg;
Alexa List(質問の削除)
先ほど取得した固有IDを利用し、専用リストからアイテム(質問)を削除します。
- Name:(任意)
- Account:(作成しているアカウントを指定)
- Select:Remove Item
- List:(事前準備2で作った専用リストを指定)
- Item Id:msg.payload
(オプション)処理3:質問受付メッセージの再生
処理が動き出したことを通知する & それっぽく見せる処理を作成します。
処理3は動作に直接影響しないので、この処理は作らなくても問題ありません。
『質問受付の返答』でアレクサにしゃべらせるため、処理3として分岐して処理させていますが、SEを鳴らすだけならば処理2や4に組み込んでもいいと思います。
必要なパーツは、次の2つです。(処理進行順)
- delay(Delay 3s)
- Alexa Routine(質問受付の返答)
delay(Delay 3s)
リストにアイテムを追加すると、アレクサが「(アイテム)をリストに追加しました」と返答します。
その返答をなるべく聞き終わってから、次の『質問受付の返答』をしゃべってほしいので、処理を数秒間待機させます。
下記の設定は一例で、時間など好みで設定してください。
- 動作:メッセージの遅延 - 指定した時間遅延
- 時間:3秒
- 名前:(任意)
Alexa Routine(質問受付の返答)
処理が進行していることを明確にする & 回答が完成するまでの時間を繋ぐためにアレクサをしゃべらせます。
下記の設定は一例で、Text(アレクサがしゃべる内容)など好みで設定してください。
- Name:(任意)
- Account:(作成しているアカウントを指定)
- Command:Speak - Regular
- Text:チャットGPTでお答えします。回答を作成しますので、しばらくお待ちください。
- Device:(しゃべるアレクサのデバイス名)
処理4:回答の作成と返答
アイテム(質問)内容を取得し、OpenAIで回答を作成します。
作成した回答をアレクサに渡して、しゃべらせます。
必要なパーツは、次の3つです。(処理進行順)
- function(質問内容の取得)
- simple-chatgpt
- Alexa Routine(回答をAlexaでしゃべる)
function(質問内容の取得)
アイテムに含まれた情報から、質問内容を取得します。
functionには、次のコードを記述します。(payloadに質問内容を格納する)
var payload = msg.payload;
var value = payload[0].value;
msg.payload = value + "。日本語かつ400文字以内で答えてください。";
msg.topic = "質問:" + value + "【Alexa x OpenAI x Node-RED】";
return msg;
回答をテキストで見る場合と違い、回答を耳で聞く場合は長いと内容が分かりにくいため、400文字で制限させます。
指定の文字数は自由に変更してください。
制限が不要な場合は、4行目を「msg.payload = value」すると、文字数の制限や回答の日本語の指定がなくなります。
なお、5行目の「msg.topic」は、処理6でOpenAIが作成した回答を『メール送信』するための1行です。
メールが不要な方は、5行目は削除してもOKです。(メールが不要な場合でも、残しておいても動作に問題ありません)
必要なオプションに応じて、『simple-chatgpt』の出力先として次の処理にも接続してください。
- エラー通知処理を作成している場合 ⇒ 処理5-1の「function(中断メール用件名作成)」
simple-chatgpt
ChatGPTに質問をし、回答を作成させます。
事前準備2で作成した、OpenAIの API Key はここで使用します。
- Name:(任意)
- Token:(事前準備2で作成した、OpenAIの API Key)
- SystemSetting:(任意)
SystemSettingでは、ChatGPTのキャラクターを設定することができます。
例えば、「大阪弁で返答して」や「語尾に『にゃん』を付けて」といった感じです。
必要なオプションに応じて、『simple-chatgpt』の出力先として次の処理にも接続してください。
- エラー通知処理を作成している場合 ⇒ 処理5-2の「function(処理中ファイル内容削除準備)」
- 回答をメールでも送信する場合 ⇒ 処理6の「template(メール文作成)」
Alexa Routine(回答をAlexaでしゃべる)
ChatGPTが作成した回答をアレクサにしゃべらせます。
- Name:(任意)
- Account:(作成しているアカウントを指定)
- Command:Speak - Regular
- Text:msg.payload
- Device:(しゃべるアレクサのデバイス名)
画面付きデバイスを持っている方は、「Command:Speak - announcement」にすると、デバイスに回答を表示することができます!
(オプション)処理5-1:エラーが起きたときの準備
『simple-chatgpt』が回答を作成している間に、Node-Redがエラーで停止することがあります。
このままでは「エラーで停止した」のか、「回答の作成に時間がかかっているだけ」なのか判断ができません。
そこで、エラーが起きた場合は「回答が作成できませんでした」とアレクサに教えてもらうようにします。
処理5は、5-1「エラーが起きたときの準備」・5-2「エラーが起きなかったときの処理」・5-3「エラーが起きたときの処理」の3つに分けて作成します。
なお、処理5は動作に直接影響しないので、この処理は作らなくても問題ありません。
5-1では、エラーが起きた時のために「質問内容をテキストに保存する処理」を作成します。
5-1に必要なパーツは、次の2つです。(処理進行順)
- function(中断メール用件名作成)
- write file(処理中ファイル書き換え)
function(中断メール用件名作成)
ChatGPTに行った質問をテキストファイルとして保存するため、テキスト本文を作成します。
functionには、次のコードを記述します。(payloadにテキストファイルへ入力する本文を格納する)
var payload = msg.payload;
var value = payload[0].value;
msg.payload = "質問:" + value + "【Alexa x OpenAI x Node-RED】";
return msg;
write file(処理中ファイル書き換え)
- ファイル名:(テキストを作成する場所とテキスト名をフルパスで記載)
- 動作:ファイルを上書き / 「メッセージの入力のたびに開業を追加」・「ディレクトリが存在しない場合は作成」のチェックはお好みで
- 文字コード:デフォルト(あるいは「utf8」)
- 名前:(任意)
先ほど作成したテキスト本文を、ファイルとして出力します。
(オプション)処理5-2:エラーが起きなかったときの処理
5-2では、正常に回答を取得できた場合の「テキストを空白にする処理」を作成します。
5-2に必要なパーツは、次の2つです。(処理進行順)
- function(処理中ファイル内容削除準備)
- write file(処理中ファイル内容削除)
そのまま放置やテキストファイル削除ではダメなのか?
5-3で作成しますが、「ChatGPTの処理が中断された場合、Node-Redが再起動する」性質を利用して、正常かエラーかの判定をします。
Node-Red起動時に「テキストの中に文字列があるか?」で直前の処理が中断されたが、正常に終了したかを判定しています。
ChatGPTの処理が正常に終了したあとにテキストを空白にしなければ、テキストに文字が残ったままになり、ChatGPT関係なくNode-Redを再起動させた際にアレクサがしゃべりだしてしまいます。
また、テキストファイルを削除した場合、ChatGPT関係なくNode-Redを再起動させた際にエラーが発生してしまいます。
上記の理由から、正常に終了した場合は、テストファイルの中身を空白にしています。
function(処理中ファイル内容削除準備)
処理5-1で作成したテキストファイルを空白にするため、テキスト本文を作成します。
functionには、次のコードを記述します。(payloadに空白を格納する)
var payload = "";
return msg;
write file(処理中ファイル内容削除)
先ほど作成した空白本文を、ファイルとして出力します。
- ファイル名:(5-1と同じ内容を記載)
- 動作:ファイルを上書き / 「メッセージの入力のたびに開業を追加」・「ディレクトリが存在しない場合は作成」のチェックはお好みで
- 文字コード:デフォルト(あるいは「utf8」)
- 名前:(任意)
(オプション)処理5-3:エラーが起きたときの処理
5-3では、エラーが起きてNode-Redが再起動した場合に「エラー発生を通知する処理」を作成します。
5-3に必要なパーツは、次の4つです。(処理進行順)
- inject(処理切断確認フロー)
- read file(処理ファイル内容確認)
- switch(処理中に再起動したか判定)
- Alexa Routine(エラーの返答)
inject(処理切断確認フロー)
途中で処理が停止した場合、「Node-Redが再起動した」をきっかけに動き出すよう、処理の始まりを作成します。
- 名前:(任意)
- (処理内容):msg.payload = 日時
- 『Node-RED起動の「3」秒後、以下を行う』でチェックを入れる
- 繰り返し:なし
read file(処理ファイル内容確認)
5-1で作成したテキストファイルの内容を取得します。
- ファイル名:(5-1と同じ内容を記載)
- 出力形式:文字列
- 文字コード:デフォルト(あるいは「utf8」)
- 名前:(任意)
switch(処理中に再起動したか判定)
テキストファイルから文字列が取得できたかどうかで、「処理中にエラーが発生したか?」を判定します。
もし文字列が取得できた場合は「エラーが発生した」と判断し、エラー通知の処理を行います。
文字列が取得できなかった(空白だった)場合は「ChatGPTとは関係のない再起動があった」と判断し、Node-RED起動時の処理はここで終了します。
- 名前:(任意)
- プロパティ:msg.payload
- 条件:空でない
メールで回答を受け取る場合は、この先に処理6を接続します。
メールが不要な場合、処理5-3は別の処理と接続する必要はありません。(独立した状態でOK)
Alexa Routine(エラーの返答)
エラーが発生したことをアレクサにしゃべらせます。
以下は一例で、メッセージ(Text)は自由に作成してください。
- Name:(任意)
- Account:(作成しているアカウントを指定)
- Command:Speak - Regular
- Text:申し訳ありません。エラーが発生し、チャットGPTから回答を取得できませんでした。
- Device:(しゃべるアレクサのデバイス名)
(オプション)処理6:回答をメールで送信する
ChatGPTの返答を耳で聞いても分かりづらいため、メールでも受信するようにします。
処理6は動作に直接影響しないので、メールが不要な方はこの処理は作らなくてもOKです。
今回は、メール送信のために次のノードを追加でインストールしました。
必要なパーツは、次の3つです。(左から順番)
- function(エラーメール本文作成準備)
- template(メール文作成)
- email(回答をメール送信)
function(エラーメール本文作成準備)
エラーが発生し、回答が作成できなかったとき用に定型のエラーメール本文を作成します。
エラーを通知する処理(処理5)を作成しない場合、このパーツは無視してOKです。
なおメールの件名は、処理4『function(質問内容の取得)』の5行目で作成しています。
functionには、次のコードを記述します。(ファイルから件名を作成し、payloadにエラー通知文を格納する)
var title = msg.payload
msg.topic = title;
msg.payload = "(回答を取得できませんでした。)";
return msg;
template(メール文作成)
正常に『simple-chatgpt』から回答を取得できたときに送信する、メールの本文を作成します。
なおメールの件名は、処理4『function(質問内容の取得)』の5行目で作成しています。
下記の設定は一例で、メール本文(テンプレート)は自由に作成してください。
{{payload}} が、メールを受信した際にChatGPTの回答に変化します。
- 名前:メッセージの遅延 - 指定した時間遅延
- プロパティ:msg.payload
- テンプレート:ChatGPTからの回答: [改行] {{payload}}
- 形式:Mustacheテンプレート
- 出力形式:平文
email(回答をメール送信)
以下はgmailを利用する場合の設定です。
設定はお使いのメールサービスによって、変更してください。
- 宛先:(送信先のメールアドレス)
- サーバ:smtp.gmail.com
- ポート:465 / 「安全な接続を使用」にチェック
- ユーザID:(送信元のメールアドレス)
- パスワード:(アプリパスワード)※
- TLSオプション:「チェックサーバ証明書は有効です」にチェック
- 名前:(任意)
アプリパスワードの作成方法
アプリパスワードを作成するには、Googleアカウントで2段階認証を有効にする必要があります。(Googleアカウントヘルプを開きます)
2段階認証を有効にした状態で、Googleアカウント ⇒ セキュリティ ⇒ アプリパスワード で作成できます。
生成するアプリは「その他」を選択し、分かりやすい名前(Node-REDなど)を付けると、自動的にアプリパスワードが作成されます。
作成したアプリパスワードを再確認する方法はありませんので、もし紛失した場合はもう一度アプリパスワードを作成してください。
まとめ:今回のシステムは、ほかにもいろいろ応用できそう
アレクサからChatGPTに質問して、回答を聞くシステムの作り方をご紹介しました。
なお『sinple-chatgpt』には、過去の会話を参照する機能が追加されていますが、トークン(利用料金)が増える関係で実装していません。
「直近の質問・回答を内容をファイルに保存」⇒「新しい質問の前に保存したファイルを読み込ませる」などの処理で簡単にできるかと思います。
また、『simple-chatgpt』ノードの部分をPythonプログラムなどに置き換えれば、別の処理にも簡単に変更ができます。
例えば「GPT-4」に対応させることも、そう難しくないかと思います。
興味がある方はぜひ実装にチャレンジしてみてください。
余談:リスト方式でオリジナルコマンドも作れる
今回の「専用リスト」方式を使えば、Node-REDを使用したオリジナルのアレクサコマンドを簡単に作成できます。
コマンドを作成する場合、先にアイテムの内容をmsg.payloadに入れ、Switchで分岐させます。
こうすることで、1つのリストから複数のコマンドに対応できるようになります。
参考にしたページ
Node-REDでChatGPTを試す
https://zenn.dev/gaomar/articles/e46cba8e489dfa
【enebular 2022】ChatGPT用ノード「node-red-contrib-simple-chatgpt」を enebular・Node-REDで試したり API を Python から利用してみた話
https://qiita.com/youtoy/items/0afc3b97a1e1e057cf40
OpenAI API で提供されている GPT-3モデル まとめ
https://note.com/npaka/n/nef372ec2e33a
ChatGPTを使ったアプリ(サービス)、ChatGPTじゃない説
https://qiita.com/Tyamamoto1007/items/464e142c2d88d314ab6c
おすすめの記事
\ バイノーラル録音のASMRで存在を感じよう♪ /
『ぼっち・ざ・ろっく』後藤ひとり 役 青山吉能さん出演のASMR。
自分だけに話しかけてくれる吐息に耳がゾクゾクします。