{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\"Banner\"\n", "\n", "# Criando uma assistente virtual com Whisper, ChatGPT e ElevenLabs API\n", "\n", "O uso do **ChatGPT** é cada vez mais comum no nosso dia-a-dia. A IA criada pela [OpenAI](https://openai.com/) é utilizada largamente para os mais diferentes propósitos, desde a criação de textos para [roteiros de vídeos](https://filmora.wondershare.com.br/chatgpt/generate-youtube-script-with-chatgpt.html), [auxílio à estudantes](https://www.techtudo.com.br/listas/2023/03/6-truques-muito-uteis-do-chatgpt-que-vao-ajudar-voce-a-estudar-melhor-edsoftwares.ghtml) e até em [processos judiciais](https://g1.globo.com/tecnologia/noticia/2023/05/29/advogado-usa-casos-inventados-pelo-chatgpt-em-processo-judicial-e-leva-puxao-de-orelha-de-juiz.ghtml). Independente das polêmicas envolvendo o seu uso, é inegável que a tecnologia já faz parte do nosso cotidiano.\n", "\n", "Assim como outros *chatbots*, todas as interações realizadas com a IA (tanto os prompts quanto as respostas geradas) ocorrem via texto. Por isso, a intenção desse projeto é realizar interações com o ChatGPT através de áudio, de modo que os prompts sejam feitos com a fala do usuário e a respostas sejam transmitidas através de voz sintética; simulando, assim, uma conversa natural. Para esse feito foram utilizadas bibliotecas para gravação de fala em **Python**, o **Whisper** para transcrição de áudio e a integração com as APIs da **OpenAI** e da **ElevenLabs**, para gerar as respostas e a voz sintética natural, respectivamente.\n", "\n", "\"Banner\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Preparando o ambiente\n", "\n", "Esse projeto será divido em 4 etapas: \n", "\n", "1. Gravação do prompt do usuário em voz;\n", "2. Transcrição do áudio em texto;\n", "3. Envio do texto transcrito para a API do ChatGPT e captura da resposta, também em texto;\n", "4. Envio do texto de resposta para a API da ElevenLabs e captura do áudio sintetizado.\n", "\n", "Iniciaremos com a preparação do ambiente, instalando as bibliotecas e pacotes necessários. \n", "\n", " - Para a gravação do áudio, utilizaremos a biblioteca **sounddevice** em conjunto com o pacote **write** da biblioteca **scipy**;\n", " - Para a transcrição do áudio utilizaremos o **Whisper**, da própria OpenAI. Precisaremos, também, da **ffmpeg-python** para a conversão do áudio gravado e envio para o Whisper;\n", " - Para a integração com a API do ChatGPT, precisaremos da biblioteca **openai**;\n", " - Finalmente, para a sintetização do áudio, precisaremos integrar com a API da ElevenLabs, utilizando sua própria biblioteca **elevenlabs**.\n", "\n", " " ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "#---Definindo o idioma padrão de gravação e reconhecimento de voz---#\n", "language = \"pt\"\n", "\n", "#---Instalando as bibliotecas necessárias para a gravação do áudio---#\n", "#%pip install sounddevice\n", "#%pip install scipy\n", "\n", "#---Instalando o Whisper para reconhecimento de voz---#\n", "#%pip install git+https://github.com/openai/whisper.git\n", "\n", "#---Instalando o ffmpeg para conversão de áudio---#\n", "#%pip install ffmpeg-python\n", "\n", "#---Instalando a biblioteca da openai para a resposta---#\n", "#%pip install openai\n", "\n", "#---Instalando a biblioteca da ElevenLABS para sintetização da voz do texto de resposta---#\n", "#%pip install elevenlabs" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 01 - Gravando o prompt em áudio\n", "\n", "A biblioteca **python-sounddevice** nos permite gravar áudios através do microfone do computador e armazená-los como um array NumPy. Esse é um tipo de dados muito útil para processamento de som que pode ser convertido posteriormente como um arquivo WAV utilizando o módulo **scipy.io.wavfile** da biblioteca **scipy** (adaptado de [Real Python](https://realpython.com/playing-and-recording-sound-python/#python-sounddevice_1))." ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Ouvindo....\n" ] } ], "source": [ "#Importando as bibliotecas para a gravação de áudio\n", "import sounddevice as sd\n", "from scipy.io.wavfile import write\n", "\n", "#Definindo os parâmetros da gravação\n", "fs = 44100 #Sample rate\n", "seconds = 5 #Duração da gravação\n", "\n", "#Ininciando a gravação\n", "print(\"Ouvindo....\")\n", "minha_gravacao = sd.rec(int(fs * seconds), samplerate = fs, channels = 2)\n", "sd.wait()\n", "\n", "#Salvando o arquivo de áudio\n", "write(\"../audio/minha_gravacao.wav\", fs, minha_gravacao)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 02 - Transcrevendo com o Whisper\n", "\n", "Para a transcrição do áudio utilizaremos a biblioteca **whisper**, da própria OpenAI, que é um modelo de reconhecimento de fala de uso geral treinado em um grande conjunto de dados de áudio e também é um modelo multitarefa que pode realizar reconhecimento de fala multilíngue, tradução de fala e identificação de idioma.\n", "\n", "São cinco tamanhos de modelos, quatro com versões somente em inglês, oferecendo *tradeoffs* de velocidade e precisão. Abaixo estão os nomes dos modelos disponíveis e seus requisitos aproximados de memória e velocidade de inferência em relação ao modelo grande; a velocidade real pode variar dependendo de muitos fatores, incluindo o hardware disponível (Adaptado de [github/openai/whisper](https://github.com/openai/whisper)).\n", "\n", "| Tamanho | Parâmetros | Modelo apenas inglês | Modelo multilíngue | VRAM necessária | Velocidade relativa |\n", "|--------|------------|--------------------|--------------------|---------------|----------------|\n", "| tiny | 39 M | tiny.en | tiny | ~1 GB | ~32x |\n", "| base | 74 M | base.en | base | ~1 GB | ~16x |\n", "| small | 244 M | small.en | small | ~2 GB | ~6x |\n", "| medium | 769 M | medium.en | medium | ~5 GB | ~2x |\n", "| large | 1550 M | N/A | large | ~10 GB | 1x |\n", "\n", "Para esse projeto utilizamos o modelo small, que já nos dá uma excelente performance." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Entendendo.....\n", "\n", "Você disse: \n", " Cri uma história infantil de até 300 caracteres.\n" ] } ], "source": [ "#Importando o Whisper\n", "import whisper\n", "\n", "#Iniciando o reconhecimento de voz\n", "print(\"Entendendo.....\")\n", "\n", "#Selecionando o modelo de reconhecimento de voz\n", "model = whisper.load_model(\"small\")\n", "\n", "#Transcrevendo o áudio gravado\n", "resultado = model.transcribe(\"../audio/minha_gravacao.wav\", fp16 = False, language = language)\n", "transcricao = resultado[\"text\"]\n", "\n", "#Imprimindo a transcrição para validação\n", "print(\"\\nVocê disse: \")\n", "print(transcricao)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 03 - Enviando para o ChatGPT via API da OpenAI\n", "\n", "Após recuperarmos a transcrição do áudio em texto feito pelo **whisper**, realizaremos uma request à API do OpenAI através do *endpoint* **Creat Chat Completions**, utilizando o modelo **GPT 3.5 Turbo** e enviando o texto recuperado.\n", "\n", "Como *response* teremos um *JSON* parecido com o exemplo abaixo (Disponível em [platform.openai](https://platform.openai.com/docs/api-reference/chat/create)):\n", "\n", "```\n", "{\n", " \"id\": \"chatcmpl-123\",\n", " \"object\": \"chat.completion\",\n", " \"created\": 1677652288,\n", " \"model\": \"gpt-3.5-turbo-0613\",\n", " \"system_fingerprint\": \"fp_44709d6fcb\",\n", " \"choices\": [{\n", " \"index\": 0,\n", " \"message\": {\n", " \"role\": \"assistant\",\n", " \"content\": \"\\n\\nHello there, how may I assist you today?\",\n", " },\n", " \"logprobs\": null,\n", " \"finish_reason\": \"stop\"\n", " }],\n", " \"usage\": {\n", " \"prompt_tokens\": 9,\n", " \"completion_tokens\": 12,\n", " \"total_tokens\": 21\n", " }\n", "}\n", "\n", "```\n", "\n", "Do qual recuperaremos a resposta enviada pelo **ChatGPT** através do conteúdo (*content*) da mensagem (*message*) da escolha (*choice*) de *index* *0* no JSON." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Gerando resposta....\n", "\n", "Minha resposta em texto: \n", "Era uma vez um coelhinho chamado Pimpão, que vivia em um lindo jardim. Um dia, ele encontrou uma mágica poção de crescimento. Curioso, Pimpão decidiu experimentar e se tornou o maior coelho que já existiu. Todos no jardim ficaram maravilhados com ele e Pimpão aprendeu a importância de ser feliz do jeito que era.\n" ] } ], "source": [ "#Importando a biblioteca da openai \n", "import openai\n", "\n", "#importando a biblioteca os para utilização da API KEY\n", "import os\n", "\n", "#Recuperando a API KEY\n", "openai.api_key = os.environ.get(\"OPENAI_API_KEY\")\n", "\n", "#Iniciando a geração da resposta\n", "print(\"Gerando resposta....\")\n", "\n", "#Enviando a transcrição para a API da openai\n", "response = openai.chat.completions.create(\n", " model = \"gpt-3.5-turbo\",\n", " messages = [{\n", " \"role\":\"user\",\n", " \"content\":transcricao\n", " }]\n", ")\n", "\n", "#Recuperando a resposta da API\n", "chatgpt_response = response.choices[0].message.content\n", "\n", "#Imprimindo a resposta para validação\n", "print(\"\\nMinha resposta em texto: \")\n", "print(chatgpt_response)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 04 - Sintetizando a resposta com a ElevenLABS API\n", "\n", "Por último, iremos utilizar a API da **ElevenLabs** para sintetizar o texto da resposta recebida pelo ChatGPT em voz. A ElevenLabs é possui um dos modelos de voz sintéticas mais avançados atualmente e que produz resultados impressionantes e bastante naturais, por isso sua escolha.\n", "\n", "Para utilizar a API precisamos apenas enviar o texto que será sintetizado e o modelo de nossa preferência (multi ou monolíngue em suas versões v1 ou v2), porém escolhi uma voz específica através da `voice_id` e realizei algumas configurações extras na `stability` e na `similarity_boost`, que modificam a **tonalidade** e a **animação** (emoção) da voz gerada. A documentação da API ([aqui](https://elevenlabs.io/docs/introduction)) trás uma descrição detalhada de todas as `voice_id` disponíveis e como as configurações impactam na voz gerada.\n" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Salvando resposta....\n", "\n", "Respondendo....\n" ] } ], "source": [ "#Importando as bibliotecas necessárias\n", "from elevenlabs import generate, play, save, Voice, VoiceSettings\n", "\n", "#configurações da voz\n", "conf = Voice(\n", " voice_id = \"21m00Tcm4TlvDq8ikWAM\", \n", " settings = VoiceSettings(\n", " stability = 0.2,\n", " similarity_boost = 0.2\n", " )\n", ")\n", "\n", "#Gerando o áudio da resposta\n", "audio = generate(\n", " text = chatgpt_response,\n", " voice = conf, \n", " model = \"eleven_multilingual_v1\" \n", ") \n", "\n", "#Salvando o áudio da resposta\n", "print(\"Salvando resposta....\")\n", "save(audio, \"../audio/resposta.wav\")\n", "\n", "#Reproduzindo o áudio da resposta\n", "print(\"\\nRespondendo....\")\n", "play(audio)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Finalizando\n", "\n", "Com esses passos conseguimos concluir com sucesso o objetivo do projeto e criar uma interação natural via áudio com o **ChatGPT**, utilizando o **python-sounddevice**, **whisper**, **openai** e **elevenlabs**. Os áudios da minha gravação e da resposta do ChatGPT sintetizada via ElevenLabs ficaram salvas na pasta `audio`, para verificação e validação." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.5" } }, "nbformat": 4, "nbformat_minor": 2 }