import argparse import os import soundfile as sf import gradio as gr import numpy as np from groq import Groq from models import build_model from kokoro import generate import torch ### NEW: We'll store the default voice name in a global variable so we can change it later. DEFAULT_VOICE_NAME = 'bm_george' def initialize_model(): device = 'cuda' if torch.cuda.is_available() else 'cpu' model = build_model('/content/Kokoro-82M/fp16/kokoro-v0_19-half.pth', device) ### UPDATED: Use our DEFAULT_VOICE_NAME here, so we can swap it out later voice_name = DEFAULT_VOICE_NAME voicepack = torch.load(f'voices/{voice_name}.pt', weights_only=True).to(device) print(f'Loaded voice: {voice_name}') return model, voicepack, device MODEL, VOICEPACK, DEVICE = initialize_model() client = None def initialize_groq(api_key): """ Initialize the Groq client with the provided API key. """ global client try: client = Groq(api_key=api_key) return "API key configured successfully" except Exception as e: return f"Error configuring API key: {str(e)}" ### NEW: Function to change voice pack after the program has started def set_voice_name(voice): """ Dynamically load the requested voicepack. """ global VOICEPACK, DEFAULT_VOICE_NAME try: VOICEPACK = torch.load(f'voices/{voice}.pt', weights_only=True).to(DEVICE) DEFAULT_VOICE_NAME = voice # store new default so we can keep track return f"Voice changed to {voice}" except FileNotFoundError: return f"Voice pack {voice} not found in voices/" def answer(question): if not client: return "Please configure Groq API key first" try: chat_completion = client.chat.completions.create( messages=[ { "role": "system", "content": "you are a helpful assistant. your answers must be short" }, { "role": "user", "content": question } ], model="llama3-8b-8192", temperature=0.5, max_tokens=1024, top_p=1, stop=None, stream=False, ) return chat_completion.choices[0].message.content except Exception as e: return f"Error: {str(e)}" def conversation_pipeline(audio_path=None, text_input=None): if not client: return "Please configure Groq API key first", None, None if audio_path and os.path.exists(audio_path): with open(audio_path, "rb") as file: transcription = client.audio.transcriptions.create( file=(audio_path, file.read()), model="distil-whisper-large-v3-en", response_format="verbose_json", ).text elif text_input: transcription = text_input else: return None, None, None gemini_response = answer(transcription) generated_audio, _ = generate(MODEL, gemini_response, VOICEPACK, lang="a") return transcription, gemini_response, generated_audio def process_audio(audio=None, text_input=None): if audio is not None: audio_path = "temp_audio.wav" sf.write(audio_path, audio[1], audio[0]) transcription, response, audio_out = conversation_pipeline(audio_path=audio_path) os.remove(audio_path) else: transcription, response, audio_out = conversation_pipeline(text_input=text_input) if audio_out is not None: audio_out = np.array(audio_out).flatten().astype(np.float32) return ( transcription if transcription else "", response if response else "", (24000, audio_out), ) return "", "", None def main(): with gr.Blocks() as interface: gr.Markdown("# Voice Chat Interface") gr.Markdown("Configure API key and start chatting") # Row for API key with gr.Row(): api_key = gr.Textbox(label="Groq API Key", type="password") api_status = gr.Textbox(label="API Status", interactive=False) configure_btn = gr.Button("Configure API") ### NEW: Row to change voice name on the fly with gr.Row(): voice_name_input = gr.Textbox(label="Voice Name", value=DEFAULT_VOICE_NAME) voice_status = gr.Textbox(label="Voice Status", interactive=False) set_voice_btn = gr.Button("Set Voice") # Row for user input with gr.Row(): audio_input = gr.Audio(sources=["microphone"], type="numpy", label="Speak") text_input = gr.Textbox(label="Or type your message here") # Row for outputs with gr.Row(): transcription = gr.Textbox(label="Transcription", interactive=False) response = gr.Textbox(label="AI Response", interactive=False) with gr.Row(): audio_output = gr.Audio(label="AI Voice Response", autoplay=True) # Configure API key configure_btn.click( initialize_groq, inputs=[api_key], outputs=[api_status] ) ### NEW: Set voice dynamically set_voice_btn.click( set_voice_name, inputs=[voice_name_input], outputs=[voice_status] ) # Process with either audio or text audio_input.change( process_audio, inputs=[audio_input, text_input], outputs=[transcription, response, audio_output] ) text_input.submit( process_audio, inputs=[audio_input, text_input], outputs=[transcription, response, audio_output] ) interface.launch(share=True) if __name__ == "__main__": main()