Anupam007 commited on
Commit
375ccf8
·
verified ·
1 Parent(s): 94da490

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +69 -124
app.py CHANGED
@@ -13,7 +13,12 @@ import speech_recognition as sr
13
  import cv2
14
  import numpy as np
15
  import ast
16
- from moviepy.editor import VideoFileClip
 
 
 
 
 
17
 
18
  # Suppress warnings
19
  warnings.filterwarnings("ignore", category=UserWarning, module="gtts")
@@ -37,60 +42,41 @@ def extract_text_from_pdf(pdf_file):
37
  return f"Error reading PDF: {str(e)}"
38
 
39
  # Analyze resume and generate questions
40
- def analyze_resume(resume_text, custom_questions=None, difficulty=1):
41
  generic_questions = [
42
  "What’s your greatest strength?",
43
  "Describe a challenge you overcame.",
44
  "Why do you want this role?"
45
  ]
46
- if not resume_text and not custom_questions:
47
  return generic_questions[:difficulty]
48
 
49
  questions = []
50
- if resume_text:
51
- skills = re.findall(r"Skills:\s*(.*?)(?:\n|$)", resume_text, re.DOTALL | re.IGNORECASE)
52
- experience = re.findall(r"Experience:\s*(.*?)(?:\n[A-Z]|\Z)", resume_text, re.DOTALL | re.IGNORECASE)
53
- education = re.findall(r"Education:\s*(.*?)(?:\n|$)", resume_text, re.DOTALL | re.IGNORECASE)
54
-
55
- if skills:
56
- first_skill = skills[0].split(',')[0].strip()
57
- questions.append(f"Tell me about a time you used {first_skill} in a project.")
58
- if experience:
59
- try:
60
- company_name = re.search(r"at\s+([\w\s]+?)\s*\(", experience[0]) or "the company"
61
- if isinstance(company_name, str):
62
- company_name = company_name
63
- else:
64
- company_name = company_name.group(1).strip()
65
- questions.append(f"Can you describe a key contribution you made at {company_name}?")
66
- except Exception:
67
- pass
68
- if education:
69
- first_education = education[0].split('(')[0].strip()
70
- questions.append(f"How did your education at {first_education} prepare you for this role?")
71
-
72
- if custom_questions:
73
- with open(custom_questions.name, "r") as f:
74
- questions.extend(f.read().splitlines())
75
 
76
  return (questions + generic_questions)[:max(1, difficulty)]
77
 
78
- # Enhanced feedback with sentiment analysis
79
  def provide_feedback(response):
80
  if not response:
81
  return "Please provide an answer."
82
- word_count = len(response.split())
83
  sentiment = sentiment_analyzer(response)[0]
84
  feedback = []
85
- if word_count < 20:
 
86
  feedback.append("Your answer is short. Please elaborate.")
87
  if "I don’t know" in response.lower():
88
  feedback.append("Try sharing a related experience instead.")
89
  if sentiment["label"] == "NEGATIVE":
90
  feedback.append("Try to sound more positive and confident!")
91
- return " ".join(feedback) or "Great answer! Well detailed and positive."
92
 
93
- # Analyze code input
 
 
94
  def analyze_code(code):
95
  if not code:
96
  return "No code provided."
@@ -100,36 +86,11 @@ def analyze_code(code):
100
  except SyntaxError as e:
101
  return f"Code error: {str(e)}"
102
 
103
- # Create interview video
104
- def create_interview_video(questions, responses, output_path="interview_simulation.mp4"):
105
- try:
106
- frame_rate = 1
107
- resolution = (1280, 720)
108
- fourcc = cv2.VideoWriter_fourcc(*'mp4v')
109
- out = cv2.VideoWriter(output_path, fourcc, frame_rate, resolution)
110
-
111
- for i, (question, response) in enumerate(zip(questions, responses)):
112
- frame = np.zeros((resolution[1], resolution[0], 3), dtype=np.uint8)
113
- cv2.putText(frame, f"Question {i+1}: {question}", (50, 200), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2)
114
- for _ in range(5 * frame_rate):
115
- out.write(frame)
116
-
117
- if response:
118
- frame = np.zeros((resolution[1], resolution[0], 3), dtype=np.uint8)
119
- cv2.putText(frame, f"Response: {response}", (50, 200), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 0), 2)
120
- for _ in range(5 * frame_rate):
121
- out.write(frame)
122
-
123
- out.release()
124
- return output_path
125
- except Exception as e:
126
- return f"Video creation failed: {str(e)}"
127
-
128
  # Transcribe audio from video or audio file
129
  def transcribe_audio(file_path):
130
  try:
131
  if file_path.endswith(".mp4"): # Handle video input
132
- video = VideoFileClip(file_path)
133
  audio_path = tempfile.NamedTemporaryFile(suffix=".wav").name
134
  video.audio.write_audiofile(audio_path)
135
  else:
@@ -141,54 +102,10 @@ def transcribe_audio(file_path):
141
  except Exception as e:
142
  return f"Error transcribing: {str(e)}"
143
 
144
- # Main interview function
145
- def run_interview(pdf_file, video_file, code_input, mc_input, user_response, question_index, questions_state, responses_state, timer_state, custom_questions, difficulty):
146
- try:
147
- # Initialize questions if not set
148
- if not questions_state:
149
- resume_text = extract_text_from_pdf(pdf_file) if pdf_file else ""
150
- questions_state = analyze_resume(resume_text, custom_questions, difficulty)
151
- responses_state = [""] * len(questions_state)
152
- timer_state = 60 # Reset timer
153
-
154
- # Process video/audio input
155
- if video_file:
156
- user_response = transcribe_audio(video_file)
157
-
158
- # Handle multiple-choice or code input if provided
159
- if mc_input:
160
- user_response = f"Selected: {mc_input}"
161
- elif code_input:
162
- user_response = code_input
163
- code_feedback = analyze_code(code_input)
164
- else:
165
- code_feedback = ""
166
-
167
- # Save response
168
- if user_response and 0 <= question_index < len(questions_state):
169
- responses_state[question_index] = user_response
170
-
171
- # Check if interview is complete
172
- if question_index >= len(questions_state):
173
- video_path = create_interview_video(questions_state, responses_state)
174
- return "Interview complete!", "Thank you!", video_path, questions_state, responses_state, question_index, 0, None
175
-
176
- # Current question and feedback
177
- current_question = questions_state[question_index]
178
- feedback = provide_feedback(user_response) + (f" {code_feedback}" if code_feedback else "")
179
-
180
- # Update timer (simplified for demo)
181
- timer_state = max(0, timer_state - 10) # Decrement by 10 seconds per submission
182
-
183
- return current_question, feedback, None, questions_state, responses_state, question_index + 1, timer_state, str(timer_state)
184
-
185
- except Exception as e:
186
- return f"Error: {str(e)}", "Something went wrong.", None, [], [], 0, 60, "60"
187
-
188
  # Gradio interface
189
  with gr.Blocks(title="Nancy AI - Advanced Interview Simulator") as demo:
190
- gr.Markdown("# Nancy AI - Advanced Interview Simulator")
191
- gr.Markdown("Upload your resume and a video response (Note: Webcam recording not supported in Colab; upload pre-recorded videos instead).")
192
 
193
  question_state = gr.State(value=0)
194
  questions_state = gr.State(value=[])
@@ -196,30 +113,58 @@ with gr.Blocks(title="Nancy AI - Advanced Interview Simulator") as demo:
196
  timer_state = gr.State(value=60)
197
 
198
  with gr.Row():
199
- pdf_input = gr.File(label="Upload PDF Resume", file_types=[".pdf"])
200
- custom_questions = gr.File(label="Upload Custom Questions (TXT)", file_types=[".txt"])
201
- difficulty = gr.Slider(1, 5, step=1, label="Difficulty Level", value=1)
202
 
203
  with gr.Row():
204
- # Updated: No 'source' parameter; use interactive=True for recording in non-Colab environments
205
- video_input = gr.Video(label="Upload or Record Video Response", interactive=True)
206
- code_input = gr.Code(language="python", label="Write Your Code (if applicable)")
207
- mc_input = gr.Radio(["Option A", "Option B", "Option C"], label="Multiple Choice (if applicable)")
208
- text_input = gr.Textbox(label="Your Response (Optional)", placeholder="Type your answer here...")
209
 
210
  with gr.Row():
211
- question_output = gr.Textbox(label="Current Question", interactive=False)
212
- feedback_output = gr.Textbox(label="Feedback", interactive=False)
213
- timer_display = gr.Textbox(label="Time Left (seconds)", interactive=False, value="60")
214
-
215
- video_output = gr.Video(label="Interview Simulation", visible=False)
216
-
217
- submit_btn = gr.Button("Submit Response & Next Question")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
218
 
219
  submit_btn.click(
220
- fn=run_interview,
221
- inputs=[pdf_input, video_input, code_input, mc_input, text_input, question_state, questions_state, responses_state, timer_state, custom_questions, difficulty],
222
- outputs=[question_output, feedback_output, video_output, questions_state, responses_state, question_state, timer_state, timer_display]
223
  )
224
 
225
- demo.launch()
 
13
  import cv2
14
  import numpy as np
15
  import ast
16
+
17
+ # Fixed moviepy import
18
+ try:
19
+ import moviepy.editor as mp
20
+ except ModuleNotFoundError:
21
+ raise ImportError("The 'moviepy' module is not installed. Please add 'moviepy' to your requirements.txt and restart your Hugging Face Space.")
22
 
23
  # Suppress warnings
24
  warnings.filterwarnings("ignore", category=UserWarning, module="gtts")
 
42
  return f"Error reading PDF: {str(e)}"
43
 
44
  # Analyze resume and generate questions
45
+ def analyze_resume(resume_text, difficulty=1):
46
  generic_questions = [
47
  "What’s your greatest strength?",
48
  "Describe a challenge you overcame.",
49
  "Why do you want this role?"
50
  ]
51
+ if not resume_text:
52
  return generic_questions[:difficulty]
53
 
54
  questions = []
55
+ skills = re.findall(r"Skills:\s*(.*?)(?:\n|$)", resume_text, re.DOTALL | re.IGNORECASE)
56
+
57
+ if skills:
58
+ first_skill = skills[0].split(',')[0].strip()
59
+ questions.append(f"Tell me about a time you used {first_skill} in a project.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
 
61
  return (questions + generic_questions)[:max(1, difficulty)]
62
 
63
+ # Analyze user response with sentiment analysis
64
  def provide_feedback(response):
65
  if not response:
66
  return "Please provide an answer."
 
67
  sentiment = sentiment_analyzer(response)[0]
68
  feedback = []
69
+
70
+ if len(response.split()) < 20:
71
  feedback.append("Your answer is short. Please elaborate.")
72
  if "I don’t know" in response.lower():
73
  feedback.append("Try sharing a related experience instead.")
74
  if sentiment["label"] == "NEGATIVE":
75
  feedback.append("Try to sound more positive and confident!")
 
76
 
77
+ return " ".join(feedback) or "Great answer!"
78
+
79
+ # Analyze code syntax
80
  def analyze_code(code):
81
  if not code:
82
  return "No code provided."
 
86
  except SyntaxError as e:
87
  return f"Code error: {str(e)}"
88
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  # Transcribe audio from video or audio file
90
  def transcribe_audio(file_path):
91
  try:
92
  if file_path.endswith(".mp4"): # Handle video input
93
+ video = mp.VideoFileClip(file_path)
94
  audio_path = tempfile.NamedTemporaryFile(suffix=".wav").name
95
  video.audio.write_audiofile(audio_path)
96
  else:
 
102
  except Exception as e:
103
  return f"Error transcribing: {str(e)}"
104
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
  # Gradio interface
106
  with gr.Blocks(title="Nancy AI - Advanced Interview Simulator") as demo:
107
+ gr.Markdown("# 🎤 Nancy AI - Advanced Interview Simulator")
108
+ gr.Markdown("Upload your resume and a video response to get interview questions and feedback.")
109
 
110
  question_state = gr.State(value=0)
111
  questions_state = gr.State(value=[])
 
113
  timer_state = gr.State(value=60)
114
 
115
  with gr.Row():
116
+ pdf_input = gr.File(label="📄 Upload PDF Resume", file_types=[".pdf"])
117
+ difficulty = gr.Slider(1, 5, step=1, label="🔹 Difficulty Level", value=1)
 
118
 
119
  with gr.Row():
120
+ video_input = gr.Video(label="🎥 Upload or Record Video Response", interactive=True)
121
+ code_input = gr.Code(language="python", label="📝 Write Your Code (if applicable)")
122
+ text_input = gr.Textbox(label="🗣️ Your Response", placeholder="Type your answer here...")
 
 
123
 
124
  with gr.Row():
125
+ question_output = gr.Textbox(label="Current Question", interactive=False)
126
+ feedback_output = gr.Textbox(label="💡 Feedback", interactive=False)
127
+ timer_display = gr.Textbox(label="Time Left (seconds)", interactive=False, value="60")
128
+
129
+ submit_btn = gr.Button(" Submit Response")
130
+
131
+ # Define click action
132
+ def process_response(pdf_file, video_file, code_input, text_input, question_index, questions_state, responses_state, timer_state, difficulty):
133
+ try:
134
+ # Load or generate interview questions
135
+ if not questions_state:
136
+ resume_text = extract_text_from_pdf(pdf_file) if pdf_file else ""
137
+ questions_state = analyze_resume(resume_text, difficulty)
138
+ responses_state = [""] * len(questions_state)
139
+ timer_state = 60 # Reset timer
140
+
141
+ # Transcribe video/audio response
142
+ user_response = transcribe_audio(video_file) if video_file else text_input
143
+ if code_input:
144
+ user_response = code_input
145
+ code_feedback = analyze_code(code_input)
146
+ else:
147
+ code_feedback = ""
148
+
149
+ # Save response
150
+ if user_response and 0 <= question_index < len(questions_state):
151
+ responses_state[question_index] = user_response
152
+
153
+ # Provide feedback
154
+ feedback = provide_feedback(user_response) + (f" {code_feedback}" if code_feedback else "")
155
+
156
+ # Move to the next question
157
+ if question_index >= len(questions_state) - 1:
158
+ return "Interview complete!", "Thank you!", questions_state, responses_state, 0, None
159
+
160
+ return questions_state[question_index], feedback, questions_state, responses_state, question_index + 1, str(max(0, timer_state - 10))
161
+ except Exception as e:
162
+ return f"Error: {str(e)}", "Something went wrong.", [], [], 0, "60"
163
 
164
  submit_btn.click(
165
+ fn=process_response,
166
+ inputs=[pdf_input, video_input, code_input, text_input, question_state, questions_state, responses_state, timer_state, difficulty],
167
+ outputs=[question_output, feedback_output, questions_state, responses_state, question_state, timer_display]
168
  )
169
 
170
+ demo.launch()