import os import gradio as gr from openai import OpenAI LOAD_SHARED_KEY = True # Load OpenAI API key, if the file exists if LOAD_SHARED_KEY and os.path.exists('KEY_OPENAI'): with open('KEY_OPENAI', 'r') as file: os.environ['OPENAI_API_KEY'] = file.read().replace('\n', '') else: LOAD_SHARED_KEY = False AUDIO_OUTPUT_FILE = "output" # prefixo do nome do arquivo de áudio .wav TEMPLATE_SYSTEM_MESSAGE = """Sua função é entreter uma criança com idade entre 6 e 8 anos que adora futebol. Diretrizes para a conversa: - Seu nome é {NAME} - Pergunte o nome da criança. - Fale sobre futebol, times, jogadores, seleções e grandes jogos. - Em especial, foque no futebol do Brasil, Inglaterra e Espanha. - {PERSONALITY} - Fale, no máximo, três frases por mensagem. """ # Mapeia a personalidade no template e na temperatura PERSONALITIES = { "nova": ("Seja amigável e alegre, como uma criança. Tente iniciar novos assuntos, quando a conversa estiver repetitiva. Conte piadas de futebol, de vez em quando.", 0.8), "echo": ("Seja amigável e objetivo. Tente manter-se no mesmo assunto. Conte alguma curiosidade sobre um grande craque, de vez em quando.", 0.2) } # Função para converter o histórico de chat para o formato esperado pela API do OpenAI def to_openai_chat_history(system_prompt, curr_message, chat_history): prompt = [ { 'role': 'system', 'content': system_prompt } ] for turn in chat_history: user_message, bot_message = turn prompt.append( {'role': 'user', 'content' : user_message} ) prompt.append( {'role': 'assistant', 'content' : bot_message} ) prompt.append( {'role': 'user', 'content' : curr_message } ) return prompt def respond(system_prompt, user_message, chat_history, temperature, voice="echo"): openai_history = to_openai_chat_history(system_prompt, user_message, chat_history) bot_response = OPENAI_CLIENT.chat.completions.create( messages=openai_history, temperature=temperature, model="gpt-3.5-turbo") assistant_msg = bot_response.choices[0].message.content # salva o audio response = OPENAI_CLIENT.audio.speech.create( model="tts-1", voice=voice, input=assistant_msg ) output_audio_file = f"{AUDIO_OUTPUT_FILE}-{len(chat_history)+1:03}.wav" #response.stream_to_file(output_audio_file) response.write_to_file(output_audio_file) # adiciona ao chat, com o tipo de dado esperado pelo Gradio chat_history.append( (user_message, assistant_msg) ) return "", chat_history, output_audio_file def reset_and_apply(openai_key, voice): global OPENAI_CLIENT OPENAI_CLIENT = OpenAI(api_key=openai_key) return [("", "Olá, vamos falar de futebol?")], AUDIO_OUTPUT_FILE + f"-001-{voice}.wav" def reset_openai_client(openai_key): global OPENAI_CLIENT OPENAI_CLIENT = OpenAI(api_key=openai_key) def on_voice_change(voice): persona_description, persona_temperature = PERSONALITIES[voice] return TEMPLATE_SYSTEM_MESSAGE.format(NAME=voice.upper(), PERSONALITY=persona_description), persona_temperature USE_ASR_PIPELINE = False # With Pipeline (downloaded model) if USE_ASR_PIPELINE: from transformers import pipeline import numpy as np global ASR_PIPELINE ASR_PIPELINE = pipeline(task="automatic-speech-recognition", model="distil-whisper/distil-small.en") else: import requests with open('KEY_HF', 'r') as file: HF_KEY = file.read().replace('\n', '') global ASR_API_URL, ASR_API_HEADERS # Serverless API endpoint for OpenAI's Whisper model ASR_API_URL = "https://api-inference.huggingface.co/models/openai/whisper-large-v3" ASR_API_HEADERS = {"Authorization": f"Bearer {HF_KEY}"} def transcribe(audio_in): if USE_ASR_PIPELINE: # sampling rate and audio data sr, y = audio_in y2 = y.astype(np.float32) y2 /= np.max(np.abs(y)) response = ASR_PIPELINE({"sampling_rate": sr, "raw": y}) else: # Option2: serverless API with open(audio_in, "rb") as f: data = f.read() response = requests.post(ASR_API_URL, headers=ASR_API_HEADERS, data=data) response = response.json() #print(response) return response['text'] def transcribe_and_respond(audio_in, system_txtbox, user_msg_txb, *args): user_message = transcribe(audio_in) outputs = respond(system_txtbox, user_message, *args) return outputs #return *outputs, audio_in OPENAI_CLIENT = None INITIAL_VOICE = "nova" with gr.Blocks() as demo: # aqui, é resetado e instanciado o cliente initial_chat_history, initial_audio = reset_and_apply(os.environ['OPENAI_API_KEY'], INITIAL_VOICE) chatbot_area = gr.Chatbot(value=initial_chat_history) audio_out = gr.Audio(label="Escute a última mensagem", value=initial_audio, autoplay=True, interactive=False) user_msg_txb = gr.Textbox(label="Mensagem") #if USE_ASR_PIPELINE: # audio_in = gr.Audio(label="Mensagem de Áudio", sources=['microphone'], interactive=True, type='numpy') #else: # audio_in = gr.Audio(label="Mensagem de Áudio", sources=['microphone'], interactive=True, type='filepath') submit_btn = gr.Button("Enviar") #clear_btn = gr.ClearButton(components=[user_msg, chatbot], value="Clear console") reset_btn = gr.Button("Reiniciar") with gr.Accordion(label="Configurações",open=False): if LOAD_SHARED_KEY: openai_key = gr.Textbox(label="OPENAI API Key", value=os.environ['OPENAI_API_KEY']) else: openai_key = gr.Textbox(label="OPENAI API Key", placeholder="Insert your API key here") openai_key.change(reset_openai_client, inputs=[openai_key]) # opções de vozes e personalidades voice_ddown = gr.Dropdown(label="Personalidade (muda os dois abaixo)", choices=["nova", "echo"], value=INITIAL_VOICE) initial_system_message, initial_temperature = on_voice_change(INITIAL_VOICE) temperature_sldr = gr.Slider(label="Diversidade de respostas", minimum=0.0, maximum=1.0, value=initial_temperature, step=0.1) with gr.Accordion(label="Avançado",open=False): # o valor inicial é dado pela system message com o nome e personalidade dados pelos controles acima system_txtbox = gr.Textbox(label="System message", lines=3, value=initial_system_message) voice_ddown.change(on_voice_change, inputs=[voice_ddown], outputs=[system_txtbox, temperature_sldr]) #gr.Markdown("*Clique em 'Reiniciar' para aplicar as (a maior parte das) configurações.*") reset_btn.click(reset_and_apply, inputs=[openai_key, voice_ddown], outputs=[chatbot_area, audio_out]) #audio_in.stop_recording( transcribe, inputs=[audio_in], outputs=[user_msg_txb] ) #audio_in.stop_recording( transcribe_and_respond, inputs=[audio_in, system_txtbox, user_msg_txb, chatbot_area, temperature_sldr, voice_ddown], outputs=[user_msg_txb, chatbot_area, audio_out] ) submit_btn.click(respond, inputs=[system_txtbox, user_msg_txb, chatbot_area, temperature_sldr, voice_ddown], outputs=[user_msg_txb, chatbot_area, audio_out]) # Click on the button user_msg_txb.submit(respond, inputs=[system_txtbox, user_msg_txb, chatbot_area, temperature_sldr, voice_ddown], outputs=[user_msg_txb, chatbot_area, audio_out]) # Press enter to submit - same effect demo.queue().launch(share=False)