# ✅ FINAL MERGED & ENHANCED CODE: AI Interview Bot (Jason Voice, One-by-One, Stylish UI) import os import gradio as gr import whisper import tempfile import re from dotenv import load_dotenv from TTS.api import TTS import google.generativeai as genai # ----------------------------- # ✅ CONFIGURE GEMINI API # ----------------------------- genai.configure(api_key="AIzaSyAeNCjKJVCT0gmQRAPq4NltXkc-1zELH28") model = genai.GenerativeModel("gemini-1.5-flash-latest") # ----------------------------- # ✅ LOAD MODELS # ----------------------------- asr_model = whisper.load_model("base") jason_tts = TTS(model_name="tts_models/en/ljspeech/tacotron2-DDC", progress_bar=False, gpu=False) # ----------------------------- # ✅ GLOBAL STATE # ----------------------------- candidate_name = "" field = "" interview_questions = [] current_question_index = 0 feedback_summary = [] # ----------------------------- # ✅ STEP 1: Collect Candidate Info # ----------------------------- def save_user_info(name, user_field): global candidate_name, field candidate_name = name field = user_field greeting = f"Welcome {name}! Jason will conduct your mock interview for the {field} internship." return greeting # ----------------------------- # ✅ STEP 2: Generate Questions with Strict Format # ----------------------------- def generate_questions(): global field, interview_questions, current_question_index, feedback_summary current_question_index = 0 feedback_summary = [] prompt = ( f"You are a professional interviewer. Generate exactly 12 internship questions (7 technical + 5 behavioral) for the field of {field}.\n" f"Output only the questions, each starting with a number (e.g., 1. ..., 2. ..., ..., 12.). Do not include headings or explanations." ) try: response = model.generate_content(prompt) raw_output = response.text.strip() lines = re.findall(r"^\d+\.\s+.*", raw_output, re.MULTILINE) interview_questions = [line.strip() for line in lines] if len(interview_questions) != 12: return "⚠️ Gemini did not return exactly 12 questions. Please try again.", "" return "✅ Questions generated successfully!", interview_questions[0] except Exception as e: return f"Error: {str(e)}", "" # ----------------------------- # ✅ STEP 3: Jason Speaks Current Question # ----------------------------- def speak_current_question(): if not interview_questions or current_question_index >= len(interview_questions): return "No more questions.", None question = interview_questions[current_question_index] temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".wav") jason_tts.tts_to_file(text=question, file_path=temp_file.name) return question, temp_file.name # ----------------------------- # ✅ STEP 4: Record Answer & Store for Analysis # ----------------------------- def record_answer(audio_file): global current_question_index if not interview_questions: return "❌ Generate questions first.", "" if audio_file is None: return "❌ Please record your answer.", "" try: result = asr_model.transcribe(audio_file) transcript = result["text"] question = interview_questions[current_question_index] feedback_summary.append({"question": question, "answer": transcript, "feedback": None}) current_question_index += 1 next_q = interview_questions[current_question_index] if current_question_index < len(interview_questions) else "✅ Interview complete. Click SUBMIT for feedback." return f"✅ Answer recorded for Q{current_question_index}.", next_q except Exception as e: return f"Error: {str(e)}", "" # ----------------------------- # ✅ STEP 5: Analyze All Answers via Gemini # ----------------------------- def analyze_all(): if not feedback_summary: return "❌ No answers recorded." final_summary = "" for i, item in enumerate(feedback_summary, 1): prompt = ( f"Interview Question: {item['question']}\n" f"Candidate's Answer: {item['answer']}\n" "Evaluate the answer:\n" "- Overall Rating: Weak/Average/Good/Excellent\n" "- Score: out of 100\n" "- Suggestions:" ) try: response = model.generate_content(prompt) feedback = response.text.strip() item['feedback'] = feedback final_summary += f"Q{i}: {item['question']}\nAnswer: {item['answer']}\n{feedback}\n{'-'*50}\n" except Exception as e: final_summary += f"Q{i}: {item['question']}\nAnswer: {item['answer']}\nError: {str(e)}\n{'-'*50}\n" return final_summary # ----------------------------- # ✅ GRADIO UI (Modern Look) # ----------------------------- with gr.Blocks(theme=gr.themes.Soft(primary_hue="violet")) as demo: gr.Markdown("""