import gradio as gr from transformers import pipeline import torch import re import os from PyPDF2 import PdfReader import gtts import tempfile import warnings import threading import time import speech_recognition as sr import cv2 import numpy as np import moviepy.editor as mp # Fixed moviepy import try: import moviepy.editor as mp except ModuleNotFoundError: raise ImportError("The 'moviepy' module is not installed. Please add 'moviepy' to your requirements.txt and restart your Hugging Face Space.") # Suppress warnings warnings.filterwarnings("ignore", category=UserWarning, module="gtts") # Initialize NLP models nlp = pipeline("text-generation", model="distilgpt2", tokenizer="distilgpt2", device=0 if torch.cuda.is_available() else -1) sentiment_analyzer = pipeline("sentiment-analysis", model="distilbert-base-uncased-finetuned-sst-2-english") # Speech recognizer setup r = sr.Recognizer() # Extract text from PDF resume def extract_text_from_pdf(pdf_file): try: reader = PdfReader(pdf_file.name) text = "" for page in reader.pages: text += page.extract_text() or "" return text if text else "No text found in the PDF." except Exception as e: return f"Error reading PDF: {str(e)}" # Analyze resume and generate questions def analyze_resume(resume_text, difficulty=1): generic_questions = [ "What’s your greatest strength?", "Describe a challenge you overcame.", "Why do you want this role?" ] if not resume_text: return generic_questions[:difficulty] questions = [] skills = re.findall(r"Skills:\s*(.*?)(?:\n|$)", resume_text, re.DOTALL | re.IGNORECASE) if skills: first_skill = skills[0].split(',')[0].strip() questions.append(f"Tell me about a time you used {first_skill} in a project.") return (questions + generic_questions)[:max(1, difficulty)] # Analyze user response with sentiment analysis def provide_feedback(response): if not response: return "Please provide an answer." sentiment = sentiment_analyzer(response)[0] feedback = [] if len(response.split()) < 20: feedback.append("Your answer is short. Please elaborate.") if "I don’t know" in response.lower(): feedback.append("Try sharing a related experience instead.") if sentiment["label"] == "NEGATIVE": feedback.append("Try to sound more positive and confident!") return " ".join(feedback) or "Great answer!" # Analyze code syntax def analyze_code(code): if not code: return "No code provided." try: ast.parse(code) return "Code syntax is valid! Consider adding comments for clarity." except SyntaxError as e: return f"Code error: {str(e)}" # Transcribe audio from video or audio file def transcribe_audio(file_path): try: if file_path.endswith(".mp4"): # Handle video input video = mp.VideoFileClip(file_path) audio_path = tempfile.NamedTemporaryFile(suffix=".wav").name video.audio.write_audiofile(audio_path) else: audio_path = file_path with sr.AudioFile(audio_path) as source: audio = r.record(source) return r.recognize_google(audio) except Exception as e: return f"Error transcribing: {str(e)}" # Gradio interface with gr.Blocks(title="Nancy AI - Advanced Interview Simulator") as demo: gr.Markdown("# 🎀 Nancy AI - Advanced Interview Simulator") gr.Markdown("Upload your resume and a video response to get interview questions and feedback.") question_state = gr.State(value=0) questions_state = gr.State(value=[]) responses_state = gr.State(value=[]) timer_state = gr.State(value=60) with gr.Row(): pdf_input = gr.File(label="πŸ“„ Upload PDF Resume", file_types=[".pdf"]) difficulty = gr.Slider(1, 5, step=1, label="πŸ”Ή Difficulty Level", value=1) with gr.Row(): video_input = gr.Video(label="πŸŽ₯ Upload or Record Video Response", interactive=True) code_input = gr.Code(language="python", label="πŸ“ Write Your Code (if applicable)") text_input = gr.Textbox(label="πŸ—£οΈ Your Response", placeholder="Type your answer here...") with gr.Row(): question_output = gr.Textbox(label="❓ Current Question", interactive=False) feedback_output = gr.Textbox(label="πŸ’‘ Feedback", interactive=False) timer_display = gr.Textbox(label="⏳ Time Left (seconds)", interactive=False, value="60") submit_btn = gr.Button("βœ… Submit Response") # Define click action def process_response(pdf_file, video_file, code_input, text_input, question_index, questions_state, responses_state, timer_state, difficulty): try: # Load or generate interview questions if not questions_state: resume_text = extract_text_from_pdf(pdf_file) if pdf_file else "" questions_state = analyze_resume(resume_text, difficulty) responses_state = [""] * len(questions_state) timer_state = 60 # Reset timer # Transcribe video/audio response user_response = transcribe_audio(video_file) if video_file else text_input if code_input: user_response = code_input code_feedback = analyze_code(code_input) else: code_feedback = "" # Save response if user_response and 0 <= question_index < len(questions_state): responses_state[question_index] = user_response # Provide feedback feedback = provide_feedback(user_response) + (f" {code_feedback}" if code_feedback else "") # Move to the next question if question_index >= len(questions_state) - 1: return "Interview complete!", "Thank you!", questions_state, responses_state, 0, None return questions_state[question_index], feedback, questions_state, responses_state, question_index + 1, str(max(0, timer_state - 10)) except Exception as e: return f"Error: {str(e)}", "Something went wrong.", [], [], 0, "60" submit_btn.click( fn=process_response, inputs=[pdf_input, video_input, code_input, text_input, question_state, questions_state, responses_state, timer_state, difficulty], outputs=[question_output, feedback_output, questions_state, responses_state, question_state, timer_display] ) demo.launch()