barbara-multimodal commited on
Commit
e6da03d
·
1 Parent(s): be454be

feat: Enhance chat interface with grading system and detailed feedback

Browse files
Files changed (1) hide show
  1. app.py +138 -36
app.py CHANGED
@@ -1,7 +1,10 @@
 
 
1
  import gradio as gr
 
2
 
3
- from src.constants import FULL_QUESTIONS
4
- from src.utils import remove_html_tags, generate_session_id
5
  from src.api_calls import chatbot_api_call, feedback_api_call, ideal_answer_api_call, conversation_feedback_api_call
6
 
7
  session_id = generate_session_id()
@@ -25,12 +28,13 @@ def handle_question_change(history, selected_question, conversation_mode):
25
  if conversation_mode == 'Interviewer':
26
  updated_label = f"Conversation turns: {current_turns}"
27
  feedback_box = gr.update(value=None)
28
-
29
  else:
30
  updated_label = "Multimodal Coach Agent"
31
  feedback_box = gr.update(value=None, show_legend=False)
 
 
32
 
33
- if len(history) > 1:
34
  first_question_selected = True
35
 
36
  if first_question_selected:
@@ -38,16 +42,39 @@ def handle_question_change(history, selected_question, conversation_mode):
38
 
39
  transition_message = f"Alright, let's move on to the next question:\n\n{selected_question}"
40
 
41
- return [("I'm ready for the next question now.", transition_message)], gr.update(interactive=False), gr.update(interactive=True), gr.update(label=updated_label), feedback_box
 
 
 
 
 
 
 
 
 
 
 
42
  else:
43
  if selected_question:
44
  last_question = f"Great start! Here's your first question:\n\n{selected_question}"
45
  else:
46
  last_question = selected_question
47
 
48
- new_history = history + [("One moment...", last_question)]
 
 
 
 
 
 
 
 
 
 
 
 
49
 
50
- return [entry for entry in new_history if entry[1] is not None], gr.update(interactive=False), gr.update(interactive=True), gr.update(label=updated_label), feedback_box
51
 
52
  def reset_interface(conversation_mode):
53
  global session_id, first_question_selected, current_turns, interview_data_with_feedback
@@ -86,24 +113,37 @@ def reset_interface(conversation_mode):
86
  feedback_box = gr.update(value=None, show_legend=False)
87
  feedback_type_state = gr.update(interactive=False, value=" ")
88
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  return (
90
- gr.update(value=[(user_greeting_message, chatbot_greeting_message)], label=chatbot_label),
91
  gr.update(choices=FULL_QUESTIONS, value=None, label="Choose an interview question (Required)", interactive=True),
92
  "",
93
  gr.update(value="Send", interactive=False),
94
  slider_state,
95
  feedback_box,
96
- feedback_type_state
 
 
 
97
  )
98
 
99
- def highlight_feedback(feedback_output):
100
- if not feedback_output["feedback_by_category"]:
101
- return False, [(feedback_output["feedback_text"], None)]
102
- return True, [(item["text"], item["category"]) for item in feedback_output["feedback_by_category"]]
103
-
104
  # Gradio interface
105
  def create_demo():
106
- with gr.Blocks() as demo:
107
  gr.Markdown("# Talent Interview Prep - Conversational Model")
108
 
109
  gr.Markdown("""### Please select a conversation mode to begin""")
@@ -113,8 +153,8 @@ def create_demo():
113
  conversation_mode = gr.Radio(choices=["Interviewer", "Coach"], label="""Choose "Interviewer" to simulate a real interview or "Coach" for guidance and feedback""", value=None)
114
 
115
  with gr.Column(scale=2):
116
- include_company_name = gr.Checkbox(label="Include the company name in the request", value=False)
117
- include_resume_text = gr.Checkbox(label="Include the candidate resume in the request", value=False)
118
 
119
  conversation_turns_limit = gr.Slider(minimum=1, maximum=20, step=1, label="Choose the number of exchanges (turns) between you and the AI agent (1 min, 20 max)", value=5, interactive=False)
120
 
@@ -131,28 +171,37 @@ def create_demo():
131
  allow_custom_value=True
132
  )
133
 
134
- chatbot = gr.Chatbot(label="""The Multimodal Chatbot will be ready once you select a mode""")
135
- # feedback_box = gr.Textbox(label="Conversation feedback", placeholder="Feedback for each conversation turn, as well as an overall feedback for the entire conversation, will be displayed here", interactive=False)
 
 
 
 
 
 
 
 
 
136
 
137
  feedback_box = gr.HighlightedText(
138
- label="Conversation feedback",
139
  show_legend=True,
140
  color_map={"Strength": "green", "Area for Improvement": "orange", "Action Item": "blue"}
141
  )
142
 
143
- msg = gr.Textbox(label="Type your answer here")
144
- send_btn = gr.Button(value="Send", variant="primary", interactive=False)
145
 
146
  msg.change(fn=enable_send_button, inputs=[msg, question_dropdown], outputs=[send_btn, question_dropdown])
147
  question_dropdown.change(fn=enable_send_button, inputs=[msg, question_dropdown], outputs=[send_btn, question_dropdown])
148
 
149
- question_dropdown.change(fn=handle_question_change, inputs=[chatbot, question_dropdown, conversation_mode], outputs=[chatbot, send_btn, msg, chatbot, feedback_box])
150
 
151
  def respond(message, history, conversation_mode, selected_question, conversation_turns_limit, feedback_type, include_company_name, include_resume_text):
152
  global session_id, current_turns, interview_data_with_feedback
153
 
154
  feedback_value = None
155
  feedback_show_legend = False
 
156
 
157
  if not message.strip():
158
  return history, message
@@ -166,6 +215,19 @@ def create_demo():
166
 
167
  updated_label = f"Conversation turns: {current_turns}" if conversation_mode == 'Interviewer' else "Multimodal Coach Agent"
168
 
 
 
 
 
 
 
 
 
 
 
 
 
 
169
  if conversation_end_flag:
170
  if conversation_mode == 'Interviewer':
171
  feedback_output = conversation_feedback_api_call(chat_memory['messages'], feedback_type.lower(), include_resume_text)
@@ -173,17 +235,30 @@ def create_demo():
173
  feedback_show_legend, highlighted_feedback = highlight_feedback(feedback_output)
174
  feedback_value = [("Whole conversation feedback\n\n", None)] + highlighted_feedback
175
 
 
 
 
 
 
 
 
 
 
 
176
  print()
177
  print(feedback_output)
178
  print()
179
  print(highlighted_feedback)
 
 
180
  return (
181
- history + [(message, bot_message)],
182
  "",
183
  gr.update(interactive=False),
184
  gr.update(interactive=False),
185
  gr.update(label=updated_label),
186
- gr.update(value=feedback_value, show_legend=feedback_show_legend)
 
187
  )
188
 
189
  if conversation_mode == 'Interviewer':
@@ -196,12 +271,23 @@ def create_demo():
196
  feedback_show_legend, highlighted_feedback = highlight_feedback(feedback_output)
197
  feedback_value = [(f"{current_turns}º conversation turn feedback\n\n", None)] + highlighted_feedback
198
 
 
 
 
 
 
 
 
 
 
 
199
  print()
200
  print(feedback_output)
201
  print()
202
  print(highlighted_feedback)
203
-
204
- # feedback = f"{current_turns}º conversation turn feedback\n\n{remove_html_tags(feedback_output).strip()}"
 
205
 
206
  interview_data_with_feedback.extend(interview_data)
207
  interview_data_with_feedback.append({"type": "feedback", "content": feedback_output["feedback_text"]})
@@ -209,29 +295,45 @@ def create_demo():
209
  print(f"{interview_data_with_feedback=}\n")
210
 
211
  ideal_answer = ideal_answer_api_call(interview_data_with_feedback, feedback_type.lower(), include_resume_text)
212
- cleaned_ideal_answer = ideal_answer.replace("\\n", "")
213
 
214
  print(cleaned_ideal_answer)
215
 
216
- bot_message += f"\n\n---"
217
- bot_message += f"\n**Ideal answer:**"
218
- bot_message += f"\n>{cleaned_ideal_answer}"
 
 
219
 
220
  updated_label = f"Conversation turns: {current_turns}" if conversation_mode == 'Interviewer' else "Multimodal Coach Agent"
221
 
222
  return (
223
- history + [(message, bot_message)],
224
  "",
225
  gr.update(interactive=True),
226
  gr.update(interactive=True),
227
  gr.update(label=updated_label),
228
- gr.update(value=feedback_value, show_legend=feedback_show_legend)
 
229
  )
230
 
231
- conversation_mode.change(fn=reset_interface, inputs=conversation_mode, outputs=[chatbot, question_dropdown, msg, send_btn, conversation_turns_limit, feedback_box, feedback_type_dropdown])
 
 
 
232
 
233
- msg.submit(fn=respond, inputs=[msg, chatbot, conversation_mode, question_dropdown, conversation_turns_limit, feedback_type_dropdown, include_company_name, include_resume_text], outputs=[chatbot, msg, send_btn, msg, chatbot, feedback_box])
234
- send_btn.click(fn=respond, inputs=[msg, chatbot, conversation_mode, question_dropdown, conversation_turns_limit, feedback_type_dropdown, include_company_name, include_resume_text], outputs=[chatbot, msg, send_btn, msg, chatbot, feedback_box])
 
 
 
 
 
 
 
 
 
 
235
 
236
  return demo
237
 
 
1
+ import pandas as pd
2
+
3
  import gradio as gr
4
+ from gradio import ChatMessage
5
 
6
+ from src.constants import FULL_QUESTIONS, DEFAULT_GRADING_SYSTEM_DF, CUSTOM_CSS
7
+ from src.utils import generate_session_id, highlight_feedback, show_popup, reset_popup
8
  from src.api_calls import chatbot_api_call, feedback_api_call, ideal_answer_api_call, conversation_feedback_api_call
9
 
10
  session_id = generate_session_id()
 
28
  if conversation_mode == 'Interviewer':
29
  updated_label = f"Conversation turns: {current_turns}"
30
  feedback_box = gr.update(value=None)
 
31
  else:
32
  updated_label = "Multimodal Coach Agent"
33
  feedback_box = gr.update(value=None, show_legend=False)
34
+
35
+ grading_system_df = gr.update(value=DEFAULT_GRADING_SYSTEM_DF, label="Insights")
36
 
37
+ if len(history) > 2:
38
  first_question_selected = True
39
 
40
  if first_question_selected:
 
42
 
43
  transition_message = f"Alright, let's move on to the next question:\n\n{selected_question}"
44
 
45
+ new_history = [
46
+ ChatMessage(
47
+ role="user",
48
+ content="I'm ready for the next question now.",
49
+ ),
50
+ ChatMessage(
51
+ role="assistant",
52
+ content=transition_message,
53
+ ),
54
+ ]
55
+
56
+ return new_history, gr.update(interactive=False), gr.update(interactive=True), gr.update(label=updated_label), feedback_box, grading_system_df
57
  else:
58
  if selected_question:
59
  last_question = f"Great start! Here's your first question:\n\n{selected_question}"
60
  else:
61
  last_question = selected_question
62
 
63
+ if last_question != None:
64
+ history.append(
65
+ {
66
+ "role": "user",
67
+ "content": "One moment...",
68
+ }
69
+ )
70
+ history.append(
71
+ {
72
+ "role": "assistant",
73
+ "content": last_question,
74
+ }
75
+ )
76
 
77
+ return [entry for entry in history if entry["content"] is not None], gr.update(interactive=False), gr.update(interactive=True), gr.update(label=updated_label), feedback_box, grading_system_df
78
 
79
  def reset_interface(conversation_mode):
80
  global session_id, first_question_selected, current_turns, interview_data_with_feedback
 
113
  feedback_box = gr.update(value=None, show_legend=False)
114
  feedback_type_state = gr.update(interactive=False, value=" ")
115
 
116
+ grading_system_df = gr.update(value=DEFAULT_GRADING_SYSTEM_DF, label="Insights")
117
+ include_company_name = gr.update(interactive=True, value=False)
118
+ include_resume_text = gr.update(interactive=True, value=False)
119
+
120
+ history = [
121
+ ChatMessage(
122
+ role="user",
123
+ content=user_greeting_message,
124
+ ),
125
+ ChatMessage(
126
+ role="assistant",
127
+ content=chatbot_greeting_message,
128
+ ),
129
+ ]
130
+
131
  return (
132
+ gr.update(value=history, label=chatbot_label),
133
  gr.update(choices=FULL_QUESTIONS, value=None, label="Choose an interview question (Required)", interactive=True),
134
  "",
135
  gr.update(value="Send", interactive=False),
136
  slider_state,
137
  feedback_box,
138
+ feedback_type_state,
139
+ grading_system_df,
140
+ include_company_name,
141
+ include_resume_text
142
  )
143
 
 
 
 
 
 
144
  # Gradio interface
145
  def create_demo():
146
+ with gr.Blocks(css=CUSTOM_CSS) as demo:
147
  gr.Markdown("# Talent Interview Prep - Conversational Model")
148
 
149
  gr.Markdown("""### Please select a conversation mode to begin""")
 
153
  conversation_mode = gr.Radio(choices=["Interviewer", "Coach"], label="""Choose "Interviewer" to simulate a real interview or "Coach" for guidance and feedback""", value=None)
154
 
155
  with gr.Column(scale=2):
156
+ include_company_name = gr.Checkbox(label="Include the company name in the request", value=False, interactive=False)
157
+ include_resume_text = gr.Checkbox(label="Include the candidate's resume in the request", value=False, interactive=False)
158
 
159
  conversation_turns_limit = gr.Slider(minimum=1, maximum=20, step=1, label="Choose the number of exchanges (turns) between you and the AI agent (1 min, 20 max)", value=5, interactive=False)
160
 
 
171
  allow_custom_value=True
172
  )
173
 
174
+ chatbot = gr.Chatbot(type="messages", label="""The Multimodal Chatbot will be ready once you select a mode""", show_copy_button=True)
175
+
176
+ with gr.Row(equal_height=True):
177
+ with gr.Column(scale=10):
178
+ msg = gr.Textbox(label="Type your answer here")
179
+ with gr.Column(min_width=50):
180
+ send_btn = gr.Button(value="Send\n", variant="primary", interactive=False, elem_id="fill-button")
181
+
182
+ gr.Markdown(" ")
183
+ gr.Markdown("---")
184
+ gr.Markdown("## Conversation Feedback", )
185
 
186
  feedback_box = gr.HighlightedText(
187
+ label="Breakdown",
188
  show_legend=True,
189
  color_map={"Strength": "green", "Area for Improvement": "orange", "Action Item": "blue"}
190
  )
191
 
192
+ grading_system_df = gr.DataFrame(value=DEFAULT_GRADING_SYSTEM_DF, interactive=False, label="Insights", max_height=200, min_width=25)
 
193
 
194
  msg.change(fn=enable_send_button, inputs=[msg, question_dropdown], outputs=[send_btn, question_dropdown])
195
  question_dropdown.change(fn=enable_send_button, inputs=[msg, question_dropdown], outputs=[send_btn, question_dropdown])
196
 
197
+ question_dropdown.change(fn=handle_question_change, inputs=[chatbot, question_dropdown, conversation_mode], outputs=[chatbot, send_btn, msg, chatbot, feedback_box, grading_system_df])
198
 
199
  def respond(message, history, conversation_mode, selected_question, conversation_turns_limit, feedback_type, include_company_name, include_resume_text):
200
  global session_id, current_turns, interview_data_with_feedback
201
 
202
  feedback_value = None
203
  feedback_show_legend = False
204
+ criteria_feedback_df = DEFAULT_GRADING_SYSTEM_DF
205
 
206
  if not message.strip():
207
  return history, message
 
215
 
216
  updated_label = f"Conversation turns: {current_turns}" if conversation_mode == 'Interviewer' else "Multimodal Coach Agent"
217
 
218
+ history.append(
219
+ ChatMessage(
220
+ role="user",
221
+ content=message,
222
+ )
223
+ )
224
+ history.append(
225
+ ChatMessage(
226
+ role="assistant",
227
+ content=bot_message,
228
+ )
229
+ )
230
+
231
  if conversation_end_flag:
232
  if conversation_mode == 'Interviewer':
233
  feedback_output = conversation_feedback_api_call(chat_memory['messages'], feedback_type.lower(), include_resume_text)
 
235
  feedback_show_legend, highlighted_feedback = highlight_feedback(feedback_output)
236
  feedback_value = [("Whole conversation feedback\n\n", None)] + highlighted_feedback
237
 
238
+ criteria_feedback_data = feedback_output["criteria_feedback"]
239
+
240
+ if criteria_feedback_data:
241
+ criteria_feedback_df = pd.DataFrame(criteria_feedback_data)
242
+
243
+ criteria_feedback_df.rename(columns={
244
+ "question_criteria": "Question criteria",
245
+ "evaluation": "Evaluation"
246
+ }, inplace=True)
247
+
248
  print()
249
  print(feedback_output)
250
  print()
251
  print(highlighted_feedback)
252
+ print()
253
+ print(criteria_feedback_df)
254
  return (
255
+ history,
256
  "",
257
  gr.update(interactive=False),
258
  gr.update(interactive=False),
259
  gr.update(label=updated_label),
260
+ gr.update(value=feedback_value, show_legend=feedback_show_legend),
261
+ gr.update(value=criteria_feedback_df, label="Insights")
262
  )
263
 
264
  if conversation_mode == 'Interviewer':
 
271
  feedback_show_legend, highlighted_feedback = highlight_feedback(feedback_output)
272
  feedback_value = [(f"{current_turns}º conversation turn feedback\n\n", None)] + highlighted_feedback
273
 
274
+ criteria_feedback_data = feedback_output["criteria_feedback"]
275
+
276
+ if criteria_feedback_data:
277
+ criteria_feedback_df = pd.DataFrame(criteria_feedback_data)
278
+
279
+ criteria_feedback_df.rename(columns={
280
+ "question_criteria": "Question criteria",
281
+ "evaluation": "Evaluation"
282
+ }, inplace=True)
283
+
284
  print()
285
  print(feedback_output)
286
  print()
287
  print(highlighted_feedback)
288
+ print()
289
+ print(criteria_feedback_df)
290
+ print()
291
 
292
  interview_data_with_feedback.extend(interview_data)
293
  interview_data_with_feedback.append({"type": "feedback", "content": feedback_output["feedback_text"]})
 
295
  print(f"{interview_data_with_feedback=}\n")
296
 
297
  ideal_answer = ideal_answer_api_call(interview_data_with_feedback, feedback_type.lower(), include_resume_text)
298
+ cleaned_ideal_answer = ideal_answer.replace("\\n", " ")
299
 
300
  print(cleaned_ideal_answer)
301
 
302
+ history.append(ChatMessage(
303
+ role="assistant",
304
+ content=cleaned_ideal_answer,
305
+ metadata={"title": "💡 Ideal answer"},
306
+ ))
307
 
308
  updated_label = f"Conversation turns: {current_turns}" if conversation_mode == 'Interviewer' else "Multimodal Coach Agent"
309
 
310
  return (
311
+ history,
312
  "",
313
  gr.update(interactive=True),
314
  gr.update(interactive=True),
315
  gr.update(label=updated_label),
316
+ gr.update(value=feedback_value, show_legend=feedback_show_legend),
317
+ gr.update(value=criteria_feedback_df, label="Insights")
318
  )
319
 
320
+ conversation_mode.change(fn=reset_interface, inputs=conversation_mode, outputs=[chatbot, question_dropdown, msg, send_btn, conversation_turns_limit, feedback_box, feedback_type_dropdown, grading_system_df, include_company_name, include_resume_text])
321
+
322
+ msg.submit(fn=respond, inputs=[msg, chatbot, conversation_mode, question_dropdown, conversation_turns_limit, feedback_type_dropdown, include_company_name, include_resume_text], outputs=[chatbot, msg, send_btn, msg, chatbot, feedback_box, grading_system_df])
323
+ send_btn.click(fn=respond, inputs=[msg, chatbot, conversation_mode, question_dropdown, conversation_turns_limit, feedback_type_dropdown, include_company_name, include_resume_text], outputs=[chatbot, msg, send_btn, msg, chatbot, feedback_box, grading_system_df])
324
 
325
+ popup = gr.HTML(label="Popup", elem_classes=["popup"])
326
+
327
+ include_company_name.change(
328
+ fn=lambda selected: show_popup(False, selected) if selected else reset_popup(),
329
+ inputs=include_company_name,
330
+ outputs=popup
331
+ )
332
+ include_resume_text.change(
333
+ fn=lambda selected: show_popup(selected, False) if selected else reset_popup(),
334
+ inputs=include_resume_text,
335
+ outputs=popup
336
+ )
337
 
338
  return demo
339