Dify と Style-Bert-VITS2 でライブ配信風音声チャットを実現 (ローカル専用)

今回作ってみたのは、Dify を使った音声チャットボットです。キーボードからの入力に対し、生成 AI が音声で答えてくれます。遊んでみた感覚としては、ちょっとラグがあってから声で返事があるので、ライブ配信に参加している感じに近いですね。参加したことないですけど。あと、昔で言えば、人工無能を使った BBS シミュレータといったところでしょうか。昔で言い換える必要も無いんですけど。

ローカル専用です

Dify でチャットボットを作り、Ollama のローカル LLM に推論させ、Style-Bert-VITS2 にしゃべらせる、という構成です。もちろん自分で作った (学習させた) 音声モデルを利用できます。Style-Bert-VITS2 が走っているサーバに直接しゃべらせるので、ローカル専用です。Dify には (本記事執筆時の最新版 0.9.1-fix1 でも) 簡単に音声ファイルを再生する機能が無いため、ある意味苦肉の策です。Style-Bert-VITS2 の API サーバに物理的に音声再生能力があれば、Mac じゃなくても今回紹介する (本家を少しいじっただけの) スクリプトで実現できると思います。

環境構築

Dify と Ollama の構築はボクのブログの別記事を見てください。RAM がいっぱい (64GB 以上) あれば、1台の Mac でまかなえます。ボクの Mac は 32GB しか RAM が無いので、Dify を別の Mac (mini) で走らせています。

下の記事で紹介していますが、Style-Bert-VITS2 の CPU 学習可能版を作りました。Mac ユーザや CUDA が動かない環境の方向けです。ブログ記事 (というか GitHub) を参考に環境を作ってください。CUDA が動く環境の方は、本家の Style-Bert-VITS2 で大丈夫です。

API サーバスクリプトの説明

まず、すでに環境構築済みの方は、pydubをインストールしてください。今回新たに構築した場合は、インストールされているはずです。

pip install pydub

しゃべる API サーバの server_speech_fastapi.py は、元のスクリプト server_fastapi.py に音声再生機能を追加しただけです。追加変更箇所は以下ですが、まるごと持って行くならこちらからどうぞ

# サーバサイドで再生する為にインポート
from pydub import AudioSegment
from pydub.playback import play
            # 以下 2行追加して、音声を再生。wav のかわりに、テキストを返す
            speech = AudioSegment.from_file(wavContent, format="wav")
            play(speech)
            #return Response(content=wavContent.getvalue(), media_type="audio/wav")
            return Response(content=text, media_type="text/html")

Response は、音声合成に使用した (クライアントから送られた) テキストです。何の工夫も無くごめんなさい。ただ、音声の再生ということで言えば、音声データをクライアントに送りクライアントが再生するとか、サーバ自身で再生するにしても、一度ファイルとして書き出してから再生する、みたいな余計な処理がない分速いと思います。

設定はconfig.ymlserver:ブロックを少しいじって、ポートの変更と受け付けるテキストの上限をそれなりに変更しましょう。ちなみにdevicempsにしても、CUDA が動かなければ APIサーバスクリプト側でcpuにしちゃいます。 → v. 1.0.3 で MPS で動くようになりました。利用可能なデバイスを自動で判定します。CPU ならキャパの半分を使用します。

server:
  device: mps
  language: JP
  limit: 20000 # 文字数の上限
  origins:
  - '*'
  port: 5055 # デフォルトの 5000 から、使っていないポートに変更

API サーバは、仮想環境内から以下コマンドで実行できます。モデルとトークナイザの読み込みに時間がかかります。

python server_speech_fastapi.py

しばらく待って、こうなれば準備完了です。

10-12 19:06:26 | DEBUG  | __init__.py:130 | pyopenjtalk worker server started
10-12 19:06:27 |  INFO  | bert_models.py:92 | Loaded the Languages.JP BERT model from /Users/handsome/Documents/Python/Style-Bert-VITS2-Mac/bert/deberta-v2-large-japanese-char-wwm
10-12 19:06:27 |  INFO  | bert_models.py:154 | Loaded the Languages.JP BERT tokenizer from /Users/handsome/Documents/Python/Style-Bert-VITS2-Mac/bert/deberta-v2-large-japanese-char-wwm
10-12 19:06:27 |WARNING | tts_model.py:397 | No model files found in model_assets/.cache, so skip it
10-12 19:06:27 |  INFO  | server_speech_fastapi.py:116 | Loading models...
10-12 19:06:27 |  INFO  | server_speech_fastapi.py:123 | The maximum length of the text is 20000. If you want to change it, modify config.yml. Set limit to -1 to remove the limit.
10-12 19:06:27 |WARNING | server_speech_fastapi.py:129 | CORS allow_origins=['*']. If you don't want, modify config.yml
10-12 19:06:27 |  INFO  | server_speech_fastapi.py:338 | server listen: http://127.0.0.1:5055
10-12 19:06:27 |  INFO  | server_speech_fastapi.py:339 | API docs: http://127.0.0.1:5055/docs
10-12 19:06:27 |  INFO  | server_speech_fastapi.py:340 | Input text length limit: 20000. You can change it in server.limit in config.yml

テストはウェブブラウザから行うのが簡単です。アドレスバーにこんな感じでしゃべって欲しいテキストとモデル名 (ModelNameを差し替え) を入れてエンターキーを叩いてください (スピーカのボリュームに注意!)。

http://localhost:5055/voice?text=こんにちは!おしゃべりできて、うれしいです!&model_name=ModelName

API サーバを自分の Mac/PC で実行していれば、スピーカーなどから音声が流れた後にブラウザに「こんにちは!おしゃべりできて、うれしいです!」と表示されるはずです。ターミナルにも SUCCESS が出ていれば OK です。次に進みましょう。

Dify で AI アプリを作る

チャットボットを Chatflow で作ってください。

LLM はお好きなのをどうぞ。Ollama でローカルモデルを使用される方は、日本語が多少怪しくてもレスポンスが速い、軽めのモデルが良いと思います (参考まで、ボクは qwen2.5:14b-instruct-q8_0 を Temperature: 0.7、Top_P: 0.9、Keep Alive: 30m で使っています。普段よく使っている Llama3.1 だと内容によっては全く答えてくれないのですが、Qwen 2.5 は多少攻めた会話もできます)。

SYSTEM プロンプトにはキャラ付けの他、「簡潔に」「markdown を使用しない」「日本語のみ」「英語や中国語は絶対に使わない」という内容を入れておくのが良いでしょう。Style-Bert-VITS2 にいい感じにしゃべってもらうには、とにかく日本語であることが重要です。

次に、LLM と回答をつなぐラインをクリックし、「HTTPリクエスト」を追加します。

最低限この内容を設定すれば大丈夫です。

API:

メソッドURL
POSThttp://<IPアドレス>:<ポート>/voice
例: http://192.168.1.12:5055/voice

パラメータ:

キー
textLLM/(x) text
model_name(自分のモデル名)
例: ModelName
入力後はこんな感じ

最後の回答ブロックには、最初から入っている LLM/(x) text か、HTTPリクエストの (x) body が良いと思います。前者はしゃべり出す前に、後者はしゃべり終わってからテキストがチャットに表示されます。

どちらか気に入った方で

ここまでできたらプレビューでテキストの生成や音声の再生をテストし、仕上げに公開しましょう。

これで、基本的なライブ配信風チャットシステムの完成です。システムプロンプトでのキャラ付けをしたり、RAG で知識を入れてあげたり、ムフフな回答もしてくれる LLM を採用したり、お好きなようにお楽しみください。ただし、音声データの著作権を持っていない場合は、あくまでも個人で楽しむだけにとどめてください。

学習につかった音声データと、満足度、そして不安

今回このシステムを楽しむに当たり、5つの mp3 の音声データを合計 40秒弱用意しました。Mac の CPU で学習にかかった時間は 20分ほどです (M2 Max 12-core CPU)。で、実際に Style-Bert-VITS2 がしゃべった感じはどうかというと、かなり良いですね。日本語の発音として相当に自然です。ラグに関しても、音声合成は CPU で処理されますが、LLM による文章の生成よりかなり短いので問題ありません。

音声データはネットで拾ってきた動画から切り出したもので、内容はファンイベントの告知です。コーパスとして適しているものなのかはわかりませんが、丁寧に視聴者に語りかける口調が素材として良かったのかもしれません。当然 Style-Bert-VITS2 やモデル、トークナイザの性能、日本語への最適化が大きいことは間違いありません。すばらしいシステムを作り上げてくださった作者様達に大感謝です。

それと、これでチャットしてるとすごく不思議な感じになりますね。LLM に、アイドルとして回答して、と指示出ししているだけでそれ以外の知識を与えているわけじゃ無いのに、レスポンスが音声なだけでかなりリアルにアイドルのライブ配信に参加している感じになります (したことないですけど)。以前、Google の AI 研究者か誰かが、AI はついに本当の知能を得た!証拠もある!と会社に報告したことで解雇された、というニュースを見ました。今回この AI アプリで遊ぶことでそのことを思い出しました。ありうるな、と。最近よく聞く「脳がバグる」状況は、かなり簡単に実現できますね。悪意のある LLM を使った場合にどうなるか、ちょっと不安になりました。

ところで Style-Bert-VITS2-Mac の学習の MPS 化はどうなったのか

PyTorch の Nightly ビルドはすでに AMP Autocast で MPS をサポートしており、学習用のコードはほぼ動くようになりました。6秒のファイルの学習は、1分20秒ほどで完了します。ただし、エラー無く処理が終わるようにコードをいじると完成したモデルは誰か知らない女性の声になり (ホラー?)、いじらずに実行するとロスの処理の部分でエラーとなり、失敗します。ボクには PyTorch や機械学習の知識や学習が足らず、不具合の特定ができないので Issue も上げられていない状況です。気になる方は、GitHub に上げているコードを見てみてください。853行目の+ loss_dur + loss_klを削除すると処理は完了し、そのままだと以下のエラーで止まります (実行には、requirements.txt の torch と torchaudio をコメントし、それぞれの nightly をインストールしてください)。

[rank0]:   File "/Users/handsome/Documents/Python/Style-Bert-VITS2-Mac/.venv/lib/python3.11/site-packages/torch/autograd/graph.py", line 825, in _engine_run_backward
[rank0]:     return Variable._execution_engine.run_backward(  # Calls into the C++ engine to run the backward pass
[rank0]:            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[rank0]: RuntimeError: view size is not compatible with input tensor's size and stride (at least one dimension spans across two contiguous subspaces). Use .reshape(...) instead.

というわけで Mac ユーザの皆さん、ボクが MPS 化を完成させるのを待つよりも、地道に CPU で学習させた方が速いですよ。

Image by Stable Diffusion

今回のトップ絵は、かなり楽勝で作れたと思います。プロンプトを書き換えたのも 2回くらい。画像のクオリティを上げようと思ってステップ数を上げると急にモニタの向こうに人が増えたりしてゾゾーッとします。不気味の谷とかじゃなくて、普通にホラー映画のやつ。

Date:
2024年10月13日 0:07:02

Model:
realisticVision-v51VAE_original_768x512_cn

Size:
768 x 512

Include in Image:
live video chat streaming event of a popular pop singar. one girl in monitor

Exclude from Image:

Seed:
2850031306

Steps:
25

Guidance Scale:
20.0

Scheduler:
DPM-Solver++

ML Compute Unit:
CPU & GPU

日本語 TTS の最高峰 Style-Bert-VITS2 の学習を mac で実行する

注意!今のところ、macOS での学習は CPU 専用です。

高性能日本語 text-t-speech である Style-Bert-VITS2 ですが、作者様が公開されているバージョンで学習するには NVIDA GPU が必要です。悔しいのでなんとかならないものかとコードをいじっていたら、mac でも学習ができるようになりました。公開時点では、まだ CPU のほんの少しの力しか使えないので非常に遅く、6秒の音声の学習に M2 Max 12 コア CPU で 7分 20秒 5分 11秒かかる状態です。とは言えこれまで macOS では既存モデルを使った音声合成しかできなかったわけですから、個人的には大きな前進だと思っています (試してないですが、他の OS でも動くかもしれません。NVIDIA GPU を持っていない、Windows や Linux の方はお試しの上、結果を教えてください)。

というわけで、とりあえず公開します。

コードと詳細は GitHub へどうぞ

インストール方法と固有の使い方は GitHub でご確認ください。

GitHub: https://github.com/tokyohandsome/Style-Bert-VITS2-Mac/tree/master

PyTorch を知らぬ男がどうやったのか

基本は気合い、そして諦めない気持ち。計算するデバイスをcudaからmpsにする程度でしょ、と思っていたら全然うまくいかず、まずはcpuでとにかく動かそう、と方針転換。エラーが出ては PyTorch 2.3 の公式ドキュメントを読み、Deepseek Coder V2 の力も借りながら一つ一つ潰していく作業。時に自分のひらめきに助けられ、二晩後。無事にトレーニングが終わり、モデル一覧に追加された音声で聞いた「こんにちは、初めまして。あなたの名前はなんていうの?」の美しさたるや。プログレスバーが動き出してから完了するまでに数分待たされたのも、今思えば粋な演出でしたね。ま、ともあれ話を戻すと、コードで実行される処理自体は複雑では無く基本的に上から下へ、なので、一つ一つ CPU で処理するようにしていっただけ、ということになります。

これからどうするか

MPS で動かすのはまだいくつもハードルがありそうなので、CPU をバンバン使って高速化できないのかな、と考えています → 使用できるコア数の半分を使用するようにし、少し高速化しました (v1.0.1)。Whisper を macOS で動かすのは多分 MLX 版が良い (しかない?) と思うのでそこをどうにかしたり、複数の音声ファイルがあればesd.listを自動生成するくらいはできそうですよね。スタイルまで手を出すかどうかはまだわかりません。とりあえずもっと学習を高速化して、モデルの品質を高める作業時間を減らしたいです。

おや?いつの間にか Whisper は pip で入れられる時代なんですね: mlx-whisper

Image by Stable Diffusion

Web UI にいる女子キャラや日本語が得意ということから、日本人の女の子をいくつか描かせたのですが全くイメージと違い、manga 調で競争している女子を描かせても顔が破綻していて多方面から怒られそうだったので、アプローチを全く変えました。深い森からやっと抜け出せた喜びと今の季節感を盛り込んだ、情緒的なトップ絵です。

Date:
2024年10月4日 23:12:07

Model:
realisticVision-v51VAE_original_768x512_cn

Size:
768 x 512

Include in Image:
photo realistic beautiful nature in the late summer. fresh air and sunshine

Exclude from Image:

Seed:
3212833797

Steps:
23

Guidance Scale:
20.0

Scheduler:
DPM-Solver++

ML Compute Unit:
CPU & GPU

© Peddals.com