手作り音声アシスタントを作りたかったが、色々調べ物が面倒だったので放置していたが、今だ!と思って調べた
cotomoに感動したからですね
検証環境
windows10pro
i7-12700 128Gmem 3070 Ti
python 3.11.9 (pyaudioをインストールする際に3.12だとコケたので3.11を利用)
今回のコード
今回は上記のコードをPGT-4oで出力しました
自分ではファイル名ぐらいしか書いてません
設定などまっさらなので、よければ参考として
import pyaudio
import json
import requests
from vosk import Model, KaldiRecognizer
import logging
import time
import threading
# ロギングの設定
logging.basicConfig(level=logging.DEBUG)
# モデルのパスを指定します
model_path = "vosk-model-ja-0.22" # 例: "vosk-model-small-en-us-0.15"
# モデルをロードします
model = Model(model_path)
recognizer = KaldiRecognizer(model, 16000)
# PyAudioの設定
p = pyaudio.PyAudio()
stream = p.open(format=pyaudio.paInt16, channels=1, rate=16000, input=True, frames_per_buffer=4096)
stream.start_stream()
def recognize_speech():
logging.debug("Listening...")
while True:
data = stream.read(4096, exception_on_overflow=False)
if recognizer.AcceptWaveform(data):
result = recognizer.Result()
text = json.loads(result)["text"]
logging.debug(f"Recognized Text: {text}")
# デバッグログ:送信されるデータを表示
logging.debug(f"Sending text to server: {text}")
# Text-generation-webuiにテキストを渡す
response = requests.post("http://127.0.0.1:5000/api/generate", json={"input": text})
if response.status_code == 200:
generated_text = response.json().get("output", "")
logging.debug(f"Generated Text: {generated_text}")
else:
logging.error(f"Error: {response.status_code}, {response.text}")
else:
partial_result = recognizer.PartialResult()
logging.debug(f"Partial Result: {json.loads(partial_result)['partial']}")
time.sleep(0.1)
def listen_loop():
while True:
recognize_speech()
if __name__ == '__main__':
listener_thread = threading.Thread(target=listen_loop)
listener_thread.start()
listener_thread.join()
サーバー部分
from flask import Flask, request, jsonify
from transformers import pipeline
import logging
app = Flask(__name__)
# ロギングの設定
logging.basicConfig(level=logging.DEBUG)
# Text-generationモデルのロード
generator = pipeline('text-generation', model='EleutherAI/gpt-neo-2.7B', pad_token_id=50256)
@app.route('/api/generate', methods=['POST'])
def generate_text():
logging.debug("Received POST request for text generation.")
input_data = request.json
if input_data is None:
logging.debug("No JSON data received.")
return jsonify({"error": "No JSON data received"}), 400
logging.debug(f"Received JSON data: {input_data}")
input_text = input_data.get('input', '').strip()
if not input_text:
logging.debug("No input text provided.")
return jsonify({"error": "No input text provided"}), 400
logging.debug(f"Input text: {input_text}")
generated = generator(input_text, max_length=50, num_return_sequences=1, truncation=True)
output_text = generated[0]['generated_text']
logging.debug(f"Generated text: {output_text}")
return jsonify({"output": output_text})
if __name__ == '__main__':
logging.debug("Starting Flask server.")
app.run(host='127.0.0.1', port=5000)
音声認識
現代ではいくつか候補があるらしい
今回は、VOSKを使用した
音声認識からテキストへの変換はこれでいいんじゃないかと思った
whisperを触っていたときに、リアルタイムではだいぶ厳しいぞと思っていたので、認識を甘くしてもうまく立ち上がるのは良いなと思った
p = pyaudio.PyAudio()
stream = p.open(format=pyaudio.paInt16, channels=1, rate=16000, input=True, frames_per_buffer=4096)
stream.start_stream()
マイクの入力が圧倒的に楽
input=True //マイク
Outpu=True //PCのオーディオ
だと見た気がする
間違ってたらごめんね
ローカルLLM
今回は一旦なんでもいいやと思って、text-generation-webuiを使おうと思った
以下のURLを参考にしたが、多分使っていない気がする
https://zenn.dev/saldra/articles/201dd9e7d8c743
少し大きいモデルを使っているが、返答に15秒ほどかかるので、これはチューンしないといけない
返事が来たらそれを読み上げさせればいいかと思ったが、音声周りでどうも躓いたのでここまでになった
シンプルにローカルだとだいぶ回答が曖昧なので、用途を絞るかオンラインのAPIを使うか、曖昧でも成立するように考えるかの必要があると思った
また、全部AIである必要もないので、時間やスケジュールなんかは参照できるものがあると良いなと思った
音声読み上げ
TTSライブラリを浸かって読み上げを試みていたが、どうにもうまくいかなかったので諦めた
利用したのは、pyttsx3
pip install pyttsx3
利用方法は以下
from flask import Flask, request, jsonify
from transformers import pipeline
import pyttsx3
app = Flask(__name__)
generator = pipeline('text-generation', model='EleutherAI/gpt-neo-2.7B')
# 音声合成エンジンの初期化
engine = pyttsx3.init()
@app.route('/api/generate', methods=['POST'])
def generate_text():
input_data = request.json
input_text = input_data.get('input', '')
if not input_text:
return jsonify({"error": "No input text provided"}), 400
generated = generator(input_text, max_length=50, num_return_sequences=1)
output_text = generated[0]['generated_text']
# テキストを音声で読み上げ
engine.say(output_text)
engine.runAndWait()
return jsonify({"output": output_text})
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
voicevoxなども試してみたが、集中力が切れたのでやめた
終わりに
音声アシスタントは多分作れる
- 基礎的なプログラミングができる
- パラメーターを調べる根気がある
- チューニングする気力がある
上記の気合があれば、かなりすぐ作れる、知識さえあれば、多分
去年騒がれていたときはコード本当にひどかったけど、一旦実行までは一発に近い感じで出るのですごい
でもやっぱり修正やチューニングはどうしたって知識が必要なので、勉強してないと無理だなって思いました
僕にはここから先は無理なので、一緒に誰かやってくれねぇかなと