Spaces:
Running
Running
Update templates/result.html
Browse files- templates/result.html +242 -470
templates/result.html
CHANGED
@@ -404,13 +404,13 @@
|
|
404 |
</head>
|
405 |
<body>
|
406 |
<!-- Header with logo and title -->
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
<img src="https://huggingface.co/spaces/aetheris-ai/aibom-generator/resolve/main/templates/images/AetherisAI-logo.png" alt="Aetheris AI Logo" style="height: 60px;">
|
411 |
-
|
412 |
<h1 style="margin: 0;">AI SBOM Generator</h1>
|
413 |
-
</div>
|
414 |
</div>
|
415 |
|
416 |
<div class="container">
|
@@ -424,10 +424,10 @@
|
|
424 |
{% if enhancement_report and enhancement_report.ai_enhanced %}
|
425 |
<div class="improvement">
|
426 |
<h3>AI Enhancement Results</h3>
|
427 |
-
<p>This AI SBOM was enhanced using <strong>{{ enhancement_report.ai_model
|
428 |
-
<p>Original Score: {{ enhancement_report.original_score.total_score|
|
429 |
-
<p>Enhanced Score: {{ enhancement_report.final_score.total_score|
|
430 |
-
<p>Improvement: <span class="improvement-value">+{{ enhancement_report.improvement|
|
431 |
</div>
|
432 |
{% endif %}
|
433 |
|
@@ -483,24 +483,17 @@
|
|
483 |
<div class="property-name">Model Parameters:</div>
|
484 |
<div class="property-value">
|
485 |
{% if aibom.components[0].modelCard.modelParameters.properties %}
|
|
|
486 |
{% for prop in aibom.components[0].modelCard.modelParameters.properties %}
|
487 |
-
|
488 |
{% endfor %}
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
{% endif %}
|
495 |
-
|
496 |
-
{% if aibom.components[0].modelCard.quantitativeAnalysis %}
|
497 |
-
<div class="aibom-property">
|
498 |
-
<div class="property-name">Performance Metrics:</div>
|
499 |
-
<div class="property-value">
|
500 |
-
{% if aibom.components[0].modelCard.quantitativeAnalysis.performanceMetrics %}
|
501 |
-
{% for metric in aibom.components[0].modelCard.quantitativeAnalysis.performanceMetrics %}
|
502 |
-
<div><strong>{{ metric.type if metric.type else 'Metric' }}:</strong> {{ metric.value if metric.value else 'Not specified' }}</div>
|
503 |
{% endfor %}
|
|
|
504 |
{% endif %}
|
505 |
</div>
|
506 |
</div>
|
@@ -510,228 +503,34 @@
|
|
510 |
<div class="aibom-property">
|
511 |
<div class="property-name">Considerations:</div>
|
512 |
<div class="property-value">
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
{% endif %}
|
519 |
-
{% if aibom.components[0].modelCard.considerations.tradeoffs %}
|
520 |
-
<div><strong>Tradeoffs:</strong> {{ aibom.components[0].modelCard.considerations.tradeoffs }}</div>
|
521 |
-
{% endif %}
|
522 |
-
</div>
|
523 |
-
</div>
|
524 |
-
{% endif %}
|
525 |
-
</div>
|
526 |
-
</div>
|
527 |
-
{% endif %}
|
528 |
-
|
529 |
-
<!-- Training Data Section -->
|
530 |
-
{% if aibom.components and aibom.components[0].trainingData %}
|
531 |
-
<div class="aibom-section">
|
532 |
-
<h4 class="collapsible" onclick="toggleCollapsible(this)">Training Data</h4>
|
533 |
-
<div class="collapsible-content">
|
534 |
-
{% if aibom.components[0].trainingData.datasets %}
|
535 |
-
<div class="aibom-property">
|
536 |
-
<div class="property-name">Datasets:</div>
|
537 |
-
<div class="property-value">
|
538 |
-
{% for dataset in aibom.components[0].trainingData.datasets %}
|
539 |
-
<div>
|
540 |
-
<strong>{{ dataset.name if dataset.name else 'Dataset' }}:</strong>
|
541 |
-
{% if dataset.description %} {{ dataset.description }}{% endif %}
|
542 |
-
{% if dataset.url %} <a href="{{ dataset.url }}" target="_blank">Link</a>{% endif %}
|
543 |
-
</div>
|
544 |
-
{% endfor %}
|
545 |
-
</div>
|
546 |
-
</div>
|
547 |
-
{% endif %}
|
548 |
-
|
549 |
-
{% if aibom.components[0].trainingData.preprocessing %}
|
550 |
-
<div class="aibom-property">
|
551 |
-
<div class="property-name">Preprocessing:</div>
|
552 |
-
<div class="property-value">{{ aibom.components[0].trainingData.preprocessing }}</div>
|
553 |
-
</div>
|
554 |
-
{% endif %}
|
555 |
-
</div>
|
556 |
-
</div>
|
557 |
-
{% endif %}
|
558 |
-
|
559 |
-
<!-- Training Process Section -->
|
560 |
-
{% if aibom.components and aibom.components[0].trainingProcess %}
|
561 |
-
<div class="aibom-section">
|
562 |
-
<h4 class="collapsible" onclick="toggleCollapsible(this)">Training Process</h4>
|
563 |
-
<div class="collapsible-content">
|
564 |
-
{% if aibom.components[0].trainingProcess.trainingMethod %}
|
565 |
-
<div class="aibom-property">
|
566 |
-
<div class="property-name">Training Method:</div>
|
567 |
-
<div class="property-value">{{ aibom.components[0].trainingProcess.trainingMethod }}</div>
|
568 |
-
</div>
|
569 |
-
{% endif %}
|
570 |
-
|
571 |
-
{% if aibom.components[0].trainingProcess.hyperparameters %}
|
572 |
-
<div class="aibom-property">
|
573 |
-
<div class="property-name">Hyperparameters:</div>
|
574 |
-
<div class="property-value">
|
575 |
-
{% for param in aibom.components[0].trainingProcess.hyperparameters %}
|
576 |
-
<div><strong>{{ param.name }}:</strong> {{ param.value }}</div>
|
577 |
-
{% endfor %}
|
578 |
-
</div>
|
579 |
-
</div>
|
580 |
-
{% endif %}
|
581 |
-
|
582 |
-
{% if aibom.components[0].trainingProcess.computeInfrastructure %}
|
583 |
-
<div class="aibom-property">
|
584 |
-
<div class="property-name">Compute Infrastructure:</div>
|
585 |
-
<div class="property-value">{{ aibom.components[0].trainingProcess.computeInfrastructure }}</div>
|
586 |
-
</div>
|
587 |
-
{% endif %}
|
588 |
-
</div>
|
589 |
-
</div>
|
590 |
-
{% endif %}
|
591 |
-
|
592 |
-
<!-- Evaluation Section -->
|
593 |
-
{% if aibom.components and aibom.components[0].evaluation %}
|
594 |
-
<div class="aibom-section">
|
595 |
-
<h4 class="collapsible" onclick="toggleCollapsible(this)">Evaluation</h4>
|
596 |
-
<div class="collapsible-content">
|
597 |
-
{% if aibom.components[0].evaluation.metrics %}
|
598 |
-
<div class="aibom-property">
|
599 |
-
<div class="property-name">Metrics:</div>
|
600 |
-
<div class="property-value">
|
601 |
-
{% for metric in aibom.components[0].evaluation.metrics %}
|
602 |
-
<div><strong>{{ metric.name }}:</strong> {{ metric.value }}</div>
|
603 |
-
{% endfor %}
|
604 |
-
</div>
|
605 |
-
</div>
|
606 |
-
{% endif %}
|
607 |
-
|
608 |
-
{% if aibom.components[0].evaluation.datasets %}
|
609 |
-
<div class="aibom-property">
|
610 |
-
<div class="property-name">Evaluation Datasets:</div>
|
611 |
-
<div class="property-value">
|
612 |
-
{% for dataset in aibom.components[0].evaluation.datasets %}
|
613 |
-
<div>
|
614 |
-
<strong>{{ dataset.name if dataset.name else 'Dataset' }}:</strong>
|
615 |
-
{% if dataset.description %} {{ dataset.description }}{% endif %}
|
616 |
-
{% if dataset.url %} <a href="{{ dataset.url }}" target="_blank">Link</a>{% endif %}
|
617 |
-
</div>
|
618 |
-
{% endfor %}
|
619 |
</div>
|
620 |
</div>
|
621 |
{% endif %}
|
622 |
</div>
|
623 |
</div>
|
624 |
{% endif %}
|
625 |
-
|
626 |
-
<!-- Usage Section -->
|
627 |
-
{% if aibom.components and aibom.components[0].usage %}
|
628 |
-
<div class="aibom-section">
|
629 |
-
<h4 class="collapsible" onclick="toggleCollapsible(this)">Usage</h4>
|
630 |
-
<div class="collapsible-content">
|
631 |
-
{% if aibom.components[0].usage.intendedUse %}
|
632 |
-
<div class="aibom-property">
|
633 |
-
<div class="property-name">Intended Use:</div>
|
634 |
-
<div class="property-value">{{ aibom.components[0].usage.intendedUse }}</div>
|
635 |
-
</div>
|
636 |
-
{% endif %}
|
637 |
-
|
638 |
-
{% if aibom.components[0].usage.outOfScopeUses %}
|
639 |
-
<div class="aibom-property">
|
640 |
-
<div class="property-name">Out of Scope Uses:</div>
|
641 |
-
<div class="property-value">{{ aibom.components[0].usage.outOfScopeUses }}</div>
|
642 |
-
</div>
|
643 |
-
{% endif %}
|
644 |
-
|
645 |
-
{% if aibom.components[0].usage.guidelines %}
|
646 |
-
<div class="aibom-property">
|
647 |
-
<div class="property-name">Usage Guidelines:</div>
|
648 |
-
<div class="property-value">{{ aibom.components[0].usage.guidelines }}</div>
|
649 |
-
</div>
|
650 |
-
{% endif %}
|
651 |
-
</div>
|
652 |
-
</div>
|
653 |
-
{% endif %}
|
654 |
-
|
655 |
-
<!-- Licenses Section -->
|
656 |
-
{% if aibom.components and aibom.components[0].licenses %}
|
657 |
-
<div class="aibom-section">
|
658 |
-
<h4 class="collapsible" onclick="toggleCollapsible(this)">Licenses</h4>
|
659 |
-
<div class="collapsible-content">
|
660 |
-
{% for license in aibom.components[0].licenses %}
|
661 |
-
<div class="aibom-property">
|
662 |
-
<div class="property-name">License:</div>
|
663 |
-
<div class="property-value">
|
664 |
-
<strong>{{ license.name }}</strong>
|
665 |
-
{% if license.url %} <a href="{{ license.url }}" target="_blank">Link</a>{% endif %}
|
666 |
-
</div>
|
667 |
-
</div>
|
668 |
-
{% endfor %}
|
669 |
-
</div>
|
670 |
-
</div>
|
671 |
-
{% endif %}
|
672 |
|
673 |
-
<!-- Metadata Section -->
|
674 |
-
{% if aibom.metadata %}
|
675 |
-
<div class="aibom-section">
|
676 |
-
<h4 class="collapsible" onclick="toggleCollapsible(this)">Metadata</h4>
|
677 |
-
<div class="collapsible-content">
|
678 |
-
{% if aibom.metadata.timestamp %}
|
679 |
-
<div class="aibom-property">
|
680 |
-
<div class="property-name">Timestamp:</div>
|
681 |
-
<div class="property-value">{{ aibom.metadata.timestamp }}</div>
|
682 |
-
</div>
|
683 |
-
{% endif %}
|
684 |
-
|
685 |
-
{% if aibom.metadata.tools %}
|
686 |
-
<div class="aibom-property">
|
687 |
-
<div class="property-name">Tools:</div>
|
688 |
-
<div class="property-value">
|
689 |
-
{% for tool in aibom.metadata.tools %}
|
690 |
-
<div>{{ tool.name }} {% if tool.version %}({{ tool.version }}){% endif %}</div>
|
691 |
-
{% endfor %}
|
692 |
-
</div>
|
693 |
-
</div>
|
694 |
-
{% endif %}
|
695 |
-
|
696 |
-
{% if aibom.metadata.authors %}
|
697 |
-
<div class="aibom-property">
|
698 |
-
<div class="property-name">Authors:</div>
|
699 |
-
<div class="property-value">
|
700 |
-
{% for author in aibom.metadata.authors %}
|
701 |
-
<div>{{ author.name }} {% if author.email %}({{ author.email }}){% endif %}</div>
|
702 |
-
{% endfor %}
|
703 |
-
</div>
|
704 |
-
</div>
|
705 |
-
{% endif %}
|
706 |
-
|
707 |
-
{% if aibom.metadata.properties %}
|
708 |
-
<div class="aibom-property">
|
709 |
-
<div class="property-name">Properties:</div>
|
710 |
-
<div class="property-value">
|
711 |
-
{% for prop in aibom.metadata.properties %}
|
712 |
-
<div><strong>{{ prop.name }}:</strong> {{ prop.value }}</div>
|
713 |
-
{% endfor %}
|
714 |
-
</div>
|
715 |
-
</div>
|
716 |
-
{% endif %}
|
717 |
-
</div>
|
718 |
-
</div>
|
719 |
-
{% endif %}
|
720 |
-
|
721 |
<!-- External References Section -->
|
722 |
{% if aibom.components and aibom.components[0].externalReferences %}
|
723 |
<div class="aibom-section">
|
724 |
<h4 class="collapsible" onclick="toggleCollapsible(this)">External References</h4>
|
725 |
<div class="collapsible-content">
|
726 |
-
|
727 |
-
|
728 |
-
<
|
729 |
-
|
730 |
<a href="{{ ref.url }}" target="_blank">{{ ref.url }}</a>
|
731 |
-
{% if ref.comment %}
|
732 |
-
|
733 |
-
|
734 |
-
|
|
|
|
|
735 |
</div>
|
736 |
</div>
|
737 |
{% endif %}
|
@@ -763,52 +562,47 @@
|
|
763 |
</div>
|
764 |
</div>
|
765 |
|
766 |
-
{% if completeness_score and completeness_score.field_checklist %}
|
767 |
<ul>
|
768 |
{% for field, status in completeness_score.field_checklist.items() %}
|
769 |
{% if "✔" in status %}
|
770 |
-
<li
|
771 |
-
<span class="check-mark"
|
772 |
<span class="field-name">{{ field }}</span>
|
|
|
773 |
{% if completeness_score.field_tiers and field in completeness_score.field_tiers %}
|
774 |
<span class="field-tier tier-{{ completeness_score.field_tiers[field] }}"></span>
|
775 |
{% endif %}
|
776 |
</li>
|
777 |
{% else %}
|
778 |
-
<li
|
779 |
-
<span class="x-mark"
|
780 |
<span class="field-name">{{ field }}</span>
|
|
|
781 |
{% if completeness_score.field_tiers and field in completeness_score.field_tiers %}
|
782 |
<span class="field-tier tier-{{ completeness_score.field_tiers[field] }}"></span>
|
783 |
{% endif %}
|
784 |
|
785 |
{% if field == "component.description" %}
|
786 |
-
<span class="importance-indicator high-importance field-stars">★★★</span>
|
787 |
<span class="tooltip">(?)
|
788 |
<span class="tooltiptext">A detailed description of the model is essential for users to understand its purpose and capabilities. Add a description that is at least 20 characters long.</span>
|
789 |
</span>
|
790 |
{% elif field == "component.purl" %}
|
791 |
-
<span class="importance-indicator high-importance field-stars">★★★</span>
|
792 |
<span class="tooltip">(?)
|
793 |
<span class="tooltiptext">Package URL (PURL) is critical for uniquely identifying the model. It should follow the format pkg:huggingface/[owner]/[name]@[version].</span>
|
794 |
</span>
|
795 |
{% elif field == "modelCard.modelParameters" %}
|
796 |
-
<span class="importance-indicator high-importance field-stars">★★★</span>
|
797 |
<span class="tooltip">(?)
|
798 |
<span class="tooltiptext">Model parameters provide essential technical details about the model architecture, training, and capabilities.</span>
|
799 |
</span>
|
800 |
{% elif field == "modelCard.considerations" %}
|
801 |
-
<span class="importance-indicator medium-importance field-stars">★★</span>
|
802 |
<span class="tooltip">(?)
|
803 |
<span class="tooltiptext">Considerations section should include ethical considerations, limitations, and risks associated with the model.</span>
|
804 |
</span>
|
805 |
{% elif field == "externalReferences" %}
|
806 |
-
<span class="importance-indicator medium-importance field-stars">★★</span>
|
807 |
<span class="tooltip">(?)
|
808 |
<span class="tooltiptext">External references provide links to additional resources like model cards, repositories, and datasets.</span>
|
809 |
</span>
|
810 |
{% else %}
|
811 |
-
<span class="importance-indicator low-importance field-stars">★</span>
|
812 |
<span class="tooltip">(?)
|
813 |
<span class="tooltiptext">This field contributes to the completeness of your AI SBOM.</span>
|
814 |
</span>
|
@@ -817,77 +611,34 @@
|
|
817 |
{% endif %}
|
818 |
{% endfor %}
|
819 |
</ul>
|
820 |
-
{% else %}
|
821 |
-
<p>Field checklist information is not available for this AI SBOM.</p>
|
822 |
-
{% endif %}
|
823 |
</div>
|
824 |
|
825 |
<div id="score-view" class="tab-content">
|
826 |
<h3>AI SBOM Completeness Score</h3>
|
827 |
|
828 |
<!-- Completeness Profile Section -->
|
829 |
-
{% if completeness_score
|
830 |
<div class="completeness-profile">
|
831 |
<h4>Completeness Profile:
|
832 |
-
<span class="profile-badge profile-{{ completeness_score.completeness_profile.name|
|
833 |
-
{{ completeness_score.completeness_profile.name
|
834 |
</span>
|
835 |
</h4>
|
836 |
-
<p>{{ completeness_score.completeness_profile.description
|
837 |
|
838 |
{% if completeness_score.completeness_profile.next_level %}
|
839 |
<p><strong>Next level:</strong> {{ completeness_score.completeness_profile.next_level.name }}
|
840 |
({{ completeness_score.completeness_profile.next_level.missing_fields_count }} fields to add)</p>
|
841 |
{% endif %}
|
842 |
</div>
|
843 |
-
{% elif enhancement_report %}
|
844 |
-
<div class="completeness-profile">
|
845 |
-
<h4>Completeness Profile:
|
846 |
-
{% set score = enhancement_report.final_score.total_score|default(0) %}
|
847 |
-
{% if score >= 80 %}
|
848 |
-
<span class="profile-badge profile-advanced">Advanced</span>
|
849 |
-
{% elif score >= 60 %}
|
850 |
-
<span class="profile-badge profile-standard">Standard</span>
|
851 |
-
{% elif score >= 40 %}
|
852 |
-
<span class="profile-badge profile-basic">Basic</span>
|
853 |
-
{% else %}
|
854 |
-
<span class="profile-badge profile-incomplete">Incomplete</span>
|
855 |
-
{% endif %}
|
856 |
-
</h4>
|
857 |
-
<p>
|
858 |
-
{% if score >= 80 %}
|
859 |
-
This AI SBOM provides comprehensive information about the model, including detailed training data, process, evaluation metrics, and usage guidelines. It meets advanced transparency requirements.
|
860 |
-
{% elif score >= 60 %}
|
861 |
-
This AI SBOM provides good information about the model, covering most key aspects of its development and usage. It meets standard transparency requirements.
|
862 |
-
{% elif score >= 40 %}
|
863 |
-
This AI SBOM provides basic information about the model but lacks detail in several areas. It meets minimal transparency requirements.
|
864 |
-
{% else %}
|
865 |
-
This AI SBOM is incomplete and missing critical information. It does not meet basic transparency requirements.
|
866 |
-
{% endif %}
|
867 |
-
</p>
|
868 |
-
</div>
|
869 |
{% endif %}
|
870 |
|
871 |
<!-- Total Score with Progress Bar -->
|
872 |
<div class="total-score-container">
|
873 |
-
{
|
874 |
-
<div class="total-score">{{ completeness_score.total_score|default(0)|round(1) }}/100</div>
|
875 |
-
{% elif enhancement_report %}
|
876 |
-
<div class="total-score">{{ enhancement_report.final_score.total_score|default(0)|round(1) }}/100</div>
|
877 |
-
{% else %}
|
878 |
-
<div class="total-score">0/100</div>
|
879 |
-
{% endif %}
|
880 |
-
|
881 |
<div class="total-progress">
|
882 |
<div class="progress-container">
|
883 |
-
{%
|
884 |
-
{% set score_percent = (completeness_score.total_score|default(0) / 100) * 100 %}
|
885 |
-
{% elif enhancement_report %}
|
886 |
-
{% set score_percent = (enhancement_report.final_score.total_score|default(0) / 100) * 100 %}
|
887 |
-
{% else %}
|
888 |
-
{% set score_percent = 0 %}
|
889 |
-
{% endif %}
|
890 |
-
|
891 |
{% set score_class = 'progress-poor' %}
|
892 |
{% set score_label = 'Poor' %}
|
893 |
|
@@ -903,18 +654,14 @@
|
|
903 |
{% endif %}
|
904 |
|
905 |
<div class="progress-bar {{ score_class }}" style="width: {{ score_percent }}%">
|
906 |
-
{{ score_percent|int }}%
|
907 |
</div>
|
908 |
</div>
|
909 |
</div>
|
910 |
-
|
911 |
-
{% if completeness_score and completeness_score.validation_penalty %}
|
912 |
-
<div style="margin-left: 15px; color: #f44336;">{{ completeness_score.validation_penalty }}</div>
|
913 |
-
{% endif %}
|
914 |
</div>
|
915 |
|
916 |
<!-- Validation Penalty Explanation -->
|
917 |
-
{% if completeness_score
|
918 |
<div class="validation-penalty-info">
|
919 |
<h4>About the Validation Penalty</h4>
|
920 |
<p>Your score includes a penalty because the AIBOM has schema validation issues. These are structural problems that don't comply with the CycloneDX specification requirements.</p>
|
@@ -922,47 +669,7 @@
|
|
922 |
</div>
|
923 |
{% endif %}
|
924 |
|
925 |
-
<!-- Scoring Rubric -->
|
926 |
-
<div class="scoring-rubric">
|
927 |
-
<h4>Scoring Rubric</h4>
|
928 |
-
<p>The AI SBOM completeness score is calculated based on the following criteria:</p>
|
929 |
-
<table>
|
930 |
-
<tr>
|
931 |
-
<th>Category</th>
|
932 |
-
<th>Weight</th>
|
933 |
-
<th>Description</th>
|
934 |
-
</tr>
|
935 |
-
<tr>
|
936 |
-
<td>Basic Information</td>
|
937 |
-
<td>20%</td>
|
938 |
-
<td>Model name, type, version, and description</td>
|
939 |
-
</tr>
|
940 |
-
<tr>
|
941 |
-
<td>Training Data</td>
|
942 |
-
<td>25%</td>
|
943 |
-
<td>Datasets used for training and preprocessing steps</td>
|
944 |
-
</tr>
|
945 |
-
<tr>
|
946 |
-
<td>Training Process</td>
|
947 |
-
<td>20%</td>
|
948 |
-
<td>Training method, hyperparameters, and compute infrastructure</td>
|
949 |
-
</tr>
|
950 |
-
<tr>
|
951 |
-
<td>Evaluation</td>
|
952 |
-
<td>15%</td>
|
953 |
-
<td>Evaluation metrics and datasets</td>
|
954 |
-
</tr>
|
955 |
-
<tr>
|
956 |
-
<td>Usage & Licensing</td>
|
957 |
-
<td>20%</td>
|
958 |
-
<td>Intended use, out-of-scope uses, and licensing information</td>
|
959 |
-
</tr>
|
960 |
-
</table>
|
961 |
-
<p>Each category is scored based on the presence and quality of relevant fields. The final score is a weighted average of all categories.</p>
|
962 |
-
</div>
|
963 |
-
|
964 |
<!-- Section Scores with Progress Bars and Tooltips -->
|
965 |
-
{% if completeness_score and completeness_score.section_scores %}
|
966 |
<table class="score-table">
|
967 |
<thead>
|
968 |
<tr>
|
@@ -991,16 +698,16 @@
|
|
991 |
{% for section, score in completeness_score.section_scores.items() %}
|
992 |
<tr>
|
993 |
<td>
|
994 |
-
{{ display_names[section]
|
995 |
<span class="tooltip">(?)
|
996 |
-
<span class="tooltiptext">{{ tooltips[section]
|
997 |
</span>
|
998 |
</td>
|
999 |
-
<td>{{ score|
|
1000 |
-
<td>{{ weights[section]
|
1001 |
<td style="width: 50%;">
|
1002 |
<div class="progress-container">
|
1003 |
-
{% set percent = (score
|
1004 |
{% set class = 'progress-poor' %}
|
1005 |
|
1006 |
{% if percent >= 90 %}
|
@@ -1020,165 +727,230 @@
|
|
1020 |
{% endfor %}
|
1021 |
</tbody>
|
1022 |
</table>
|
1023 |
-
{% endif %}
|
1024 |
|
1025 |
-
<!--
|
1026 |
-
|
1027 |
-
|
1028 |
-
|
1029 |
-
|
1030 |
-
<
|
1031 |
-
|
1032 |
-
|
1033 |
-
|
1034 |
-
|
1035 |
-
|
1036 |
-
|
1037 |
-
|
1038 |
-
|
1039 |
-
|
1040 |
-
|
1041 |
-
|
1042 |
-
|
1043 |
-
|
1044 |
-
|
1045 |
-
|
1046 |
-
|
1047 |
-
|
1048 |
-
|
1049 |
-
|
1050 |
-
|
1051 |
-
|
1052 |
-
|
1053 |
-
|
1054 |
-
|
1055 |
{% endif %}
|
|
|
|
|
|
|
1056 |
{% endif %}
|
1057 |
-
|
1058 |
-
|
1059 |
-
|
1060 |
-
|
1061 |
-
|
1062 |
-
|
1063 |
-
|
1064 |
-
|
1065 |
-
|
1066 |
-
|
1067 |
-
|
1068 |
-
|
1069 |
-
|
1070 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1071 |
|
1072 |
-
|
1073 |
-
|
1074 |
-
<li>
|
1075 |
-
|
1076 |
-
|
1077 |
-
|
1078 |
-
<li>Add model parameters section with architecture, size, and training details</li>
|
1079 |
-
{% endif %}
|
1080 |
-
{% if "modelCard.quantitativeAnalysis" not in completeness_score.field_checklist or completeness_score.field_checklist["modelCard.quantitativeAnalysis"] != "✔" %}
|
1081 |
-
<li>Add quantitative analysis with performance metrics</li>
|
1082 |
-
{% endif %}
|
1083 |
-
{% if "modelCard.considerations" not in completeness_score.field_checklist or completeness_score.field_checklist["modelCard.considerations"] != "✔" %}
|
1084 |
-
<li>Add ethical considerations, limitations, and tradeoffs</li>
|
1085 |
-
{% endif %}
|
1086 |
-
</ul>
|
1087 |
-
</li>
|
1088 |
-
{% endif %}
|
1089 |
|
1090 |
-
|
1091 |
-
|
1092 |
-
<li>
|
1093 |
-
|
1094 |
-
|
1095 |
-
|
1096 |
-
<li>Add a detailed description of the model (at least 20 characters)</li>
|
1097 |
-
{% endif %}
|
1098 |
-
{% if "component.purl" not in completeness_score.field_checklist or completeness_score.field_checklist["component.purl"] != "✔" %}
|
1099 |
-
<li>Add a valid PURL in the format pkg:huggingface/[owner]/[name]@[version]</li>
|
1100 |
-
{% endif %}
|
1101 |
-
{% if "component.licenses" not in completeness_score.field_checklist or completeness_score.field_checklist["component.licenses"] != "✔" %}
|
1102 |
-
<li>Add licensing information</li>
|
1103 |
-
{% endif %}
|
1104 |
-
</ul>
|
1105 |
-
</li>
|
1106 |
-
{% endif %}
|
1107 |
|
1108 |
-
{% if
|
1109 |
-
|
1110 |
-
{% endif %}
|
1111 |
-
</ol>
|
1112 |
-
</div>
|
1113 |
-
{% endif %}
|
1114 |
-
|
1115 |
-
<!-- Score Calculation Explanation -->
|
1116 |
-
<div class="score-calculation">
|
1117 |
-
<h3>How Your Score Is Calculated</h3>
|
1118 |
-
<div class="calculation-section">
|
1119 |
-
<h4>Completeness Score ({{ completeness_score.total_score|default(enhancement_report.final_score.total_score|default(0))|round(1) }}/100)</h4>
|
1120 |
-
<p>Your AI SBOM completeness score measures how thoroughly you've documented your AI model. The score is calculated by evaluating the presence and quality of key information across several categories.</p>
|
1121 |
-
<p>Each field in your AI SBOM contributes to the overall score, with critical fields having the highest weight. Missing critical fields significantly impact your score.</p>
|
1122 |
-
</div>
|
1123 |
-
|
1124 |
-
<div class="calculation-section">
|
1125 |
-
<h4>Field Importance Tiers</h4>
|
1126 |
<ul>
|
1127 |
-
<li
|
1128 |
-
<li
|
1129 |
-
<li><strong>Supplementary fields (★):</strong> Additional information that provides more context about the model</li>
|
1130 |
</ul>
|
|
|
1131 |
</div>
|
1132 |
-
|
1133 |
-
{% if enhancement_report and enhancement_report.ai_enhanced %}
|
1134 |
-
<div class="calculation-section">
|
1135 |
-
<h4>AI Enhancement</h4>
|
1136 |
-
<p>The AI enhancement process improved your original SBOM by adding missing information and enriching existing fields. The improvement of {{ enhancement_report.improvement|default(0)|round(1) }} points represents the difference between your original score ({{ enhancement_report.original_score.total_score|default(0)|round(1) }}) and your enhanced score ({{ enhancement_report.final_score.total_score|default(0)|round(1) }}).</p>
|
1137 |
-
</div>
|
1138 |
-
{% endif %}
|
1139 |
</div>
|
1140 |
</div>
|
1141 |
</div>
|
1142 |
|
1143 |
-
{{ download_script|safe if download_script else '' }}
|
1144 |
-
|
1145 |
<script>
|
1146 |
-
function downloadJSON() {
|
1147 |
-
const a = document.createElement('a');
|
1148 |
-
a.href = '{{ download_url }}';
|
1149 |
-
a.download = '{{ model_id|replace("/", "_") }}_aibom.json';
|
1150 |
-
document.body.appendChild(a);
|
1151 |
-
a.click();
|
1152 |
-
document.body.removeChild(a);
|
1153 |
-
}
|
1154 |
-
|
1155 |
function switchTab(tabId) {
|
1156 |
// Hide all tab contents
|
1157 |
-
|
1158 |
-
for (
|
1159 |
tabContents[i].classList.remove('active');
|
1160 |
}
|
1161 |
|
1162 |
// Deactivate all tabs
|
1163 |
-
|
1164 |
-
for (
|
1165 |
tabs[i].classList.remove('active');
|
1166 |
}
|
1167 |
|
1168 |
// Activate the selected tab and content
|
1169 |
document.getElementById(tabId).classList.add('active');
|
1170 |
-
document.querySelector('.aibom-tab[onclick="switchTab(\'' + tabId + '\')"]')
|
|
|
1171 |
}
|
1172 |
|
1173 |
function toggleCollapsible(element) {
|
1174 |
element.classList.toggle('active');
|
1175 |
-
|
|
|
|
|
1176 |
if (content.classList.contains('active')) {
|
1177 |
-
content.
|
1178 |
} else {
|
1179 |
-
content.
|
1180 |
}
|
1181 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1182 |
</script>
|
1183 |
</body>
|
1184 |
</html>
|
|
|
404 |
</head>
|
405 |
<body>
|
406 |
<!-- Header with logo and title -->
|
407 |
+
<div class="header">
|
408 |
+
<div class="header" style="display: flex; align-items: center; gap: 10px;">
|
409 |
+
<a href="https://aetheris.ai/" target="_blank">
|
410 |
<img src="https://huggingface.co/spaces/aetheris-ai/aibom-generator/resolve/main/templates/images/AetherisAI-logo.png" alt="Aetheris AI Logo" style="height: 60px;">
|
411 |
+
</a>
|
412 |
<h1 style="margin: 0;">AI SBOM Generator</h1>
|
413 |
+
</div>
|
414 |
</div>
|
415 |
|
416 |
<div class="container">
|
|
|
424 |
{% if enhancement_report and enhancement_report.ai_enhanced %}
|
425 |
<div class="improvement">
|
426 |
<h3>AI Enhancement Results</h3>
|
427 |
+
<p>This AI SBOM was enhanced using <strong>{{ enhancement_report.ai_model }}</strong></p>
|
428 |
+
<p>Original Score: {{ enhancement_report.original_score.total_score|round(1) }}/100</p>
|
429 |
+
<p>Enhanced Score: {{ enhancement_report.final_score.total_score|round(1) }}/100</p>
|
430 |
+
<p>Improvement: <span class="improvement-value">+{{ enhancement_report.improvement|round(1) }} points</span></p>
|
431 |
</div>
|
432 |
{% endif %}
|
433 |
|
|
|
483 |
<div class="property-name">Model Parameters:</div>
|
484 |
<div class="property-value">
|
485 |
{% if aibom.components[0].modelCard.modelParameters.properties %}
|
486 |
+
<ul>
|
487 |
{% for prop in aibom.components[0].modelCard.modelParameters.properties %}
|
488 |
+
<li><strong>{{ prop.name }}:</strong> {{ prop.value }}</li>
|
489 |
{% endfor %}
|
490 |
+
</ul>
|
491 |
+
{% else %}
|
492 |
+
<ul>
|
493 |
+
{% for key, value in aibom.components[0].modelCard.modelParameters.items() %}
|
494 |
+
<li><strong>{{ key }}:</strong> {{ value }}</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
495 |
{% endfor %}
|
496 |
+
</ul>
|
497 |
{% endif %}
|
498 |
</div>
|
499 |
</div>
|
|
|
503 |
<div class="aibom-property">
|
504 |
<div class="property-name">Considerations:</div>
|
505 |
<div class="property-value">
|
506 |
+
<ul>
|
507 |
+
{% for key, value in aibom.components[0].modelCard.considerations.items() %}
|
508 |
+
<li><strong>{{ key }}:</strong> {{ value }}</li>
|
509 |
+
{% endfor %}
|
510 |
+
</ul>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
511 |
</div>
|
512 |
</div>
|
513 |
{% endif %}
|
514 |
</div>
|
515 |
</div>
|
516 |
{% endif %}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
517 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
518 |
<!-- External References Section -->
|
519 |
{% if aibom.components and aibom.components[0].externalReferences %}
|
520 |
<div class="aibom-section">
|
521 |
<h4 class="collapsible" onclick="toggleCollapsible(this)">External References</h4>
|
522 |
<div class="collapsible-content">
|
523 |
+
<ul>
|
524 |
+
{% for ref in aibom.components[0].externalReferences %}
|
525 |
+
<li>
|
526 |
+
<strong>{{ ref.type }}:</strong>
|
527 |
<a href="{{ ref.url }}" target="_blank">{{ ref.url }}</a>
|
528 |
+
{% if ref.comment %}
|
529 |
+
<br><em>{{ ref.comment }}</em>
|
530 |
+
{% endif %}
|
531 |
+
</li>
|
532 |
+
{% endfor %}
|
533 |
+
</ul>
|
534 |
</div>
|
535 |
</div>
|
536 |
{% endif %}
|
|
|
562 |
</div>
|
563 |
</div>
|
564 |
|
|
|
565 |
<ul>
|
566 |
{% for field, status in completeness_score.field_checklist.items() %}
|
567 |
{% if "✔" in status %}
|
568 |
+
<li>
|
569 |
+
<span class="check-mark">✔</span>
|
570 |
<span class="field-name">{{ field }}</span>
|
571 |
+
<span class="field-stars">{{ status.split('✔')[1] }}</span>
|
572 |
{% if completeness_score.field_tiers and field in completeness_score.field_tiers %}
|
573 |
<span class="field-tier tier-{{ completeness_score.field_tiers[field] }}"></span>
|
574 |
{% endif %}
|
575 |
</li>
|
576 |
{% else %}
|
577 |
+
<li>
|
578 |
+
<span class="x-mark">✘</span>
|
579 |
<span class="field-name">{{ field }}</span>
|
580 |
+
<span class="field-stars">{{ status.split('✘')[1] }}</span>
|
581 |
{% if completeness_score.field_tiers and field in completeness_score.field_tiers %}
|
582 |
<span class="field-tier tier-{{ completeness_score.field_tiers[field] }}"></span>
|
583 |
{% endif %}
|
584 |
|
585 |
{% if field == "component.description" %}
|
|
|
586 |
<span class="tooltip">(?)
|
587 |
<span class="tooltiptext">A detailed description of the model is essential for users to understand its purpose and capabilities. Add a description that is at least 20 characters long.</span>
|
588 |
</span>
|
589 |
{% elif field == "component.purl" %}
|
|
|
590 |
<span class="tooltip">(?)
|
591 |
<span class="tooltiptext">Package URL (PURL) is critical for uniquely identifying the model. It should follow the format pkg:huggingface/[owner]/[name]@[version].</span>
|
592 |
</span>
|
593 |
{% elif field == "modelCard.modelParameters" %}
|
|
|
594 |
<span class="tooltip">(?)
|
595 |
<span class="tooltiptext">Model parameters provide essential technical details about the model architecture, training, and capabilities.</span>
|
596 |
</span>
|
597 |
{% elif field == "modelCard.considerations" %}
|
|
|
598 |
<span class="tooltip">(?)
|
599 |
<span class="tooltiptext">Considerations section should include ethical considerations, limitations, and risks associated with the model.</span>
|
600 |
</span>
|
601 |
{% elif field == "externalReferences" %}
|
|
|
602 |
<span class="tooltip">(?)
|
603 |
<span class="tooltiptext">External references provide links to additional resources like model cards, repositories, and datasets.</span>
|
604 |
</span>
|
605 |
{% else %}
|
|
|
606 |
<span class="tooltip">(?)
|
607 |
<span class="tooltiptext">This field contributes to the completeness of your AI SBOM.</span>
|
608 |
</span>
|
|
|
611 |
{% endif %}
|
612 |
{% endfor %}
|
613 |
</ul>
|
|
|
|
|
|
|
614 |
</div>
|
615 |
|
616 |
<div id="score-view" class="tab-content">
|
617 |
<h3>AI SBOM Completeness Score</h3>
|
618 |
|
619 |
<!-- Completeness Profile Section -->
|
620 |
+
{% if completeness_score.completeness_profile %}
|
621 |
<div class="completeness-profile">
|
622 |
<h4>Completeness Profile:
|
623 |
+
<span class="profile-badge profile-{{ completeness_score.completeness_profile.name|lower }}">
|
624 |
+
{{ completeness_score.completeness_profile.name }}
|
625 |
</span>
|
626 |
</h4>
|
627 |
+
<p>{{ completeness_score.completeness_profile.description }}</p>
|
628 |
|
629 |
{% if completeness_score.completeness_profile.next_level %}
|
630 |
<p><strong>Next level:</strong> {{ completeness_score.completeness_profile.next_level.name }}
|
631 |
({{ completeness_score.completeness_profile.next_level.missing_fields_count }} fields to add)</p>
|
632 |
{% endif %}
|
633 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
634 |
{% endif %}
|
635 |
|
636 |
<!-- Total Score with Progress Bar -->
|
637 |
<div class="total-score-container">
|
638 |
+
<div class="total-score">{{ completeness_score.total_score|round(1) }}/100</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
639 |
<div class="total-progress">
|
640 |
<div class="progress-container">
|
641 |
+
{% set score_percent = (completeness_score.total_score / 100) * 100 %}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
642 |
{% set score_class = 'progress-poor' %}
|
643 |
{% set score_label = 'Poor' %}
|
644 |
|
|
|
654 |
{% endif %}
|
655 |
|
656 |
<div class="progress-bar {{ score_class }}" style="width: {{ score_percent }}%">
|
657 |
+
{{ score_percent|int }}% {{ score_label }}
|
658 |
</div>
|
659 |
</div>
|
660 |
</div>
|
|
|
|
|
|
|
|
|
661 |
</div>
|
662 |
|
663 |
<!-- Validation Penalty Explanation -->
|
664 |
+
{% if completeness_score.validation_penalty %}
|
665 |
<div class="validation-penalty-info">
|
666 |
<h4>About the Validation Penalty</h4>
|
667 |
<p>Your score includes a penalty because the AIBOM has schema validation issues. These are structural problems that don't comply with the CycloneDX specification requirements.</p>
|
|
|
669 |
</div>
|
670 |
{% endif %}
|
671 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
672 |
<!-- Section Scores with Progress Bars and Tooltips -->
|
|
|
673 |
<table class="score-table">
|
674 |
<thead>
|
675 |
<tr>
|
|
|
698 |
{% for section, score in completeness_score.section_scores.items() %}
|
699 |
<tr>
|
700 |
<td>
|
701 |
+
{{ display_names[section] }}
|
702 |
<span class="tooltip">(?)
|
703 |
+
<span class="tooltiptext">{{ tooltips[section] }}</span>
|
704 |
</span>
|
705 |
</td>
|
706 |
+
<td>{{ score|round(1) }}/{{ completeness_score.max_scores[section] }}</td>
|
707 |
+
<td>{{ weights[section] }}%</td>
|
708 |
<td style="width: 50%;">
|
709 |
<div class="progress-container">
|
710 |
+
{% set percent = (score / completeness_score.max_scores[section]) * 100 %}
|
711 |
{% set class = 'progress-poor' %}
|
712 |
|
713 |
{% if percent >= 90 %}
|
|
|
727 |
{% endfor %}
|
728 |
</tbody>
|
729 |
</table>
|
|
|
730 |
|
731 |
+
<!-- How the Overall Score is Calculated Section -->
|
732 |
+
<div class="score-calculation">
|
733 |
+
<h3>How the Overall Score is Calculated</h3>
|
734 |
+
|
735 |
+
<!-- Missing Fields Section -->
|
736 |
+
<div class="calculation-section missing-fields">
|
737 |
+
<h4>Critical Missing Fields</h4>
|
738 |
+
<p>The following fields are missing or incomplete and have the biggest impact on your score:</p>
|
739 |
+
<ul>
|
740 |
+
{% set missing_critical = [] %}
|
741 |
+
{% for field, status in completeness_score.field_checklist.items() %}
|
742 |
+
{% if "✘" in status %}
|
743 |
+
{% if completeness_score.field_tiers and field in completeness_score.field_tiers and completeness_score.field_tiers[field] == 'critical' %}
|
744 |
+
{% set _ = missing_critical.append(field) %}
|
745 |
+
<li>
|
746 |
+
<strong>{{ field }}</strong>
|
747 |
+
<span class="field-tier tier-critical"></span>
|
748 |
+
{% if field == "component.description" %}
|
749 |
+
- Add a detailed description of the model (at least 20 characters)
|
750 |
+
{% elif field == "component.purl" %}
|
751 |
+
- Add a valid PURL in the format pkg:huggingface/[owner]/[name]@[version]
|
752 |
+
{% elif field == "modelCard.modelParameters" %}
|
753 |
+
- Add model parameters section with architecture, size, and training details
|
754 |
+
{% elif field == "primaryPurpose" %}
|
755 |
+
- Add primary purpose information (what the model is designed for)
|
756 |
+
{% else %}
|
757 |
+
- This field is required for comprehensive documentation
|
758 |
+
{% endif %}
|
759 |
+
</li>
|
760 |
+
{% endif %}
|
761 |
{% endif %}
|
762 |
+
{% endfor %}
|
763 |
+
{% if missing_critical|length == 0 %}
|
764 |
+
<li>No critical fields are missing. Great job!</li>
|
765 |
{% endif %}
|
766 |
+
</ul>
|
767 |
+
</div>
|
768 |
+
|
769 |
+
<!-- Recommendations Section -->
|
770 |
+
<div class="calculation-section recommendations">
|
771 |
+
<h4>Recommendations to Improve Your Score</h4>
|
772 |
+
<ol>
|
773 |
+
{% if completeness_score.section_scores.component_model_card < completeness_score.max_scores.component_model_card %}
|
774 |
+
<li>
|
775 |
+
<strong>Enhance Model Card</strong> (+{{ ((completeness_score.max_scores.component_model_card - completeness_score.section_scores.component_model_card) * 0.3)|round(1) }} points):
|
776 |
+
<ul>
|
777 |
+
{% if completeness_score.missing_fields.critical %}
|
778 |
+
{% for field in completeness_score.missing_fields.critical %}
|
779 |
+
{% if field.startswith('modelCard') %}
|
780 |
+
<li>Add {{ field }} section</li>
|
781 |
+
{% endif %}
|
782 |
+
{% endfor %}
|
783 |
+
{% endif %}
|
784 |
+
{% if completeness_score.missing_fields.important %}
|
785 |
+
{% for field in completeness_score.missing_fields.important %}
|
786 |
+
{% if field.startswith('modelCard') %}
|
787 |
+
<li>Add {{ field }} section</li>
|
788 |
+
{% endif %}
|
789 |
+
{% endfor %}
|
790 |
+
{% endif %}
|
791 |
+
</ul>
|
792 |
+
</li>
|
793 |
+
{% endif %}
|
794 |
+
|
795 |
+
{% if completeness_score.section_scores.component_basic < completeness_score.max_scores.component_basic %}
|
796 |
+
<li>
|
797 |
+
<strong>Improve Component Information</strong> (+{{ ((completeness_score.max_scores.component_basic - completeness_score.section_scores.component_basic) * 0.2)|round(1) }} points):
|
798 |
+
<ul>
|
799 |
+
{% if completeness_score.missing_fields.critical %}
|
800 |
+
{% for field in completeness_score.missing_fields.critical %}
|
801 |
+
{% if field == "name" or field == "description" or field == "purl" %}
|
802 |
+
<li>Add {{ field }} information</li>
|
803 |
+
{% endif %}
|
804 |
+
{% endfor %}
|
805 |
+
{% endif %}
|
806 |
+
{% if completeness_score.missing_fields.important %}
|
807 |
+
{% for field in completeness_score.missing_fields.important %}
|
808 |
+
{% if field == "type" or field == "licenses" %}
|
809 |
+
<li>Add {{ field }} information</li>
|
810 |
+
{% endif %}
|
811 |
+
{% endfor %}
|
812 |
+
{% endif %}
|
813 |
+
</ul>
|
814 |
+
</li>
|
815 |
+
{% endif %}
|
816 |
+
|
817 |
+
{% if completeness_score.section_scores.metadata < completeness_score.max_scores.metadata %}
|
818 |
+
<li>
|
819 |
+
<strong>Add Metadata</strong> (+{{ ((completeness_score.max_scores.metadata - completeness_score.section_scores.metadata) * 0.2)|round(1) }} points):
|
820 |
+
<ul>
|
821 |
+
{% if completeness_score.missing_fields.critical %}
|
822 |
+
{% for field in completeness_score.missing_fields.critical %}
|
823 |
+
{% if field == "primaryPurpose" or field == "suppliedBy" %}
|
824 |
+
<li>Add {{ field }} information</li>
|
825 |
+
{% endif %}
|
826 |
+
{% endfor %}
|
827 |
+
{% endif %}
|
828 |
+
{% if completeness_score.missing_fields.supplementary %}
|
829 |
+
{% for field in completeness_score.missing_fields.supplementary %}
|
830 |
+
{% if field == "standardCompliance" or field == "domain" or field == "autonomyType" %}
|
831 |
+
<li>Add {{ field }} information</li>
|
832 |
+
{% endif %}
|
833 |
+
{% endfor %}
|
834 |
+
{% endif %}
|
835 |
+
</ul>
|
836 |
+
</li>
|
837 |
+
{% endif %}
|
838 |
+
|
839 |
+
{% if completeness_score.section_scores.external_references < completeness_score.max_scores.external_references %}
|
840 |
+
<li>
|
841 |
+
<strong>Add External References</strong> (+{{ ((completeness_score.max_scores.external_references - completeness_score.section_scores.external_references) * 0.1)|round(1) }} points):
|
842 |
+
<ul>
|
843 |
+
{% if completeness_score.missing_fields.critical %}
|
844 |
+
{% for field in completeness_score.missing_fields.critical %}
|
845 |
+
{% if field == "downloadLocation" %}
|
846 |
+
<li>Add download location reference</li>
|
847 |
+
{% endif %}
|
848 |
+
{% endfor %}
|
849 |
+
{% endif %}
|
850 |
+
<li>Add links to model card, repository, and dataset</li>
|
851 |
+
</ul>
|
852 |
+
</li>
|
853 |
+
{% endif %}
|
854 |
+
|
855 |
+
{% if completeness_score.validation and not completeness_score.validation.valid %}
|
856 |
+
<li>
|
857 |
+
<strong>Fix Validation Issues</strong> (remove validation penalty):
|
858 |
+
<ul>
|
859 |
+
{% for recommendation in completeness_score.validation.recommendations %}
|
860 |
+
<li>{{ recommendation }}</li>
|
861 |
+
{% endfor %}
|
862 |
+
</ul>
|
863 |
+
</li>
|
864 |
+
{% endif %}
|
865 |
+
</ol>
|
866 |
+
</div>
|
867 |
+
|
868 |
+
<!-- Scoring Rubric Section -->
|
869 |
+
<div class="calculation-section scoring-rubric">
|
870 |
+
<h4>Scoring Rubric</h4>
|
871 |
+
<p>The overall score is calculated using a weighted category approach:</p>
|
872 |
+
<p><strong>Total Score = (Sum of (Category Score × Category Weight)) × 100</strong></p>
|
873 |
+
<p>Where:</p>
|
874 |
+
<ul>
|
875 |
+
<li>Category Score = Sum of weights for present fields in that category</li>
|
876 |
+
<li>Category Weight = Max Category Score ÷ Sum of All Max Category Scores</li>
|
877 |
+
</ul>
|
878 |
|
879 |
+
<p>Fields are classified into three tiers based on importance:</p>
|
880 |
+
<ul>
|
881 |
+
<li><span class="field-tier tier-critical"></span> <strong>Critical fields</strong>: Highest weight (3-4 points each)</li>
|
882 |
+
<li><span class="field-tier tier-important"></span> <strong>Important fields</strong>: Medium weight (2-4 points each)</li>
|
883 |
+
<li><span class="field-tier tier-supplementary"></span> <strong>Supplementary fields</strong>: Lower weight (1-2 points each)</li>
|
884 |
+
</ul>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
885 |
|
886 |
+
<p>Penalties are applied for missing critical fields:</p>
|
887 |
+
<ul>
|
888 |
+
<li>Missing >3 critical fields: 20% penalty (score × 0.8)</li>
|
889 |
+
<li>Missing 1-3 critical fields: 10% penalty (score × 0.9)</li>
|
890 |
+
<li>Missing >5 important fields: 5% penalty (score × 0.95)</li>
|
891 |
+
</ul>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
892 |
|
893 |
+
{% if completeness_score.validation_penalty %}
|
894 |
+
<p>Additional penalties are applied based on validation results:</p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
895 |
<ul>
|
896 |
+
<li>Schema errors: Up to 50% reduction (10% per error)</li>
|
897 |
+
<li>Schema warnings: Up to 20% reduction (5% per warning)</li>
|
|
|
898 |
</ul>
|
899 |
+
{% endif %}
|
900 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
901 |
</div>
|
902 |
</div>
|
903 |
</div>
|
904 |
|
|
|
|
|
905 |
<script>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
906 |
function switchTab(tabId) {
|
907 |
// Hide all tab contents
|
908 |
+
var tabContents = document.getElementsByClassName('tab-content');
|
909 |
+
for (var i = 0; i < tabContents.length; i++) {
|
910 |
tabContents[i].classList.remove('active');
|
911 |
}
|
912 |
|
913 |
// Deactivate all tabs
|
914 |
+
var tabs = document.getElementsByClassName('aibom-tab');
|
915 |
+
for (var i = 0; i < tabs.length; i++) {
|
916 |
tabs[i].classList.remove('active');
|
917 |
}
|
918 |
|
919 |
// Activate the selected tab and content
|
920 |
document.getElementById(tabId).classList.add('active');
|
921 |
+
var selectedTab = document.querySelector('.aibom-tab[onclick="switchTab(\'' + tabId + '\')"]');
|
922 |
+
selectedTab.classList.add('active');
|
923 |
}
|
924 |
|
925 |
function toggleCollapsible(element) {
|
926 |
element.classList.toggle('active');
|
927 |
+
var content = element.nextElementSibling;
|
928 |
+
content.classList.toggle('active');
|
929 |
+
|
930 |
if (content.classList.contains('active')) {
|
931 |
+
content.style.maxHeight = content.scrollHeight + 'px';
|
932 |
} else {
|
933 |
+
content.style.maxHeight = '0';
|
934 |
}
|
935 |
}
|
936 |
+
|
937 |
+
function downloadJSON() {
|
938 |
+
var dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify({{ aibom|tojson }}, null, 2));
|
939 |
+
var downloadAnchorNode = document.createElement('a');
|
940 |
+
downloadAnchorNode.setAttribute("href", dataStr);
|
941 |
+
downloadAnchorNode.setAttribute("download", "{{ model_id|replace('/', '_') }}_aibom.json");
|
942 |
+
document.body.appendChild(downloadAnchorNode);
|
943 |
+
downloadAnchorNode.click();
|
944 |
+
downloadAnchorNode.remove();
|
945 |
+
}
|
946 |
+
|
947 |
+
// Initialize collapsible sections
|
948 |
+
document.addEventListener('DOMContentLoaded', function() {
|
949 |
+
var collapsibles = document.getElementsByClassName('collapsible');
|
950 |
+
for (var i = 0; i < collapsibles.length; i++) {
|
951 |
+
toggleCollapsible(collapsibles[i]);
|
952 |
+
}
|
953 |
+
});
|
954 |
</script>
|
955 |
</body>
|
956 |
</html>
|