Главная

Monday, 24 July 2023

Создаем голосовой помощник c GPT.

Всем привет.

Мы уже пробовали использовать 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

А что вы думаете по этому поводу?