from transformers import AutoModelForCausalLM, AutoTokenizer
import torchaudio
from transformers import Wav2Vec2ForCTC, Wav2Vec2Tokenizer
from gtts import gTTS
import os
import tempfile
import torch
import gradio as gr

# Device configuration
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

# Load conversational language model
language_model_name = "microsoft/DialoGPT-medium"  # Changed from BioGPT to DialoGPT
tokenizer = AutoTokenizer.from_pretrained(language_model_name)
language_model = AutoModelForCausalLM.from_pretrained(language_model_name).to(device)

# Load Speech-to-Text (Wav2Vec2) model
stt_model_name = "facebook/wav2vec2-base-960h"
stt_tokenizer = Wav2Vec2Tokenizer.from_pretrained(stt_model_name)
stt_model = Wav2Vec2ForCTC.from_pretrained(stt_model_name).to(device)

# Conversation history for context
chat_history_ids = None

def transcribe_audio(audio_path):
    waveform, sample_rate = torchaudio.load(audio_path)

    # Resample to 16000 if necessary
    if sample_rate != 16000:
        resampler = torchaudio.transforms.Resample(orig_freq=sample_rate, new_freq=16000)
        waveform = resampler(waveform)
    
    input_values = stt_tokenizer(waveform.squeeze().numpy(), return_tensors="pt", sampling_rate=16000).input_values.to(device)

    with torch.no_grad():
        logits = stt_model(input_values).logits

    predicted_ids = torch.argmax(logits, dim=-1)
    transcription = stt_tokenizer.batch_decode(predicted_ids)[0]
    return transcription.lower()

def get_bot_response(user_input):
    global chat_history_ids

    # Encode the user input and append to chat history
    new_user_input_ids = tokenizer.encode(user_input + tokenizer.eos_token, return_tensors='pt').to(device)
    if chat_history_ids is not None:
        bot_input_ids = torch.cat([chat_history_ids, new_user_input_ids], dim=-1)
    else:
        bot_input_ids = new_user_input_ids

    # Generate response
    chat_history_ids = language_model.generate(
        bot_input_ids,
        max_length=1000,
        pad_token_id=tokenizer.eos_token_id,
        no_repeat_ngram_size=3,
        do_sample=True,
        top_p=0.95,
        temperature=0.7
    )

    # Decode the response
    response = tokenizer.decode(chat_history_ids[:, bot_input_ids.shape[-1]:][0], skip_special_tokens=True)
    return response

def text_to_speech(text):
    tts = gTTS(text=text, lang='en')
    with tempfile.NamedTemporaryFile(delete=True, suffix=".mp3") as fp:
        tts.save(fp.name)
        return fp.name

def chatbot_interface(audio):
    if audio is None:
        return "Please provide an audio input.", None
    
    try:
        # Step 1: Transcribe audio to text
        user_input = transcribe_audio(audio)
        if not user_input.strip():
            return "Sorry, I could not understand the audio.", None
    except Exception as e:
        return f"Error in transcription: {str(e)}", None





    try:
        # Step 2: Get bot response
        bot_response = get_bot_response(user_input)
        if not bot_response.strip():
            bot_response = "I'm sorry, I don't have an answer to that. Please consult a professional."
    except Exception as e:
        bot_response = f"Error in generating response: {str(e)}"

    try:
        # Step 3: Convert bot response to speech
        audio_file = text_to_speech(bot_response)
    except Exception as e:
        return f"Error in generating speech: {str(e)}", None

    return f"You: {user_input}", (bot_response, audio_file)

# Gradio Interface using Blocks for better layout
with gr.Blocks() as demo:
    gr.Markdown("# 🏥 Healthcare AI Chatbot")
    gr.Markdown("**Ask health-related questions. Please consult a professional for medical advice.**")

    with gr.Row():
        audio_input = gr.Audio(source="microphone", type="filepath", label="Your Voice")
        submit_btn = gr.Button("Submit")

    with gr.Row():
        user_text = gr.Textbox(label="You:", interactive=False, lines=2)
        bot_text = gr.Textbox(label="Bot:", interactive=False, lines=5)
    
    with gr.Row():
        bot_audio = gr.Audio(label="Bot's Voice")

    submit_btn.click(
        fn=chatbot_interface,
        inputs=audio_input,
        outputs=[user_text, bot_text, bot_audio]
    )

# Launch the interface
demo.launch()


Traceback (most recent call last):
  File "/home/user/app/app.py", line 112, in <module>
    audio_input = gr.Audio(source="microphone", type="filepath", label="Your Voice")
  File "/usr/local/lib/python3.10/site-packages/gradio/component_meta.py", line 163, in wrapper
    return fn(self, **kwargs)
TypeError: Audio.__init__() got an unexpected keyword argument 'source'