見出し画像

スタックチャンの声は、どこへ行っているのか

ローカルLLM化の前に地図を描く


前回、スタックチャンの記事を書きました。

その記事の最後で、私はこう書いています。

 あとは、自分の使用したいAIの設定に適宜変更してください。

適宜とは?

数週間後、私のPCにはOllama、FunASR、Docker、XiaoZhi互換サーバーが並んでいました。

さらに後からVOICEVOXが増え、ラズベリーパイが加わり、設定を切り替えるためのボタンまで生えてきました。

何ひとつ「適宜」ではなかった。

ローカルLLMでスタックチャンを喋らせる手順を書こうと思ったのですが、そもそも私自身が「何が、どこで、何をしているのか」を整理し直す必要がありました。

今回は具体的なコマンドを入力しません。

まず、スタックチャンの声がどこへ行き、どこで返事が作られ、どこから音声になって戻ってくるのか。工事を始める前に、地図を描きます。


買ったままのスタックチャンは、誰と話しているのか

スタックチャンは、購入時の公式ファームウェアのままでもAIと会話できます。

私も最初は、初期設定で選べるQwenを使って動作確認をしました。話しかければ返事をします。首も動きます。「機械として正常に動いているか」を確かめるには、これが一番簡単です。

ただし、このAIがスタックチャン本体の中だけで動いているわけではありません。

スタックチャン本体には、マイク、スピーカー、画面、カメラ、首を動かすモーターなどがあります。しかし、大きなAIモデルを本体の中で動かしているわけではなく、AI Agentを使うにはインターネット上のサービスへ接続します。

私が調べた時点では、

`api.tenclass.net/xiaozhi/`
`api.tenclass.net/xiaozhi/v1/`
`mqtt.xiaozhi.me`

上記のサーバーへ接続されているようでした。
私自身がパケットを取得したわけではなく、M5Stack公式リポジトリのissueに投稿されていた通信ログを見て知りました。

Tenclassの公式サイトによると、Tenclassは中国・深圳の企業で、XiaoZhi AIを運営しています。

つまり、少なくとも
「買ったままAI Agentを使えば、
音声会話が端末と自宅の中だけで完結する」

という構成ではありません。

公開されている接続先から運営元は確認できますが、実際の処理がどの国のデータセンターで行われるのか、音声や会話がどのように保存されるのかまでは、私は確認できていません。

それでも、「自分の声をどのサービスへ送っているのか知りたい」「海外のサービスを経由せずに使いたい」と考える人にとって、接続先は最初に確認したいところだと思います。

私も、そこが気になった一人でした。


「自分のAIを使う」には、大きく三つの道がある

調べていくと、スタックチャンで自分の好きなAIを使う方法は、大きく三つに分かれていることがわかりました。

1.公式ファームウェアのAI Agentを使う

一番簡単な方法です。
公式マニュアルを見て行う、前回の私の記事の設定そのままにするだけです。


2.コミュニティ製ファームウェアを使う

技術力のある人が制作してくれたファームウェアを使用する方法です。
コミュニティ製ファームウェアの例として、
ciniml/stackchan-idf
があります。

このファームウェアは、OpenAI Realtime、Google Gemini Live、XiaoZhiサーバーへの接続に対応しています。OpenAIやGeminiのAPIキーはファームウェアへ埋め込むのではなく、設定画面から入力し、スタックチャン本体のNVSという保存領域へ入る仕組みになっています。

Web Flasherも用意されているため、ソースコードを自分でビルドしなくても、ブラウザから書き込めます。
多くの人にとっては、この道が「自分の好きなAIを、比較的簡単にスタックチャンで使う」方法になると思います。


3.自宅に会話サーバーを建てる

XiaoZhiサーバーのようなものを自前で用意する方法です。
会話処理をできるだけ自宅側へ移したい場合は、この方法が候補になります。

私は三番目を選びました。
自宅のPCで動かしているGemmaで、スタックチャンを会話させてみたかったからです。
サーバーは自宅PC内のDocker内に設置しました。
私の構成では、スタックチャンとローカルLLMで会話するために、Docker内のXiaoZhi互換サーバーとOllamaを起動しておく必要があります。
これにはかなり苦労して・・・ChatGPTに言われるがままに作業を進めたので自分の言葉で説明がしづらい部分です。

Dockerとは、アプリケーションと、その動作に必要な環境をひとまとめにして動かす仕組みです。

今回は、XiaoZhi互換サーバーを私のWindows環境へ直接組み込むのではなく、Dockerの中で動かしました。箱ごと用意された実行環境を、PCの上で動かすようなイメージです。


Ollamaを入れれば完成ではない

私は最初、OllamaでGemmaが動けば、それをスタックチャンにつなぐだけで会話できるような気がしていました。

しかし、OllamaとGemmaが担当するのは、基本的に「文字を受け取り、返事の文字を作る」部分です。

人間にたとえるなら、脳だけが机の上に置かれています。
スタックチャンと声で会話するには、ほかにも役割が必要でした。

Ollamaを入れた段階では、耳も声帯も受付係もいません。

おめでとうございます。脳ができました。🧠
しかし話しかけても、完全に無視されます。🥹

耳・脳・声帯の正体

ここで、私の構成に登場する「耳・脳・声帯」が、実際には何をしているのか整理します。

耳は、FunASRとSenseVoiceSmallです。

FunASRは、音声認識を動かすための仕組みです。その中で実際に音声を聞き取り、文字へ変換するモデルとして、SenseVoiceSmallを使用しました。

人間でたとえるなら、FunASRが「聞き取り窓口」で、SenseVoiceSmallがそこで働いている「聞き取り担当者」のような関係です。

脳は、Ollamaで動かしているGemmaです。

耳が音声を文字にすると、その文章をGemmaへ渡します。Gemmaが返答を考え、今度は文章で答えを返します。
ここまでは、私の自宅にあるPCの中で処理されています。

声帯は、最初に動かした構成ではEdgeTTSでした。

Gemmaが作った返答文を、EdgeTTSが音声へ変換します。ただし、EdgeTTSはPCにインストールして使うソフトではあるものの、音声合成そのものにはMicrosoftのオンラインサービスを利用します。

これで、耳、脳、声帯はそろいました。
しかし、三つとも同じ場所にいたわけではありません。


「ローカルLLM」と「全部ローカル」は同じではない

ここが、私が一番混乱したところです。

ローカルLLMを使っていても、会話に使うすべての処理が自宅内にあるとは限りません。

たとえば、返事を考えるGemmaは自分のPCで動かし、音声認識は外部サービスへ送る構成も作れます。反対に、音声認識とLLMは自宅で動かしていても、読み上げだけオンラインのサービスを使う構成もあります。

「ローカルか、クラウドか」の二択ではなく、耳、脳、声帯を一つずつ、どこへ置くか決める話でした。

私が最初に会話まで成功した構成は、次のようになっていました。

私の声

スタックチャン

自宅のXiaoZhi互換サーバー

FunASR/SenseVoiceSmall(声を文字にする)

Ollama/Gemma(返事を考える)

EdgeTTS(返事を音声にする)

スタックチャンが喋る


このとき、音声認識(耳)とLLM(脳)は自宅のPCで動いていました。

しかし、EdgeTTS(声帯)はMicrosoft Edgeのオンライン音声合成サービスを使うツールです。EdgeTTSで返答文を音声へ変換するときは、音声合成のためにMicrosoftのオンラインサービスへ接続していたということです。つまり、最初に成功した構成は、会話処理の多くを自宅へ移してはいましたが、全部がローカルだったわけではありません。

私は後から、Claude Code内のClaudeがPCやスタックチャンから喋るための声としてVOICEVOXを追加しました。VOICEVOXは自宅のPCで動かせます。
読み上げ部分をVOICEVOXへ切り替えれば、少なくとも音声合成のために外部サービスへ接続する必要はなくなります。

VOICEVOXは、ずんだもんで有名な「無料で使える中品質なテキスト読み上げ・歌声合成ソフトウェア」です。
「~なのだ!」って話すアレです。

ただし、既存のGemmaとの通常会話と、Claudeが追加した発話経路は別です。現在どの会話がどちらの声帯を通っているのかは、サービスを一つずつ止めて確認しないと断定できません。

「ローカルLLMで喋りました!」と書くのは簡単です。

でも、声の入口から出口までを調べると、ローカルの中にも濃淡がありました。


ここからは、私が実際にこの構成へたどり着くまでの話です。

最初に作った会話経路

最初から、現在の仕組みが全部できていたわけではありません。
私が最初に作ったのは、一本の会話経路でした。
分からないなりに、とりあえずローカルLLMのGemmaが音声で発話できる状態を目指しました。

スタックチャンの声が自宅のXiaoZhi互換サーバーへ届く

FunASR上で動くSenseVoiceSmallが、日本語の音声を文字にする

その文字をOllamaで動く`gemma4:e4b` が受け取り、返事を考える

EdgeTTSが返事を音声にして、スタックチャンのスピーカーから再生する

ここまでの会話経路は、ChatGPTと少しずつ確認しながら作りました。

実際にスタックチャンが私の声を聞き、Gemmaが日本語で返事をしたとき、ようやく一本の経路がつながりました。

「赤く光って」と頼むと、Gemmaが用意された道具を使い、スタックチャンのLEDを赤くするところまで動きました。

ここまでが、後からClaude CodeのClaudeが目や口や手足を増築する前に、私とChatGPTで作った基盤です。


複数のPCから接続したくなった

その後、「メインPCだけでなく、ノートPCのローカルLLMも使いたい」と考えました。

しかし、PCを替えるたびにスタックチャンのファームウェアを書き換えるのは面倒です。


そこで、スタックチャンがいつも接続する住所をラズベリーパイの固定IP `192.168.0.2` にしました。メインPCは `192.168.0.3` へ移し、将来ノートPCを追加しても、ラズベリーパイ側の設定を切り替えれば済む形を考えました。

ラズベリーパイ(Raspberry Pi)とは、Linux OSで動作する超小型のPCのようなものです。 私は既に所有していたRaspberry Pi 4を使用しました。


スタックチャン
↓ いつも 192.168.0.2 へ接続
ラズベリーパイ(入口)

そのとき使うPCのローカルLLM

この構成なら、スタックチャンから見ると、いつも同じ受付へ行けばよいだけなので、切り替えが楽になります。

現在、ラズベリーパイではスタックチャン用のDockerやローカルLLMを動かしていません。ラズベリーパイは、スタックチャンから届いた通信を、メインPCで動いているDocker/XiaoZhi互換サーバーへ転送する中継役です。

そのため、現在はメインPCを終了すると会話も止まります。ラズベリーパイを「いつも同じ住所の受付」にしたことで、PCを替えるたびにスタックチャンのファームウェアを書き換えなくて済むようにした、という段階です。


Claude CodeのAIから接続する

ここまで設定した後、Claude CodeのClaudeがスタックチャンを使えるようにしたくなりました。

ここまで設定してきて疲れた私は、CC内のClaudeにMCPを作ってもらうことにしました。
サクサクとMCPを増設していくClaude。
正直何をしているのかよくわかりませんでした。😂

Claudeはすでに動いていた基盤へ、Webカメラの目、PCのマイクの耳、VOICEVOXの口、スタックチャンの首やLEDを操作する手足を、MCPとして増設しました。Claudeは家を建てたのではなく、完成していた家に自分用の目と口と手足を増築したのです。

こうして私は、スタックチャンをローカルLLMで喋らせようとしていたはずなのに、いつの間にかAIたちが身体を共有する施設を建設していました。


公式ファームウェアへは戻せる

ファームウェアを書き換えるとき、私が最初に怖かったのは
「元へ戻せなくなったらどうしよう」でした。

「文鎮になる」とかなんとかそういう言葉を聞いて
ビビってしまったのです。

※書き込みに失敗する可能性がないわけではありませんが、少なくとも公式の復旧手順は用意されています。

現在、M5Stackの公式ドキュメントには、M5Burnerを使って公式ファームウェアへ戻す手順があります。

M5Burnerで `StackChan` を検索し、`Only Official` を選び、公式ファームウェアを書き込めます。

M5 Burnerの画面写真

つまり、公式へ戻るためだけなら、公式ファームウェアのソースコードを自分でビルドする必要はありません。

私はそれを知らず、先に公式ファームウェアをソースからビルドしました。

工場を建て終わってから、隣にホームセンターがあることを知りました。

やばかったときのために、復旧方法を先に確認しておこう!と思い行いました😂😂復旧確認としては不要でした。ただ、このあと接続先を書き換えたファームウェアを自分でビルドすることになるので、予行演習にはなっていました。

なお、`ciniml/stackchan-idf`のWeb Flasherにある「初回/リカバリ時用」は、同ファームウェアを初めて入れる、または入れ直すためのものです。M5Stackの純正ファームウェアへ戻す機能ではありません。

戻る先は実家ではなく、改造先の新居です。


まずは、自分がどこまでローカルにしたいのか

ここまで整理して、ようやく最初に考えるべきことが分かりました。

いきなりファームウェアを焼くのではなく、まず自分が何をしたいのかを分解します。

  • 好きなクラウド系AIと、簡単に会話できればよいのか

  • 返事を考えるLLMだけ、自宅のPCで動かしたいのか

  • 音声認識や音声合成も、自宅の中へ置きたいのか

  • スタックチャンの首、LED、カメラまでAIから使いたいのか

  • 複数のPCやモデルを切り替えたいのか

ここが決まらないと、必要なものも決まりません。

クラウドAPIなら、耳、脳、声帯がそろったコールセンターへ接続できます。

ローカル構成では、それを全部自分で用意します。

これからローカルLLMでスタックチャンを動かしたい人が、自分に必要な構成を考える材料になれば幸いです。

私は「Gemmaをスタックチャンから使いたい」と思っただけでした。
ところが、受付係を雇い、耳と脳と声帯を用意し、住所を決め、別のPCへ案内する係まで置いていました。

何を建設しているんだ。


参考リンク


いいなと思ったら応援しよう!