Мы уже пробовали использовать OpenAI для ответов на вопросы и извлечения текста из речи с помощью Whisper. Что, если мы теперь объединим эти и другие компоненты для создания голосового помощника на основе ИИ? Т.е. в отличие от предыдущего проекта будем ответы GPT не только читать, но и слушать.
Теперь наша цель – использовать базу знаний GPT, чтобы получить ответы на вопросы, которые мы можем задать. Создадим некое подобие голосового помощника Alexa. Но наш интеллектуальный голосовой помощник сможет ответить на более сложные вопросы и предоставить больше полезной информации.
Наш помощник будет работать по такому алгоритму:
• пользователь задает свой вопрос с помощью микрофона. Мы будем использовать Python SpeechRecognition (https://github.com/Uberi/speech_recognition);
• Whisper автоматически преобразует вопрос в текст;
• текст передается в конечные точки GPT;
• API OpenAI возвращает ответ;
• ответ сохраняется в файле mp3 и передается в Google Text to Speech (gTTS) для создания голосового ответа. Помощник проигрывает нам ответ в виде mp3.
Для голосового помощника на понадобяться три функции:
1. Запрос пользователя и запись его голоса - функция def record_audio для записи звука.
2. Расшифровка аудио з записью голоса пользователя - функция def transcribe_forever, которая использует OpenAI Whisper для расшифровки аудио.
3. Голосовой ответ на запрос пользователя - для ответа на запрос пользователя мы будем использовать функцию def reply дл ягенерации голосового ответа от GPT.
И самая главная функция main, которая вызывает три указанных функции в отдельном потоке.
Функция main будет определять функцию командной строки с использованием библиотеки click, которая принимает несколько параметров (таких как model, english, energy, wake_word и т. д.) в качестве аргументов командной строки. Затем она загружает соответствующую модель для распознавания речи, используя указанные параметры, создает очередь для хранения аудиоданных и запускает три потока для одновременного запуска функций record_audio, transcribe_forever и reply. Наконец, функция выводит на консоль текст ответа, полученный из result_queue:
from pydub import AudioSegment
from pydub.playback import play
import speech_recognition as sr
import whisper
import queue
import os
import threading
import torch
import numpy as np
import re
from gtts import gTTS
import openai
import click
def init_api():
with open(".env") as env:
for line in env:
key, value = line.strip().split("=")
os.environ[key] = value
openai.api_key = os.environ.get("API_KEY")
# чтение аргументов
@click.command()
@click.option("--model", default="base", help="Используемая модель", type=click.Choice(["tiny","base", "small","medium","large"]))
@click.option("--english", default=True, help="Использовать ли английскую модель",is_flag=True, type=bool)
@click.option("--energy", default=300, help="Уровень сигнала для обнаружения голоса", type=int)
@click.option("--pause", default=0.8, help="Длительность паузы перед окончанием", type=float)
@click.option("--dynamic_energy", default=False,is_flag=True, help="Флаг включения динамической энергии", type=bool)
@click.option("--wake_word", default="Hello", help="Команда пробуждения", type=str)
@click.option("--verbose", default=False, help="Печатать ли подробный вывод",is_flag=True, type=bool)
def main(model, english, energy, pause, dynamic_energy, wake_word, verbose):
# не существует английской модели с параметром large
if model != "large" and english:
model = model + ".en"
audio_model = whisper.load_model(model)
audio_queue = queue.Queue()
result_queue = queue.Queue()
threading.Thread(target=record_audio, args=(audio_queue, energy, pause, dynamic_energy,)).start()
threading.Thread(target=transcribe_forever, args=(audio_queue, result_queue, audio_model, english, wake_word, verbose,)).start()
threading.Thread(target=reply, args=(result_queue,)).start()
# while True:
print(result_queue.get())
# запись речи
def record_audio(audio_queue, energy, pause, dynamic_energy):
# загружаем систему распознавания речи и настраиваем пороговые значения речи и паузы
r = sr.Recognizer()
r.energy_threshold = energy
r.pause_threshold = pause
r.dynamic_energy_threshold = dynamic_energy
with sr.Microphone(sample_rate=16000) as source:
print("Tell me ...")
i = 0
while True:
# получаем запись и сохраняем ее в файл wav
audio = r.listen(source)
torch_audio = torch.from_numpy(np.frombuffer(audio.get_raw_data(), np.int16).flatten().astype(np.float32) / 32768.0)
audio_data = torch_audio
audio_queue.put_nowait(audio_data)
i += 1
# Расшифровка записи
def transcribe_forever(audio_queue, result_queue, audio_model, english, wake_word, verbose):
while True:
audio_data = audio_queue.get()
if english:
result = audio_model.transcribe(audio_data, language='english', fp16=False)
else:
result = audio_model.transcribe(audio_data, fp16=False)
predicted_text = result["text"]
if predicted_text.strip().lower().startswith(wake_word.strip().lower()):
pattern = re.compile(re.escape(wake_word), re.IGNORECASE)
predicted_text = pattern.sub("", predicted_text).strip()
punc = '''!()-[]{};:'"\,<>./?@#$%^&*_~'''
predicted_text.translate({ord(i): None for i in punc})
if verbose:
print("Вы произнесли команду пробуждения... Обработка {}...".format(predicted_text))
result_queue.put_nowait(predicted_text)
else:
if verbose:
print("Вы не произнесли команду пробуждения... Речь проигнорирована")
# Ответ пользователю
def reply(result_queue):
while True:
result = result_queue.get()
data = openai.Completion.create(
model="text-davinci-003",
prompt=result,
temperature=0.5,
max_tokens=150,
n=1,
stop=["\n"]
)
answer = data["choices"][0]["text"]
mp3_obj = gTTS(text=answer, lang="en", slow=False)
mp3_obj.save("reply.mp3")
reply_audio = AudioSegment.from_mp3("reply.mp3")
play(reply_audio)
os.remove("reply.mp3")
# Главная точка входа
init_api()
main()
Для создания некоторых элементов был использован следующий код:
• https://github.com/openai/whisper/blob/main/whisper/audio.py;
• https://github.com/mallorbc/whisper_mic/blob/main/mic.py.
Представленный выше пример будет работать в большинстве случаев, но иногда будет возвращать случайные ответы, не имеющие отношения к вопросу. У меня так и было). Чтобы улучшить качество ответов, предлагаю вам сперва начать общение с помощником на Английском языке, потому моя фраза пробуждения в коде указана "Hello". Далее полагайтесь на свое воображение и везение!
Успехов.
No comments:
Post a Comment
А что вы думаете по этому поводу?