Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -17,8 +17,6 @@ import traceback
|
|
| 17 |
from streamlit_webrtc import webrtc_streamer, WebRtcMode
|
| 18 |
from twilio.rest import Client
|
| 19 |
import logging
|
| 20 |
-
import numpy as np
|
| 21 |
-
import soundfile as sf
|
| 22 |
|
| 23 |
|
| 24 |
# β
MUST be the first Streamlit command
|
|
@@ -183,17 +181,24 @@ def generate_improvement_suggestions():
|
|
| 183 |
---
|
| 184 |
{cleaned_initial_evaluation}
|
| 185 |
---
|
|
|
|
| 186 |
Based on all this information, your task is to provide DETAILED and CONSTRUCTIVE suggestions for each question to help the candidate improve. Be supportive and encouraging.
|
|
|
|
| 187 |
For EACH question, please provide:
|
| 188 |
1. **How to Improve This Answer:** Specific, actionable advice on what the candidate could have added, clarified, or approached differently to make their answer better for their {level_string} level. Focus on 1-2 key improvement points.
|
| 189 |
2. **Hints for an Ideal Answer:** Briefly mention 2-3 key concepts, terms, or elements that a strong answer (appropriate for their {level_string} level) would typically include. DO NOT provide a full model answer, just hints and pointers.
|
|
|
|
| 190 |
Keep the tone positive and focused on learning.
|
|
|
|
| 191 |
Structure your response clearly for each question. Example for one question:
|
|
|
|
| 192 |
---
|
| 193 |
**Regarding Question X: "[Original Question Text Here]"**
|
|
|
|
| 194 |
*How to Improve This Answer:*
|
| 195 |
[Your specific suggestion 1 for improvement...]
|
| 196 |
[Your specific suggestion 2 for improvement...]
|
|
|
|
| 197 |
*Hints for an Ideal Answer (Key Points to Consider):*
|
| 198 |
- Hint 1 or Key concept 1
|
| 199 |
- Hint 2 or Key concept 2
|
|
@@ -283,11 +288,15 @@ def evaluate_answers():
|
|
| 283 |
hr_prompt_template = f"""
|
| 284 |
You are an experienced HR interview evaluator assessing a candidate's soft skills based on their answers to interview questions.
|
| 285 |
The candidate's performance across ALL answers should inform your scores for the following parameters.
|
|
|
|
| 286 |
**Parameters to Score (Assign a score from 1 to 5 for each):**
|
| 287 |
{hr_prompt_parameter_list}
|
|
|
|
| 288 |
After providing a score (1-5) for each of the above parameters, also write an **Overall Qualitative Feedback** section.
|
| 289 |
This section should summarize the candidate's general soft skill strengths and areas for improvement, based on their communication, engagement, and professionalism throughout the interview.
|
|
|
|
| 290 |
**REQUIRED OUTPUT FORMAT (Strictly Adhere):**
|
|
|
|
| 291 |
**Parameter Scores (1-5):**
|
| 292 |
Voice Modulation: [score]
|
| 293 |
Confidence: [score]
|
|
@@ -298,6 +307,7 @@ def evaluate_answers():
|
|
| 298 |
Basics of Grammar + SVA: [score]
|
| 299 |
Persuasiveness: [score]
|
| 300 |
Quality of Answers: [score]
|
|
|
|
| 301 |
**Overall Qualitative Feedback:**
|
| 302 |
[Your holistic qualitative feedback here. Be encouraging and constructive.]
|
| 303 |
"""
|
|
@@ -407,9 +417,11 @@ def evaluate_answers():
|
|
| 407 |
{base_assessment_criteria_qualitative_non_hr}
|
| 408 |
**YOUR RESPONSE MUST STRICTLY FOLLOW THIS FORMAT. PROVIDE SCORES FOR EACH QUESTION.**
|
| 409 |
Output format:
|
|
|
|
| 410 |
**Per-Question Scores:**
|
| 411 |
Question 1 Score: [Score for Q1 out of 5]
|
| 412 |
... (repeat for all {num_answered_questions} questions provided)
|
|
|
|
| 413 |
**Overall Evaluation Summary:**
|
| 414 |
- Concept Understanding: [Overall qualitative feedback here]
|
| 415 |
- Communication: [Overall qualitative feedback here]
|
|
@@ -489,6 +501,7 @@ def evaluate_answers():
|
|
| 489 |
BEGINNER_PROMPT = """
|
| 490 |
You are a friendly mock interview trainer conducting a **Beginner-level** spoken interview in the domain of **{domain}**.
|
| 491 |
Ask basic verbal interview questions based on the candidate's input: **{input_text}**.
|
|
|
|
| 492 |
Guidelines:
|
| 493 |
- Ask simple conceptual questions.
|
| 494 |
- Avoid jargon and complex examples.
|
|
@@ -497,6 +510,7 @@ Guidelines:
|
|
| 497 |
Ensure the questions are clear, to the point, and suitable for a {difficulty_level}-level interview in {selected_domain}.
|
| 498 |
**New Requirement:**
|
| 499 |
π« **Do NOT repeat any questions from previous generations again and again.** Ensure all generated questions are unique and different from past sessions.
|
|
|
|
| 500 |
**Guidelines:**
|
| 501 |
β
Questions should focus on key concepts, best practices, and problem-solving within {selected_domain}.
|
| 502 |
β
Ensure questions are direct, structured, and relevant to real-world applications.
|
|
@@ -507,6 +521,7 @@ Ensure the questions are clear, to the point, and suitable for a {difficulty_lev
|
|
| 507 |
INTERMEDIATE_PROMPT = """
|
| 508 |
You are a professional mock interviewer conducting an **Intermediate-level** spoken interview in the domain of **{domain}**.
|
| 509 |
Ask moderately challenging verbal interview questions based on the candidate's input: **{input_text}**.
|
|
|
|
| 510 |
Guidelines:
|
| 511 |
- Use a mix of conceptual and real-world scenario questions.
|
| 512 |
- Include light critical thinking.
|
|
@@ -514,6 +529,7 @@ Guidelines:
|
|
| 514 |
Ensure the questions are clear, to the point, and suitable for a {difficulty_level}-level interview in {selected_domain}.
|
| 515 |
**New Requirement:**
|
| 516 |
π« **Do NOT repeat any questions from previous generations again and again.** Ensure all generated questions are unique and different from past sessions.
|
|
|
|
| 517 |
**Guidelines:**
|
| 518 |
β
Questions should focus on key concepts, best practices, and problem-solving within {selected_domain}.
|
| 519 |
β
Ensure questions are direct, structured, and relevant to real-world applications.
|
|
@@ -524,13 +540,15 @@ Ensure the questions are clear, to the point, and suitable for a {difficulty_lev
|
|
| 524 |
ADVANCED_PROMPT = """
|
| 525 |
You are a strict mock interviewer conducting an **Advanced-level** spoken interview in the domain of **{domain}**.
|
| 526 |
Ask deep, analytical, real-world scenario-based questions from the candidate's input: **{input_text}**.
|
|
|
|
| 527 |
Guidelines:
|
| 528 |
- Expect detailed, logical, well-structured answers.
|
| 529 |
-
- Include challenging
|
| 530 |
- No need for code, but assume candidate has high expertise.
|
| 531 |
Ensure the questions are clear, to the point, and suitable for a {difficulty_level}-level interview in {selected_domain}.
|
| 532 |
**New Requirement:**
|
| 533 |
π« **Do NOT repeat any questions from previous generations again and again.** Ensure all generated questions are unique and different from past sessions.
|
|
|
|
| 534 |
**Guidelines:**
|
| 535 |
β
Questions should focus on key concepts, best practices, and problem-solving within {selected_domain}.
|
| 536 |
β
Ensure questions are direct, structured, and relevant to real-world applications.
|
|
@@ -569,6 +587,7 @@ st.markdown("""
|
|
| 569 |
box-shadow: 0 0 0 0.2rem rgba(0,123,255,.5) !important;
|
| 570 |
outline: none !important;
|
| 571 |
}
|
|
|
|
| 572 |
.timer-text {
|
| 573 |
font-size: 1.3rem;
|
| 574 |
font-weight: 600;
|
|
@@ -580,6 +599,7 @@ st.markdown("""
|
|
| 580 |
50% {opacity: 0.4;}
|
| 581 |
100% {opacity: 1;}
|
| 582 |
}
|
|
|
|
| 583 |
.summary-card {
|
| 584 |
background-color: #f9f9f9;
|
| 585 |
padding: 20px;
|
|
@@ -774,8 +794,8 @@ def get_ice_servers():
|
|
| 774 |
account_sid = os.environ["TWILIO_ACCOUNT_SID"]
|
| 775 |
auth_token = os.environ["TWILIO_AUTH_TOKEN"]
|
| 776 |
except KeyError:
|
| 777 |
-
|
| 778 |
-
"Twilio credentials are not set. Fallback to a free STUN server from Google."
|
| 779 |
)
|
| 780 |
return [{"urls": ["stun:stun.l.google.com:19302"]}]
|
| 781 |
|
|
@@ -849,101 +869,38 @@ if st.session_state["generated_questions"]:
|
|
| 849 |
if remaining > 0:
|
| 850 |
st.markdown(f"<h4 class='timer-text'>ποΈ {remaining} seconds to answer...</h4>", unsafe_allow_html=True)
|
| 851 |
|
| 852 |
-
|
| 853 |
-
|
| 854 |
-
|
| 855 |
-
|
| 856 |
-
|
| 857 |
-
|
| 858 |
-
|
| 859 |
-
|
| 860 |
-
|
| 861 |
-
|
| 862 |
-
|
| 863 |
-
|
| 864 |
-
|
| 865 |
-
)
|
| 866 |
-
|
| 867 |
-
if webrtc_ctx.state.playing:
|
| 868 |
-
if st.button("βΉοΈ Stop Voice Recording", key=f"stop_voice_{idx}"):
|
| 869 |
-
wav_path = f"response_{idx}.wav"
|
| 870 |
-
try:
|
| 871 |
-
frames = webrtc_ctx.audio_receiver.get_frames(timeout=1)
|
| 872 |
-
except Exception as e:
|
| 873 |
-
st.error(f"β οΈ Audio capture error: {e}")
|
| 874 |
-
frames = []
|
| 875 |
-
|
| 876 |
-
if frames:
|
| 877 |
-
try:
|
| 878 |
-
pcm = np.concatenate([f.to_ndarray() for f in frames], axis=0)
|
| 879 |
-
sample_rate = frames[0].sample_rate
|
| 880 |
-
sf.write(wav_path, pcm, sample_rate)
|
| 881 |
-
st.audio(wav_path)
|
| 882 |
-
st.session_state["answers"].append({
|
| 883 |
-
"question": question,
|
| 884 |
-
"response_file": wav_path
|
| 885 |
-
})
|
| 886 |
-
except Exception as e:
|
| 887 |
-
st.error(f"β οΈ Error saving recording: {e}")
|
| 888 |
-
st.session_state["answers"].append({
|
| 889 |
-
"question": question,
|
| 890 |
-
"response": "[Error saving recording]"
|
| 891 |
-
})
|
| 892 |
-
else:
|
| 893 |
-
st.warning("β οΈ No audio captured.")
|
| 894 |
-
st.session_state["answers"].append({
|
| 895 |
-
"question": question,
|
| 896 |
-
"response": "[No response]"
|
| 897 |
-
})
|
| 898 |
-
|
| 899 |
-
st.session_state.update({
|
| 900 |
-
"record_phase": "idle",
|
| 901 |
-
"question_played": False,
|
| 902 |
-
"current_question_index": idx + 1
|
| 903 |
-
})
|
| 904 |
-
|
| 905 |
-
if st.session_state["current_question_index"] == len(st.session_state["generated_questions"]):
|
| 906 |
-
evaluate_answers()
|
| 907 |
-
st.session_state["show_summary"] = True
|
| 908 |
-
|
| 909 |
-
st.experimental_rerun()
|
| 910 |
-
except Exception as webrtc_error:
|
| 911 |
-
st.warning("β οΈ Voice recording not available")
|
| 912 |
-
st.info("This is common on Hugging Face Spaces")
|
| 913 |
-
|
| 914 |
-
with col2:
|
| 915 |
-
st.markdown("**βοΈ Text Input (Alternative):**")
|
| 916 |
-
# Always show text input as alternative
|
| 917 |
-
text_response = st.text_area(
|
| 918 |
-
f"Type your answer:",
|
| 919 |
-
key=f"text_response_{idx}",
|
| 920 |
-
height=150,
|
| 921 |
-
placeholder="Enter your response here..."
|
| 922 |
-
)
|
| 923 |
-
|
| 924 |
-
if st.button("β
Submit Text Answer", key=f"submit_text_{idx}"):
|
| 925 |
-
if text_response.strip():
|
| 926 |
-
st.session_state["answers"].append({
|
| 927 |
-
"question": question,
|
| 928 |
-
"response": text_response.strip()
|
| 929 |
-
})
|
| 930 |
-
else:
|
| 931 |
-
st.session_state["answers"].append({
|
| 932 |
-
"question": question,
|
| 933 |
-
"response": "[No text response provided]"
|
| 934 |
-
})
|
| 935 |
|
| 936 |
-
|
| 937 |
-
|
| 938 |
-
|
| 939 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 940 |
})
|
| 941 |
|
| 942 |
-
|
| 943 |
-
|
| 944 |
-
|
| 945 |
|
| 946 |
-
|
| 947 |
|
| 948 |
else:
|
| 949 |
st.markdown("<div style='padding:10px; background:#fff3e0; border-left:5px solid orange;'>β οΈ <strong>No response detected.</strong> Moving to next question...</div>", unsafe_allow_html=True)
|
|
@@ -961,17 +918,23 @@ if st.session_state["generated_questions"]:
|
|
| 961 |
st.rerun()
|
| 962 |
|
| 963 |
elif st.session_state["record_phase"] == "listening":
|
| 964 |
-
st.success("π§
|
| 965 |
-
|
| 966 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 967 |
st.session_state.update({
|
| 968 |
"record_phase": "idle",
|
| 969 |
-
"recorded_text": "",
|
| 970 |
"recording_started": False,
|
| 971 |
"question_played": False,
|
| 972 |
"question_start_time": 0.0,
|
| 973 |
"current_question_index": idx + 1
|
| 974 |
})
|
|
|
|
| 975 |
if st.session_state["current_question_index"] == len(st.session_state["generated_questions"]):
|
| 976 |
evaluate_answers()
|
| 977 |
st.session_state["show_summary"] = True
|
|
@@ -1118,4 +1081,4 @@ if st.session_state.get("show_summary", False):
|
|
| 1118 |
keys_to_fully_clear = list(st.session_state.keys())
|
| 1119 |
for key_to_del_full in keys_to_fully_clear:
|
| 1120 |
del st.session_state[key_to_del_full]
|
| 1121 |
-
|
|
|
|
| 17 |
from streamlit_webrtc import webrtc_streamer, WebRtcMode
|
| 18 |
from twilio.rest import Client
|
| 19 |
import logging
|
|
|
|
|
|
|
| 20 |
|
| 21 |
|
| 22 |
# β
MUST be the first Streamlit command
|
|
|
|
| 181 |
---
|
| 182 |
{cleaned_initial_evaluation}
|
| 183 |
---
|
| 184 |
+
|
| 185 |
Based on all this information, your task is to provide DETAILED and CONSTRUCTIVE suggestions for each question to help the candidate improve. Be supportive and encouraging.
|
| 186 |
+
|
| 187 |
For EACH question, please provide:
|
| 188 |
1. **How to Improve This Answer:** Specific, actionable advice on what the candidate could have added, clarified, or approached differently to make their answer better for their {level_string} level. Focus on 1-2 key improvement points.
|
| 189 |
2. **Hints for an Ideal Answer:** Briefly mention 2-3 key concepts, terms, or elements that a strong answer (appropriate for their {level_string} level) would typically include. DO NOT provide a full model answer, just hints and pointers.
|
| 190 |
+
|
| 191 |
Keep the tone positive and focused on learning.
|
| 192 |
+
|
| 193 |
Structure your response clearly for each question. Example for one question:
|
| 194 |
+
|
| 195 |
---
|
| 196 |
**Regarding Question X: "[Original Question Text Here]"**
|
| 197 |
+
|
| 198 |
*How to Improve This Answer:*
|
| 199 |
[Your specific suggestion 1 for improvement...]
|
| 200 |
[Your specific suggestion 2 for improvement...]
|
| 201 |
+
|
| 202 |
*Hints for an Ideal Answer (Key Points to Consider):*
|
| 203 |
- Hint 1 or Key concept 1
|
| 204 |
- Hint 2 or Key concept 2
|
|
|
|
| 288 |
hr_prompt_template = f"""
|
| 289 |
You are an experienced HR interview evaluator assessing a candidate's soft skills based on their answers to interview questions.
|
| 290 |
The candidate's performance across ALL answers should inform your scores for the following parameters.
|
| 291 |
+
|
| 292 |
**Parameters to Score (Assign a score from 1 to 5 for each):**
|
| 293 |
{hr_prompt_parameter_list}
|
| 294 |
+
|
| 295 |
After providing a score (1-5) for each of the above parameters, also write an **Overall Qualitative Feedback** section.
|
| 296 |
This section should summarize the candidate's general soft skill strengths and areas for improvement, based on their communication, engagement, and professionalism throughout the interview.
|
| 297 |
+
|
| 298 |
**REQUIRED OUTPUT FORMAT (Strictly Adhere):**
|
| 299 |
+
|
| 300 |
**Parameter Scores (1-5):**
|
| 301 |
Voice Modulation: [score]
|
| 302 |
Confidence: [score]
|
|
|
|
| 307 |
Basics of Grammar + SVA: [score]
|
| 308 |
Persuasiveness: [score]
|
| 309 |
Quality of Answers: [score]
|
| 310 |
+
|
| 311 |
**Overall Qualitative Feedback:**
|
| 312 |
[Your holistic qualitative feedback here. Be encouraging and constructive.]
|
| 313 |
"""
|
|
|
|
| 417 |
{base_assessment_criteria_qualitative_non_hr}
|
| 418 |
**YOUR RESPONSE MUST STRICTLY FOLLOW THIS FORMAT. PROVIDE SCORES FOR EACH QUESTION.**
|
| 419 |
Output format:
|
| 420 |
+
|
| 421 |
**Per-Question Scores:**
|
| 422 |
Question 1 Score: [Score for Q1 out of 5]
|
| 423 |
... (repeat for all {num_answered_questions} questions provided)
|
| 424 |
+
|
| 425 |
**Overall Evaluation Summary:**
|
| 426 |
- Concept Understanding: [Overall qualitative feedback here]
|
| 427 |
- Communication: [Overall qualitative feedback here]
|
|
|
|
| 501 |
BEGINNER_PROMPT = """
|
| 502 |
You are a friendly mock interview trainer conducting a **Beginner-level** spoken interview in the domain of **{domain}**.
|
| 503 |
Ask basic verbal interview questions based on the candidate's input: **{input_text}**.
|
| 504 |
+
|
| 505 |
Guidelines:
|
| 506 |
- Ask simple conceptual questions.
|
| 507 |
- Avoid jargon and complex examples.
|
|
|
|
| 510 |
Ensure the questions are clear, to the point, and suitable for a {difficulty_level}-level interview in {selected_domain}.
|
| 511 |
**New Requirement:**
|
| 512 |
π« **Do NOT repeat any questions from previous generations again and again.** Ensure all generated questions are unique and different from past sessions.
|
| 513 |
+
|
| 514 |
**Guidelines:**
|
| 515 |
β
Questions should focus on key concepts, best practices, and problem-solving within {selected_domain}.
|
| 516 |
β
Ensure questions are direct, structured, and relevant to real-world applications.
|
|
|
|
| 521 |
INTERMEDIATE_PROMPT = """
|
| 522 |
You are a professional mock interviewer conducting an **Intermediate-level** spoken interview in the domain of **{domain}**.
|
| 523 |
Ask moderately challenging verbal interview questions based on the candidate's input: **{input_text}**.
|
| 524 |
+
|
| 525 |
Guidelines:
|
| 526 |
- Use a mix of conceptual and real-world scenario questions.
|
| 527 |
- Include light critical thinking.
|
|
|
|
| 529 |
Ensure the questions are clear, to the point, and suitable for a {difficulty_level}-level interview in {selected_domain}.
|
| 530 |
**New Requirement:**
|
| 531 |
π« **Do NOT repeat any questions from previous generations again and again.** Ensure all generated questions are unique and different from past sessions.
|
| 532 |
+
|
| 533 |
**Guidelines:**
|
| 534 |
β
Questions should focus on key concepts, best practices, and problem-solving within {selected_domain}.
|
| 535 |
β
Ensure questions are direct, structured, and relevant to real-world applications.
|
|
|
|
| 540 |
ADVANCED_PROMPT = """
|
| 541 |
You are a strict mock interviewer conducting an **Advanced-level** spoken interview in the domain of **{domain}**.
|
| 542 |
Ask deep, analytical, real-world scenario-based questions from the candidate's input: **{input_text}**.
|
| 543 |
+
|
| 544 |
Guidelines:
|
| 545 |
- Expect detailed, logical, well-structured answers.
|
| 546 |
+
- Include challenging βwhyβ and βhowβ based questions.
|
| 547 |
- No need for code, but assume candidate has high expertise.
|
| 548 |
Ensure the questions are clear, to the point, and suitable for a {difficulty_level}-level interview in {selected_domain}.
|
| 549 |
**New Requirement:**
|
| 550 |
π« **Do NOT repeat any questions from previous generations again and again.** Ensure all generated questions are unique and different from past sessions.
|
| 551 |
+
|
| 552 |
**Guidelines:**
|
| 553 |
β
Questions should focus on key concepts, best practices, and problem-solving within {selected_domain}.
|
| 554 |
β
Ensure questions are direct, structured, and relevant to real-world applications.
|
|
|
|
| 587 |
box-shadow: 0 0 0 0.2rem rgba(0,123,255,.5) !important;
|
| 588 |
outline: none !important;
|
| 589 |
}
|
| 590 |
+
|
| 591 |
.timer-text {
|
| 592 |
font-size: 1.3rem;
|
| 593 |
font-weight: 600;
|
|
|
|
| 599 |
50% {opacity: 0.4;}
|
| 600 |
100% {opacity: 1;}
|
| 601 |
}
|
| 602 |
+
|
| 603 |
.summary-card {
|
| 604 |
background-color: #f9f9f9;
|
| 605 |
padding: 20px;
|
|
|
|
| 794 |
account_sid = os.environ["TWILIO_ACCOUNT_SID"]
|
| 795 |
auth_token = os.environ["TWILIO_AUTH_TOKEN"]
|
| 796 |
except KeyError:
|
| 797 |
+
logger.warning(
|
| 798 |
+
"Twilio credentials are not set. Fallback to a free STUN server from Google." # noqa: E501
|
| 799 |
)
|
| 800 |
return [{"urls": ["stun:stun.l.google.com:19302"]}]
|
| 801 |
|
|
|
|
| 869 |
if remaining > 0:
|
| 870 |
st.markdown(f"<h4 class='timer-text'>ποΈ {remaining} seconds to answer...</h4>", unsafe_allow_html=True)
|
| 871 |
|
| 872 |
+
audio_value = st.audio_input("π€ Tap to record β then stop when done", key=f"audio_{idx}")
|
| 873 |
+
if audio_value:
|
| 874 |
+
wav_path = f"response_{idx}.wav"
|
| 875 |
+
with open(wav_path, "wb") as f:
|
| 876 |
+
f.write(audio_value.getbuffer())
|
| 877 |
+
st.audio(wav_path, format="audio/wav")
|
| 878 |
+
|
| 879 |
+
st.session_state.update({
|
| 880 |
+
"record_phase": "listening",
|
| 881 |
+
"response_file": wav_path,
|
| 882 |
+
})
|
| 883 |
+
st.rerun()
|
| 884 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 885 |
|
| 886 |
+
else:
|
| 887 |
+
st.warning("β οΈ No audio captured.")
|
| 888 |
+
st.session_state["answers"].append({
|
| 889 |
+
"question": question,
|
| 890 |
+
"response": "[No response]"
|
| 891 |
+
})
|
| 892 |
+
|
| 893 |
+
st.session_state.update({
|
| 894 |
+
"record_phase": "idle",
|
| 895 |
+
"question_played": False,
|
| 896 |
+
"current_question_index": idx + 1
|
| 897 |
})
|
| 898 |
|
| 899 |
+
if st.session_state["current_question_index"] == len(st.session_state["generated_questions"]):
|
| 900 |
+
evaluate_answers()
|
| 901 |
+
st.session_state["show_summary"] = True
|
| 902 |
|
| 903 |
+
st.rerun()
|
| 904 |
|
| 905 |
else:
|
| 906 |
st.markdown("<div style='padding:10px; background:#fff3e0; border-left:5px solid orange;'>β οΈ <strong>No response detected.</strong> Moving to next question...</div>", unsafe_allow_html=True)
|
|
|
|
| 918 |
st.rerun()
|
| 919 |
|
| 920 |
elif st.session_state["record_phase"] == "listening":
|
| 921 |
+
st.success("π§ Review your response below:")
|
| 922 |
+
st.audio(st.session_state["response_file"], format="audio/wav")
|
| 923 |
+
if st.button("βΉοΈ Confirm & Next"):
|
| 924 |
+
st.session_state["answers"].append({
|
| 925 |
+
"question": question,
|
| 926 |
+
"response_file": st.session_state["response_file"],
|
| 927 |
+
"response_text": st.session_state.get("recorded_text", "")
|
| 928 |
+
})
|
| 929 |
+
|
| 930 |
st.session_state.update({
|
| 931 |
"record_phase": "idle",
|
|
|
|
| 932 |
"recording_started": False,
|
| 933 |
"question_played": False,
|
| 934 |
"question_start_time": 0.0,
|
| 935 |
"current_question_index": idx + 1
|
| 936 |
})
|
| 937 |
+
|
| 938 |
if st.session_state["current_question_index"] == len(st.session_state["generated_questions"]):
|
| 939 |
evaluate_answers()
|
| 940 |
st.session_state["show_summary"] = True
|
|
|
|
| 1081 |
keys_to_fully_clear = list(st.session_state.keys())
|
| 1082 |
for key_to_del_full in keys_to_fully_clear:
|
| 1083 |
del st.session_state[key_to_del_full]
|
| 1084 |
+
|