Spaces:
Sleeping
Sleeping
feat: add export functionality and skip option to Enhanced Verification
Browse files- Add export buttons for CSV, JSON, and Excel formats in Standard Verification
- Implement export results functionality with proper error handling
- Add Skip button to allow skipping messages without feedback
- Reorganize session statistics to include skipped messages count
- Add proper session control section with export and navigation options
- Improve user experience with comprehensive result export capabilities
src/interface/enhanced_verification_interface.py
CHANGED
|
@@ -321,7 +321,15 @@ class EnhancedVerificationInterface:
|
|
| 321 |
"**Progress:** 0/0\n**Correct:** 0\n**Incorrect:** 0\n**Accuracy:** 0%"
|
| 322 |
)
|
| 323 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 324 |
# Navigation
|
|
|
|
| 325 |
with gr.Row():
|
| 326 |
skip_btn = gr.Button("โญ๏ธ Skip", variant="secondary")
|
| 327 |
finish_btn = gr.Button("๐ Finish Session", variant="primary")
|
|
@@ -1067,6 +1075,105 @@ class EnhancedVerificationInterface:
|
|
| 1067 |
"โ
Session finished. You can start a new verification or select another dataset." # dataset_status_message
|
| 1068 |
)
|
| 1069 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1070 |
# Bind dataset interface events
|
| 1071 |
dataset_selector.change(
|
| 1072 |
on_dataset_selection_change,
|
|
@@ -1143,11 +1250,44 @@ class EnhancedVerificationInterface:
|
|
| 1143 |
]
|
| 1144 |
)
|
| 1145 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1146 |
finish_btn.click(
|
| 1147 |
on_finish_session,
|
| 1148 |
inputs=[verification_session_state],
|
| 1149 |
outputs=[message_review_section, dataset_status_message]
|
| 1150 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1151 |
|
| 1152 |
return interface
|
| 1153 |
|
|
|
|
| 321 |
"**Progress:** 0/0\n**Correct:** 0\n**Incorrect:** 0\n**Accuracy:** 0%"
|
| 322 |
)
|
| 323 |
|
| 324 |
+
# Export section
|
| 325 |
+
gr.Markdown("## ๐พ Export Results")
|
| 326 |
+
with gr.Column():
|
| 327 |
+
export_csv_btn = gr.Button("๐ Export CSV", variant="secondary", size="sm")
|
| 328 |
+
export_json_btn = gr.Button("๐ Export JSON", variant="secondary", size="sm")
|
| 329 |
+
export_xlsx_btn = gr.Button("๐ Export Excel", variant="secondary", size="sm")
|
| 330 |
+
|
| 331 |
# Navigation
|
| 332 |
+
gr.Markdown("## ๐ฎ Session Control")
|
| 333 |
with gr.Row():
|
| 334 |
skip_btn = gr.Button("โญ๏ธ Skip", variant="secondary")
|
| 335 |
finish_btn = gr.Button("๐ Finish Session", variant="primary")
|
|
|
|
| 1075 |
"โ
Session finished. You can start a new verification or select another dataset." # dataset_status_message
|
| 1076 |
)
|
| 1077 |
|
| 1078 |
+
def on_export_results(format_type, session):
|
| 1079 |
+
"""Export verification results."""
|
| 1080 |
+
try:
|
| 1081 |
+
if not session:
|
| 1082 |
+
return "โ No active session to export"
|
| 1083 |
+
|
| 1084 |
+
success, message, file_path = dataset_controller.export_session_results(format_type)
|
| 1085 |
+
|
| 1086 |
+
if success:
|
| 1087 |
+
return f"โ
Results exported to {format_type.upper()} format"
|
| 1088 |
+
else:
|
| 1089 |
+
return message
|
| 1090 |
+
except Exception as e:
|
| 1091 |
+
return f"โ Export error: {str(e)}"
|
| 1092 |
+
|
| 1093 |
+
def on_skip_message(current_dataset, session, msg_index, classification):
|
| 1094 |
+
"""Skip current message without feedback."""
|
| 1095 |
+
try:
|
| 1096 |
+
if not session or not current_dataset:
|
| 1097 |
+
return (
|
| 1098 |
+
gr.update(), # current_message_display
|
| 1099 |
+
gr.update(), # classifier_decision_display
|
| 1100 |
+
gr.update(), # classifier_confidence_display
|
| 1101 |
+
gr.update(), # session_stats_display
|
| 1102 |
+
msg_index, # current_message_index_state
|
| 1103 |
+
classification, # current_classification_state
|
| 1104 |
+
"โ No active session" # dataset_status_message
|
| 1105 |
+
)
|
| 1106 |
+
|
| 1107 |
+
# Move to next message without recording feedback
|
| 1108 |
+
dataset_controller.current_message_index += 1
|
| 1109 |
+
|
| 1110 |
+
if dataset_controller.current_message_index >= len(current_dataset.messages):
|
| 1111 |
+
# Session complete
|
| 1112 |
+
stats_text = f"""**๐ Session Complete!**
|
| 1113 |
+
**Total:** {session.verified_count}
|
| 1114 |
+
**Correct:** {session.correct_count}
|
| 1115 |
+
**Incorrect:** {session.incorrect_count}
|
| 1116 |
+
**Skipped:** {dataset_controller.current_message_index - session.verified_count}
|
| 1117 |
+
**Final Accuracy:** {(session.correct_count / session.verified_count * 100) if session.verified_count > 0 else 0:.1f}%"""
|
| 1118 |
+
|
| 1119 |
+
return (
|
| 1120 |
+
"โ
Verification session complete!", # current_message_display
|
| 1121 |
+
"๐ **COMPLETE**", # classifier_decision_display
|
| 1122 |
+
"", # classifier_confidence_display
|
| 1123 |
+
stats_text, # session_stats_display
|
| 1124 |
+
dataset_controller.current_message_index, # current_message_index_state
|
| 1125 |
+
None, # current_classification_state
|
| 1126 |
+
"โ
Session complete!" # dataset_status_message
|
| 1127 |
+
)
|
| 1128 |
+
|
| 1129 |
+
# Get next message
|
| 1130 |
+
next_message, next_classification = dataset_controller.get_current_message_for_verification()
|
| 1131 |
+
|
| 1132 |
+
if next_message:
|
| 1133 |
+
decision = next_classification.get('decision', 'unknown').upper()
|
| 1134 |
+
confidence = next_classification.get('confidence', 0) * 100
|
| 1135 |
+
|
| 1136 |
+
decision_colors = {'GREEN': '๐ข', 'YELLOW': '๐ก', 'RED': '๐ด'}
|
| 1137 |
+
decision_badge = f"{decision_colors.get(decision, 'โ')} **{decision}**"
|
| 1138 |
+
confidence_text = f"Confidence: **{confidence:.1f}%**"
|
| 1139 |
+
|
| 1140 |
+
skipped_count = dataset_controller.current_message_index - session.verified_count
|
| 1141 |
+
stats_text = f"""**Progress:** {dataset_controller.current_message_index + 1}/{len(current_dataset.messages)}
|
| 1142 |
+
**Correct:** {session.correct_count}
|
| 1143 |
+
**Incorrect:** {session.incorrect_count}
|
| 1144 |
+
**Skipped:** {skipped_count}
|
| 1145 |
+
**Accuracy:** {(session.correct_count / session.verified_count * 100) if session.verified_count > 0 else 0:.1f}%"""
|
| 1146 |
+
|
| 1147 |
+
return (
|
| 1148 |
+
next_message.text, # current_message_display
|
| 1149 |
+
decision_badge, # classifier_decision_display
|
| 1150 |
+
confidence_text, # classifier_confidence_display
|
| 1151 |
+
stats_text, # session_stats_display
|
| 1152 |
+
dataset_controller.current_message_index, # current_message_index_state
|
| 1153 |
+
next_classification, # current_classification_state
|
| 1154 |
+
"โญ๏ธ Message skipped" # dataset_status_message
|
| 1155 |
+
)
|
| 1156 |
+
else:
|
| 1157 |
+
return (
|
| 1158 |
+
"No more messages", # current_message_display
|
| 1159 |
+
"", # classifier_decision_display
|
| 1160 |
+
"", # classifier_confidence_display
|
| 1161 |
+
"All messages processed", # session_stats_display
|
| 1162 |
+
msg_index, # current_message_index_state
|
| 1163 |
+
None, # current_classification_state
|
| 1164 |
+
"โ
All messages processed" # dataset_status_message
|
| 1165 |
+
)
|
| 1166 |
+
except Exception as e:
|
| 1167 |
+
return (
|
| 1168 |
+
gr.update(), # current_message_display
|
| 1169 |
+
gr.update(), # classifier_decision_display
|
| 1170 |
+
gr.update(), # classifier_confidence_display
|
| 1171 |
+
gr.update(), # session_stats_display
|
| 1172 |
+
msg_index, # current_message_index_state
|
| 1173 |
+
classification, # current_classification_state
|
| 1174 |
+
f"โ Error skipping: {str(e)}" # dataset_status_message
|
| 1175 |
+
)
|
| 1176 |
+
|
| 1177 |
# Bind dataset interface events
|
| 1178 |
dataset_selector.change(
|
| 1179 |
on_dataset_selection_change,
|
|
|
|
| 1250 |
]
|
| 1251 |
)
|
| 1252 |
|
| 1253 |
+
skip_btn.click(
|
| 1254 |
+
on_skip_message,
|
| 1255 |
+
inputs=[current_dataset_state, verification_session_state, current_message_index_state, current_classification_state],
|
| 1256 |
+
outputs=[
|
| 1257 |
+
current_message_display,
|
| 1258 |
+
classifier_decision_display,
|
| 1259 |
+
classifier_confidence_display,
|
| 1260 |
+
session_stats_display,
|
| 1261 |
+
current_message_index_state,
|
| 1262 |
+
current_classification_state,
|
| 1263 |
+
dataset_status_message
|
| 1264 |
+
]
|
| 1265 |
+
)
|
| 1266 |
+
|
| 1267 |
finish_btn.click(
|
| 1268 |
on_finish_session,
|
| 1269 |
inputs=[verification_session_state],
|
| 1270 |
outputs=[message_review_section, dataset_status_message]
|
| 1271 |
)
|
| 1272 |
+
|
| 1273 |
+
# Export buttons
|
| 1274 |
+
export_csv_btn.click(
|
| 1275 |
+
lambda session: on_export_results("csv", session),
|
| 1276 |
+
inputs=[verification_session_state],
|
| 1277 |
+
outputs=[dataset_status_message]
|
| 1278 |
+
)
|
| 1279 |
+
|
| 1280 |
+
export_json_btn.click(
|
| 1281 |
+
lambda session: on_export_results("json", session),
|
| 1282 |
+
inputs=[verification_session_state],
|
| 1283 |
+
outputs=[dataset_status_message]
|
| 1284 |
+
)
|
| 1285 |
+
|
| 1286 |
+
export_xlsx_btn.click(
|
| 1287 |
+
lambda session: on_export_results("xlsx", session),
|
| 1288 |
+
inputs=[verification_session_state],
|
| 1289 |
+
outputs=[dataset_status_message]
|
| 1290 |
+
)
|
| 1291 |
|
| 1292 |
return interface
|
| 1293 |
|