Raspberry PiとChatGPTでつくるボイス・アシスタント・ロボット #2
ChatGPT実験ロボット "Voice Assistant Robot_GPT"
ハードウェア
- 本体: RaspberryPi4 ModelB 4GB
- パンチルトハット: Pimoroni Pan-Tilt HAT
- カラーLEDスティック: Adafruit NeoPixel Stick 8
- 熱対策(オプション) GeeekPi Fan Hat for Raspberry Pi 4 Model B
- 気温・湿度・照度・水分計測(オプション): WioNode
- USBマイク・USBスピーカー: RaspberryPiで使用可能なものを適宜使用してください
ソフトウェア
- OS: Raspberry Pi OS (64-bit) / Raspberry Pi 設定チートシート
- Python3.9.2: requirements
- 音声認識: Vosk / vosk-model-small-ja-0.22
- 音声発話: Aques Talk Pi / AquesTalk Installer
- 画像処理: OpenCV 64bit 4.5.5 / Install OpenCV on Raspberry 64 OS
- 顔認識モデル: yunet.onnx
- 顔識別モデル: face_recognizer_fast.onnx
- 性別識別モデル: gender_net.caffemodel / gender_deploy.prototxt
- 年令識別モデル: age_net.caffemodel / age_deploy.prototxt
- 物体識別モデル: frozen_inference_graph.pb / ssd_mobilenet_v3_large_coco_2020_01_14.pbtxt / coco.names
- モーター制御・LED制御: pantilt-hat
- 生成AI: ChatGPT API / openai
- LLMフレームワーク: LangChain
- 検索エンジンAPI: DuckDuckGo Search
仕組み
実験用ロボットの仕組みをフローチャートと共に解説します。
実験ロボット "VoiceAssistantRobot"
音声発話(ユーザー)
ユーザーの音声発話は、RaspberryPiに接続したUSBマイクから得た音声をPythonのオーディオライブラリPyAudioを使ってストリーミングします。
音声認識(Vosk)
ストリーミングデータを音声認識エンジンVoskを使いテキストに変換します。
コマンド実行(analyze関数)
独自関数analize()
により、入力されたテキストが事前に登録されたコマンドと一致するか、条件分岐により振り分けを行います。
実験用に登録した実行コマンドは以下の通りです
- 日時データ取得(
datetime
モジュール) - WioNodeからのデータ取得(
requests
モジュールを利用したGETメソッド) - 顔認証・物体認識(OpenCVとDNNモデルを使ったリアルタイム顔認識、物体認識)
- サーボモーター・LEDライト制御(PanTiltHATライブラリを使用)
コマンドの実行と合わせて、ロボットの回答は事前に記述しておきます。
音声合成(Aques Talk Pi)
各コマンドの回答テキストはAques Talk Piを使って音声合成を行います。Pythonのsubprocess
を使い、合成音声されたwavファイルをパイプでつなぎaplay
で再生出来るようになっており、記述がシンプルに行えます。
合成音声発話(ロボット)
aplay
で再生されたwavファイルをスピーカーで再生します。
ChatGPT実験ロボット "VoiceAssistantRobot_GPT"
LangChain Agent
上記チャート図のanalize
をLangChainの「エージェント」機能を使って置き換えます。ドキュメントには以下のように書かれています。
アプリケーションによっては、LLM/他のツール(
tools
)へのあらかじめ決められた呼び出しの連鎖(chain
)だけでなく、ユーザーの入力に依存する未知の連鎖を必要とする可能性があります。このような連鎖では、一連のツールにアクセスできる "エージェント(Agent
)"を活用できます。ユーザーの入力に応じて、エージェントはこれらのツールのうちどれを呼び出すかを決定することができます。
引用: Agent | 🦜️🔗 LangChain
事前に定義したtools
の順番や実行を「エージェント」が実行します。名前が似ていて少しややこしいのですが、「エージェント」のTool
モジュールを使うことで用途別のツールを利用することができます。例を挙げると、数学の計算を行うllm-math
モジュールやGoogleカスタム検索を行うgoogle-serper
などがあります。
実験用に登録したTool
は以下の2つのモジュールです
- 複雑な計算を行うツール(
LLMMathChain
モジュール) - DuckDuckGoで検索を行うツール(
DuckDuckGoSearchRun
モジュール)
検索モジュールはGoogle、Microsoftともに利用数に応じてAPIが有料となるため、無料で利用できるDuckDuckGo検索モジュールを選択しました。
「エージェント」はlangchainが用意したモジュールだけでなく、ChatGPTのFunction calling
(関数呼び出し)機能をツールとして利用することが出来ます。以下LangChainのドキュメント引用です、
特定のOpenAIモデル(gpt-3.5-turbo-0613やgpt-4-0613など)は、関数が呼び出されるタイミングを検出し、関数に渡されるべき入力を応答するように微調整されています。API呼び出しの中で、関数を記述し、モデルがそれらの関数を呼び出すための引数を含むJSONオブジェクトを出力するようにインテリジェントに選択することができます。OpenAI関数APIのゴールは、一般的なテキスト補完やチャットAPIよりも、より確実に有効で有用な関数呼び出しを返すことです。
OpenAI Functions Agent
は、これらのモデルで動作するように設計されています。
引用: OpenAI functions | 🦜️🔗 LangChain
ChatGPTのプロンプトを定義する際、ヘルパー関数OpenAIFunctionsAgent
を使うことで、ChatGPTのFunction calling
機能をツールに指定することが出来ます。Function calling
をツールとして指定する際はデコレート関数@tool
で定義します。
実験用に定義した@tool
は以下の通りです
- 日時データ取得(
datetime
モジュール) - WioNodeからのデータ取得(
requests
モジュールを利用したGETメソッド) - 顔認証・物体認識(OpenCVとDNNモデルを使ったリアルタイム顔認識、物体認識)
- サーボモーター・LEDライト制御(PanTiltHATライブラリを利用)
テキストに変換された音声データをChatGPT API経由で送信すると、「エージェント」が自律的にに定義したツールを選択し、実行します。その際、ChatGPTの関数呼び出し機能を「エージェント」が適切に活用し、返される関数呼び出し結果を回答します。
この仕組みにより、実験ロボットはユーザーの様々なリクエストに対して柔軟な応答やアクションを行うことが出来ます。
Discussion