Spaces:
Sleeping
Sleeping
feat: Simplify conversation verification UI for HF Spaces compatibility
Browse files
src/interface/conversation_verification_ui.py
CHANGED
|
@@ -38,11 +38,10 @@ class VerificationInterface:
|
|
| 38 |
self.current_session = session
|
| 39 |
self.current_record_index = 0
|
| 40 |
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
interface.theme = gr.themes.Soft()
|
| 46 |
|
| 47 |
# Session header
|
| 48 |
with gr.Row():
|
|
@@ -133,75 +132,54 @@ class VerificationInterface:
|
|
| 133 |
export_btn = gr.Button("π Export to CSV", variant="primary")
|
| 134 |
export_status = gr.HTML(value="")
|
| 135 |
|
| 136 |
-
#
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
|
| 142 |
-
|
| 143 |
-
|
| 144 |
-
|
| 145 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 146 |
|
| 147 |
-
# Event handlers
|
| 148 |
correct_btn.click(
|
| 149 |
-
fn=
|
| 150 |
-
|
| 151 |
-
outputs=[exchange_display, current_position, stats_display, progress_bar, current_index]
|
| 152 |
)
|
| 153 |
|
|
|
|
|
|
|
|
|
|
| 154 |
incorrect_btn.click(
|
| 155 |
-
fn=
|
| 156 |
outputs=[correction_section]
|
| 157 |
)
|
| 158 |
|
| 159 |
-
|
| 160 |
-
|
| 161 |
-
inputs=[session_state, current_index, correction_radio, correction_reason, correction_notes],
|
| 162 |
-
outputs=[exchange_display, current_position, stats_display, progress_bar, current_index, correction_section]
|
| 163 |
-
)
|
| 164 |
-
|
| 165 |
-
cancel_correction_btn.click(
|
| 166 |
-
fn=lambda: (gr.Column(visible=False), "", "", ""),
|
| 167 |
-
outputs=[correction_section, correction_radio, correction_reason, correction_notes]
|
| 168 |
-
)
|
| 169 |
|
| 170 |
-
|
| 171 |
-
fn=
|
| 172 |
-
|
| 173 |
-
outputs=[exchange_display, current_position, current_index]
|
| 174 |
)
|
| 175 |
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
|
| 179 |
-
outputs=[exchange_display, current_position, current_index]
|
| 180 |
-
)
|
| 181 |
|
| 182 |
mark_all_correct_btn.click(
|
| 183 |
-
fn=
|
| 184 |
-
inputs=[session_state, current_index],
|
| 185 |
outputs=[exchange_display, current_position, stats_display, progress_bar]
|
| 186 |
)
|
| 187 |
-
|
| 188 |
-
mark_green_correct_btn.click(
|
| 189 |
-
fn=self._mark_all_green_correct,
|
| 190 |
-
inputs=[session_state],
|
| 191 |
-
outputs=[exchange_display, current_position, stats_display, progress_bar, current_index]
|
| 192 |
-
)
|
| 193 |
-
|
| 194 |
-
skip_to_errors_btn.click(
|
| 195 |
-
fn=self._skip_to_next_error,
|
| 196 |
-
inputs=[session_state, current_index],
|
| 197 |
-
outputs=[exchange_display, current_position, current_index]
|
| 198 |
-
)
|
| 199 |
-
|
| 200 |
-
export_btn.click(
|
| 201 |
-
fn=self._export_results,
|
| 202 |
-
inputs=[session_state],
|
| 203 |
-
outputs=[export_status]
|
| 204 |
-
)
|
| 205 |
|
| 206 |
return interface
|
| 207 |
|
|
@@ -674,4 +652,144 @@ class VerificationInterface:
|
|
| 674 |
|
| 675 |
except Exception as e:
|
| 676 |
print(f"Error in skip to errors: {e}")
|
| 677 |
-
return f"β Error: {str(e)}", "Error", current_index
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 38 |
self.current_session = session
|
| 39 |
self.current_record_index = 0
|
| 40 |
|
| 41 |
+
# Create interface without theme for HF Spaces compatibility
|
| 42 |
+
interface = gr.Blocks(title=f"Verify Conversation - {session.patient_name}")
|
| 43 |
+
|
| 44 |
+
with interface:
|
|
|
|
| 45 |
|
| 46 |
# Session header
|
| 47 |
with gr.Row():
|
|
|
|
| 132 |
export_btn = gr.Button("π Export to CSV", variant="primary")
|
| 133 |
export_status = gr.HTML(value="")
|
| 134 |
|
| 135 |
+
# Initialize interface with first exchange data
|
| 136 |
+
if session.verification_records:
|
| 137 |
+
initial_exchange_html = self._render_exchange_review(session.verification_records[0])
|
| 138 |
+
initial_position_html = f"Exchange 1 of {len(session.verification_records)}"
|
| 139 |
+
initial_stats_html = self._render_statistics(session)
|
| 140 |
+
initial_progress_html = self._render_progress_bar(session)
|
| 141 |
+
|
| 142 |
+
exchange_display.value = initial_exchange_html
|
| 143 |
+
current_position.value = initial_position_html
|
| 144 |
+
stats_display.value = initial_stats_html
|
| 145 |
+
progress_bar.value = initial_progress_html
|
| 146 |
+
else:
|
| 147 |
+
exchange_display.value = "No exchanges to verify"
|
| 148 |
+
current_position.value = "No exchanges"
|
| 149 |
+
|
| 150 |
+
# Event handlers - simplified for HF Spaces compatibility
|
| 151 |
+
def handle_correct_click():
|
| 152 |
+
return self._handle_correct_feedback_simple()
|
| 153 |
|
|
|
|
| 154 |
correct_btn.click(
|
| 155 |
+
fn=handle_correct_click,
|
| 156 |
+
outputs=[exchange_display, current_position, stats_display, progress_bar]
|
|
|
|
| 157 |
)
|
| 158 |
|
| 159 |
+
def show_correction_section():
|
| 160 |
+
return gr.Column(visible=True)
|
| 161 |
+
|
| 162 |
incorrect_btn.click(
|
| 163 |
+
fn=show_correction_section,
|
| 164 |
outputs=[correction_section]
|
| 165 |
)
|
| 166 |
|
| 167 |
+
def handle_export_click():
|
| 168 |
+
return self._export_results_simple()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 169 |
|
| 170 |
+
export_btn.click(
|
| 171 |
+
fn=handle_export_click,
|
| 172 |
+
outputs=[export_status]
|
|
|
|
| 173 |
)
|
| 174 |
|
| 175 |
+
# Simplified handlers for basic functionality
|
| 176 |
+
def handle_mark_all_correct():
|
| 177 |
+
return self._mark_all_remaining_correct_simple()
|
|
|
|
|
|
|
| 178 |
|
| 179 |
mark_all_correct_btn.click(
|
| 180 |
+
fn=handle_mark_all_correct,
|
|
|
|
| 181 |
outputs=[exchange_display, current_position, stats_display, progress_bar]
|
| 182 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 183 |
|
| 184 |
return interface
|
| 185 |
|
|
|
|
| 652 |
|
| 653 |
except Exception as e:
|
| 654 |
print(f"Error in skip to errors: {e}")
|
| 655 |
+
return f"β Error: {str(e)}", "Error", current_index
|
| 656 |
+
|
| 657 |
+
def _handle_correct_feedback_simple(self) -> Tuple[str, str, str, str]:
|
| 658 |
+
"""Simplified correct feedback handler for HF Spaces compatibility."""
|
| 659 |
+
try:
|
| 660 |
+
if not self.current_session or self.current_record_index >= len(self.current_session.verification_records):
|
| 661 |
+
return "No more exchanges", "Complete", "", ""
|
| 662 |
+
|
| 663 |
+
record = self.current_session.verification_records[self.current_record_index]
|
| 664 |
+
|
| 665 |
+
# Submit feedback
|
| 666 |
+
from src.core.conversation_verification import VerificationFeedback
|
| 667 |
+
feedback = VerificationFeedback(
|
| 668 |
+
exchange_id=record.exchange_id,
|
| 669 |
+
is_correct=True
|
| 670 |
+
)
|
| 671 |
+
|
| 672 |
+
success = self.manager.submit_exchange_verification(self.current_session.session_id, record.exchange_id, feedback)
|
| 673 |
+
if not success:
|
| 674 |
+
return "β Failed to submit feedback", f"Exchange {self.current_record_index + 1}", "", ""
|
| 675 |
+
|
| 676 |
+
# Reload session
|
| 677 |
+
updated_session = self.manager.load_session(self.current_session.session_id)
|
| 678 |
+
if not updated_session:
|
| 679 |
+
return "β Failed to reload session", f"Exchange {self.current_record_index + 1}", "", ""
|
| 680 |
+
|
| 681 |
+
self.current_session = updated_session
|
| 682 |
+
|
| 683 |
+
# Move to next unverified exchange
|
| 684 |
+
next_index = self._find_next_unverified_index(updated_session, self.current_record_index)
|
| 685 |
+
|
| 686 |
+
if next_index is not None:
|
| 687 |
+
self.current_record_index = next_index
|
| 688 |
+
next_record = updated_session.verification_records[next_index]
|
| 689 |
+
exchange_html = self._render_exchange_review(next_record)
|
| 690 |
+
position_html = f"Exchange {next_index + 1} of {len(updated_session.verification_records)}"
|
| 691 |
+
else:
|
| 692 |
+
exchange_html = """
|
| 693 |
+
<div style='text-align: center; padding: 2em; background-color: #d4edda; border-radius: 8px;'>
|
| 694 |
+
<h3>π All exchanges verified!</h3>
|
| 695 |
+
<p>Great job! You can now export the results.</p>
|
| 696 |
+
</div>
|
| 697 |
+
"""
|
| 698 |
+
position_html = "Verification Complete"
|
| 699 |
+
|
| 700 |
+
stats_html = self._render_statistics(updated_session)
|
| 701 |
+
progress_html = self._render_progress_bar(updated_session)
|
| 702 |
+
|
| 703 |
+
return exchange_html, position_html, stats_html, progress_html
|
| 704 |
+
|
| 705 |
+
except Exception as e:
|
| 706 |
+
print(f"Error in simplified correct feedback: {e}")
|
| 707 |
+
return f"β Error: {str(e)}", f"Exchange {self.current_record_index + 1}", "", ""
|
| 708 |
+
|
| 709 |
+
def _export_results_simple(self) -> str:
|
| 710 |
+
"""Simplified export results for HF Spaces compatibility."""
|
| 711 |
+
try:
|
| 712 |
+
if not self.current_session:
|
| 713 |
+
return "β No session to export"
|
| 714 |
+
|
| 715 |
+
verified_count = len([r for r in self.current_session.verification_records if r.is_correct is not None])
|
| 716 |
+
if verified_count == 0:
|
| 717 |
+
return """
|
| 718 |
+
<div style="background-color: #fff3cd; padding: 1em; border-radius: 4px;">
|
| 719 |
+
<strong>β οΈ Nothing to Export</strong><br>
|
| 720 |
+
Please verify some exchanges first.
|
| 721 |
+
</div>
|
| 722 |
+
"""
|
| 723 |
+
|
| 724 |
+
from src.core.verification_exporter import VerificationExporter
|
| 725 |
+
exporter = VerificationExporter()
|
| 726 |
+
csv_path = exporter.export_session_to_csv(self.current_session)
|
| 727 |
+
|
| 728 |
+
import os
|
| 729 |
+
file_size = os.path.getsize(csv_path) if os.path.exists(csv_path) else 0
|
| 730 |
+
file_size_kb = file_size / 1024
|
| 731 |
+
|
| 732 |
+
return f"""
|
| 733 |
+
<div style="background-color: #d4edda; padding: 1em; border-radius: 4px;">
|
| 734 |
+
<strong>β
Export Successful!</strong><br>
|
| 735 |
+
<strong>File:</strong> <code>{os.path.basename(csv_path)}</code><br>
|
| 736 |
+
<strong>Size:</strong> {file_size_kb:.1f} KB<br>
|
| 737 |
+
<strong>Records:</strong> {verified_count} verified exchanges
|
| 738 |
+
</div>
|
| 739 |
+
"""
|
| 740 |
+
except Exception as e:
|
| 741 |
+
return f"""
|
| 742 |
+
<div style="background-color: #f8d7da; padding: 1em; border-radius: 4px;">
|
| 743 |
+
<strong>β Export Failed</strong><br>
|
| 744 |
+
<strong>Error:</strong> {str(e)}
|
| 745 |
+
</div>
|
| 746 |
+
"""
|
| 747 |
+
|
| 748 |
+
def _mark_all_remaining_correct_simple(self) -> Tuple[str, str, str, str]:
|
| 749 |
+
"""Simplified mark all remaining correct for HF Spaces compatibility."""
|
| 750 |
+
try:
|
| 751 |
+
if not self.current_session:
|
| 752 |
+
return "β No session", "Error", "", ""
|
| 753 |
+
|
| 754 |
+
unverified_records = self.current_session.get_unverified_records()
|
| 755 |
+
if not unverified_records:
|
| 756 |
+
return """
|
| 757 |
+
<div style='text-align: center; padding: 2em; background-color: #fff3cd; border-radius: 8px;'>
|
| 758 |
+
<h3>β οΈ No unverified exchanges</h3>
|
| 759 |
+
<p>All exchanges have already been verified.</p>
|
| 760 |
+
</div>
|
| 761 |
+
""", "All Verified", "", ""
|
| 762 |
+
|
| 763 |
+
success_count = 0
|
| 764 |
+
from src.core.conversation_verification import VerificationFeedback
|
| 765 |
+
for record in unverified_records:
|
| 766 |
+
feedback = VerificationFeedback(
|
| 767 |
+
exchange_id=record.exchange_id,
|
| 768 |
+
is_correct=True
|
| 769 |
+
)
|
| 770 |
+
if self.manager.submit_exchange_verification(self.current_session.session_id, record.exchange_id, feedback):
|
| 771 |
+
success_count += 1
|
| 772 |
+
|
| 773 |
+
# Reload session
|
| 774 |
+
updated_session = self.manager.load_session(self.current_session.session_id)
|
| 775 |
+
if not updated_session:
|
| 776 |
+
return "β Failed to reload session", "Error", "", ""
|
| 777 |
+
|
| 778 |
+
self.current_session = updated_session
|
| 779 |
+
|
| 780 |
+
exchange_html = f"""
|
| 781 |
+
<div style='text-align: center; padding: 2em; background-color: #d4edda; border-radius: 8px;'>
|
| 782 |
+
<h3>π Batch verification complete!</h3>
|
| 783 |
+
<p>Marked <strong>{success_count}</strong> exchanges as correct.</p>
|
| 784 |
+
<p>You can now export the results.</p>
|
| 785 |
+
</div>
|
| 786 |
+
"""
|
| 787 |
+
position_html = "Verification Complete"
|
| 788 |
+
stats_html = self._render_statistics(updated_session)
|
| 789 |
+
progress_html = self._render_progress_bar(updated_session)
|
| 790 |
+
|
| 791 |
+
return exchange_html, position_html, stats_html, progress_html
|
| 792 |
+
|
| 793 |
+
except Exception as e:
|
| 794 |
+
print(f"Error in batch verification: {e}")
|
| 795 |
+
return f"β Error: {str(e)}", "Error", "", ""
|