style-bert-vits2等のTTSにPOST時、threadingを使って少し時間短縮
import re
import anthropic
from datetime import datetime
import concurrent
import io
import threading
import time
import wave
from concurrent.futures import ThreadPoolExecutor
import pyaudio
import requests
api_key = "**************************************************************"
end_of_playback = 0
messages = []
count = 0
def create_synthesis(text, count):
# 音声合成用のクエリを作成
parameters = {"text": text, "model_id": 0, "style": "Neutral",
"style_weight": 5} # 最低限のパラメーター。
# style: Neutral,Angry,Disgust,Fear,Happy,Sad,Surprise。Neutralがデフォルト。
endpoint = "http://127.0.0.1:5000/voice/"
headers = {
"Content-Type": "application/json"}
response_synth = requests.post(endpoint, params=parameters, headers=headers, timeout=25)
# レスポンスから音声データを取得
audio_data = response_synth.content
# 音声データを保存せずに直接再生
audio_io = io.BytesIO(audio_data)
if count == 0:
time.sleep(1.2)
time.sleep(0.8)
return audio_io
def playback(end_of_playback,audio_io):
wave_file = wave.open(audio_io, 'rb')
p = pyaudio.PyAudio()
stream = p.open(format=p.get_format_from_width(wave_file.getsampwidth()),
channels=wave_file.getnchannels(),
rate=wave_file.getframerate(),
output=True)
data = wave_file.readframes(1024)
while data != b'':
stream.write(data)
data = wave_file.readframes(1024)
time.sleep(0.3)
stream.stop_stream()
stream.close()
p.terminate()
end_of_playback += 1
return end_of_playback
def threading_synthesis(a_dict, end_of_playback, count):
# 関数の中に小さい関数を作成
def create_synthesis_and_get_audio_io(text):
audio_io = create_synthesis(text,count)
return audio_io
# 並列処理
executor = ThreadPoolExecutor(max_workers=len(a_dict))
futures = []
for i in range(len(a_dict)):
future = executor.submit(create_synthesis_and_get_audio_io, str(a_dict['text' + str(i + 1)]))
futures.append(future)
audio_ios = [future.result() for future in futures]
for i in range(len(a_dict)):
# 並列処理
thread = threading.Thread(
target=lambda: create_synthesis_and_get_audio_io(str(a_dict['text' + str(i + 1)])))
thread.start()
thread.join(5) # 5秒
for i, audio_io in enumerate(audio_ios):
# 並列処理
executor = concurrent.futures.ThreadPoolExecutor(max_workers=1) # 再生は1つのみ
executor.submit(end_of_playback)
end_of_playback = 0
playback(end_of_playback, audio_io)
system_content = f"""あなたは優秀なAIアシスタントです。質問に答えてください。
現在時刻は{datetime.now()}です。"""
client = anthropic.Anthropic(
api_key=api_key,
)
print(" anthropic haikuとチャット。")
while True:
u = input(" You: ")
if not u:
break
messages.append({"role": "user", "content": u})
resp = client.messages.create(
model="claude-3-haiku-20240307",
system=system_content,
max_tokens=190,
temperature=0.7,
messages=messages,
)
a = resp.content[0].text
print(" chatbot: ", a)
messages.append({"role": "assistant", "content": a})
# テキストの最後に。!?のいずれかがあった場合削除
a = re.sub(r'[。!?]$', '', a)
# テキストを。!?で分割
a_list = re.split('[。!?]', a)
a_dict = {}
for i, split_text in enumerate(a_list):
a_dict['text' + str(i + 1)] = split_text
threading_synthesis(a_dict, end_of_playback, count)
count += 1
全体の構成はざっとこんな感じになりますが、肝心なのは中ほどにあるthreading_synthesis関数です。この構成にするとすごく短い返答の場合はthreadindをしない方が速いのですが、anthropicのclaude3みたいなおしゃべりなllmの場合、長い返答が多くなるので重宝します。
追記:
create_synthesis関数のtime.sleep()の値は環境(PC)に合わせて調節してください
この記事が気に入ったらサポートをしてみませんか?