Mohinikathro commited on
Commit
ce8343a
·
verified ·
1 Parent(s): b365559

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +196 -0
app.py ADDED
@@ -0,0 +1,196 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import gradio as gr
3
+ from transformers import AutoTokenizer, AutoModelForSeq2SeqLM, AutoModelForCausalLM, BitsAndBytesConfig
4
+ import torch
5
+ import os
6
+ import gradio_client.utils as client_utils
7
+ import sys
8
+
9
+
10
+ # ===============================
11
+ # Device and Model Setup
12
+ # ===============================
13
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
14
+ hf_token = os.environ["HF_TOKEN"]
15
+
16
+ #Load the model
17
+ model_path = "AI-Mock-Interviewer/T5"
18
+ tokenizer = AutoTokenizer.from_pretrained(model_path)
19
+ model = AutoModelForSeq2SeqLM.from_pretrained(model_path)
20
+ model.to(device)
21
+
22
+ model = torch.compile(model)
23
+
24
+ # ------------------- UPDATED SYSTEM PROMPT -------------------
25
+ system_prompt = """
26
+ You are conducting a mock technical interview. The candidate's experience level can be entry-level, mid-level, or senior-level. Generate questions and follow-up questions based on the domain and the candidate's experience level. Consider these aspects:
27
+ 1. The question should be relevant to the domain (e.g., software engineering, machine learning) and appropriate for the candidate's experience level.
28
+ 2. Ensure each question is unique and does not repeat previously asked questions.
29
+ 3. Ensure each question covers a different sub-topic within the domain, avoiding redundancy.
30
+ 4. If no clear follow-up can be derived, generate a fresh, related question from a different aspect of the domain.
31
+ Important: Ensure that each question is clear, concise, and allows the candidate to demonstrate their technical and communicative abilities effectively.
32
+ """
33
+
34
+ # Define sub-topic categories for different domains
35
+ subtopic_keywords = {
36
+ "data analysis": [
37
+ "data cleaning", "missing data", "outliers",
38
+ "feature engineering", "EDA", "trend analysis",
39
+ "data visualization"
40
+ ],
41
+ "machine learning": [
42
+ "supervised learning", "unsupervised learning",
43
+ "model evaluation", "bias-variance tradeoff",
44
+ "overfitting", "hyperparameter tuning"
45
+ ],
46
+ "software engineering": [
47
+ "agile methodology", "code optimization",
48
+ "design patterns", "database design",
49
+ "testing strategies"
50
+ ],
51
+ }
52
+
53
+ def identify_subtopic(question, domain):
54
+ """Identify the sub-topic of a question using predefined keywords."""
55
+ domain = domain.lower()
56
+ if domain in subtopic_keywords:
57
+ for subtopic in subtopic_keywords[domain]:
58
+ if subtopic in question.lower():
59
+ return subtopic
60
+ return None
61
+
62
+ # We'll keep global sets here only if needed as a fallback:
63
+ asked_questions = set()
64
+ asked_subtopics = set()
65
+
66
+ def generate_question(prompt, domain, state=None):
67
+ """
68
+ Generates a unique question based on the prompt and domain.
69
+ Uses 'state' to track uniqueness in the conversation session.
70
+ """
71
+ while True:
72
+ full_prompt = system_prompt + "\n" + prompt
73
+ inputs = tokenizer(full_prompt, return_tensors="pt").to(device)
74
+ outputs = model.generate(
75
+ inputs["input_ids"],
76
+ max_new_tokens=50,
77
+ num_return_sequences=1,
78
+ no_repeat_ngram_size=2,
79
+ top_k=30,
80
+ top_p=0.9,
81
+ temperature=0.7,
82
+ do_sample=True,
83
+ pad_token_id=tokenizer.eos_token_id,
84
+ )
85
+ question = tokenizer.decode(outputs[0], skip_special_tokens=True)
86
+ question = question.replace(full_prompt, "").strip()
87
+
88
+ # Ensure question ends with a question mark
89
+ if not question.endswith("?"):
90
+ question = question.split("?")[0] + "?"
91
+
92
+ # Identify the subtopic
93
+ subtopic = identify_subtopic(question, domain)
94
+
95
+ if state is not None:
96
+ # Use session-level sets to ensure uniqueness
97
+ if (question not in state["asked_questions"] and
98
+ (subtopic is None or subtopic not in state["asked_subtopics"])):
99
+ state["asked_questions"].add(question)
100
+ if subtopic:
101
+ state["asked_subtopics"].add(subtopic)
102
+ return question
103
+ else:
104
+ # Fallback to global sets if no state is provided
105
+ if question not in asked_questions and (subtopic is None or subtopic not in asked_subtopics):
106
+ asked_questions.add(question)
107
+ if subtopic:
108
+ asked_subtopics.add(subtopic)
109
+ return question
110
+
111
+ def reset_state(domain, company, level):
112
+ """
113
+ Resets or initializes the session state.
114
+ """
115
+ return {
116
+ "domain": domain,
117
+ "company": company,
118
+ "level": level,
119
+ "asked_questions": set(),
120
+ "asked_subtopics": set(),
121
+ "conversation": [] # List of (speaker, message) tuples
122
+ }
123
+
124
+ def start_interview(domain, company, level):
125
+ """
126
+ Initializes a new interactive interview session with the first question.
127
+ """
128
+ state = reset_state(domain, company, level)
129
+ prompt = (f"Domain: {domain}. "
130
+ + (f"Company: {company}. " if company else "")
131
+ + f"Candidate experience level: {level}. "
132
+ "Generate the first question:")
133
+
134
+ question = generate_question(prompt, domain, state)
135
+ state["conversation"].append(("Interviewer", question))
136
+ return state["conversation"], state
137
+
138
+ def submit_response(candidate_response, state):
139
+ """
140
+ Accepts the candidate's response, updates conversation, generates the next question.
141
+ Allows quitting the interview by typing 'quit'.
142
+ """
143
+ if candidate_response.strip().lower() == "quit":
144
+ state["conversation"].append(("Candidate", candidate_response))
145
+ state["conversation"].append(("Interviewer", "Interview session has ended. Thank you for participating!"))
146
+ return state["conversation"], state
147
+
148
+ state["conversation"].append(("Candidate", candidate_response))
149
+ prompt = (f"Domain: {state['domain']}. "
150
+ f"Candidate's experience level: {state['level']}. "
151
+ "Generate the next interview question:")
152
+
153
+ question = generate_question(prompt, state["domain"], state)
154
+ state["conversation"].append(("Interviewer", question))
155
+ return state["conversation"], state
156
+
157
+ # Build an interactive Gradio interface using Blocks
158
+ with gr.Blocks() as demo:
159
+ gr.Markdown("# Interactive Mock Interview")
160
+ with gr.Row():
161
+ domain_input = gr.Textbox(label="Domain", placeholder="e.g. Software Engineering")
162
+ company_input = gr.Textbox(label="Company (Optional)", placeholder="e.g. Google")
163
+ level_input = gr.Dropdown(
164
+ label="Experience Level",
165
+ choices=["Entry-Level", "Mid-Level", "Senior-Level"],
166
+ value="Entry-Level"
167
+ )
168
+
169
+ start_button = gr.Button("Start Interview")
170
+ chatbot = gr.Chatbot(label="Interview Conversation")
171
+
172
+ with gr.Row():
173
+ response_input = gr.Textbox(label="Your Response", placeholder="Type 'quit' to end the interview")
174
+ submit_button = gr.Button("Submit")
175
+
176
+ # State to hold session data
177
+ state = gr.State()
178
+
179
+ # Start interview
180
+ start_button.click(
181
+ start_interview,
182
+ inputs=[domain_input, company_input, level_input],
183
+ outputs=[chatbot, state]
184
+ )
185
+
186
+ # Submit response
187
+ submit_button.click(
188
+ submit_response,
189
+ inputs=[response_input, state],
190
+ outputs=[chatbot, state]
191
+ ).then(
192
+ lambda: "", None, response_input # Clear input box after submission
193
+ )
194
+
195
+
196
+ demo.launch()