OpenAIのFunction Callingを使って、robo8080さんのAIスタックチャン2に様々な機能を追加しました。
※Function Callingを使わない通常の会話もできます。
開発にはM5Stack Core2(白)とCoreS3を使用しており、ポート設定は次のようになっています。ご自身のハードウェアに合わせて変更してください。
デバイス | ポートA | ポートB | ポートC |
---|---|---|---|
M5Stack Core2 | PWMサーボ | - | - |
M5Stack CoreS3 | NeoPixel互換LED搭載 HEXボード | - | PWMサーボ |
サーボ用のポートは StackchanExConfig.h (または後述のYAMLファイル)で設定します。
※シリアルサーボには対応していません。
#define DEFAULT_SERVO_PIN_X 33 //Core2 PORT A
#define DEFAULT_SERVO_PIN_Y 32
HEXボード用のポートは HexLED.h で設定します。
#define LED_DATA_PIN 2 //CoreS3 PORTA
Function Callingで呼び出せる機能の一覧を下表に示します。
プロンプトや関数の実装は FunctionCall.cpp にまとめています。指示に応じてスタックチャンが関数を使いこなしてくれます。FunctionCall.cppを改造することで、新たな機能を追加するなどのカスタマイズができます。
※ChatGPTのモデルはFunction Callingの精度を上げるためにGPT-4oにしています。GPT-4o miniに変更するにはFunctionCall.cpp内のプロンプトを編集してください。
String json_ChatString =
//"{\"model\": \"gpt-4o-mini\","
"{\"model\": \"gpt-4o\","
"\"messages\": [{\"role\": \"user\", \"content\": \"\"}],"
No. | 機能 | 使用例 | デモ | 補足 |
---|---|---|---|---|
1 | 時刻 | 「今何時?」 「今日は何日?」 「今日は何曜日?」 |
||
2 | タイマー | 「3分のアラームをセットして」 「1時間後にパワーオフして」 「タイマーをキャンセルして」 |
動画(X) | |
3 | メモ(SDカード) | 「~をメモして」 「これから言うことをメモして」 「メモを読んで」 「メモを消去して」 |
メモは notepad.txt というファイル名でSDカードに保存されます。 | |
4 | メール送信 | 「メモをメールして」 「~をメールして」 |
動画(X) | GmailのアプリパスワードをSDカードに保存しておく必要があります(「各種設定ファイル」参照)。 |
5 | メール受信 | 「メールを読んで」 | 動画(X) | ・送信と同じアプリパスワードを使います。 ・メールサーバを5分毎に確認し、新しいメールがあれば「〇件のメールを受信しています」と教えてくれます。 |
6 | バス(電車)時刻表 | 「次のバスの時間は?」 「その次は?」 |
動画(X) | 時刻表をSDカードのファイルに保存しておく必要があります(「各種設定ファイル」参照)。 |
7 | 天気予報 | 「今日の天気は?」 「明日の天気は?」 |
・robo8080さんがGistに公開してくださったコードを参考にさせていただきました。 ・City IDはSDカードの設定ファイルで変更することができます(「各種設定ファイル」参照)。 |
|
8 | ウェイクワード登録 | 「ウェイクワードを登録」 「ウェイクワードを有効化」 |
||
9 | リマインダ | 「新しいリマインダを設定して」 | 動画(X) | |
10 | 最新ニュース (NewsAPI連携) | 「今日のニュースは?」 | ・K.Yamaさん(X)から提供いただいたコードを参考にさせていただきました。 ・APIキーをSDカードに保存しておく必要があります(「各種設定ファイル」参照)。 |
以降に示す設定ファイルを必要に応じてSDカードに保存してください。
v0.8.0からSD UpdaterとYAML設定ファイルに対応したため、フォルダ、ファイルの構成が変更になりました。
(YAMLの対応にはmongonta0716さんのstackchan-arduinoライブラリを使用しています。)
以下の通り、YAMLファイルでWi-FiとAPIキーの設定をします。
※APIキーはスタックチャンとの会話に必須です。APIキーの取得方法などの詳細はAIスタックチャン2のREADMEを参照ください。
フォルダ:/yaml
ファイル名:SC_SecConfig.yaml
wifi:
ssid: "********"
password: "********"
apikey:
stt: "********" # ApiKey of SpeechToText Service (VoiceVox)
aiservice: "********" # ApiKey of AIService (ChatGPT)
tts: "********" # ApiKey of TextToSpeech Service (Google Cloud TTS)
以下の通り、YAMLファイルでPWMサーボのピン番号を設定します。
フォルダ:/yaml
ファイル名:SC_BasicConfig.yaml
servo:
pin:
# ServoPin
# Core1 PortA X:22,Y:21 PortC X:16,Y:17
# Core2 PortA X:33,Y:32 PortC X:13,Y:14
# Stack-chanPCB Core1 X:5,Y:2 Core2 X:19,Y27
# When using SCS0009, x:RX, y:TX (not used).(StackchanRT Version:Core1 x16,y17, Core2: x13,y14)
x: 33
y: 32
※SC_BasicConfig.yamlには他にも様々な基本設定が記述されていますが、現状、本ソフトが対応しているのは上記のPWMサーボピンのみです。
以下の通り、YAMLファイルでFunction Callingの各機能の設定をします。使わない機能についての設定はブランクでも問題ありません。
フォルダ:/app/AiStackChan2FuncCall
ファイル名:SC_ExConfig.yaml
mail:
account: "********@gmail.com" # Gmailアカウントのメールアドレス
app_pwd: "********" # Gmailアカウントのアプリパスワード
to_addr: "********@gmail.com" # 送信先のメールアドレス
weather:
city_id: "140010" # 天気予報APIのCity ID
news:
apikey: "********" # NewsAPIのAPIキー
メール送受信機能を使う場合に設定が必要です。
天気予報機能を使う場合に設定が必要です。
City IDはこちらで調べることができます。
News機能を使う場合に設定が必要です。
APIキーはNewsAPIのWEBページから取得できます(Developerプランであれば料金はかかりません)。
時刻表機能を使う場合は、SDカードに次のように時刻表を保存してください。 ※現行は祝日の判別はできません。
フォルダ:/app/AiStackChan2FuncCall
ファイル名:bus_timetable.txt(平日)、bus_timetable_sat.txt(土曜)、bus_timetable_holiday.txt(日曜)
06:01
06:33
06:53
・
・
・
21:33
22:03
22:33
SDカードに次のようにMP3ファイルを保存しておくと、タイマー機能やリマインダ機能のアラーム音として再生されます。
フォルダ:/app/AiStackChan2FuncCall
ファイル名:alarm.mp3
※SDカードの相性により音が途切れることがあるため、起動時にMP3ファイルをSPIFFSにコピーして使用するように改善しました。すでにSPIFFSにalarm.mp3が存在する場合は起動時のコピーは行われません。
SD Updaterに対応し、NoRiさんのBinsPack-for-StackChan-Core2で公開されている他のSD Updater対応アプリとの切り替えが可能になりました。
【適用方法】
① env:m5stack-core2-sduでビルドする。
② ビルド結果の.pio/build/m5stack-core2-sdu/firmware.binを適切な名前(xx_AiStackChan2FuncCall.bin等)に変更し、SDカードのルートディレクトリにコピーする。
※本リポジトリのCopy-to-SDフォルダにビルド済みのbinファイルを置いています。
※現状、Core2 V1.1ではランチャーソフトが動作しないため切り替えはできません。
画面の右端をタップすると表示が切り替わり、さまざまなステータスを確認できます。
時間を指定して任意のコールバック関数を実行することができます。サンプルとして次の動きを実装してあります。
コールバック関数は、次のようにadd_schedule()という関数と、スケジュールの種類毎(時間指定、一定間隔で繰り返し等)に用意したScheduleクラスを使って登録します。
/* MySchedule.cpp */
void init_schedule(void)
{
add_schedule(new ScheduleEveryDay(6, 30, sched_fn_wake)); //6:30 省エネモードから復帰
add_schedule(new ScheduleEveryDay(7, 00, sched_fn_morning_info)); //7:00 今日の日付、天気、メモの内容を話す
add_schedule(new ScheduleEveryDay(7, 30, sched_fn_morning_info)); //7:30 同上
add_schedule(new ScheduleEveryDay(23, 30, sched_fn_sleep)); //23:30 省エネモードに遷移
add_schedule(new ScheduleEveryHour(sched_fn_announce_time, 7, 23)); //時報(7時から23時の間)
add_schedule(new ScheduleIntervalMinute(5, sched_fn_recv_mail, 7, 23)); //5分置きに受信メールを確認(7時から23時の間)
}
各ScheduleクラスはScheduleBaseクラスを継承しており、仮想関数run()をどのようにオーバライドするかによって異なる動き(時間指定、一定間隔で繰り返し等)を実現しています。現在用意しているScheduleクラスは次の通りです。
クラス | 動作 | 備考 |
---|---|---|
ScheduleEveryDay | 毎日、指定した時間にコールバック関数を実行する | |
ScheduleEveryHour | 毎時、コールバック関数を実行する(主に時報用) | |
ScheduleIntervalMinute | 指定した間隔[分]でコールバック関数を繰り返し実行する | |
ScheduleReminder | 一度だけ指定した時間にコールバック関数を実行する | Function Callのリマインダー機能で使用している |
AIスタックチャン2同様、ウェイクワードに対応しています。使い方はAIスタックチャン2のREADMEを参照ください。
また、v0.6.0から、ウェイクワードを10個まで登録することが可能です。これにより、家族全員の声に反応するようにすることも可能になりました。
登録したウェイクワードのデータはSPIFFSにwakeword#.binという名前で保存されます。現行、10個に到達すると新たなウェイクワードは登録できませんので、Function Callingで「ウェイクワードの#番を削除して」とお願いするか、FFFTP等のFTPクライアントソフトで不要なウェイクワードを削除してください(FTPはユーザ名:stackchan、パスワード:stackchan)。
FFFTPでSPIFFSのファイル一覧を取得した様子
※ウェイクワードの誤認識が気になる場合は、DIST_THRESHOLD の値を小さくすると誤認識を減らせますが、小さくし過ぎると逆に正しい呼びかけにも反応しづらくなります。
WakeWord.h
#define DIST_THRESHOLD (250)
※CoreS3はA、Bボタンがないため、ウェイクワードの登録、有効化はFunction Callingで「ウェイクワードを登録」「ウェイクワードを有効化」というように指示してください。
CoreS3の場合、ポートAにLEDパネル(NeoPixel互換LED搭載 HEXボード )を接続すると、次の状態に応じて点灯します。
なお、起動完了時の流れるドット絵は次の手順で編集できます。
① tool/LED_Scroll_Pattern.xlsmでドット絵を編集してコードに変換する。
② HexLED.cpp内の配列led_scroll_pattern01の値を①のコードに差し替える。
※顔検出はメモリ消費量が多く動作が不安定になることがあるため、初期状態ではplatformio.iniで以下のように無効化されています。
build_flags=
-DBOARD_HAS_PSRAM
-DARDUINO_M5STACK_CORES3
;-DENABLE_FACE_DETECT
-DENABLE_WAKEWORD