gemma3:4bの返答を pyttsx3 を使って 自然にリアルタイム読み上げる

gemma3:4bの返答を
pyttsx3 を使って
自然にリアルタイム読み上げる

読み上げは

touch main4.py

でファイルを作成し問題が起きた時にわかりやすくする

from module.module_audio_to_text import AudioToTextCorrector
from ollama import chat, ChatResponse
import pyttsx3
import re
import emoji

# モデル名
OLLAMA_MODEL = 'gemma3:4b'

# pyttsx3初期化
engine = pyttsx3.init()

def ask_ollama(prompt: str) -> str:
    try:
        response: ChatResponse = chat(model=OLLAMA_MODEL, messages=[
            {
                'role': 'user',
                'content': prompt,
            }
        ])
        return response.message.content.strip()
    except Exception as e:
        print(f"Ollamaエラー: {e}")
        return "エラーが発生しました。"

def remove_emoji(text: str) -> str:
    return emoji.replace_emoji(text, replace='')

def speak(text: str):
    clean_text = remove_emoji(text)
    print("\n【読み上げるテキスト】")
    print(clean_text)
    engine.say(clean_text)
    engine.runAndWait()

def main():
    audio_to_text = AudioToTextCorrector("config.json")

    while True:
        corrected_text = audio_to_text.record_and_correct(timeout_seconds=10)

        if corrected_text is None:
            print("終了条件に達したため、ループを抜けます。")
            break

        print("\n【認識・補正したテキスト】")
        print(corrected_text)

        # Ollamaへ質問
        ollama_reply = ask_ollama(corrected_text)

        print("\n【gemma3:4bの返答】")
        print(ollama_reply)

        # gemma3:4bの返答を音声で読み上げ
        speak(ollama_reply)

if __name__ == "__main__":
    main()

実行したけど

[2025-05-09 19:01:12.451] [ctranslate2] [thread 8719969] [warning] The compute type inferred from the saved model is float16, but the target device or backend do not support efficient float16 computation. The model weights have been automatically converted to use the float32 compute type instead. stand by ready OK recording... finished Ollamaエラー: llama runner process has terminated: exit status 2 終了条件に達したため、ループを抜けます。

となる

エラー内容を調べると

Ollamaエラー: llama runner process has terminated: exit status 2
は、Ollamaの内部プロセス(llama-runner)がクラッシュして終了

このため chrome を一度終了してから再度実行

しかし音声が出ない

engine = pyttsx3.init('nsss')  # macOSならこれで確実に動く

と明示的にしてもだめ

touch tts_test.py

でファイルを作成

import pyttsx3

engine = pyttsx3.init('nsss')
text = "こんにちは。今日はどんな気分ですか?映画でも見ませんか?"
engine.say(text)
engine.runAndWait()

として実行

しかし音声が再生されない
色々試した結果、再起動したら音声が再生された

どうやら再起動することで解決したらしい
メモリが足りなくてエラーだったので
もう少しマシンスペックを上げないと厳しいかもしれない

とりあえず動くので
次は音声再生部分をモジュールにする
その後ウェイクワードエンジンをやってみる

認識したテキストをgemma3:4bへ質問して 返答を表示する

認識したテキストをgemma3:4bへ質問して 返答を表示する

🎯 目標
* マイクで音声入力
* faster-whisperでテキスト化
* Ollama(gemma3:4b)に質問として送信
* 返答を画面に表示するだけ(まだ読み上げはしない)

AudioToTextCorrector でテキストを取得
そのテキストを gemma3:4b に渡す
gemma3:4bの返答をprintする

これに伴い

from module.module_audio_to_text import AudioToTextCorrector

def main():
    audio_to_text = AudioToTextCorrector("config.json")

    recognized_texts = []

    while True:
        corrected_text = audio_to_text.record_and_correct(timeout_seconds=10)

        if corrected_text is None:
            print("終了条件に達したため、ループを抜けます。")
            break

        recognized_texts.append(corrected_text)
        print(corrected_text)

    if recognized_texts:
        message = "\n".join(recognized_texts)
        print("\n入力された音声テキスト一覧:")
        print(message)
    else:
        print("入力メッセージはありませんでした")

if __name__ == "__main__":
    main()

のコードを変更

これで実行

今日の天気
と音声入力すると

python main3.py
[2025-05-08 04:08:59.862] [ctranslate2] [thread 8630251] [warning] The compute type inferred from the saved model is float16, but the target device or backend do not support efficient float16 computation. The model weights have been automatically converted to use the float32 compute type instead.
stand by ready OK
recording...
finished

【認識・補正したテキスト】
今日の気候はどうでしょうか。

【gemma3:4bの返答】
はい、今日の気候についてお調べします。

現在(2024年5月16日16時30分)の天気は以下の通りです。

*   **場所:** 東京都
*   **天気:** 晴れ
*   **気温:** 18℃
*   **降水確率:** 0%
*   **風:** 北西風 3~5km/h

より詳細な情報が必要な場合は、場所を具体的に指定してください。例えば、「大阪府の今日の天気は?」のように聞いていただければ、より正確な情報をお伝えできます。

また、以下のサイトでも最新の天気予報を確認できます。

*   **Yahoo!天気・災害:** [https://weather.yahoo.co.jp/](https://weather.yahoo.co.jp/)
*   **日本気象協会 tenki.jp:** [https://tenki.jp/](https://tenki.jp/)
stand by ready OK
recording...
finished
10秒間音声が入力されなかったため、処理を終了します。
終了条件に達したため、ループを抜けます。

となる

とりあえず音声で入力し
これを認識補正することで簡単な質問でも適切に回答可能できそう

次は
gemma3:4bの返答を
pyttsx3 を使って
自然にリアルタイム読み上げる

Ollama gemma3 4b の読み上げ

Ollama gemma3 4b の読み上げ

import requests
import pyttsx3

# Ollama設定
OLLAMA_URL = "http://localhost:11434/api/generate"
MODEL_NAME = "gemma3:4b"  # モデル名(必要に応じてgemma3:4bに)

# 音声読み上げエンジン初期化
engine = pyttsx3.init()

def ask_ollama(prompt):
    payload = {
        "model": MODEL_NAME,
        "prompt": prompt,
        "stream": False
    }
    response = requests.post(OLLAMA_URL, json=payload)
    if response.status_code == 200:
        result = response.json()
        return result.get("response", "")
    else:
        print(f"Error: {response.status_code}")
        return ""

def speak(text):
    engine.say(text)
    engine.runAndWait()

def main():
    # 質問文
    prompt = "おはよう"
    
    # Ollamaに送信
    reply = ask_ollama(prompt)
    print("Ollamaの回答:", reply)
    
    # 読み上げ
    if reply:
        speak(reply)
    else:
        speak("エラーが発生しました。")

if __name__ == "__main__":
    main()

で実行したけど絵文字が入ると読み上げが変になるので削除

またrequest を使わないようにするので
Ollama gemma3 python で検索

OllamaとGemma3でローカルLLMをPythonで実行する
を参考に変更

読み上げの時に回答に絵文字などがあるとわかりにくいため、絵文字などは削除するので
Re を使う

from ollama import chat
from ollama import ChatResponse
import pyttsx3
import re

# モデル名
MODEL_NAME = 'gemma3:4b'

# pyttsx3 初期化
engine = pyttsx3.init()

def remove_emoji(text: str) -> str:
    # Unicode範囲を指定して絵文字を除去する正規表現
    emoji_pattern = re.compile(
        "["
        "\U0001F600-\U0001F64F"  # 顔文字
        "\U0001F300-\U0001F5FF"  # 天気や地図記号
        "\U0001F680-\U0001F6FF"  # 乗り物
        "\U0001F1E0-\U0001F1FF"  # 国旗
        "\U00002700-\U000027BF"  # その他の記号
        "\U000024C2-\U0001F251"
        "]+",
        flags=re.UNICODE
    )
    cleaned_text = emoji_pattern.sub('', text)
    return cleaned_text

def ask_ollama(prompt: str) -> str:
    try:
        response: ChatResponse = chat(model=MODEL_NAME, messages=[
            {
                'role': 'user',
                'content': prompt,
            }
        ])
        return response.message.content
    except Exception as e:
        print(f"Ollamaエラー: {e}")
        return "エラーが発生しました。"

def speak(text: str):
    # ここで絵文字を除去してから読み上げ
    clean_text = remove_emoji(text)
    engine.say(clean_text)
    engine.runAndWait()

def main():
    prompt = "おはよう。日本語で答えてください。"

    reply = ask_ollama(prompt)
    print("Ollamaの回答(絵文字付き):", reply)

    speak(reply)

if __name__ == "__main__":
    main()

これだと機能しない

pip install emoji

で絵文字を削除できるのでインストールしておく

import emoji

def remove_emoji(text: str) -> str:
    # emojiパッケージを使う方法(こちらの方が確実)
    return emoji.replace_emoji(text, replace='')

を追加

全体は

from ollama import chat
from ollama import ChatResponse
import pyttsx3
import re

# モデル名
MODEL_NAME = 'gemma3:4b'

# pyttsx3 初期化
engine = pyttsx3.init()

def ask_ollama(prompt: str) -> str:
    try:
        response: ChatResponse = chat(model=MODEL_NAME, messages=[
            {
                'role': 'user',
                'content': prompt,
            }
        ])
        return response.message.content
    except Exception as e:
        print(f"Ollamaエラー: {e}")
        return "エラーが発生しました。"

def speak(text: str):
    # 絵文字を除去
    clean_text = remove_emoji(text)
    print("読み上げ用のテキスト:", clean_text)  # ←追加してデバッグ
    engine.say(clean_text)
    engine.runAndWait()

import emoji

def remove_emoji(text: str) -> str:
    # emojiパッケージを使う方法(こちらの方が確実)
    return emoji.replace_emoji(text, replace='')


def main():
    prompt = "おはよう。日本語で答えてください。"

    reply = ask_ollama(prompt)
    print("Ollamaの回答(絵文字付き):", reply)

    speak(reply)

if __name__ == "__main__":
    main()

で実行すると

python voice_test.py
Ollamaの回答(絵文字付き): おはようございます!何かお手伝いできることはありますか? 😊

読み上げ用のテキスト: おはようございます!何かお手伝いできることはありますか? 

となって結果から絵文字を削除し読み上げが可能になる

次は
Faster-whisper で音声の取得

Ollama + gemma3 4B の結果を音声にする

Ollama + gemma3 4B の結果を音声にする

Gemma 3 で RAG 機能付きの安全なローカル AI チャット環境を構築する

を参考に行う

MacBook Pro 14 インチ 2021
* M1 Pro
* 16GB RAM

で動いているなら
M1MacbookAir 16GBでもいけそう

 mkdir gemma
 cd gemma 

ollama pull gemma3:4b

を実行したら

pulling manifest 
Error: pull model manifest: 412: 

The model you are attempting to pull requires a newer version of Ollama.

Please download the latest version at:

	https://ollama.com/download

となる


ollama --version
ollama version is 0.5.11

The model you are attempting to pull requires a newer version of Ollama.

→ 「このモデル(gemma3:4b)をダウンロードするには、Ollama本体を最新版にアップデートする必要がある」 という意味

最近(2025年4月末〜5月頭)にGemma 3系モデル(4B, 9B, 27B)が追加されたばかりで、
それに合わせてOllama側も内部仕様が更新され
古いOllamaではGemma3対応できない

m1macbookAir での ollamaのインストール方法は2つ

Homebrewで管理している
公式サイトから再インストール

となる

状況 更新方法
普通に公式サイトからインストールしていた場合 公式サイトから最新のdmgをダウンロード&上書き
Homebrewで管理していた場合 brew upgrade ollama で更新

どちらかわからないのなら

which ollama

を実行する

/usr/local/bin/ollama

が今回の結果

/usr/local/bin/ollama ならbrewインストール版
/Applications/Ollama.app/Contents/MacOS/ollama ならアプリ版

ということなので
Brewで更新可能

しかし

brew update
brew upgrade ollama

を実行すると

brew upgrade ollama
Warning: Treating ollama as a formula. For the cask, use homebrew/cask/ollama or specify the `--cask` flag. To silence this message, use the `--formula` flag.
Error: ollama not installed
==> `brew cleanup` has not been run in the last 30 days, running now...
Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).
Removing: /opt/homebrew/Cellar/dtc/1.7.0... (18 files, 619.2KB)
Removing: /opt/homebrew/Cellar/freetype/2.13.2... (67 files, 2.4MB)
Removing: /opt/homebrew/Cellar/fribidi/1.0.15... (68 files, 740KB)
Removing: /opt/homebrew/Cellar/imath/3.1.11... (49 files, 940.5KB)
Removing: /opt/homebrew/Cellar/isl/0.26... (73 files, 7.6MB)
Removing: /opt/homebrew/Cellar/jpeg-turbo/3.0.3... (45 files, 3.4MB)
Removing: /opt/homebrew/Cellar/libssh/0.10.6... (23 files, 1.3MB)
Removing: /opt/homebrew/Cellar/libssh2/1.11.0_1... (197 files, 1.2MB)
Removing: /opt/homebrew/Cellar/libunistring/1.2... (59 files, 5MB)
Removing: /opt/homebrew/Cellar/libxau/1.0.11... (21 files, 123.5KB)
Removing: /opt/homebrew/Cellar/libxrender/0.9.11... (12 files, 214.1KB)
Removing: /opt/homebrew/Cellar/lz4/1.9.4... (22 files, 681.5KB)
Removing: /opt/homebrew/Cellar/mpg123/1.32.6... (34 files, 2.0MB)
Removing: /opt/homebrew/Cellar/npth/1.7... (12 files, 162.1KB)
Removing: /opt/homebrew/Cellar/nspr/4.35... (86 files, 1.2MB)
Removing: /opt/homebrew/Cellar/protobuf/21.12... (285 files, 10.2MB)
Removing: /opt/homebrew/Cellar/rubberband/3.3.0... (13 files, 1.7MB)
Removing: /opt/homebrew/Cellar/srt/1.5.3... (20 files, 4.4MB)
Removing: /opt/homebrew/Cellar/x265/3.6... (12 files, 12MB)
==> Autoremoving 1 unneeded formula:
libgit2@1.7
Removing: /Users/snowpool/Library/Caches/Homebrew/portable-ruby-3.3.5.arm64_big_sur.bottle.tar.gz... (11.2MB)
Removing: /Users/snowpool/Library/Logs/Homebrew/python@3.13... (2 files, 2KB)
Removing: /Users/snowpool/Library/Logs/Homebrew/python@3.12... (2 files, 2KB)
Removing: /Users/snowpool/Library/Logs/Homebrew/glib... (64B)
Removing: /Users/snowpool/Library/Logs/Homebrew/rust... (64B)
Removing: /Users/snowpool/Library/Logs/Homebrew/llvm... (64B)
Removing: /Users/snowpool/Library/Logs/Homebrew/gcc... (64B)
Removing: /Users/snowpool/Library/Logs/Homebrew/openssl@3... (64B)
Removing: /Users/snowpool/Library/Logs/Homebrew/ca-certificates... (64B)
Removing: /Users/snowpool/Library/Logs/Homebrew/python@3.10... (2 files, 2.5KB)
Removing: /Users/snowpool/Library/Logs/Homebrew/unbound... (64B)
Removing: /Users/snowpool/Library/Logs/Homebrew/python@3.11... (2 files, 2.5KB)
Removing: /Users/snowpool/Library/Logs/Homebrew/guile... (64B)
Removing: /Users/snowpool/Library/Logs/Homebrew/gnupg... (64B)
Removing: /Users/snowpool/Library/Logs/Homebrew/ruby... (64B)
Pruned 0 symbolic links and 8 directories from /opt/homebrew

これで再度パスから調べたら

/usr/local/bin/ollama

の場合
これを見ると、あなたの環境のOllamaは
* /Applications/Ollama.app みたいなアプリ版じゃなくて
* コマンドラインインストール(たぶん過去に手動インストール)されたものです。
つまり:
Homebrew管理でもないし、アプリ版でもない。
→ /usr/local/bin に直接インストールされてる独立版。

とのこと

このため過去ログを探す

 ollama --version

だと

ollama version is 0.3.6

2024年8月の時点のものなので最新のものにする

Apple Silicon(M3) Macで Ollama を動かしてみ
を参考に

https://ollama.com/download
からダウンロードして
Ollama-darwin.zip
をダブルクリックで解凍

Ollama.app
ができているので
これをダブルクリックで進めればOK

再度

ollama --version          

で最新のものになるのを確認

ollama version is 0.5.11

となっていたので

https://zenn.dev/cloud_ace/articles/gemma3-ollama-openwebui-rag#6.-セットアップ手順
を参考に

https://ollama.com
から最新版をダウンロードする

インストール後

ollama --version   
ollama version is 0.6.7

でバージョン更新されたのを確認

ollama pull gemma3:4b

pulling manifest 
pulling aeda25e63ebd: 100% ▕██████████████████████▏ 3.3 GB                         
pulling e0a42594d802: 100% ▕██████████████████████▏  358 B                         
pulling dd084c7d92a3: 100% ▕██████████████████████▏ 8.4 KB                         
pulling 3116c5225075: 100% ▕██████████████████████▏   77 B                         
pulling b6ae5839783f: 100% ▕██████████████████████▏  489 B                         
verifying sha256 digest 
writing manifest 
success 

でインストール成功

次にモデルの実行

ollama run gemma3:4b

プロンプトを抜けるには

/bye

とするか
Ctrl +d を実行

Open WebUI を使うなら
デフォルトでは http://localhost:11434/api に接続

試しに
Google Cloudとは?
と聞いてみると

Google Cloud(グーグル クラウド)は、Googleが提供するクラウドコンピューティング
サービスです。簡単に言うと、インターネットを通じてコンピューターの計算資源(サー
バー、ストレージ、データベースなど)を借りて利用するサービスです。

**Google Cloudの主な特徴とサービス内容**

* **幅広いサービス:**
* **コンピューティング:**
* **Compute Engine:** 仮想サーバーを構築・管理できます。
* **Kubernetes Engine (GKE):** コンテナ化されたアプリケーションを簡単に
デプロイ・管理できます。
* **Cloud Functions:** サーバーを管理することなく、イベントやトリガーに
応じてコードを実行できます。
* **ストレージ:**
* **Cloud Storage:** 画像、動画、バックアップデータなどのオブジェクトを
保存できます。
* **Cloud SQL:** MySQL、PostgreSQL、SQL Serverなどのデータベースを管理で
きます。
* **Cloud Firestore:** NoSQLデータベースです。
* **分析:**
* **BigQuery:** 大量のデータを高速に分析できるデータウェアハウスです。
* **Cloud Dataflow:** リアルタイムデータ処理パイプラインを構築・実行でき
ます。
* **機械学習:**
* **Vertex AI:** 機械学習モデルの構築、トレーニング、デプロイを支援する
プラットフォームです。
* **その他:**
* **App Engine:** Webアプリケーションを簡単にデプロイ・実行できます。
* **Cloud Identity:** ユーザー管理サービスです。
* **Cloud Operations:** アプリケーションの監視、ログ収集、エラー分析など
を支援するプラットフォームです。

* **Googleの技術との連携:**
* Google検索、YouTube、Google MapsなどのGoogleの既存のサービスとシームレスに
連携できます。
* 機械学習、データ分析、セキュリティなどの分野で、Googleが持つ高度な技術を活
用できます。

* **柔軟性とスケーラビリティ:**
* 必要な時に必要な分だけリソースを拡張したり縮小したりできるため、コストを最
適化できます。
* どのデバイスからでもアクセスできます。

**Google Cloudが活用されている事例**

* **Webアプリケーション開発:** WebサイトやWebアプリケーションのホスティング
* **データ分析:** 顧客データの分析、マーケティング分析、ビジネスインテリジェンス

* **機械学習:** レコメンデーションシステム、画像認識、自然言語処理
* **ゲーム開発:** ゲームサーバーの構築、ゲームデータの分析
* **IoT:** IoTデバイスからのデータ収集・分析、デバイス管理

**Google Cloudの料金体系**

* **従量課金制:** 実際に使用したリソースに対してのみ料金を支払います。
* **無料枠:** 一部のサービスには無料枠が用意されています。

**詳細な情報:**

* **Google Cloud公式ウェブサイト:**
[https://cloud.google.com/](https://cloud.google.com/)

Google Cloudは、規模の大小、業種の異なる様々な企業で利用されています。ご自身のビ
ジネスニーズに合わせて、最適なサービスを選択し、活用することで、ビジネスの成長を
加速させることができます。

より具体的な質問があれば、お気軽にお尋ねください。例えば、「WebサイトをGoogle
Cloudでホスティングしたいのですが、どのようなサービスを選べば良いですか?」のよ
うに、具体的な状況を教えていただければ、より詳細なアドバイスができます。

という回答が数秒で出る

なお docker で OpeenWebUI を使ってるのが多いけど
スペック的に docker をさらに動かすよりも
Enchanted アプリを使うことで同じようなことができる

使い方は

Mac用 Enchanted アプリで文章を自由自在に活用してみる
を参考に

Enchanted:iOSとmacOSのネイティブプライベートモデルをサポートしたマルチモーダルチャットアプリ
をみた感じではマルチモーダル対応っぽい

なお OpenWebUI を使うことで
RAG(検索拡張生成)も可能らしい

とりあえず文字の入力と回答だけなら快適に動く