barbara-multimodal's picture
refactor: Adjust message insertion and update metadata title
c97f1e2
import pandas as pd
import gradio as gr
from gradio import ChatMessage
from src.constants import FULL_QUESTIONS, DEFAULT_GRADING_SYSTEM_DF, CUSTOM_CSS
from src.utils import generate_session_id, highlight_feedback, show_popup, reset_popup, generate_skills_evaluation_markdown
from src.api_calls import chatbot_api_call, feedback_api_call, ideal_answer_api_call, conversation_feedback_api_call
session_id = generate_session_id()
first_question_selected = False
current_turns = 0
interview_data_with_feedback = []
def enable_send_button(message, selected_question):
if selected_question and message.strip():
return gr.update(interactive=True), gr.update(label="Choose an interview question")
elif selected_question:
return gr.update(interactive=False), gr.update(label="Choose an interview question")
return gr.update(interactive=False), gr.update(label="Choose an interview question (Required)")
def handle_question_change(history, selected_question, conversation_mode):
global session_id, first_question_selected, current_turns, interview_data_with_feedback
current_turns = 0
interview_data_with_feedback = []
if conversation_mode == 'Interviewer':
updated_label = f"Conversation turns: {current_turns}"
feedback_box = gr.update(value=None)
else:
updated_label = "Multimodal Coach Agent"
feedback_box = gr.update(value=None, show_legend=False)
grading_system_df = gr.update(value=DEFAULT_GRADING_SYSTEM_DF, label="Insights")
if len(history) > 2:
first_question_selected = True
if first_question_selected:
session_id = generate_session_id()
transition_message = f"Alright, let's move on to the next question:\n\n{selected_question}"
new_history = [
ChatMessage(
role="user",
content="I'm ready for the next question now.",
),
ChatMessage(
role="assistant",
content=transition_message,
),
]
return new_history, gr.update(interactive=False), gr.update(interactive=True), gr.update(label=updated_label), feedback_box, grading_system_df
else:
if selected_question:
last_question = f"Great start! Here's your first question:\n\n{selected_question}"
else:
last_question = selected_question
if last_question != None:
history.append(
{
"role": "user",
"content": "One moment...",
}
)
history.append(
{
"role": "assistant",
"content": last_question,
}
)
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
def reset_interface(conversation_mode):
global session_id, first_question_selected, current_turns, interview_data_with_feedback
first_question_selected = False
current_turns = 0
interview_data_with_feedback = []
if conversation_mode == "Interviewer":
chatbot_label = f"Conversation turns: {current_turns}"
session_id = generate_session_id()
user_greeting_message = "I've selected Interviewer mode, and I'm ready to begin."
chatbot_greeting_message = (
"Hello, and welcome to your interview for the Senior Product Manager position!\n\n"
"Select a question from the list above to begin."
)
slider_state = gr.update(interactive=True)
feedback_box = gr.update(value=None)
feedback_type_state = gr.update(interactive=True, value="Standard")
else:
chatbot_label = "Multimodal Coach Agent"
session_id = generate_session_id()
user_greeting_message = "Hey there! I've selected Coach mode. Let's dive in."
chatbot_greeting_message = (
"Hi!\n\n"
"Welcome to your interview preparation session for the Senior Product Manager role.\n\n"
"Please pick a question above to get started!"
)
slider_state = gr.update(interactive=False)
feedback_box = gr.update(value=None, show_legend=False)
feedback_type_state = gr.update(interactive=False, value=" ")
grading_system_df = gr.update(value=DEFAULT_GRADING_SYSTEM_DF, label="Insights")
include_company_name = gr.update(interactive=True, value=False)
include_resume_text = gr.update(interactive=True, value=False)
include_job_description = gr.update(interactive=True, value=True)
history = [
ChatMessage(
role="user",
content=user_greeting_message,
),
ChatMessage(
role="assistant",
content=chatbot_greeting_message,
)
]
return (
gr.update(value=history, label=chatbot_label),
gr.update(choices=FULL_QUESTIONS, value=None, label="Choose an interview question (Required)", interactive=True),
"",
gr.update(value="Send", interactive=False),
slider_state,
feedback_box,
feedback_type_state,
grading_system_df,
include_company_name,
include_resume_text,
include_job_description
)
# Gradio interface
def create_demo():
with gr.Blocks(css=CUSTOM_CSS) as demo:
gr.Markdown("# Talent Interview Prep - Conversational Model")
gr.Markdown("""### Please select a conversation mode to begin""")
with gr.Row(equal_height=True):
with gr.Column(scale=6):
conversation_mode = gr.Radio(
choices=["Interviewer", "Coach"],
label="""Choose "Interviewer" to simulate a real interview or "Coach" for guidance and feedback""",
info=""">**Important note:**\n>This has been *hardcoded* for a **Senior Product Manager** role.""",
value=None
)
with gr.Column(scale=2, variant="panel"):
include_company_name = gr.Checkbox(label="Include the company name in the request", value=False, interactive=False)
include_job_description = gr.Checkbox(label="Include the job description in the request", value=True, interactive=False)
include_resume_text = gr.Checkbox(label="Include the candidate's resume in the request", value=False, interactive=False)
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)
with gr.Row():
with gr.Column(scale=6):
question_dropdown = gr.Dropdown(choices=[], label="Choose an interview question")
with gr.Column(scale=2):
feedback_type_dropdown = gr.Dropdown(
choices=["Standard", "STAR"],
value=" ",
label="Select the feedback type",
interactive=False,
allow_custom_value=True
)
chatbot = gr.Chatbot(type="messages", label="""The Multimodal Chatbot will be ready once you select a mode""", show_copy_button=True)
with gr.Row(equal_height=True):
with gr.Column(scale=10):
msg = gr.Textbox(show_label=False, placeholder="Type a message...")
with gr.Column(min_width=50):
send_btn = gr.Button(value="Send\n", variant="primary", interactive=False, elem_id="fill-button")
gr.Markdown(" ")
gr.Markdown("---")
gr.Markdown("## Conversation Feedback")
feedback_box = gr.HighlightedText(
label="Breakdown",
show_legend=True,
color_map={"Strength": "green", "Area for Improvement": "orange", "Action Item": "blue"}
)
grading_system_df = gr.DataFrame(value=DEFAULT_GRADING_SYSTEM_DF, interactive=False, label="Insights", max_height=200, min_width=25)
msg.change(fn=enable_send_button, inputs=[msg, question_dropdown], outputs=[send_btn, question_dropdown])
question_dropdown.change(fn=enable_send_button, inputs=[msg, question_dropdown], outputs=[send_btn, question_dropdown])
question_dropdown.change(fn=handle_question_change, inputs=[chatbot, question_dropdown, conversation_mode], outputs=[chatbot, send_btn, msg, chatbot, feedback_box, grading_system_df])
def respond(message, history, conversation_mode, selected_question, conversation_turns_limit, feedback_type, include_company_name, include_resume_text, include_job_description):
global session_id, current_turns, interview_data_with_feedback
feedback_value = None
feedback_show_legend = False
criteria_feedback_df = DEFAULT_GRADING_SYSTEM_DF
if not message.strip():
return history, message
clean_question = selected_question.split(":", 1)[1] if ": " in selected_question else selected_question
bot_message, conversation_end_flag, chat_memory = chatbot_api_call(session_id, clean_question, message, conversation_mode, conversation_turns_limit, include_company_name, include_resume_text)
print(f"Conversation end? {conversation_end_flag}\n")
print(f"{chat_memory=}\n")
updated_label = f"Conversation turns: {current_turns}" if conversation_mode == 'Interviewer' else "Multimodal Coach Agent"
history.append(
ChatMessage(
role="user",
content=message,
)
)
history.append(
ChatMessage(
role="assistant",
content=bot_message,
)
)
if conversation_end_flag:
if conversation_mode == 'Interviewer':
feedback_output = conversation_feedback_api_call(chat_memory['messages'], feedback_type.lower(), include_resume_text, include_job_description)
feedback_show_legend, highlighted_feedback = highlight_feedback(feedback_output)
feedback_value = [("Whole conversation feedback\n\n", None)] + highlighted_feedback
criteria_feedback_data = feedback_output["criteria_feedback"]
skills_evaluation_data = feedback_output["skills_evaluation"]
if criteria_feedback_data:
criteria_feedback_df = pd.DataFrame(criteria_feedback_data)
criteria_feedback_df.rename(columns={
"question_criteria": "Question criteria",
"evaluation": "Evaluation"
}, inplace=True)
if skills_evaluation_data:
skills_evaluation = generate_skills_evaluation_markdown(skills_evaluation_data)
history.append(ChatMessage(
role="assistant",
content=skills_evaluation,
metadata={"title": "🛠️ Skills evaluation"}
))
print()
print(feedback_output)
print()
print(highlighted_feedback)
print()
print(criteria_feedback_df)
return (
history,
"",
gr.update(interactive=False),
gr.update(interactive=False),
gr.update(label=updated_label),
gr.update(value=feedback_value, show_legend=feedback_show_legend),
gr.update(value=criteria_feedback_df, label="Insights")
)
if conversation_mode == 'Interviewer':
current_turns += 1
interview_data = chat_memory['messages'][:-1]
print(f"{interview_data=}\n")
feedback_output = feedback_api_call(interview_data, feedback_type.lower(), include_resume_text)
feedback_show_legend, highlighted_feedback = highlight_feedback(feedback_output)
feedback_value = [(f"{current_turns}º conversation turn feedback\n\n", None)] + highlighted_feedback
criteria_feedback_data = feedback_output["criteria_feedback"]
if criteria_feedback_data:
criteria_feedback_df = pd.DataFrame(criteria_feedback_data)
criteria_feedback_df.rename(columns={
"question_criteria": "Question criteria",
"evaluation": "Evaluation"
}, inplace=True)
print()
print(feedback_output)
print()
print(highlighted_feedback)
print()
print(criteria_feedback_df)
print()
interview_data_with_feedback.extend(interview_data)
interview_data_with_feedback.append({"type": "feedback", "content": feedback_output["feedback_text"]})
print(f"{interview_data_with_feedback=}\n")
ideal_answer = ideal_answer_api_call(interview_data_with_feedback, feedback_type.lower(), include_resume_text)
cleaned_ideal_answer = ideal_answer.replace("\\n", " ")
cleaned_ideal_answer_html = f"""<p style="text-align: left; font-size: 14px;">{cleaned_ideal_answer}</p>"""
print(cleaned_ideal_answer)
history.insert(-1, ChatMessage(
role="assistant",
content=cleaned_ideal_answer_html,
metadata={"title": "💡 Your last message framed as an ideal answer"}
))
updated_label = f"Conversation turns: {current_turns}" if conversation_mode == 'Interviewer' else "Multimodal Coach Agent"
return (
history,
"",
gr.update(interactive=True),
gr.update(interactive=True),
gr.update(label=updated_label),
gr.update(value=feedback_value, show_legend=feedback_show_legend),
gr.update(value=criteria_feedback_df, label="Insights")
)
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, include_job_description])
msg.submit(fn=respond, inputs=[msg, chatbot, conversation_mode, question_dropdown, conversation_turns_limit, feedback_type_dropdown, include_company_name, include_resume_text, include_job_description], outputs=[chatbot, msg, send_btn, msg, chatbot, feedback_box, grading_system_df])
send_btn.click(fn=respond, inputs=[msg, chatbot, conversation_mode, question_dropdown, conversation_turns_limit, feedback_type_dropdown, include_company_name, include_resume_text, include_job_description], outputs=[chatbot, msg, send_btn, msg, chatbot, feedback_box, grading_system_df])
popup = gr.HTML(label="Popup", elem_classes=["popup"])
include_company_name.change(
fn=lambda selected: show_popup(False, selected, False) if selected else reset_popup(),
inputs=include_company_name,
outputs=popup
)
include_job_description.change(
fn=lambda selected: show_popup(False, False, selected) if selected else reset_popup(),
inputs=include_job_description,
outputs=popup
)
include_resume_text.change(
fn=lambda selected: show_popup(selected, False, False) if selected else reset_popup(),
inputs=include_resume_text,
outputs=popup
)
return demo
print("Launching Gradio interface...")
app = create_demo().launch(share=False, inline=False)