sparshmehta commited on
Commit
fb448f1
·
verified ·
1 Parent(s): 767088e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +216 -202
app.py CHANGED
@@ -908,107 +908,26 @@ def display_evaluation(evaluation: Dict[str, Any]):
908
  tabs = st.tabs(["Communication", "Teaching", "Recommendations", "Transcript"])
909
 
910
  with tabs[0]:
911
- with st.status("Loading communication metrics...") as status:
912
- progress_bar = st.progress(0)
913
- progress_bar.progress(0.2)
914
- st.header("Communication")
915
-
916
- # Speed metrics
917
- st.subheader("Speed")
918
- col1, col2 = st.columns(2)
919
- with col1:
920
- st.metric("Score", "Pass" if evaluation["communication"]["speed"]["score"] == 1
921
- else "Need Improvement")
922
- with col2:
923
- st.metric("Words per Minute",
924
- f"{evaluation['communication']['speed']['wpm']:.1f}")
925
- st.caption("Acceptable Range: 130-150 WPM")
926
- progress_bar.progress(0.4)
927
-
928
- # Fluency metrics
929
- st.subheader("Fluency")
930
- col1, col2, col3 = st.columns(3)
931
- with col1:
932
- st.metric("Score", "Pass" if evaluation["communication"]["fluency"]["score"] == 1
933
- else "Need Improvement")
934
- with col2:
935
- st.metric("Fillers/Min",
936
- f"{evaluation['communication']['fluency']['fillersPerMin']:.1f}")
937
- with col3:
938
- st.metric("Errors/Min",
939
- f"{evaluation['communication']['fluency']['errorsPerMin']:.1f}")
940
- progress_bar.progress(0.6)
941
-
942
- # Flow metrics
943
- st.subheader("Flow")
944
- col1, col2 = st.columns(2)
945
- with col1:
946
- st.metric("Score", "Pass" if evaluation["communication"]["flow"]["score"] == 1
947
- else "Need Improvement")
948
- with col2:
949
- st.metric("Pauses/Min",
950
- f"{evaluation['communication']['flow']['pausesPerMin']:.1f}")
951
- st.caption("Acceptable Range: 8-12 pauses/min")
952
-
953
- # Intonation metrics
954
- st.subheader("Intonation")
955
-
956
- # Frequency/Pitch section
957
- st.write("**Frequency/Pitch Metrics:**")
958
- col1, col2, col3 = st.columns(3)
959
- with col1:
960
- st.metric("Base Frequency",
961
- f"{evaluation['communication']['intonation']['pitch']:.1f} Hz")
962
- with col2:
963
- st.metric("Pitch Score",
964
- "Pass" if evaluation["communication"]["intonation"]["pitchScore"] == 1
965
- else "Need Improvement")
966
- with col3:
967
- st.metric("Pitch Variation (σ)",
968
- f"{evaluation['communication']['intonation']['pitchVariation']:.1f} Hz")
969
- st.caption("Acceptable Pitch Variation Range: 80-90 Hz")
970
-
971
- # Patterns section
972
- st.write("**Pattern Analysis:**")
973
- col1, col2, col3, col4 = st.columns(4)
974
- with col1:
975
- st.metric("Pattern Score",
976
- "Pass" if evaluation["communication"]["intonation"]["patternScore"] == 1
977
- else "Need Improvement")
978
- with col2:
979
- st.metric("Rising Patterns",
980
- evaluation["communication"]["intonation"]["risingPatterns"])
981
- with col3:
982
- st.metric("Falling Patterns",
983
- evaluation["communication"]["intonation"]["fallingPatterns"])
984
- with col4:
985
- st.metric("Variations/Min",
986
- f"{evaluation['communication']['intonation']['variationsPerMin']:.1f}")
987
- st.caption("Acceptable Variations per Minute: >=8")
988
- progress_bar.progress(0.8)
989
-
990
- # Energy metrics
991
- st.subheader("Energy")
992
- col1, col2, col3 = st.columns(3)
993
- with col1:
994
- st.metric("Score",
995
- "Pass" if evaluation["communication"]["energy"]["score"] == 1
996
- else "Need Improvement")
997
- with col2:
998
- st.metric("Mean Amplitude",
999
- f"{evaluation['communication']['energy']['meanAmplitude']:.1f}")
1000
- with col3:
1001
- st.metric("Amplitude Deviation (σ/μ)",
1002
- f"{evaluation['communication']['energy']['amplitudeDeviation']:.2f}")
1003
-
1004
- st.caption("""
1005
- Acceptable Ranges:
1006
- - Mean Amplitude: 20 - 40 (normalized RMS value)
1007
- - Amplitude Deviation (σ/μ): >0.2
1008
- """)
1009
 
1010
- progress_bar.progress(1.0)
1011
- status.update(label="Communication metrics loaded!", state="complete")
 
 
 
 
 
 
1012
 
1013
  with tabs[1]:
1014
  st.header("Teaching Analysis")
@@ -1128,122 +1047,53 @@ def display_evaluation(evaluation: Dict[str, Any]):
1128
  # Geography Fit with improved formatting
1129
  st.subheader("🌍 Geography Fit")
1130
  geography_fit = recommendations.get("geographyFit", "Not specified")
1131
- st.write(geography_fit)
1132
 
1133
  # Improvements Needed with better formatting
1134
  st.subheader("💡 Suggested Improvements")
1135
  improvements = recommendations.get("improvements", [])
1136
  if isinstance(improvements, list):
1137
  for i, improvement in enumerate(improvements, 1):
1138
- if isinstance(improvement, dict):
1139
- aspect = improvement.get('aspect', 'General').title()
1140
- recommendation = improvement.get('recommendation', '')
1141
- st.markdown(f"""
1142
- **{i}. {aspect}**
1143
- {recommendation}
1144
- """)
1145
- elif isinstance(improvement, str):
1146
- # If improvement is a string, create a meaningful category based on content
1147
- if "amplitude" in improvement.lower() or "voice" in improvement.lower():
1148
- aspect = "Voice and Energy"
1149
- elif "interaction" in improvement.lower() or "audience" in improvement.lower():
1150
- aspect = "Engagement"
1151
- elif "citation" in improvement.lower() or "accuracy" in improvement.lower():
1152
- aspect = "Content Quality"
1153
- elif "connection" in improvement.lower() or "narrative" in improvement.lower():
1154
- aspect = "Structure and Flow"
1155
- else:
1156
- aspect = "General Improvement"
1157
 
1158
  st.markdown(f"""
1159
- **{i}. {aspect}**
1160
- {improvement}
1161
- """)
 
 
1162
 
1163
- # Rigor Assessment with enhanced display
1164
  st.subheader("📊 Rigor Assessment")
1165
  rigor = recommendations.get("rigor", {})
1166
 
1167
- # Handle different rigor data structures
1168
  if isinstance(rigor, dict):
1169
  for category, assessment in rigor.items():
1170
- if isinstance(assessment, dict):
1171
- # Format category name for better display
1172
- category_display = category.replace('ability', ' Ability').title()
1173
- score_text = "Pass" if assessment.get('score') == 1 else "Needs Improvement"
1174
- score_color = "green" if assessment.get('score') == 1 else "orange"
1175
-
1176
- st.markdown(f"""
1177
- **{category_display}**
1178
- Score: :{score_color}[{score_text}]
1179
- {assessment.get('justification', '')}
1180
- """)
1181
- st.markdown("---")
1182
- else:
1183
- st.write(f"**{category.title()}:** {assessment}")
1184
- elif isinstance(rigor, str):
1185
- # If rigor is a string, display it directly
1186
- st.write(rigor)
1187
- else:
1188
- st.write("No rigor assessment available")
1189
-
1190
- # Add visual separator before metrics
1191
- st.markdown("---")
1192
-
1193
- # Summary metrics with error handling
1194
- st.subheader("📈 Overall Scores")
1195
- col1, col2, col3 = st.columns(3)
1196
-
1197
- with col1:
1198
- # Calculate teaching score correctly from the teaching data
1199
- teaching_data = evaluation.get("teaching", {})
1200
- concept_assessment = teaching_data.get("Concept Assessment", {})
1201
- code_assessment = teaching_data.get("Code Assessment", {})
1202
-
1203
- # Calculate concept scores
1204
- concept_scores = [
1205
- category.get("Score", 0)
1206
- for category in concept_assessment.values()
1207
- ]
1208
-
1209
- # Calculate code scores
1210
- code_scores = [
1211
- category.get("Score", 0)
1212
- for category in code_assessment.values()
1213
- ]
1214
-
1215
- # Calculate overall teaching score
1216
- all_teaching_scores = concept_scores + code_scores
1217
- teaching_score = (sum(all_teaching_scores) / len(all_teaching_scores) * 100) if all_teaching_scores else 0
1218
- st.metric("Teaching Score", f"{teaching_score:.1f}%")
1219
-
1220
- with col2:
1221
- # Calculate communication score
1222
- communication = evaluation.get("communication", {})
1223
- comm_categories = ["speed", "fluency", "flow", "intonation", "energy"]
1224
- comm_scores = [
1225
- communication.get(cat, {}).get("score", 0)
1226
- for cat in comm_categories
1227
- ]
1228
- comm_score = (sum(comm_scores) / len(comm_scores) * 100) if comm_scores else 0
1229
- st.metric("Communication Score", f"{comm_score:.1f}%")
1230
-
1231
- with col3:
1232
- # Calculate overall score (average of teaching and communication)
1233
- overall_score = (teaching_score + comm_score) / 2
1234
- st.metric("Overall Score", f"{overall_score:.1f}%")
1235
-
1236
- # Additional metrics row
1237
- col1, col2 = st.columns(2)
1238
- with col1:
1239
- # Count total improvement points
1240
- improvement_count = len(improvements) if isinstance(improvements, list) else 1
1241
- st.metric("Improvement Points", improvement_count)
1242
-
1243
- with col2:
1244
- # Display words per minute if available
1245
- wpm = communication.get("speed", {}).get("wpm", 0)
1246
- st.metric("Speaking Speed", f"{wpm:.1f} WPM")
1247
 
1248
  # Transcript tab with error handling
1249
  with tabs[3]:
@@ -1255,6 +1105,54 @@ def display_evaluation(evaluation: Dict[str, Any]):
1255
  st.error(f"Error displaying results: {str(e)}")
1256
  st.error("Please check the evaluation data structure and try again.")
1257
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1258
  def check_dependencies() -> List[str]:
1259
  """Check if required dependencies are installed"""
1260
  missing = []
@@ -1266,6 +1164,115 @@ def check_dependencies() -> List[str]:
1266
 
1267
  def main():
1268
  try:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1269
  st.set_page_config(page_title="🎓 Mentor Demo Review System", layout="wide")
1270
 
1271
  st.title("🎓 Mentor Demo Review System")
@@ -1332,6 +1339,13 @@ def main():
1332
  )
1333
 
1334
  if uploaded_file:
 
 
 
 
 
 
 
1335
  # Create temp directory for processing
1336
  temp_dir = tempfile.mkdtemp()
1337
  video_path = os.path.join(temp_dir, uploaded_file.name)
 
908
  tabs = st.tabs(["Communication", "Teaching", "Recommendations", "Transcript"])
909
 
910
  with tabs[0]:
911
+ st.markdown("""
912
+ <div class="category-header slide-in">
913
+ <h2>Communication Metrics</h2>
914
+ </div>
915
+ """, unsafe_allow_html=True)
916
+
917
+ # Update metrics to use the new card style
918
+ metrics = evaluation.get("communication", {})
919
+ for category, data in metrics.items():
920
+ score = data.get("score", 0)
921
+ score_class = "score-pass" if score == 1 else "score-fail"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
922
 
923
+ st.markdown(f"""
924
+ <div class="metric-card fade-in">
925
+ <h3>{category.title()}</h3>
926
+ <span class="score-badge {score_class}">
927
+ {"Pass" if score == 1 else "Needs Improvement"}
928
+ </span>
929
+ </div>
930
+ """, unsafe_allow_html=True)
931
 
932
  with tabs[1]:
933
  st.header("Teaching Analysis")
 
1047
  # Geography Fit with improved formatting
1048
  st.subheader("🌍 Geography Fit")
1049
  geography_fit = recommendations.get("geographyFit", "Not specified")
1050
+ st.info(geography_fit)
1051
 
1052
  # Improvements Needed with better formatting
1053
  st.subheader("💡 Suggested Improvements")
1054
  improvements = recommendations.get("improvements", [])
1055
  if isinstance(improvements, list):
1056
  for i, improvement in enumerate(improvements, 1):
1057
+ if isinstance(improvement, str):
1058
+ # Create categories based on content keywords
1059
+ category = "General"
1060
+ if any(keyword in improvement.lower() for keyword in ["voice", "volume", "pitch", "pace"]):
1061
+ category = "Voice and Delivery"
1062
+ elif any(keyword in improvement.lower() for keyword in ["explain", "concept", "understanding"]):
1063
+ category = "Teaching Approach"
1064
+ elif any(keyword in improvement.lower() for keyword in ["engage", "interact", "question"]):
1065
+ category = "Engagement"
1066
+ elif any(keyword in improvement.lower() for keyword in ["code", "technical", "implementation"]):
1067
+ category = "Technical Content"
 
 
 
 
 
 
 
 
1068
 
1069
  st.markdown(f"""
1070
+ <div class="recommendation-card">
1071
+ <h4>{i}. {category}</h4>
1072
+ <p>{improvement}</p>
1073
+ </div>
1074
+ """, unsafe_allow_html=True)
1075
 
1076
+ # Rigor Assessment with enhanced formatting
1077
  st.subheader("📊 Rigor Assessment")
1078
  rigor = recommendations.get("rigor", {})
1079
 
 
1080
  if isinstance(rigor, dict):
1081
  for category, assessment in rigor.items():
1082
+ # Format category name
1083
+ category_display = " ".join(word.capitalize() for word in category.replace("assessment", "").split())
1084
+
1085
+ # Get score and format assessment data
1086
+ score = "Pass" if isinstance(assessment, dict) and assessment.get('score') == 1 else "Needs Improvement"
1087
+ score_color = "green" if score == "Pass" else "orange"
1088
+
1089
+ # Display assessment in a card format
1090
+ st.markdown(f"""
1091
+ <div class="rigor-card">
1092
+ <h4>{category_display}</h4>
1093
+ <p class="score-badge {score_color.lower()}-score">{score}</p>
1094
+ <p>{assessment.get('justification', '') if isinstance(assessment, dict) else assessment}</p>
1095
+ </div>
1096
+ """, unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1097
 
1098
  # Transcript tab with error handling
1099
  with tabs[3]:
 
1105
  st.error(f"Error displaying results: {str(e)}")
1106
  st.error("Please check the evaluation data structure and try again.")
1107
 
1108
+ # Add these styles to the existing CSS in the main function
1109
+ st.markdown("""
1110
+ <style>
1111
+ /* ... existing styles ... */
1112
+
1113
+ .recommendation-card {
1114
+ background-color: #f8f9fa;
1115
+ border-left: 4px solid #1f77b4;
1116
+ padding: 15px;
1117
+ margin: 10px 0;
1118
+ border-radius: 4px;
1119
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
1120
+ }
1121
+
1122
+ .recommendation-card h4 {
1123
+ color: #1f77b4;
1124
+ margin: 0 0 10px 0;
1125
+ }
1126
+
1127
+ .rigor-card {
1128
+ background-color: #ffffff;
1129
+ border: 1px solid #e0e0e0;
1130
+ padding: 20px;
1131
+ margin: 10px 0;
1132
+ border-radius: 8px;
1133
+ box-shadow: 0 2px 4px rgba(0,0,0,0.05);
1134
+ }
1135
+
1136
+ .score-badge {
1137
+ display: inline-block;
1138
+ padding: 4px 12px;
1139
+ border-radius: 15px;
1140
+ font-weight: bold;
1141
+ margin: 10px 0;
1142
+ }
1143
+
1144
+ .green-score {
1145
+ background-color: #28a745;
1146
+ color: white;
1147
+ }
1148
+
1149
+ .orange-score {
1150
+ background-color: #fd7e14;
1151
+ color: white;
1152
+ }
1153
+ </style>
1154
+ """, unsafe_allow_html=True)
1155
+
1156
  def check_dependencies() -> List[str]:
1157
  """Check if required dependencies are installed"""
1158
  missing = []
 
1164
 
1165
  def main():
1166
  try:
1167
+ # Add custom CSS for animations and styling
1168
+ st.markdown("""
1169
+ <style>
1170
+ @keyframes fadeIn {
1171
+ from { opacity: 0; }
1172
+ to { opacity: 1; }
1173
+ }
1174
+
1175
+ @keyframes slideIn {
1176
+ from { transform: translateX(-100%); }
1177
+ to { transform: translateX(0); }
1178
+ }
1179
+
1180
+ @keyframes pulse {
1181
+ 0% { transform: scale(1); }
1182
+ 50% { transform: scale(1.05); }
1183
+ 100% { transform: scale(1); }
1184
+ }
1185
+
1186
+ .fade-in {
1187
+ animation: fadeIn 1s ease-in;
1188
+ }
1189
+
1190
+ .slide-in {
1191
+ animation: slideIn 0.5s ease-out;
1192
+ }
1193
+
1194
+ .pulse {
1195
+ animation: pulse 2s infinite;
1196
+ }
1197
+
1198
+ .metric-card {
1199
+ background-color: #f0f2f6;
1200
+ border-radius: 10px;
1201
+ padding: 20px;
1202
+ margin: 10px 0;
1203
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
1204
+ transition: transform 0.3s ease;
1205
+ }
1206
+
1207
+ .metric-card:hover {
1208
+ transform: translateY(-5px);
1209
+ }
1210
+
1211
+ .stButton>button {
1212
+ transition: all 0.3s ease;
1213
+ }
1214
+
1215
+ .stButton>button:hover {
1216
+ transform: scale(1.05);
1217
+ }
1218
+
1219
+ .category-header {
1220
+ background: linear-gradient(90deg, #1f77b4, #2c3e50);
1221
+ color: white;
1222
+ padding: 10px;
1223
+ border-radius: 5px;
1224
+ margin: 10px 0;
1225
+ }
1226
+
1227
+ .score-badge {
1228
+ padding: 5px 10px;
1229
+ border-radius: 15px;
1230
+ font-weight: bold;
1231
+ }
1232
+
1233
+ .score-pass {
1234
+ background-color: #28a745;
1235
+ color: white;
1236
+ }
1237
+
1238
+ .score-fail {
1239
+ background-color: #dc3545;
1240
+ color: white;
1241
+ }
1242
+ </style>
1243
+ """, unsafe_allow_html=True)
1244
+
1245
+ # Animated title
1246
+ st.markdown("""
1247
+ <div class="fade-in">
1248
+ <h1 style='text-align: center; color: #1f77b4;'>
1249
+ 🎓 Mentor Demo Review System
1250
+ </h1>
1251
+ </div>
1252
+ """, unsafe_allow_html=True)
1253
+
1254
+ # Animated sidebar
1255
+ with st.sidebar:
1256
+ st.markdown("""
1257
+ <div class="slide-in">
1258
+ <h2>Instructions</h2>
1259
+ </div>
1260
+ """, unsafe_allow_html=True)
1261
+
1262
+ st.markdown("""
1263
+ <div class="fade-in">
1264
+ <ol>
1265
+ <li>Upload your teaching video</li>
1266
+ <li>Wait for the analysis</li>
1267
+ <li>Review the detailed feedback</li>
1268
+ <li>Download the report</li>
1269
+ </ol>
1270
+
1271
+ <p><strong>Supported formats:</strong> MP4, AVI, MOV<br>
1272
+ <strong>Maximum file size:</strong> 500mb</p>
1273
+ </div>
1274
+ """, unsafe_allow_html=True)
1275
+
1276
  st.set_page_config(page_title="🎓 Mentor Demo Review System", layout="wide")
1277
 
1278
  st.title("🎓 Mentor Demo Review System")
 
1339
  )
1340
 
1341
  if uploaded_file:
1342
+ # Add a pulsing animation while processing
1343
+ st.markdown("""
1344
+ <div class="pulse" style="text-align: center;">
1345
+ <h3>Processing your video...</h3>
1346
+ </div>
1347
+ """, unsafe_allow_html=True)
1348
+
1349
  # Create temp directory for processing
1350
  temp_dir = tempfile.mkdtemp()
1351
  video_path = os.path.join(temp_dir, uploaded_file.name)