Macbookで動く、ボイス設定可能な音声アシスタントを作る
現在世に出回っているLLMアプリはチャットUIが主流となっています。
でも、すでにあるSiriやAlexaやGoogle Homeのように、音声でのコミュニケーションの中にLLMを組み込んでいければその応用範囲はもっと広がっていくと思いませんか?
そこで今回は、LLMとwhisper、Style-Bert-VITS2を組み合わせて、CPUで動く常駐型の音声アシスタントをPythonで作ってみました。
以下のリポジトリにソースコードも公開しています!
デモ
こんな感じで、音声での入力に対して返答が返ってきます。返答内容はLLMによって生成されています。
検証環境
以下の環境で検証しています。
- Macbook Pro (Apple M1 Pro, メモリ32GB)
- Python 3.12
使用している技術
音声認識: openai-whisper
音声認識はOpenAIが公開しているwhisperをローカルで動作させて実現しています。
動作の高速化のため、faster-whisperおよび先月公開されたturboモデルを利用しています。
またマイクに接続してリアルタイムな音声認識を動作させるためにwhisper_micというライブラリを利用しています。
詳細はこちらの記事にもまとめています。
音声合成: Style-Bert-VITS2
Style-Bert-VITS2(SBV2)は、感情豊かな音声を生成できる高性能な音声合成モデルであるBert-VITS2をベースに、日本語音声に特化した改良を加えたモデルです。Bertを活用して感情や発話スタイルを制御でき、少数の音声データセットから学習した独自のモデルを簡単に作成することができます。
制作者の方が記事を公開されているので詳細はこちらをご参照ください。
構成
プログラムは以下のコンポーネントで構成されています。
-
Style-Bert-VITS2 + FastAPI サーバー: ローカルのWebサーバーでエンドポイント
/speak
を提供し、Style-Bert-VITS2による音声合成処理を実行する - whisper_mic: 音声入力を待ち受けるバックグラウンドプロセス
- Assistant: 音声認識結果を受け取り、LLM による応答を生成して音声合成サーバーへのリクエストを送信
動作フローは以下のようになります。
- whisper_mic が音声入力を検知
- 音声認識を実行し、結果を Assistant に渡す
- Assistant が LLM で応答を生成
- FastAPI サーバーに音声合成リクエストを送信
- 合成された音声を再生
音声合成過程では、文章を句点ごとに分割し、並列で音声合成を実行して準備ができたところまでを段階的に再生することで、遅延の削減を行なっています。
また、音声合成はあえてWebサーバーにせずにAssistantから直接実行することもできますが、拡張性を考えてAssistant本体からは切り分ける構成としています。
カスタマイズ
必要に応じて以下の設定項目をカスタマイズすることができます。
- 音声認識のwhisperではturbo+faster-whisperをCPUで動かしていますが、環境によってより軽量なモデルやGPUを使って高速化できます。
- LLMには任意のモデルが使えます。またLangGraph等を組み合わせてよりエージェント的な振る舞いを実装することもできます。
- 合成音声にはStyle-Bert-VITS2で学習した好きなモデルが使えます! 学習方法の詳細は本家のREADMEを参照してください。
[Mac] Dockへの追加と自動起動
PCの起動のたびに毎回自分で立ち上げるのはめんどくさいので、ワンクリックでポチッと立ち上げたい & できるなら勝手に起動するようにしたいです。
pyinstallerを使ってアプリ化する方法なども検討したのですが、シェルスクリプトをcommand化してDockに登録するのが一番簡単だと思います。
こちらの記事を参考にさせて頂きました。アイコンも設定できますし、「オプション > ログイン時に開く」で自動起動も設定できます。
がおぱわるぅアイコンにしてみました
改善ポイント
返答までの遅延
音声認識+LLM返答生成+音声合成までで合わせて10-15秒程度、長い文章の場合はさらに時間がかかります。ストレスなく使うにはこのラグをいかに削減できるかが課題になりそうです。音声合成についてはすでにセンテンス分割によるパフォーマンス改善を行なっていますが、音声認識・LLM返答生成においてもストリーミング的に処理することで改善できる余地はありそうです。
音声認識精度(日本語以外で解釈されてしまう)
音声認識がうまくいかず英語で解釈されてしまうことがあります。この場合にはLLMの返答も英語で返ってくるのですが、読み上げがアルファベットでの発話(askをエーエスケーのように読んでしまう)になってしまいます。この辺りはStyle-Berts-VITS2の設定で何とかできそうでもありますが、日本語以外のメッセージが来たら無視するとかでも良いかもしれません。
LLM部分の作り込み
LLM部分は現在素のchat completionを繋いでいるだけなので、天気を調べることもできません。ここはRAGやfunction call・エージェント動作などを実装することで複雑なタスクをお願いすることができるようになるはずなので、今後試していきたいと思っています。
クレジット
サンプルとして以下の音声モデルをお借りしています。モデルの利用の際は、ライセンスや利用規約を十分に確認してください。
特にStyle-Bert-VITS2の利用にあたっては利用規約をよく確認してください。デフォルトの事前学習モデルはデータの出所が不明な部分があるため、つくよみちゃんコーパスを使った事前学習モデル等の利用も検討してもらえると良いかと思います。
サンプルモデルとして以下のモデルをお借りしています。
- Style-BertVITS2 モデル:
- https://huggingface.co/litagin/sbv2_koharune_ami
- 小春音アミ、あみたろの声素材工房 (https://amitaro.net/)
その他、以下のパッケージを利用しています。
Discussion