Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -405,124 +405,88 @@ def create_shared_entity_html(entity, entity_colors):
|
|
405 |
f'title="SHARED: {tooltip}">'
|
406 |
f'{entity["text"]} π€</span>')
|
407 |
|
408 |
-
def
|
409 |
-
"""Create
|
410 |
-
if
|
411 |
-
|
412 |
-
|
413 |
-
# Share overlapping entities
|
414 |
-
shared_entities = find_overlapping_entities(entities)
|
415 |
-
|
416 |
-
# Group entities by type
|
417 |
-
entity_groups = {}
|
418 |
-
for entity in shared_entities:
|
419 |
-
if entity.get('is_shared', False):
|
420 |
-
key = 'SHARED_ENTITIES'
|
421 |
-
else:
|
422 |
-
key = entity['label']
|
423 |
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
|
|
|
|
|
|
|
|
438 |
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
</tr>
|
451 |
-
</thead>
|
452 |
-
<tbody>
|
453 |
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
454 |
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
{entity['entity_count']}
|
467 |
-
</span>
|
468 |
-
</td>
|
469 |
-
</tr>
|
470 |
-
"""
|
471 |
-
|
472 |
-
table_html += "</tbody></table></div>"
|
473 |
-
tab_contents[f"π€ SHARED ({len(entities_of_type)})"] = table_html
|
474 |
-
|
475 |
-
else:
|
476 |
-
colour = entity_colors.get(entity_type.upper(), '#f0f0f0')
|
477 |
-
# Determine if it's common or custom
|
478 |
-
is_standard = entity_type in STANDARD_ENTITIES
|
479 |
-
icon = "π―" if is_standard else "β¨"
|
480 |
-
source_text = "Common NER" if is_standard else "Custom GLiNER"
|
481 |
-
header = f"{icon} {source_text} - {entity_type} ({len(entities_of_type)} found)"
|
482 |
-
|
483 |
-
# Create table for this entity type
|
484 |
-
table_html = f"""
|
485 |
-
<div style="margin: 15px 0;">
|
486 |
-
<h4 style="color: {colour}; margin-bottom: 15px;">{header}</h4>
|
487 |
-
<table style="width: 100%; border-collapse: collapse; border: 1px solid #ddd;">
|
488 |
-
<thead>
|
489 |
-
<tr style="background-color: {colour}; color: white;">
|
490 |
-
<th style="padding: 12px; text-align: left; border: 1px solid #ddd;">Entity Text</th>
|
491 |
-
<th style="padding: 12px; text-align: left; border: 1px solid #ddd;">Confidence</th>
|
492 |
-
<th style="padding: 12px; text-align: left; border: 1px solid #ddd;">Type</th>
|
493 |
-
<th style="padding: 12px; text-align: left; border: 1px solid #ddd;">Source</th>
|
494 |
-
</tr>
|
495 |
-
</thead>
|
496 |
-
<tbody>
|
497 |
"""
|
498 |
-
|
499 |
-
# Sort by confidence score
|
500 |
-
entities_of_type.sort(key=lambda x: x.get('confidence', 0), reverse=True)
|
501 |
-
|
502 |
-
for entity in entities_of_type:
|
503 |
-
confidence = entity.get('confidence', 0.0)
|
504 |
-
confidence_colour = "#28a745" if confidence > 0.7 else "#ffc107" if confidence > 0.4 else "#dc3545"
|
505 |
-
source = entity.get('source', 'Unknown')
|
506 |
-
source_badge = f"<span style='background-color: #007bff; color: white; padding: 2px 6px; border-radius: 10px; font-size: 11px;'>{source}</span>"
|
507 |
-
|
508 |
-
table_html += f"""
|
509 |
-
<tr style="background-color: #fff;">
|
510 |
-
<td style="padding: 10px; border: 1px solid #ddd; font-weight: bold;">{entity['text']}</td>
|
511 |
-
<td style="padding: 10px; border: 1px solid #ddd;">
|
512 |
-
<span style="color: {confidence_colour}; font-weight: bold;">
|
513 |
-
{confidence:.3f}
|
514 |
-
</span>
|
515 |
-
</td>
|
516 |
-
<td style="padding: 10px; border: 1px solid #ddd;">{entity['label']}</td>
|
517 |
-
<td style="padding: 10px; border: 1px solid #ddd;">{source_badge}</td>
|
518 |
-
</tr>
|
519 |
-
"""
|
520 |
-
|
521 |
-
table_html += "</tbody></table></div>"
|
522 |
-
tab_label = f"{icon} {entity_type} ({len(entities_of_type)})"
|
523 |
-
tab_contents[tab_label] = table_html
|
524 |
|
525 |
-
|
|
|
526 |
|
527 |
def create_legend_html(entity_colors, standard_entities, custom_entities):
|
528 |
"""Create a legend showing entity colours"""
|
@@ -559,7 +523,7 @@ ner_manager = HybridNERManager()
|
|
559 |
def process_text(text, standard_entities, custom_entities_str, confidence_threshold, selected_model, progress=gr.Progress()):
|
560 |
"""Main processing function for Gradio interface with progress tracking"""
|
561 |
if not text.strip():
|
562 |
-
return "β Please enter some text to analyse", "",
|
563 |
|
564 |
progress(0.1, desc="Initialising...")
|
565 |
|
@@ -572,7 +536,7 @@ def process_text(text, standard_entities, custom_entities_str, confidence_thresh
|
|
572 |
selected_standard = [entity for entity in standard_entities if entity]
|
573 |
|
574 |
if not selected_standard and not custom_entities:
|
575 |
-
return "β Please select at least one common entity type OR enter custom entity types", "",
|
576 |
|
577 |
progress(0.2, desc="Loading models...")
|
578 |
|
@@ -591,7 +555,7 @@ def process_text(text, standard_entities, custom_entities_str, confidence_thresh
|
|
591 |
all_entities.extend(custom_entity_results)
|
592 |
|
593 |
if not all_entities:
|
594 |
-
return "β No entities found. Try lowering the confidence threshold or using different entity types.", "",
|
595 |
|
596 |
progress(0.8, desc="Processing results...")
|
597 |
|
@@ -601,14 +565,26 @@ def process_text(text, standard_entities, custom_entities_str, confidence_thresh
|
|
601 |
# Create outputs
|
602 |
legend_html = create_legend_html(entity_colors, selected_standard, custom_entities)
|
603 |
highlighted_html = create_highlighted_html(text, all_entities, entity_colors)
|
604 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
605 |
|
606 |
progress(0.9, desc="Creating summary...")
|
607 |
|
608 |
-
# Create summary
|
609 |
-
# Note: Shared entities are those found by BOTH common NER models AND custom GLiNER
|
610 |
total_entities = len(all_entities)
|
611 |
-
shared_entities = find_overlapping_entities(all_entities)
|
612 |
final_count = len(shared_entities)
|
613 |
shared_count = sum(1 for e in shared_entities if e.get('is_shared', False))
|
614 |
|
@@ -622,7 +598,29 @@ def process_text(text, standard_entities, custom_entities_str, confidence_thresh
|
|
622 |
|
623 |
progress(1.0, desc="Complete!")
|
624 |
|
625 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
626 |
|
627 |
# Create Gradio interface
|
628 |
def create_interface():
|
@@ -723,142 +721,40 @@ def create_interface():
|
|
723 |
with gr.Row():
|
724 |
highlighted_output = gr.HTML(label="Highlighted Text")
|
725 |
|
726 |
-
#
|
727 |
-
results_tabs = gr.State({})
|
728 |
-
|
729 |
-
def update_tabs(tab_contents):
|
730 |
-
"""Update the results tabs based on the analysis"""
|
731 |
-
if not tab_contents or not isinstance(tab_contents, dict):
|
732 |
-
return {gr.HTML("No results to display"): gr.update(visible=True)}
|
733 |
-
|
734 |
-
# Create tabs dynamically
|
735 |
-
tab_components = {}
|
736 |
-
for tab_name, content in tab_contents.items():
|
737 |
-
tab_components[tab_name] = gr.HTML(content)
|
738 |
-
|
739 |
-
return tab_components
|
740 |
-
|
741 |
-
# Results section with tabs
|
742 |
with gr.Row():
|
743 |
with gr.Column():
|
744 |
gr.Markdown("### π Detailed Results")
|
745 |
|
746 |
-
|
747 |
-
|
748 |
-
|
749 |
-
|
750 |
-
def process_and_display(text, standard_entities, custom_entities, confidence_threshold, selected_model):
|
751 |
-
# Get results from main processing function
|
752 |
-
summary, highlighted, tab_contents = process_text(
|
753 |
-
text, standard_entities, custom_entities, confidence_threshold, selected_model
|
754 |
-
)
|
755 |
-
|
756 |
-
# Create tabs HTML manually since Gradio dynamic tabs are complex
|
757 |
-
if isinstance(tab_contents, dict) and tab_contents:
|
758 |
-
# Generate unique IDs to avoid conflicts
|
759 |
-
import time
|
760 |
-
timestamp = str(int(time.time() * 1000))
|
761 |
-
|
762 |
-
tabs_html = f"""
|
763 |
-
<div style="margin: 20px 0;" id="tab-container-{timestamp}">
|
764 |
-
<div style="border-bottom: 2px solid #ddd; margin-bottom: 20px;">
|
765 |
-
"""
|
766 |
-
|
767 |
-
# Create tab buttons
|
768 |
-
tab_names = list(tab_contents.keys())
|
769 |
-
for i, tab_name in enumerate(tab_names):
|
770 |
-
active_style = "background-color: #f8f9fa; border-bottom: 3px solid #4ECDC4;" if i == 0 else "background-color: #fff;"
|
771 |
-
default_bg = '#f8f9fa' if i == 0 else '#fff'
|
772 |
-
tabs_html += f"""
|
773 |
-
<button onclick="showResultTab{timestamp}('{i}')" id="result-tab-{timestamp}-{i}"
|
774 |
-
style="padding: 12px 24px; margin-right: 5px; border: 1px solid #ddd;
|
775 |
-
border-bottom: none; cursor: pointer; font-weight: bold; {active_style}
|
776 |
-
transition: all 0.3s ease;"
|
777 |
-
onmouseover="this.style.backgroundColor='#e9ecef'"
|
778 |
-
onmouseout="this.style.backgroundColor='{default_bg}'">
|
779 |
-
{tab_name}
|
780 |
-
</button>
|
781 |
-
"""
|
782 |
-
|
783 |
-
tabs_html += "</div>"
|
784 |
-
|
785 |
-
# Create tab content
|
786 |
-
for i, (tab_name, content) in enumerate(tab_contents.items()):
|
787 |
-
display_style = "display: block;" if i == 0 else "display: none;"
|
788 |
-
tabs_html += f"""
|
789 |
-
<div id="result-content-{timestamp}-{i}" style="{display_style}">
|
790 |
-
{content}
|
791 |
-
</div>
|
792 |
-
"""
|
793 |
-
|
794 |
-
# Add JavaScript for tab switching with unique function name
|
795 |
-
tabs_html += f"""
|
796 |
-
<script>
|
797 |
-
function showResultTab{timestamp}(tabIndex) {{
|
798 |
-
console.log('Tab clicked:', tabIndex);
|
799 |
-
|
800 |
-
// Hide all content for this specific tab container
|
801 |
-
var contents = document.querySelectorAll('[id^="result-content-{timestamp}-"]');
|
802 |
-
contents.forEach(function(content) {{
|
803 |
-
content.style.display = 'none';
|
804 |
-
}});
|
805 |
-
|
806 |
-
// Reset all tab styles for this specific tab container
|
807 |
-
var tabs = document.querySelectorAll('[id^="result-tab-{timestamp}-"]');
|
808 |
-
tabs.forEach(function(tab) {{
|
809 |
-
tab.style.backgroundColor = '#fff';
|
810 |
-
tab.style.borderBottom = 'none';
|
811 |
-
}});
|
812 |
-
|
813 |
-
// Show selected content
|
814 |
-
var targetContent = document.getElementById('result-content-{timestamp}-' + tabIndex);
|
815 |
-
if (targetContent) {{
|
816 |
-
targetContent.style.display = 'block';
|
817 |
-
}}
|
818 |
-
|
819 |
-
// Highlight selected tab
|
820 |
-
var activeTab = document.getElementById('result-tab-{timestamp}-' + tabIndex);
|
821 |
-
if (activeTab) {{
|
822 |
-
activeTab.style.backgroundColor = '#f8f9fa';
|
823 |
-
activeTab.style.borderBottom = '3px solid #4ECDC4';
|
824 |
-
}}
|
825 |
-
}}
|
826 |
|
827 |
-
|
828 |
-
|
829 |
-
var tabs = document.querySelectorAll('[id^="result-tab-{timestamp}-"]');
|
830 |
-
tabs.forEach(function(tab, index) {{
|
831 |
-
tab.addEventListener('click', function(e) {{
|
832 |
-
e.preventDefault();
|
833 |
-
showResultTab{timestamp}(index.toString());
|
834 |
-
}});
|
835 |
-
}});
|
836 |
-
}});
|
837 |
|
838 |
-
|
839 |
-
|
840 |
-
|
841 |
-
|
842 |
-
|
843 |
-
|
844 |
-
|
845 |
-
|
846 |
-
|
847 |
-
|
848 |
-
|
849 |
-
|
850 |
-
|
851 |
-
|
852 |
-
|
853 |
-
|
854 |
-
|
855 |
-
results_display = str(tab_contents) if tab_contents else "No results to display"
|
856 |
-
|
857 |
-
return summary, highlighted, results_display
|
858 |
|
859 |
# Connect the button to the processing function
|
860 |
analyse_btn.click(
|
861 |
-
fn=
|
862 |
inputs=[
|
863 |
text_input,
|
864 |
standard_entities,
|
@@ -866,7 +762,18 @@ def create_interface():
|
|
866 |
confidence_threshold,
|
867 |
model_dropdown
|
868 |
],
|
869 |
-
outputs=[
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
870 |
)
|
871 |
|
872 |
# Add examples
|
|
|
405 |
f'title="SHARED: {tooltip}">'
|
406 |
f'{entity["text"]} π€</span>')
|
407 |
|
408 |
+
def create_entity_table_html(entities_of_type, entity_type, colour, is_shared=False):
|
409 |
+
"""Create HTML table for a specific entity type"""
|
410 |
+
if is_shared:
|
411 |
+
header = f"π€ Shared Entities ({len(entities_of_type)} found)"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
412 |
|
413 |
+
table_html = f"""
|
414 |
+
<div style="margin: 15px 0;">
|
415 |
+
<h4 style="color: {colour}; margin-bottom: 15px;">{header}</h4>
|
416 |
+
<table style="width: 100%; border-collapse: collapse; border: 1px solid #ddd;">
|
417 |
+
<thead>
|
418 |
+
<tr style="background-color: {colour}; color: white;">
|
419 |
+
<th style="padding: 12px; text-align: left; border: 1px solid #ddd;">Entity Text</th>
|
420 |
+
<th style="padding: 12px; text-align: left; border: 1px solid #ddd;">All Labels</th>
|
421 |
+
<th style="padding: 12px; text-align: left; border: 1px solid #ddd;">Sources</th>
|
422 |
+
<th style="padding: 12px; text-align: left; border: 1px solid #ddd;">Count</th>
|
423 |
+
</tr>
|
424 |
+
</thead>
|
425 |
+
<tbody>
|
426 |
+
"""
|
427 |
+
|
428 |
+
for entity in entities_of_type:
|
429 |
+
labels_text = " | ".join(entity['labels'])
|
430 |
+
sources_text = " | ".join(entity['sources'])
|
431 |
|
432 |
+
table_html += f"""
|
433 |
+
<tr style="background-color: #fff;">
|
434 |
+
<td style="padding: 10px; border: 1px solid #ddd; font-weight: bold;">{entity['text']}</td>
|
435 |
+
<td style="padding: 10px; border: 1px solid #ddd;">{labels_text}</td>
|
436 |
+
<td style="padding: 10px; border: 1px solid #ddd;">{sources_text}</td>
|
437 |
+
<td style="padding: 10px; border: 1px solid #ddd; text-align: center;">
|
438 |
+
<span style='background-color: #28a745; color: white; padding: 2px 6px; border-radius: 10px; font-size: 11px;'>
|
439 |
+
{entity['entity_count']}
|
440 |
+
</span>
|
441 |
+
</td>
|
442 |
+
</tr>
|
|
|
|
|
|
|
443 |
"""
|
444 |
+
else:
|
445 |
+
# Determine if it's common or custom
|
446 |
+
is_standard = entity_type in STANDARD_ENTITIES
|
447 |
+
icon = "π―" if is_standard else "β¨"
|
448 |
+
source_text = "Common NER" if is_standard else "Custom GLiNER"
|
449 |
+
header = f"{icon} {source_text} - {entity_type} ({len(entities_of_type)} found)"
|
450 |
+
|
451 |
+
table_html = f"""
|
452 |
+
<div style="margin: 15px 0;">
|
453 |
+
<h4 style="color: {colour}; margin-bottom: 15px;">{header}</h4>
|
454 |
+
<table style="width: 100%; border-collapse: collapse; border: 1px solid #ddd;">
|
455 |
+
<thead>
|
456 |
+
<tr style="background-color: {colour}; color: white;">
|
457 |
+
<th style="padding: 12px; text-align: left; border: 1px solid #ddd;">Entity Text</th>
|
458 |
+
<th style="padding: 12px; text-align: left; border: 1px solid #ddd;">Confidence</th>
|
459 |
+
<th style="padding: 12px; text-align: left; border: 1px solid #ddd;">Type</th>
|
460 |
+
<th style="padding: 12px; text-align: left; border: 1px solid #ddd;">Source</th>
|
461 |
+
</tr>
|
462 |
+
</thead>
|
463 |
+
<tbody>
|
464 |
+
"""
|
465 |
+
|
466 |
+
# Sort by confidence score
|
467 |
+
entities_of_type.sort(key=lambda x: x.get('confidence', 0), reverse=True)
|
468 |
+
|
469 |
+
for entity in entities_of_type:
|
470 |
+
confidence = entity.get('confidence', 0.0)
|
471 |
+
confidence_colour = "#28a745" if confidence > 0.7 else "#ffc107" if confidence > 0.4 else "#dc3545"
|
472 |
+
source = entity.get('source', 'Unknown')
|
473 |
+
source_badge = f"<span style='background-color: #007bff; color: white; padding: 2px 6px; border-radius: 10px; font-size: 11px;'>{source}</span>"
|
474 |
|
475 |
+
table_html += f"""
|
476 |
+
<tr style="background-color: #fff;">
|
477 |
+
<td style="padding: 10px; border: 1px solid #ddd; font-weight: bold;">{entity['text']}</td>
|
478 |
+
<td style="padding: 10px; border: 1px solid #ddd;">
|
479 |
+
<span style="color: {confidence_colour}; font-weight: bold;">
|
480 |
+
{confidence:.3f}
|
481 |
+
</span>
|
482 |
+
</td>
|
483 |
+
<td style="padding: 10px; border: 1px solid #ddd;">{entity['label']}</td>
|
484 |
+
<td style="padding: 10px; border: 1px solid #ddd;">{source_badge}</td>
|
485 |
+
</tr>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
486 |
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
487 |
|
488 |
+
table_html += "</tbody></table></div>"
|
489 |
+
return table_html
|
490 |
|
491 |
def create_legend_html(entity_colors, standard_entities, custom_entities):
|
492 |
"""Create a legend showing entity colours"""
|
|
|
523 |
def process_text(text, standard_entities, custom_entities_str, confidence_threshold, selected_model, progress=gr.Progress()):
|
524 |
"""Main processing function for Gradio interface with progress tracking"""
|
525 |
if not text.strip():
|
526 |
+
return "β Please enter some text to analyse", "", None, None, None, None, None, None, None, None
|
527 |
|
528 |
progress(0.1, desc="Initialising...")
|
529 |
|
|
|
536 |
selected_standard = [entity for entity in standard_entities if entity]
|
537 |
|
538 |
if not selected_standard and not custom_entities:
|
539 |
+
return "β Please select at least one common entity type OR enter custom entity types", "", None, None, None, None, None, None, None, None
|
540 |
|
541 |
progress(0.2, desc="Loading models...")
|
542 |
|
|
|
555 |
all_entities.extend(custom_entity_results)
|
556 |
|
557 |
if not all_entities:
|
558 |
+
return "β No entities found. Try lowering the confidence threshold or using different entity types.", "", None, None, None, None, None, None, None, None
|
559 |
|
560 |
progress(0.8, desc="Processing results...")
|
561 |
|
|
|
565 |
# Create outputs
|
566 |
legend_html = create_legend_html(entity_colors, selected_standard, custom_entities)
|
567 |
highlighted_html = create_highlighted_html(text, all_entities, entity_colors)
|
568 |
+
|
569 |
+
# Share overlapping entities
|
570 |
+
shared_entities = find_overlapping_entities(all_entities)
|
571 |
+
|
572 |
+
# Group entities by type
|
573 |
+
entity_groups = {}
|
574 |
+
for entity in shared_entities:
|
575 |
+
if entity.get('is_shared', False):
|
576 |
+
key = 'SHARED_ENTITIES'
|
577 |
+
else:
|
578 |
+
key = entity['label']
|
579 |
+
|
580 |
+
if key not in entity_groups:
|
581 |
+
entity_groups[key] = []
|
582 |
+
entity_groups[key].append(entity)
|
583 |
|
584 |
progress(0.9, desc="Creating summary...")
|
585 |
|
586 |
+
# Create summary
|
|
|
587 |
total_entities = len(all_entities)
|
|
|
588 |
final_count = len(shared_entities)
|
589 |
shared_count = sum(1 for e in shared_entities if e.get('is_shared', False))
|
590 |
|
|
|
598 |
|
599 |
progress(1.0, desc="Complete!")
|
600 |
|
601 |
+
# Create HTML tables for each entity type
|
602 |
+
tables = {}
|
603 |
+
|
604 |
+
# Create table for shared entities if any
|
605 |
+
if 'SHARED_ENTITIES' in entity_groups:
|
606 |
+
tables['shared'] = create_entity_table_html(entity_groups['SHARED_ENTITIES'], 'SHARED_ENTITIES', '#666666', is_shared=True)
|
607 |
+
else:
|
608 |
+
tables['shared'] = None
|
609 |
+
|
610 |
+
# Create tables for other entity types (up to 7 for the interface)
|
611 |
+
entity_types = [k for k in entity_groups.keys() if k != 'SHARED_ENTITIES']
|
612 |
+
for i in range(7):
|
613 |
+
if i < len(entity_types):
|
614 |
+
entity_type = entity_types[i]
|
615 |
+
colour = entity_colors.get(entity_type.upper(), '#f0f0f0')
|
616 |
+
tables[f'tab{i+1}'] = create_entity_table_html(entity_groups[entity_type], entity_type, colour)
|
617 |
+
else:
|
618 |
+
tables[f'tab{i+1}'] = None
|
619 |
+
|
620 |
+
return (summary, legend_html + highlighted_html,
|
621 |
+
tables.get('shared'), tables.get('tab1'), tables.get('tab2'),
|
622 |
+
tables.get('tab3'), tables.get('tab4'), tables.get('tab5'),
|
623 |
+
tables.get('tab6'), tables.get('tab7'))
|
624 |
|
625 |
# Create Gradio interface
|
626 |
def create_interface():
|
|
|
721 |
with gr.Row():
|
722 |
highlighted_output = gr.HTML(label="Highlighted Text")
|
723 |
|
724 |
+
# Results section with native Gradio tabs
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
725 |
with gr.Row():
|
726 |
with gr.Column():
|
727 |
gr.Markdown("### π Detailed Results")
|
728 |
|
729 |
+
with gr.Tabs() as results_tabs:
|
730 |
+
# Pre-create tabs for different entity types
|
731 |
+
with gr.Tab("π€ Shared", visible=False) as shared_tab:
|
732 |
+
shared_output = gr.HTML()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
733 |
|
734 |
+
with gr.Tab("Entity Type 1", visible=False) as tab1:
|
735 |
+
tab1_output = gr.HTML()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
736 |
|
737 |
+
with gr.Tab("Entity Type 2", visible=False) as tab2:
|
738 |
+
tab2_output = gr.HTML()
|
739 |
+
|
740 |
+
with gr.Tab("Entity Type 3", visible=False) as tab3:
|
741 |
+
tab3_output = gr.HTML()
|
742 |
+
|
743 |
+
with gr.Tab("Entity Type 4", visible=False) as tab4:
|
744 |
+
tab4_output = gr.HTML()
|
745 |
+
|
746 |
+
with gr.Tab("Entity Type 5", visible=False) as tab5:
|
747 |
+
tab5_output = gr.HTML()
|
748 |
+
|
749 |
+
with gr.Tab("Entity Type 6", visible=False) as tab6:
|
750 |
+
tab6_output = gr.HTML()
|
751 |
+
|
752 |
+
with gr.Tab("Entity Type 7", visible=False) as tab7:
|
753 |
+
tab7_output = gr.HTML()
|
|
|
|
|
|
|
754 |
|
755 |
# Connect the button to the processing function
|
756 |
analyse_btn.click(
|
757 |
+
fn=process_text,
|
758 |
inputs=[
|
759 |
text_input,
|
760 |
standard_entities,
|
|
|
762 |
confidence_threshold,
|
763 |
model_dropdown
|
764 |
],
|
765 |
+
outputs=[
|
766 |
+
summary_output,
|
767 |
+
highlighted_output,
|
768 |
+
shared_output,
|
769 |
+
tab1_output,
|
770 |
+
tab2_output,
|
771 |
+
tab3_output,
|
772 |
+
tab4_output,
|
773 |
+
tab5_output,
|
774 |
+
tab6_output,
|
775 |
+
tab7_output
|
776 |
+
]
|
777 |
)
|
778 |
|
779 |
# Add examples
|