futeboy / app.py
Pablo Sampaio
Using Google API
8ca0441
raw
history blame
No virus
9.8 kB
import os
import gradio as gr
from openai import OpenAI
import google.generativeai as genai
LOAD_KEYS_FROM_FILES = False
USE_LOCAL_ASR_PIPELINE = True
if LOAD_KEYS_FROM_FILES:
# Load OpenAI API key
with open('KEY_OPENAI', 'r') as file:
OPENAI_API_KEY = file.read().replace('\n', '')
# Hugging Face API key, used for the serverless access to ASR model
with open('KEY_HF', 'r') as file:
os.environ['HUGGINGFACE_API_KEY'] = file.read().replace('\n', '')
# Google AI API key, to acces Gemini model
with open('KEY_GOOGLE_AI', 'r') as file:
GOOGLE_API_KEY = file.read().replace('\n', '')
else:
# testar se existe a variável OPENAI_API_KEY
OPENAI_API_KEY = "" if 'OPENAI_API_KEY' not in os.environ else os.environ['OPENAI_API_KEY']
GOOGLE_API_KEY = "" if 'GOOGLE_API_KEY' not in os.environ else os.environ['GOOGLE_API_KEY']
assert 'HUUGINGFACE_API_KEY' in os.environ, "Hugging Face API key not found in environment variables"
USE_OPENAI_LLM = (GOOGLE_API_KEY == "")
OPENAI_CLIENT = None
if USE_OPENAI_LLM:
OPENAI_CLIENT = OpenAI(api_key=OPENAI_API_KEY)
else:
genai.configure(api_key=GOOGLE_API_KEY)
GOOGLE_GEN_CONFIG = genai.types.GenerationConfig(
candidate_count=1,
temperature=0.5)
AUDIO_OUT_FILE_PREFIX = "output" # prefixo do nome do arquivo de áudio .wav
TEMPLATE_SYSTEM_MESSAGE = """Você é assistente virtual com a função é entreter uma criança de idade entre 6 e 8 anos que adora futebol. Diretrizes para a conversa:
- Você é {GENRE}, 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": ("Sua personalidade é bastante 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.5, "F"),
"echo": ("Sua personalidade é amigável, mas objetivo. Tente manter-se no mesmo assunto. Conte alguma curiosidade sobre um grande craque, de vez em quando.", 0.2, "M")
}
INITIAL_PERSON = "nova"
# 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 } ]
if len(chat_history) > 10:
chat_history = chat_history[0:3] + chat_history[-5:]
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
# Função para converter o histórico de chat para o formato esperado pela API do Google AI
def to_google_history(curr_message, chat_history):
prompt = []
for turn in chat_history:
user_message, bot_message = turn
prompt.append( {'role':'user', 'parts': [user_message]} )
prompt.append( {'role': 'model', 'parts': [bot_message]} )
prompt.append( {'role': 'user', 'parts': [curr_message]} )
return prompt
def respond(system_prompt, user_message, chat_history, temperature, voice="echo"):
if USE_OPENAI_LLM:
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
else:
GOOGLE_GEN_CONFIG.temperature = temperature
model = genai.GenerativeModel('gemini-1.5-pro-latest',
system_instruction=system_prompt,
generation_config=GOOGLE_GEN_CONFIG)
google_history = to_google_history(user_message, chat_history)
bot_response = model.generate_content(google_history, generation_config=GOOGLE_GEN_CONFIG)
assistant_msg = bot_response.text
# salva o audio
response = OPENAI_CLIENT.audio.speech.create(
model="tts-1",
voice=voice,
input=assistant_msg
)
output_audio_file = f"{AUDIO_OUT_FILE_PREFIX}-{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(voice):
return [("", "Olá, vamos falar de futebol?")], AUDIO_OUT_FILE_PREFIX + f"-001-{voice}.wav"
def reset_openai_client(openai_key):
global USE_OPENAI_LLM, OPENAI_CLIENT, OPENAI_API_KEY, GOOGLE_API_KEY
USE_OPENAI_LLM = (GOOGLE_API_KEY != "")
OPENAI_API_KEY = openai_key
OPENAI_CLIENT = OpenAI(api_key=OPENAI_API_KEY)
def reset_google_client(google_key):
global GOOGLE_API_KEY, USE_OPENAI_LLM
GOOGLE_API_KEY = google_key
USE_OPENAI_LLM = (google_key != "")
def on_voice_change(voice):
persona_description, persona_temperature, sex = PERSONALITIES[voice]
genre = "menina" if sex=="F" else "menino"
return TEMPLATE_SYSTEM_MESSAGE.format(NAME=voice.upper(), PERSONALITY=persona_description, GENRE=genre), persona_temperature
# With pipeline (downloaded model)
if USE_LOCAL_ASR_PIPELINE:
from transformers import pipeline
import numpy as np
global ASR_PIPELINE
ASR_PIPELINE = pipeline(task="automatic-speech-recognition",
model="openai/whisper-large-v3")
#model="distil-whisper/distil-small.en") # English only
else:
import requests
global ASR_API_URL, ASR_API_HEADERS
HF_KEY = os.environ['HUGGINGFACE_API_KEY']
# 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):
# from numpy data:
#sr, y = audio_in # sampling rate and audio data
#y2 = y.astype(np.float32)
#y2 /= np.max(np.abs(y))
#response = ASR_PIPELINE({"sampling_rate": sr, "raw": y})
# using 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
with gr.Blocks() as demo:
# aqui, é resetado e instanciado o cliente
initial_chat_history, initial_audio = reset_and_apply(INITIAL_PERSON)
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")
#audio_in = gr.Audio(label="Mensagem de Áudio", sources=['microphone'], interactive=True, type='filepath') # TODO: tentar type='numpy'
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):
openai_key = gr.Textbox(label="OpenAI API Key (GPT 3.5)", value="", placeholder="Insira a chave aqui")
openai_key.change(reset_openai_client, inputs=[openai_key])
openai_key = gr.Textbox(label="Google API Key (Gemini 1.5)", value="", placeholder="Insira a chave aqui")
openai_key.change(reset_google_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_PERSON)
initial_system_message, initial_temperature = on_voice_change(INITIAL_PERSON)
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_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)