生成AIでもっとスマートなスピーカーを作りたい!【意図を察して家電操作編】

はじめに

こんにちは、AIコンサルティンググループの清水です。

スマートスピーカーに話しかけるだけで、もっと柔軟に家電を操作できたら便利だと思いませんか? 例えば、「ちょっと寒い」と話しかけるだけでエアコンが暖房をつけてくれたり、「眠い」と言えば照明を消してくれたり。

前回の記事に引き続き、Alexa(Amazon Echoなどに搭載されている音声アシスタント)と生成AIを連携させ、ユーザーの曖昧な指示でも意図を汲み取って家電を操作するような"もっとスマートなスピーカー" を作ることを最終ゴールとしています。実際に自宅のAlexaで動かしてみた動画もあるので、技術部分を読み飛ばして最後の結果だけでも見てもらえれば嬉しいです。

前回の記事では、Alexaと生成AIを対話させるための基本的な仕組み(Alexaスキル ※)を作成しました。
※Alexaスキル:特定の機能を追加するためのAlexa用のアプリのようなもの。

今回はその仕組みをさらに発展させ、対話を通じて得られたユーザーの意図に基づき、実際に家電を操作する機能を実装します。この記事のポイントは、単にAlexaとAIを対話させるだけでなく、その対話内容に応じて、外部APIを呼び出し、物理的なデバイス(家電)を操作するという、一連の流れを繋ぎ合わせて実装した点にあります。

本記事では、"もっとスマートなスピーカー"を実現するために、スマートスピーカーの以下の開発方法に関して紹介します。

  • 外部 API(SwitchBot API)を呼び出して実際に家電を動かす部分の実装
  • 生成AIが「寒い」「眠い」といった曖昧な指示から、具体的な家電操作を判断させる部分(Function Calling)の実装
  • Alexaに話しかけるだけで、本当に意図通りに家電が動くのか? 実際に試してみた結果とその動画

 

スマートスピーカーの進化と業界動向

最近のスマートスピーカーでは、ユーザーのリクエストに柔軟に対応してくれるようなアシスタントを続々発表しています。

例えばAmazonでは、2025年2月、「Alexa+」という生成AI搭載の次世代アシスタントを発表しました。Amazonによれば、「単なる会話だけでなく、実際にタスクを実行できる」ことを大きな特徴としており、スマートホームデバイスの操作はもちろん、レストランの予約やチケットの購入まで行えるようになると発表されています。最初の提供地域は北米から数ヶ月ごとに段階的に広げていくとのことです。

また、Googleも2025年3月に、ほとんどのデバイスを「Google アシスタント」から「Gemini」に数ヶ月かけて更新していくと発表しています。今まではPublic Previewでの提供で、いくつか設定が必要でしたが、これからは一般ユーザーにも提供されていくようです。

このような業界の動きからも、スマートスピーカーは「単なる音楽プレーヤーや天気予報を伝えるだけのデバイス」から、「高度な判断ができる生活アシスタント」へと進化していることがわかります。いわゆる自律的に行動する「AIエージェント」となり、さらに便利になっていきそうです。「AIエージェント」についてはいくつか過去記事もあるのでぜひ見てみてください。

 

従来のスマートスピーカーの限界

従来のスマートスピーカーによる家電操作は、ほとんどが「定型コマンド」によるものでした。例えば:

・「エアコンをつけて」→ エアコンがONになる
・「照明を消して」→ 照明がOFFになる

しかし、既存の製品は以下のような曖昧な指示からユーザーの意図を察して実行するのは苦手でした:

・「暑い」→ エアコンがONになる
・「眠い」→ 照明がOFFになる

これらのような曖昧な指示に対して、我が家のAlexaくんは、「すみません、よくわかりません」と返すだけです。「Alexa+」ではこういったユーザーのニュアンスや意図を理解して柔軟に対応してくれると期待しています。ただし、日本ではまだ未対応なので待つしかありません。しかし私もエンジニアの端くれ、ないものは自分で作ればいいじゃないか!ということで生成AIを使い、曖昧な指示で、意図を察して家電操作をしてくれるスマートなスピーカーを作ってみます。

技術構成

今回実装したシステムの構成は以下のようになっています:

この流れを詳しく説明すると:

1. ユーザーの音声入力: 「ちょっと寒い」などの指示

2. 音声認識・テキスト変換: Alexaが音声を認識してテキストに変換

3.AIによる家電操作の判断: Azure OpenAI Serviceで指示を分析し、最適な操作を判断

4. 家電操作: SwitchBot Hub 2を通じて適切な家電操作を実行

5. 結果の報告: 操作結果を自然言語でユーザーに報告

前回の記事では、生成AIと対話する部分は作成しました。今回は主に質問に応じてAIが判断して家電操作(SwitchBot APIで送受信)を作成しました。家電を実際に操作するのは、スマートホームハブとして販売されているSwitchBot Hub 2で、もともとは温度計がついているので部屋の室温をみたり、ベッドでエアコンや照明をつけるのが目的で購入したものですが、IoT機能として提供されているSwitchBot APIにより、プログラムから操作して室温情報の取得や家電操作を自分のアプリケーションに組み込みやすいのもいい点です。

 

SwitchBot APIによる家電操作

家のIoTデバイスの構成として、Alexaに対してSwitchBot Hub 2を経由してエアコンや照明を繋げて操作しています。特にSwitchBotでは、家電を繋げてくれるだけでなく、情報取得や操作を行うAPIも提供しています。これにより、自作のアプリケーションでも家電の情報を取得したり、操作を行ったりすることができます。今回はSwitchBot APIの仕様をもとに、デバイスの一覧の取得、Hub 2の状態の取得(部屋の湿度や温度)、エアコンの操作、照明の操作を実行する関数を作成しました。

ただ、これを実装するのは、Hub 2やエアコン、照明などの各デバイスについてのSwitchBot APIの仕様を読む必要があり、少し面倒でした。そこで最近GitHub Copilotのagent modeが一般公開されたので、ちょうどいい機会なので使ってみました。GitHub Copilotはコーディングでの補完機能や編集などの多機能なAIコードアシスタントです。コーディングするときや文章を書くときによく利用していて、非常に重宝しています。よく使うVS Codeの拡張機能で使えるのがハードル低くていい点です。そして最近、GitHub Copilotに agent modeというWeb検索で情報を取得しつつ、複数ファイルを跨いで編集を実行、といった複数のタスクを自分で考えて実行してくれる機能が登場しました。これを使うことで、APIのGitHubリポジトリのリンクを見せると、APIの仕様を理解しつつ、実装してもらえるので便利です。

適宜修正しつつ、出来上がったSwitchBot APIを利用して家電を操作するコードは以下です。

Python
def get_headers(token, secret):
    """SwitchBot API認証用のヘッダーを生成"""
    nonce = uuid.uuid4()
    t = int(round(time.time() * 1000))
    string_to_sign = '{}{}{}'.format(token, t, nonce)

    string_to_sign = bytes(string_to_sign, 'utf-8')
    secret = bytes(secret, 'utf-8')

    sign = base64.b64encode(hmac.new(secret, msg=string_to_sign, digestmod=hashlib.sha256).digest())

    headers = {
        'Authorization': token,
        'Content-Type': 'application/json; charset=utf8',
        't': str(t),
        'sign': str(sign, 'utf-8'),
        'nonce': str(nonce)
    }
    return headers


def get_device_list(token, secret):
    """すべてのSwitchBotデバイスの一覧を取得"""
    url = 'https://api.switch-bot.com/v1.1/devices'
    headers = get_headers(token, secret)
    response = requests.get(url, headers=headers)
    return response.json()


def get_device_status(device_id, token, secret):
    """デバイスの現在の状態を取得"""
    url = f'https://api.switch-bot.com/v1.1/devices/{device_id}/status'
    headers = get_headers(token, secret)
    response = requests.get(url, headers=headers)
    return response.json()


def control_light(device_id, token, secret, power_state):
    """照明のオン/オフを制御"""
    url = f'https://api.switch-bot.com/v1.1/devices/{device_id}/commands'
    headers = get_headers(token, secret)
    payload = {
        'command': 'turnOn' if power_state == 'on' else 'turnOff',
        'parameter': 'default',
        'commandType': 'command'
    }
    response = requests.post(url, headers=headers, json=payload)
    return response.json()


def control_aircon(device_id, token, secret, temp, mode, fan_speed, power_state):
    """エアコンの温度、モード、風量、電源を制御"""
    url = f'https://api.switch-bot.com/v1.1/devices/{device_id}/commands'
    headers = get_headers(token, secret)
    payload = {
        'command': 'setAll',
        'parameter': f'{temp},{mode},{fan_speed},{power_state}',
        'commandType': 'command'
    }
    response = requests.post(url, headers=headers, json=payload)
    return response.json()

AIによる家電操作の判断

先ほどは、実際に家電操作を行う部分は作りました。あとはユーザーの指示に対して、生成AIが何のデバイスをどの設定値で操作するか判断する部分を作ります。
生成AIが判断ができるように、Azure OpenAI ServiceのFunction Calling機能を活用しています。これを用いることで、質問に対して、適切な引数を入れて定義した関数を呼び出してくれます。

Python
tools = [
    {
        "type": "function",
        "function": {
            "name": "aircon_control",
            "description": "エアコンを操作します",
            "parameters": {
                "type": "object",
                "properties": {
                    "power_state": {
                        "type": "string",
                        "enum": ["on", "off"],
                        "description": "エアコンのオン/オフ状態"
                    },
                    "mode": {
                        "type": "integer",
                        "enum": [0, 1, 2, 3, 4, 5],
                        "description": "運転モード: 0/1=自動, 2=冷房, 3=除湿, 4=送風, 5=暖房"
                    },
                    # ...他のパラメータ...
                }
            }
        }
    }
]

この機能により、生成AIは「暑い」という曖昧な指示から、エアコンを操作する関数に電源や運転モードなどを考えて実行します。

Alexaでの実行結果

上記を実装し、前回の記事の生成AIとの対話部分と組み合わせることで、家電操作ができるようになりました。実際に動かしてみると、以下のような会話が実現できました。

 

試しに動かしてみると、「ちょっと寒い」「もうちょっとあったかくして」といった曖昧な表現に対して、生成AIが状況を理解して適切なエアコン操作を行い、「そろそろ眠い」という発言から就寝準備のために照明を消すという判断をしています。従来のスマートスピーカーでは実現が難しかった、ニュアンスを理解した自然な対話が可能になっています。

一方で、たまに冷房、暖房の指定が逆になっている現象がみられました。原因としては、運転モードを指定する際に、各運転モードに対応する数値[0, 1, 2, 3, 4, 5]を指定する必要があり、生成AIにとってわかりづらい仕様になっていることが考えられます。Function Callingでは関数定義や引数ができるだけ分かりやすいものがいいとされていますが、数値による指定では人間でも「どの番号が冷房と対応してたっけ?」と迷うことがあるので、関数の引数をより明確に英単語に変更すると精度が上がりました。また、送風モードは使っているエアコンでは使えないので削除しています。

Python
"mode": {
        "type": "string",
        "enum": ["auto", "cool", "dry", "heat"],
        "description": "運転モード: auto=自動, cool=冷房, dry=除湿, heat=暖房"
}

最終的に自宅のAlexaで動くようにしました。動画は以下です。

まとめとスマートスピーカーの今後

生成AIを活用することで、従来のスマートスピーカーでは難しかった「意図を理解した柔軟な対応」が可能になりました。例えば、「ちょっと寒い」といった曖昧な指示に対しても、エアコンの温度を調整するなど、ユーザーの気持ちを汲み取って実行してくれます。

実際使ってみると、私生活のなかで、何かしながら生成AIを呼び出せるのは便利に感じます。また、デバイスの指定などの細かい指示が不要で以前感じていたストレスが無くなりました。

今回実装したのは家電操作だけを行うシンプルなものですが、関数次第でWeb検索や予定の管理など幅広い操作を行わせることができます。ただし、ツールとなる関数を作成するのが手間なので、もっと操作可能な家電を楽に増やしたいところです。最近ではそういった需要が高まり、MCPサーバーといったものが登場し、上記のような操作を手軽に生成AIに組み込めるようになりつつあります。スマートスピーカーでもMCPサーバーとの接続が簡単になれば、好みの操作を登録して音声で指示させることが実現しそうです。

また、一度に複数のステップで実行してくれるようなAIエージェントも組み込まれて、店の予約などの複雑な処理も会話でできるようになりそうです。そうなると、生活に生成AIやAIエージェントが浸透していくことをより感じられそうですね。

筆者
AIコンサルティンググループ
清水 大輝