vai0511 commited on
Commit
b3bfe9d
·
verified ·
1 Parent(s): 806fb3a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +121 -117
app.py CHANGED
@@ -6,126 +6,130 @@ model_name = "vai0511/flan-t5-ai-mock-interviewer"
6
  tokenizer = T5Tokenizer.from_pretrained(model_name)
7
  model = T5ForConditionalGeneration.from_pretrained(model_name)
8
 
9
- # Function to generate a question
10
- def generate_question_from_input(domain, company=None):
11
- # Dynamically create input text based on domain and company
12
- if company:
13
- input_text = f"Generate a question for {domain} at {company}"
14
- else:
15
- input_text = f"Generate a question for {domain}"
16
-
17
- # Tokenize the input text for model inference
18
- inputs = tokenizer(input_text, return_tensors="pt", padding=True, truncation=True)
19
- input_ids = inputs["input_ids"].to(model.device)
20
- attention_mask = inputs["attention_mask"].to(model.device)
21
-
22
- # Generate the question
23
- generated_ids = model.generate(
24
- input_ids=input_ids,
25
- attention_mask=attention_mask,
26
- max_length=128,
27
- temperature=0.7,
28
- top_k=50,
29
- top_p=0.95,
30
- do_sample=True
31
- )
32
- generated_question = tokenizer.decode(generated_ids[0], skip_special_tokens=True)
33
-
34
- return generated_question
35
-
36
- # Initialize the state for the interview
37
- def init_state():
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  return {
39
- "domain": "",
40
- "company": "",
41
- "questions": [],
42
- "current_step": 0,
 
43
  }
44
 
45
- # Respond function for generating questions
46
- def respond(history, message, state):
47
- if state["current_step"] == 0:
48
- # First question generation
49
- question = generate_question_from_input(state["domain"], state["company"])
50
-
51
- state["questions"].append({"question": question, "response": None})
52
- state["current_step"] += 1
53
-
54
- return [
55
- (None, f"Starting {state['domain']} interview for {state['company'] or 'general'}"),
56
- (None, question)
57
- ], state
58
-
59
- else:
60
- # Stop interview if the user types 'stop'
61
- if message.strip().lower() == "stop":
62
- return [(None, "Interview ended. Thank you for your participation!")], init_state()
63
-
64
- # Store the response (not used here since no follow-up question)
65
- state["questions"][-1]["response"] = message
66
-
67
- # Generate the next question (if any)
68
- question = generate_question_from_input(state["domain"], state["company"])
69
-
70
- state["questions"].append({"question": question, "response": None})
71
- state["current_step"] += 1
72
-
73
- history.append((message, None)) # User response
74
- history.append((None, question)) # AI question
75
- return history, state
76
-
77
- # Gradio interface
78
- with gr.Blocks(title="AI Interviewer") as demo:
79
- state = gr.State(init_state)
80
-
81
- with gr.Column():
82
- gr.Markdown("## Technical Interview Simulator")
83
-
84
- with gr.Row():
85
- domain = gr.Textbox(label="Domain (e.g., Machine Learning)", interactive=True)
86
- company = gr.Textbox(label="Company (Optional)", interactive=True)
87
- start_btn = gr.Button("Start Interview")
88
-
89
- chatbot = gr.Chatbot(label="Conversation")
90
- msg = gr.Textbox(label="Your Answer", interactive=True)
91
- submit_btn = gr.Button("Submit Answer")
92
- end_btn = gr.Button("End Interview")
93
-
94
- # Start interview
95
- start_btn.click(
96
- fn=lambda d, c, s: (s.update({"domain": d, "company": c, "current_step": 0}), s),
97
- inputs=[domain, company, state],
98
- outputs=[state]
99
- ).then(
100
- respond,
101
- inputs=[chatbot, gr.Textbox("", visible=False), state],
102
- outputs=[chatbot, state]
103
- )
104
-
105
- # Handle responses
106
- submit_btn.click(
107
- lambda x: x, # Temporary to capture input
108
- inputs=[msg],
109
- outputs=[msg]
110
- ).then(
111
- respond,
112
- inputs=[chatbot, msg, state],
113
- outputs=[chatbot, state]
114
- ).then(
115
- lambda: "", # Clear input
116
- None,
117
- msg
118
- )
119
-
120
- # End interview
121
- end_btn.click(
122
- lambda: [(None, "Interview ended. Thank you!")],
123
- None,
124
- chatbot
125
- ).then(
126
- init_state,
127
- None,
128
- state
129
  )
130
 
131
  demo.launch()
 
 
6
  tokenizer = T5Tokenizer.from_pretrained(model_name)
7
  model = T5ForConditionalGeneration.from_pretrained(model_name)
8
 
9
+ import json
10
+ import gradio as gr
11
+ from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig
12
+ import torch
13
+
14
+ # Set up device
15
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
16
+
17
+ model.to(device)
18
+
19
+ # System prompt to guide the interview generation
20
+ system_prompt = """
21
+ You are conducting a mock technical interview. Generate questions and follow-up questions based on the domain provided. Consider these aspects:
22
+ 1. The question should be relevant to the domain (e.g., software engineering, machine learning).
23
+ 2. For follow-up questions, analyze the candidate's last response and ask questions that probe deeper into their understanding, challenge their approach, or request clarification.
24
+ 3. The follow-up question should aim to explore the candidate's depth of knowledge and ability to adapt.
25
+ 4. Ensure each question is unique and does not repeat previously asked questions.
26
+ 5. Ensure each question covers a different sub-topic within the domain, avoiding redundancy.
27
+ 6. If no clear follow-up can be derived, generate a fresh, related question from a different aspect of the domain.
28
+ Important: Ensure that each question is clear, concise, and allows the candidate to demonstrate their technical and communicative abilities effectively.
29
+ """
30
+
31
+ # Define sub-topic categories for different domains
32
+ subtopic_keywords = {
33
+ "data analysis": ["data cleaning", "missing data", "outliers", "feature engineering", "EDA", "trend analysis", "data visualization"],
34
+ "machine learning": ["supervised learning", "unsupervised learning", "model evaluation", "bias-variance tradeoff", "overfitting", "hyperparameter tuning"],
35
+ "software engineering": ["agile methodology", "code optimization", "design patterns", "database design", "testing strategies"],
36
+ }
37
+
38
+ def identify_subtopic(question, domain):
39
+ """Identify the sub-topic of a question using predefined keywords."""
40
+ domain = domain.lower()
41
+ if domain in subtopic_keywords:
42
+ for subtopic in subtopic_keywords[domain]:
43
+ if subtopic in question.lower():
44
+ return subtopic
45
+ return None
46
+
47
+ # Modified generate_question that accepts an optional state to track uniqueness per session
48
+ def generate_question(prompt, domain, state=None):
49
+ while True:
50
+ full_prompt = system_prompt + "\n" + prompt
51
+ inputs = tokenizer(full_prompt, return_tensors="pt").to(device)
52
+ outputs = model.generate(
53
+ inputs["input_ids"],
54
+ max_new_tokens=50,
55
+ num_return_sequences=1,
56
+ no_repeat_ngram_size=2,
57
+ top_k=30,
58
+ top_p=0.9,
59
+ temperature=0.7,
60
+ do_sample=True,
61
+ pad_token_id=tokenizer.eos_token_id,
62
+ )
63
+ question = tokenizer.decode(outputs[0], skip_special_tokens=True)
64
+ question = question.replace(full_prompt, "").strip()
65
+ if not question.endswith("?"):
66
+ question = question.split("?")[0] + "?"
67
+ subtopic = identify_subtopic(question, domain)
68
+ # Use session state to ensure uniqueness
69
+ if state is not None:
70
+ if question not in state["asked_questions"] and (subtopic is None or subtopic not in state["asked_subtopics"]):
71
+ state["asked_questions"].add(question)
72
+ if subtopic:
73
+ state["asked_subtopics"].add(subtopic)
74
+ return question
75
+ else:
76
+ # Fallback to global trackers if no state provided
77
+ if question not in asked_questions and (subtopic is None or subtopic not in asked_subtopics):
78
+ asked_questions.add(question)
79
+ if subtopic:
80
+ asked_subtopics.add(subtopic)
81
+ return question
82
+
83
+ # Reset session state for a new interview
84
+ def reset_state(domain, company):
85
  return {
86
+ "domain": domain,
87
+ "company": company,
88
+ "asked_questions": set(),
89
+ "asked_subtopics": set(),
90
+ "conversation": [] # List of tuples: (speaker, message)
91
  }
92
 
93
+ def start_interview(domain, company):
94
+ """
95
+ Initializes a new interactive interview session.
96
+ Returns the initial conversation (with the first question) and the session state.
97
+ """
98
+ state = reset_state(domain, company)
99
+ prompt = f"Domain: {domain}. " + (f"Company: {company}. " if company else "") + "Generate the first question:"
100
+ question = generate_question(prompt, domain, state)
101
+ state["conversation"].append(("Interviewer", question))
102
+ return state["conversation"], state
103
+
104
+ def submit_response(candidate_response, state):
105
+ """
106
+ Accepts the candidate's response, updates the conversation, and generates a follow-up question.
107
+ """
108
+ state["conversation"].append(("Candidate", candidate_response))
109
+ prompt = f"Domain: {state['domain']}. Candidate's last response: {candidate_response}. Generate a follow-up question with a new perspective:"
110
+ question = generate_question(prompt, state["domain"], state)
111
+ state["conversation"].append(("Interviewer", question))
112
+ return state["conversation"], state
113
+
114
+ # Build an interactive Gradio interface using Blocks
115
+ with gr.Blocks() as demo:
116
+ gr.Markdown("# Interactive Mock Interview")
117
+ with gr.Row():
118
+ domain_input = gr.Textbox(label="Domain")
119
+ company_input = gr.Textbox(label="Company (Optional)")
120
+ start_button = gr.Button("Start Interview")
121
+ chatbot = gr.Chatbot(label="Interview Conversation")
122
+ with gr.Row():
123
+ response_input = gr.Textbox(label="Your Response")
124
+ submit_button = gr.Button("Submit")
125
+ # gr.State to hold our session data (state is preserved across interactions)
126
+ state = gr.State()
127
+ # Clicking start initializes the interview and shows the first question.
128
+ start_button.click(start_interview, inputs=[domain_input, company_input], outputs=[chatbot, state])
129
+ # Submitting a response updates the conversation with a follow-up question.
130
+ submit_button.click(submit_response, inputs=[response_input, state], outputs=[chatbot, state]).then(
131
+ lambda: "", None, response_input # Clear the response input after submission
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
132
  )
133
 
134
  demo.launch()
135
+