a1c00l commited on
Commit
eddbdb8
Β·
verified Β·
1 Parent(s): 54927c3

Update templates/result.html

Browse files
Files changed (1) hide show
  1. templates/result.html +628 -536
templates/result.html CHANGED
@@ -4,38 +4,14 @@
4
  <meta charset="UTF-8">
5
  <title>AI SBOM Generated</title>
6
  <style>
7
- body { font-family: Arial, sans-serif; margin: 0; padding: 0; }
8
- .container { margin: 0 20px; }
9
-
10
- /* Header styling */
11
- .header {
12
- background-color: #f8f9fa;
13
- padding: 15px 20px;
14
- border-bottom: 1px solid #e9ecef;
15
- display: flex;
16
- align-items: center;
17
- margin-bottom: 20px;
18
- }
19
- .header img {
20
- height: 40px;
21
- margin-right: 15px;
22
- }
23
- .header h1 {
24
- margin: 0;
25
- font-size: 24px;
26
- color: #333;
27
- }
28
-
29
  table { border-collapse: collapse; width: 60%; margin-top: 15px; }
30
  th, td { border: 1px solid #ddd; padding: 8px; }
31
  th { background-color: #f4f4f4; }
32
-
33
  /* Fixed color styling for field checklist items */
34
- .check-mark { color: #27ae60; } /* Green color for check marks */
35
- .x-mark { color: #e74c3c; } /* Red color for x marks */
36
- .field-name { color: #000; } /* Black color for field names */
37
- .field-stars { color: #000; } /* Black color for importance stars */
38
-
39
  .improvement { color: #2c3e50; background-color: #ecf0f1; padding: 15px; border-radius: 5px; margin-bottom: 20px; }
40
  .improvement-value { color: #27ae60; font-weight: bold; }
41
  .ai-badge { background-color: #3498db; color: white; padding: 3px 8px; border-radius: 3px; font-size: 0.8em; margin-left: 10px; }
@@ -152,9 +128,6 @@
152
  line-height: 20px;
153
  color: white;
154
  font-size: 12px;
155
- display: flex;
156
- align-items: center;
157
- justify-content: center;
158
  }
159
  .progress-excellent {
160
  background-color: #4CAF50; /* Green */
@@ -192,7 +165,18 @@
192
  color: white;
193
  font-size: 0.8em;
194
  margin-left: 5px;
195
- background-color: transparent; /* Make background transparent */
 
 
 
 
 
 
 
 
 
 
 
196
  }
197
  .total-score-container {
198
  display: flex;
@@ -206,6 +190,7 @@
206
  }
207
  .total-progress {
208
  flex: 1;
 
209
  }
210
 
211
  /* New styles for improved user understanding */
@@ -382,575 +367,682 @@
382
  margin-top: 0;
383
  color: #e65100;
384
  }
385
-
386
- /* New section for score calculation explanation */
387
- .score-calculation {
388
- margin-top: 30px;
389
- padding: 15px;
390
- background-color: #f5f5f5;
391
- border-radius: 5px;
392
- }
393
- .score-calculation h3 {
394
- margin-top: 0;
395
- color: #333;
396
- border-bottom: 1px solid #ddd;
397
- padding-bottom: 10px;
398
- margin-bottom: 15px;
399
- }
400
- .calculation-section {
401
- margin-bottom: 20px;
402
- }
403
  </style>
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">
417
- <a href="/">Generate another AI SBOM</a>
418
- <h2>AI SBOM Generated for {{ model_id }}</h2>
419
-
420
- <div class="download-section">
421
- <p>Download generated AI SBOM in CycloneDX format <button onclick="downloadJSON()">Download JSON</button></p>
422
- </div>
423
 
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
 
434
- <!-- Human-friendly AI SBOM Viewer -->
435
- <div class="note-box">
436
- <p><strong>Note:</strong> This page displays the AI SBOM in a human-friendly format for easier readability.
437
- The downloaded JSON file follows the standard CycloneDX format required for interoperability with other tools.</p>
438
- </div>
439
-
440
- <div class="aibom-tabs">
441
- <div class="aibom-tab active" onclick="switchTab('human-view')">Human-Friendly View</div>
442
- <div class="aibom-tab" onclick="switchTab('json-view')">JSON View</div>
443
- <div class="aibom-tab" onclick="switchTab('field-checklist')">Field Checklist</div>
444
- <div class="aibom-tab" onclick="switchTab('score-view')">Score Report</div>
445
- </div>
446
 
447
- <div id="human-view" class="tab-content active">
448
- <div class="aibom-viewer">
449
- <!-- Key Information Section -->
450
- <div class="aibom-section key-info">
451
- <h4>Key Information</h4>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
452
  <div class="aibom-property">
453
- <div class="property-name">Model Name:</div>
454
- <div class="property-value">{{ aibom.components[0].name if aibom.components and aibom.components[0].name else 'Not specified' }}</div>
 
 
 
 
 
 
 
 
455
  </div>
 
 
 
456
  <div class="aibom-property">
457
- <div class="property-name">Type:</div>
458
- <div class="property-value">{{ aibom.components[0].type if aibom.components and aibom.components[0].type else 'Not specified' }}</div>
 
 
 
 
 
 
459
  </div>
 
 
 
460
  <div class="aibom-property">
461
- <div class="property-name">Version:</div>
462
- <div class="property-value">{{ aibom.components[0].version if aibom.components and aibom.components[0].version else 'Not specified' }}</div>
 
 
 
 
 
 
 
 
 
 
463
  </div>
 
 
 
 
 
 
 
 
 
 
 
464
  <div class="aibom-property">
465
- <div class="property-name">PURL:</div>
466
- <div class="property-value">{{ aibom.components[0].purl if aibom.components and aibom.components[0].purl else 'Not specified' }}</div>
 
 
 
 
 
 
 
 
467
  </div>
468
- {% if aibom.components and aibom.components[0].description %}
 
 
469
  <div class="aibom-property">
470
- <div class="property-name">Description:</div>
471
- <div class="property-value">{{ aibom.components[0].description }}</div>
472
  </div>
473
  {% endif %}
474
  </div>
 
 
475
 
476
- <!-- Model Card Section -->
477
- {% if aibom.components and aibom.components[0].modelCard %}
478
- <div class="aibom-section">
479
- <h4 class="collapsible" onclick="toggleCollapsible(this)">Model Card</h4>
480
- <div class="collapsible-content">
481
- {% if aibom.components[0].modelCard.modelParameters %}
482
- <div class="aibom-property">
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>
500
- {% endif %}
501
-
502
- {% if aibom.components[0].modelCard.considerations %}
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 %}
537
  </div>
538
- </div>
539
 
540
- <div id="json-view" class="tab-content">
541
- <div class="json-view">
542
- <pre>{{ aibom | tojson(indent=2) }}</pre>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
543
  </div>
544
- </div>
545
 
546
- <div id="field-checklist" class="tab-content">
547
- <h3>Field Checklist</h3>
548
-
549
- <!-- Field Tier Legend -->
550
- <div class="tier-legend">
551
- <div class="tier-legend-item">
552
- <span class="field-tier tier-critical"></span>
553
- <span>Critical</span>
554
- </div>
555
- <div class="tier-legend-item">
556
- <span class="field-tier tier-important"></span>
557
- <span>Important</span>
558
- </div>
559
- <div class="tier-legend-item">
560
- <span class="field-tier tier-supplementary"></span>
561
- <span>Supplementary</span>
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>
609
- {% endif %}
610
- </li>
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
-
645
- {% if score_percent >= 90 %}
646
- {% set score_class = 'progress-excellent' %}
647
- {% set score_label = 'Excellent' %}
648
- {% elif score_percent >= 70 %}
649
- {% set score_class = 'progress-good' %}
650
- {% set score_label = 'Good' %}
651
- {% elif score_percent >= 50 %}
652
- {% set score_class = 'progress-fair' %}
653
- {% set score_label = 'Fair' %}
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 AI SBOM has schema validation issues. These are structural problems that don't comply with the CycloneDX specification requirements.</p>
668
- <p><strong>How to fix this:</strong> Look at the "Fix Validation Issues" section in the recommendations below. Fixing these issues will remove the penalty and improve your overall score.</p>
669
  </div>
670
- {% endif %}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
671
 
672
- <!-- Section Scores with Progress Bars and Tooltips -->
673
- <table class="score-table">
674
- <thead>
675
- <tr>
676
- <th>Section</th>
677
- <th>Score</th>
678
- <th>Weight</th>
679
- <th>Progress</th>
680
- </tr>
681
- </thead>
682
- <tbody>
683
- {% set weights = {'required_fields': 20, 'metadata': 20, 'component_basic': 20, 'component_model_card': 30, 'external_references': 10} %}
684
- {% set tooltips = {
685
- 'required_fields': 'Basic SBOM fields required by the CycloneDX specification: bomFormat, specVersion, serialNumber, and version.',
686
- 'metadata': 'Information about the AI SBOM itself: timestamp, tools used to generate it, authors, and component metadata.',
687
- 'component_basic': 'Basic information about the AI model: type, name, bom-ref, PURL, description, and licenses.',
688
- 'component_model_card': 'Detailed information about the model: parameters, quantitative analysis, and ethical considerations.',
689
- 'external_references': 'Links to external resources like model cards, repositories, and datasets.'
690
- } %}
691
- {% set display_names = {
692
- 'required_fields': 'Required Fields',
693
- 'metadata': 'Metadata',
694
- 'component_basic': 'Component Basic',
695
- 'component_model_card': 'Model Card',
696
- 'external_references': 'External References'
697
- } %}
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 %}
714
- {% set class = 'progress-excellent' %}
715
- {% elif percent >= 70 %}
716
- {% set class = 'progress-good' %}
717
- {% elif percent >= 50 %}
718
- {% set class = 'progress-fair' %}
719
- {% endif %}
720
-
721
- <div class="progress-bar {{ class }}" style="width: {{ percent }}%">
722
- {{ percent|int }}%
723
- </div>
724
- </div>
725
- </td>
726
- </tr>
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>
 
4
  <meta charset="UTF-8">
5
  <title>AI SBOM Generated</title>
6
  <style>
7
+ body { font-family: Arial, sans-serif; margin: 20px; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  table { border-collapse: collapse; width: 60%; margin-top: 15px; }
9
  th, td { border: 1px solid #ddd; padding: 8px; }
10
  th { background-color: #f4f4f4; }
 
11
  /* Fixed color styling for field checklist items */
12
+ .missing { color: #e74c3c; } /* Red color for missing fields */
13
+ .present { color: #27ae60; } /* Green color for present fields */
14
+ .unknown { color: #f39c12; } /* Orange color for unknown status */
 
 
15
  .improvement { color: #2c3e50; background-color: #ecf0f1; padding: 15px; border-radius: 5px; margin-bottom: 20px; }
16
  .improvement-value { color: #27ae60; font-weight: bold; }
17
  .ai-badge { background-color: #3498db; color: white; padding: 3px 8px; border-radius: 3px; font-size: 0.8em; margin-left: 10px; }
 
128
  line-height: 20px;
129
  color: white;
130
  font-size: 12px;
 
 
 
131
  }
132
  .progress-excellent {
133
  background-color: #4CAF50; /* Green */
 
165
  color: white;
166
  font-size: 0.8em;
167
  margin-left: 5px;
168
+ }
169
+ .label-excellent {
170
+ background-color: #4CAF50;
171
+ }
172
+ .label-good {
173
+ background-color: #2196F3;
174
+ }
175
+ .label-fair {
176
+ background-color: #FF9800;
177
+ }
178
+ .label-poor {
179
+ background-color: #f44336;
180
  }
181
  .total-score-container {
182
  display: flex;
 
190
  }
191
  .total-progress {
192
  flex: 1;
193
+ max-width: 300px;
194
  }
195
 
196
  /* New styles for improved user understanding */
 
367
  margin-top: 0;
368
  color: #e65100;
369
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
370
  </style>
371
  </head>
372
  <body>
373
+ <a href="/">Generate another AI SBOM</a>
374
+ <h2>AI SBOM Generated for {{ model_id }}</h2>
 
 
 
 
 
 
 
375
 
376
+ <div class="download-section">
377
+ <p>Download generated AI SBOM in CycloneDX format <button onclick="downloadJSON()">Download JSON</button></p>
378
+ </div>
 
 
 
 
379
 
380
+ {% if enhancement_report and enhancement_report.ai_enhanced %}
381
+ <div class="improvement">
382
+ <h3>AI Enhancement Results</h3>
383
+ <p>This AI SBOM was enhanced using <strong>{{ enhancement_report.ai_model }}</strong></p>
384
+ <p>Original Score: {{ enhancement_report.original_score.total_score|default(0)|round(1) }}/100</p>
385
+ <p>Enhanced Score: {{ enhancement_report.final_score.total_score|default(0)|round(1) }}/100</p>
386
+ <p>Improvement: <span class="improvement-value">+{{ enhancement_report.improvement|default(0)|round(1) }} points</span></p>
387
+ </div>
388
+ {% endif %}
389
 
390
+ <!-- Human-friendly AI SBOM Viewer -->
391
+ <div class="note-box">
392
+ <p><strong>Note:</strong> This page displays the AI SBOM in a human-friendly format for easier readability.
393
+ The downloaded JSON file follows the standard CycloneDX format required for interoperability with other tools.</p>
394
+ </div>
395
+
396
+ <div class="aibom-tabs">
397
+ <div class="aibom-tab active" onclick="switchTab('human-view')">Human-Friendly View</div>
398
+ <div class="aibom-tab" onclick="switchTab('json-view')">JSON View</div>
399
+ <div class="aibom-tab" onclick="switchTab('field-checklist')">Field Checklist</div>
400
+ <div class="aibom-tab" onclick="switchTab('score-view')">Score Report</div>
401
+ </div>
402
 
403
+ <div id="human-view" class="tab-content active">
404
+ <div class="aibom-viewer">
405
+ <!-- Key Information Section -->
406
+ <div class="aibom-section key-info">
407
+ <h4>Key Information</h4>
408
+ <div class="aibom-property">
409
+ <div class="property-name">Model Name:</div>
410
+ <div class="property-value">{{ aibom.components[0].name if aibom.components and aibom.components[0].name else 'Not specified' }}</div>
411
+ </div>
412
+ <div class="aibom-property">
413
+ <div class="property-name">Type:</div>
414
+ <div class="property-value">{{ aibom.components[0].type if aibom.components and aibom.components[0].type else 'Not specified' }}</div>
415
+ </div>
416
+ <div class="aibom-property">
417
+ <div class="property-name">Version:</div>
418
+ <div class="property-value">{{ aibom.components[0].version if aibom.components and aibom.components[0].version else 'Not specified' }}</div>
419
+ </div>
420
+ <div class="aibom-property">
421
+ <div class="property-name">PURL:</div>
422
+ <div class="property-value">{{ aibom.components[0].purl if aibom.components and aibom.components[0].purl else 'Not specified' }}</div>
423
+ </div>
424
+ {% if aibom.components and aibom.components[0].description %}
425
+ <div class="aibom-property">
426
+ <div class="property-name">Description:</div>
427
+ <div class="property-value">{{ aibom.components[0].description }}</div>
428
+ </div>
429
+ {% endif %}
430
+ </div>
431
+
432
+ <!-- Model Card Section -->
433
+ {% if aibom.components and aibom.components[0].modelCard %}
434
+ <div class="aibom-section">
435
+ <h4 class="collapsible" onclick="toggleCollapsible(this)">Model Card</h4>
436
+ <div class="collapsible-content">
437
+ {% if aibom.components[0].modelCard.modelParameters %}
438
  <div class="aibom-property">
439
+ <div class="property-name">Model Parameters:</div>
440
+ <div class="property-value">
441
+ {% if aibom.components[0].modelCard.modelParameters.properties %}
442
+ {% for prop in aibom.components[0].modelCard.modelParameters.properties %}
443
+ <div><strong>{{ prop.name }}:</strong> {{ prop.value }}</div>
444
+ {% endfor %}
445
+ {% elif aibom.components[0].modelCard.modelParameters.description %}
446
+ {{ aibom.components[0].modelCard.modelParameters.description }}
447
+ {% endif %}
448
+ </div>
449
  </div>
450
+ {% endif %}
451
+
452
+ {% if aibom.components[0].modelCard.quantitativeAnalysis %}
453
  <div class="aibom-property">
454
+ <div class="property-name">Performance Metrics:</div>
455
+ <div class="property-value">
456
+ {% if aibom.components[0].modelCard.quantitativeAnalysis.performanceMetrics %}
457
+ {% for metric in aibom.components[0].modelCard.quantitativeAnalysis.performanceMetrics %}
458
+ <div><strong>{{ metric.type if metric.type else 'Metric' }}:</strong> {{ metric.value if metric.value else 'Not specified' }}</div>
459
+ {% endfor %}
460
+ {% endif %}
461
+ </div>
462
  </div>
463
+ {% endif %}
464
+
465
+ {% if aibom.components[0].modelCard.considerations %}
466
  <div class="aibom-property">
467
+ <div class="property-name">Considerations:</div>
468
+ <div class="property-value">
469
+ {% if aibom.components[0].modelCard.considerations.ethicalConsiderations %}
470
+ <div><strong>Ethical Considerations:</strong> {{ aibom.components[0].modelCard.considerations.ethicalConsiderations }}</div>
471
+ {% endif %}
472
+ {% if aibom.components[0].modelCard.considerations.limitations %}
473
+ <div><strong>Limitations:</strong> {{ aibom.components[0].modelCard.considerations.limitations }}</div>
474
+ {% endif %}
475
+ {% if aibom.components[0].modelCard.considerations.tradeoffs %}
476
+ <div><strong>Tradeoffs:</strong> {{ aibom.components[0].modelCard.considerations.tradeoffs }}</div>
477
+ {% endif %}
478
+ </div>
479
  </div>
480
+ {% endif %}
481
+ </div>
482
+ </div>
483
+ {% endif %}
484
+
485
+ <!-- Training Data Section -->
486
+ {% if aibom.components and aibom.components[0].trainingData %}
487
+ <div class="aibom-section">
488
+ <h4 class="collapsible" onclick="toggleCollapsible(this)">Training Data</h4>
489
+ <div class="collapsible-content">
490
+ {% if aibom.components[0].trainingData.datasets %}
491
  <div class="aibom-property">
492
+ <div class="property-name">Datasets:</div>
493
+ <div class="property-value">
494
+ {% for dataset in aibom.components[0].trainingData.datasets %}
495
+ <div>
496
+ <strong>{{ dataset.name if dataset.name else 'Dataset' }}:</strong>
497
+ {% if dataset.description %} {{ dataset.description }}{% endif %}
498
+ {% if dataset.url %} <a href="{{ dataset.url }}" target="_blank">Link</a>{% endif %}
499
+ </div>
500
+ {% endfor %}
501
+ </div>
502
  </div>
503
+ {% endif %}
504
+
505
+ {% if aibom.components[0].trainingData.preprocessing %}
506
  <div class="aibom-property">
507
+ <div class="property-name">Preprocessing:</div>
508
+ <div class="property-value">{{ aibom.components[0].trainingData.preprocessing }}</div>
509
  </div>
510
  {% endif %}
511
  </div>
512
+ </div>
513
+ {% endif %}
514
 
515
+ <!-- Training Process Section -->
516
+ {% if aibom.components and aibom.components[0].trainingProcess %}
517
+ <div class="aibom-section">
518
+ <h4 class="collapsible" onclick="toggleCollapsible(this)">Training Process</h4>
519
+ <div class="collapsible-content">
520
+ {% if aibom.components[0].trainingProcess.trainingMethod %}
521
+ <div class="aibom-property">
522
+ <div class="property-name">Training Method:</div>
523
+ <div class="property-value">{{ aibom.components[0].trainingProcess.trainingMethod }}</div>
524
+ </div>
525
+ {% endif %}
526
+
527
+ {% if aibom.components[0].trainingProcess.hyperparameters %}
528
+ <div class="aibom-property">
529
+ <div class="property-name">Hyperparameters:</div>
530
+ <div class="property-value">
531
+ {% for param in aibom.components[0].trainingProcess.hyperparameters %}
532
+ <div><strong>{{ param.name }}:</strong> {{ param.value }}</div>
533
+ {% endfor %}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
534
  </div>
 
535
  </div>
536
+ {% endif %}
537
+
538
+ {% if aibom.components[0].trainingProcess.computeInfrastructure %}
539
+ <div class="aibom-property">
540
+ <div class="property-name">Compute Infrastructure:</div>
541
+ <div class="property-value">{{ aibom.components[0].trainingProcess.computeInfrastructure }}</div>
542
+ </div>
543
+ {% endif %}
544
  </div>
545
+ </div>
546
+ {% endif %}
547
+
548
+ <!-- Evaluation Section -->
549
+ {% if aibom.components and aibom.components[0].evaluation %}
550
+ <div class="aibom-section">
551
+ <h4 class="collapsible" onclick="toggleCollapsible(this)">Evaluation</h4>
552
+ <div class="collapsible-content">
553
+ {% if aibom.components[0].evaluation.metrics %}
554
+ <div class="aibom-property">
555
+ <div class="property-name">Metrics:</div>
556
+ <div class="property-value">
557
+ {% for metric in aibom.components[0].evaluation.metrics %}
558
+ <div><strong>{{ metric.name }}:</strong> {{ metric.value }}</div>
 
 
559
  {% endfor %}
560
+ </div>
561
  </div>
562
+ {% endif %}
563
+
564
+ {% if aibom.components[0].evaluation.datasets %}
565
+ <div class="aibom-property">
566
+ <div class="property-name">Evaluation Datasets:</div>
567
+ <div class="property-value">
568
+ {% for dataset in aibom.components[0].evaluation.datasets %}
569
+ <div>
570
+ <strong>{{ dataset.name if dataset.name else 'Dataset' }}:</strong>
571
+ {% if dataset.description %} {{ dataset.description }}{% endif %}
572
+ {% if dataset.url %} <a href="{{ dataset.url }}" target="_blank">Link</a>{% endif %}
573
+ </div>
574
+ {% endfor %}
575
+ </div>
576
+ </div>
577
+ {% endif %}
578
  </div>
 
579
  </div>
580
+ {% endif %}
581
 
582
+ <!-- Usage Section -->
583
+ {% if aibom.components and aibom.components[0].usage %}
584
+ <div class="aibom-section">
585
+ <h4 class="collapsible" onclick="toggleCollapsible(this)">Usage</h4>
586
+ <div class="collapsible-content">
587
+ {% if aibom.components[0].usage.intendedUse %}
588
+ <div class="aibom-property">
589
+ <div class="property-name">Intended Use:</div>
590
+ <div class="property-value">{{ aibom.components[0].usage.intendedUse }}</div>
591
+ </div>
592
+ {% endif %}
593
+
594
+ {% if aibom.components[0].usage.outOfScopeUses %}
595
+ <div class="aibom-property">
596
+ <div class="property-name">Out of Scope Uses:</div>
597
+ <div class="property-value">{{ aibom.components[0].usage.outOfScopeUses }}</div>
598
+ </div>
599
+ {% endif %}
600
+
601
+ {% if aibom.components[0].usage.guidelines %}
602
+ <div class="aibom-property">
603
+ <div class="property-name">Usage Guidelines:</div>
604
+ <div class="property-value">{{ aibom.components[0].usage.guidelines }}</div>
605
+ </div>
606
+ {% endif %}
607
+ </div>
608
  </div>
609
+ {% endif %}
610
 
611
+ <!-- Licenses Section -->
612
+ {% if aibom.components and aibom.components[0].licenses %}
613
+ <div class="aibom-section">
614
+ <h4 class="collapsible" onclick="toggleCollapsible(this)">Licenses</h4>
615
+ <div class="collapsible-content">
616
+ {% for license in aibom.components[0].licenses %}
617
+ <div class="aibom-property">
618
+ <div class="property-name">License:</div>
619
+ <div class="property-value">
620
+ <strong>{{ license.name }}</strong>
621
+ {% if license.url %} <a href="{{ license.url }}" target="_blank">Link</a>{% endif %}
622
+ </div>
623
+ </div>
624
+ {% endfor %}
 
 
625
  </div>
626
  </div>
627
+ {% endif %}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
628
  </div>
629
+ </div>
630
 
631
+ <div id="json-view" class="tab-content">
632
+ <div class="json-view">
633
+ <pre>{{ aibom|tojson(indent=2) }}</pre>
634
+ </div>
635
+ </div>
636
+
637
+ <div id="field-checklist" class="tab-content">
638
+ <h3>AI SBOM Field Completeness</h3>
639
+
640
+ <div class="tier-legend">
641
+ <div class="tier-legend-item">
642
+ <div class="field-tier tier-critical"></div>
643
+ <span>Critical Fields</span>
 
 
 
 
644
  </div>
645
+ <div class="tier-legend-item">
646
+ <div class="field-tier tier-important"></div>
647
+ <span>Important Fields</span>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
648
  </div>
649
+ <div class="tier-legend-item">
650
+ <div class="field-tier tier-supplementary"></div>
651
+ <span>Supplementary Fields</span>
 
 
 
 
652
  </div>
653
+ </div>
654
+
655
+ <table>
656
+ <tr>
657
+ <th>Field</th>
658
+ <th>Status</th>
659
+ </tr>
660
+ <!-- Basic Information -->
661
+ <tr>
662
+ <td><div class="field-tier tier-critical"></div> Model Name</td>
663
+ <td class="{{ 'present' if aibom.components and aibom.components[0].name else 'missing' }}">
664
+ {{ 'Present' if aibom.components and aibom.components[0].name else 'Missing' }}
665
+ </td>
666
+ </tr>
667
+ <tr>
668
+ <td><div class="field-tier tier-critical"></div> Model Type</td>
669
+ <td class="{{ 'present' if aibom.components and aibom.components[0].type else 'missing' }}">
670
+ {{ 'Present' if aibom.components and aibom.components[0].type else 'Missing' }}
671
+ </td>
672
+ </tr>
673
+ <tr>
674
+ <td><div class="field-tier tier-critical"></div> Model Version</td>
675
+ <td class="{{ 'present' if aibom.components and aibom.components[0].version else 'missing' }}">
676
+ {{ 'Present' if aibom.components and aibom.components[0].version else 'Missing' }}
677
+ </td>
678
+ </tr>
679
+ <tr>
680
+ <td><div class="field-tier tier-important"></div> Model Description</td>
681
+ <td class="{{ 'present' if aibom.components and aibom.components[0].description else 'missing' }}">
682
+ {{ 'Present' if aibom.components and aibom.components[0].description else 'Missing' }}
683
+ </td>
684
+ </tr>
685
 
686
+ <!-- Model Card -->
687
+ <tr>
688
+ <td><div class="field-tier tier-important"></div> Model Parameters</td>
689
+ <td class="{{ 'present' if aibom.components and aibom.components[0].modelCard and aibom.components[0].modelCard.modelParameters else 'missing' }}">
690
+ {{ 'Present' if aibom.components and aibom.components[0].modelCard and aibom.components[0].modelCard.modelParameters else 'Missing' }}
691
+ </td>
692
+ </tr>
693
+ <tr>
694
+ <td><div class="field-tier tier-important"></div> Performance Metrics</td>
695
+ <td class="{{ 'present' if aibom.components and aibom.components[0].modelCard and aibom.components[0].modelCard.quantitativeAnalysis and aibom.components[0].modelCard.quantitativeAnalysis.performanceMetrics else 'missing' }}">
696
+ {{ 'Present' if aibom.components and aibom.components[0].modelCard and aibom.components[0].modelCard.quantitativeAnalysis and aibom.components[0].modelCard.quantitativeAnalysis.performanceMetrics else 'Missing' }}
697
+ </td>
698
+ </tr>
699
+ <tr>
700
+ <td><div class="field-tier tier-supplementary"></div> Ethical Considerations</td>
701
+ <td class="{{ 'present' if aibom.components and aibom.components[0].modelCard and aibom.components[0].modelCard.considerations and aibom.components[0].modelCard.considerations.ethicalConsiderations else 'missing' }}">
702
+ {{ 'Present' if aibom.components and aibom.components[0].modelCard and aibom.components[0].modelCard.considerations and aibom.components[0].modelCard.considerations.ethicalConsiderations else 'Missing' }}
703
+ </td>
704
+ </tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
705
 
706
+ <!-- Training Data -->
707
+ <tr>
708
+ <td><div class="field-tier tier-critical"></div> Training Datasets</td>
709
+ <td class="{{ 'present' if aibom.components and aibom.components[0].trainingData and aibom.components[0].trainingData.datasets else 'missing' }}">
710
+ {{ 'Present' if aibom.components and aibom.components[0].trainingData and aibom.components[0].trainingData.datasets else 'Missing' }}
711
+ </td>
712
+ </tr>
713
+ <tr>
714
+ <td><div class="field-tier tier-important"></div> Data Preprocessing</td>
715
+ <td class="{{ 'present' if aibom.components and aibom.components[0].trainingData and aibom.components[0].trainingData.preprocessing else 'missing' }}">
716
+ {{ 'Present' if aibom.components and aibom.components[0].trainingData and aibom.components[0].trainingData.preprocessing else 'Missing' }}
717
+ </td>
718
+ </tr>
719
+
720
+ <!-- Training Process -->
721
+ <tr>
722
+ <td><div class="field-tier tier-important"></div> Training Method</td>
723
+ <td class="{{ 'present' if aibom.components and aibom.components[0].trainingProcess and aibom.components[0].trainingProcess.trainingMethod else 'missing' }}">
724
+ {{ 'Present' if aibom.components and aibom.components[0].trainingProcess and aibom.components[0].trainingProcess.trainingMethod else 'Missing' }}
725
+ </td>
726
+ </tr>
727
+ <tr>
728
+ <td><div class="field-tier tier-important"></div> Hyperparameters</td>
729
+ <td class="{{ 'present' if aibom.components and aibom.components[0].trainingProcess and aibom.components[0].trainingProcess.hyperparameters else 'missing' }}">
730
+ {{ 'Present' if aibom.components and aibom.components[0].trainingProcess and aibom.components[0].trainingProcess.hyperparameters else 'Missing' }}
731
+ </td>
732
+ </tr>
733
+ <tr>
734
+ <td><div class="field-tier tier-supplementary"></div> Compute Infrastructure</td>
735
+ <td class="{{ 'present' if aibom.components and aibom.components[0].trainingProcess and aibom.components[0].trainingProcess.computeInfrastructure else 'missing' }}">
736
+ {{ 'Present' if aibom.components and aibom.components[0].trainingProcess and aibom.components[0].trainingProcess.computeInfrastructure else 'Missing' }}
737
+ </td>
738
+ </tr>
739
+
740
+ <!-- Evaluation -->
741
+ <tr>
742
+ <td><div class="field-tier tier-important"></div> Evaluation Metrics</td>
743
+ <td class="{{ 'present' if aibom.components and aibom.components[0].evaluation and aibom.components[0].evaluation.metrics else 'missing' }}">
744
+ {{ 'Present' if aibom.components and aibom.components[0].evaluation and aibom.components[0].evaluation.metrics else 'Missing' }}
745
+ </td>
746
+ </tr>
747
+ <tr>
748
+ <td><div class="field-tier tier-important"></div> Evaluation Datasets</td>
749
+ <td class="{{ 'present' if aibom.components and aibom.components[0].evaluation and aibom.components[0].evaluation.datasets else 'missing' }}">
750
+ {{ 'Present' if aibom.components and aibom.components[0].evaluation and aibom.components[0].evaluation.datasets else 'Missing' }}
751
+ </td>
752
+ </tr>
753
+
754
+ <!-- Usage -->
755
+ <tr>
756
+ <td><div class="field-tier tier-important"></div> Intended Use</td>
757
+ <td class="{{ 'present' if aibom.components and aibom.components[0].usage and aibom.components[0].usage.intendedUse else 'missing' }}">
758
+ {{ 'Present' if aibom.components and aibom.components[0].usage and aibom.components[0].usage.intendedUse else 'Missing' }}
759
+ </td>
760
+ </tr>
761
+ <tr>
762
+ <td><div class="field-tier tier-supplementary"></div> Out of Scope Uses</td>
763
+ <td class="{{ 'present' if aibom.components and aibom.components[0].usage and aibom.components[0].usage.outOfScopeUses else 'missing' }}">
764
+ {{ 'Present' if aibom.components and aibom.components[0].usage and aibom.components[0].usage.outOfScopeUses else 'Missing' }}
765
+ </td>
766
+ </tr>
767
+
768
+ <!-- Licenses -->
769
+ <tr>
770
+ <td><div class="field-tier tier-critical"></div> Licenses</td>
771
+ <td class="{{ 'present' if aibom.components and aibom.components[0].licenses else 'missing' }}">
772
+ {{ 'Present' if aibom.components and aibom.components[0].licenses else 'Missing' }}
773
+ </td>
774
+ </tr>
775
+ </table>
776
+ </div>
777
+
778
+ <div id="score-view" class="tab-content">
779
+ <h3>AI SBOM Completeness Score</h3>
780
+
781
+ <div class="total-score-container">
782
+ <div class="total-score">{{ enhancement_report.final_score.total_score|default(0)|round(1) }}/100</div>
783
+ <div class="total-progress">
784
+ <div class="progress-container">
785
+ {% set score = enhancement_report.final_score.total_score|default(0) %}
786
+ <div class="progress-bar
787
+ {{- ' progress-excellent' if score >= 80 -}}
788
+ {{- ' progress-good' if score >= 60 and score < 80 -}}
789
+ {{- ' progress-fair' if score >= 40 and score < 60 -}}
790
+ {{- ' progress-poor' if score < 40 -}}"
791
+ style="width: {{ score }}%">
792
+ {{ score|round(1) }}%
793
+ </div>
794
  </div>
795
+ </div>
796
+ </div>
797
+
798
+ <div class="completeness-profile">
799
+ {% set score = enhancement_report.final_score.total_score|default(0) %}
800
+ <h4>Completeness Profile:
801
+ {% if score >= 80 %}
802
+ <span class="profile-badge profile-advanced">Advanced</span>
803
+ {% elif score >= 60 %}
804
+ <span class="profile-badge profile-standard">Standard</span>
805
+ {% elif score >= 40 %}
806
+ <span class="profile-badge profile-basic">Basic</span>
807
+ {% else %}
808
+ <span class="profile-badge profile-incomplete">Incomplete</span>
809
+ {% endif %}
810
+ </h4>
811
+ <p>
812
+ {% if score >= 80 %}
813
+ This AI SBOM provides comprehensive information about the model, including detailed training data, process, evaluation metrics, and usage guidelines. It meets advanced transparency requirements.
814
+ {% elif score >= 60 %}
815
+ This AI SBOM provides good information about the model, covering most key aspects of its development and usage. It meets standard transparency requirements.
816
+ {% elif score >= 40 %}
817
+ This AI SBOM provides basic information about the model but lacks detail in several areas. It meets minimal transparency requirements.
818
+ {% else %}
819
+ This AI SBOM is incomplete and missing critical information. It does not meet basic transparency requirements.
820
+ {% endif %}
821
+ </p>
822
+ </div>
823
+
824
+ <table class="score-table">
825
+ <tr>
826
+ <th>Category</th>
827
+ <th>Score</th>
828
+ <th>Details</th>
829
+ </tr>
830
+ <tr>
831
+ <td>Basic Information <span class="score-weight">(20%)</span></td>
832
+ <td>
833
+ {% set basic_score = 0 %}
834
+ {% if aibom.components and aibom.components[0].name %}{% set basic_score = basic_score + 5 %}{% endif %}
835
+ {% if aibom.components and aibom.components[0].type %}{% set basic_score = basic_score + 5 %}{% endif %}
836
+ {% if aibom.components and aibom.components[0].version %}{% set basic_score = basic_score + 5 %}{% endif %}
837
+ {% if aibom.components and aibom.components[0].description %}{% set basic_score = basic_score + 5 %}{% endif %}
838
+ {{ basic_score }}/20
839
+ {% if basic_score >= 15 %}
840
+ <span class="score-label label-excellent">Excellent</span>
841
+ {% elif basic_score >= 10 %}
842
+ <span class="score-label label-good">Good</span>
843
+ {% elif basic_score >= 5 %}
844
+ <span class="score-label label-fair">Fair</span>
845
+ {% else %}
846
+ <span class="score-label label-poor">Poor</span>
847
+ {% endif %}
848
+ </td>
849
+ <td>
850
+ {% if basic_score < 20 %}
851
+ Missing:
852
+ {% if not aibom.components or not aibom.components[0].name %}Model Name, {% endif %}
853
+ {% if not aibom.components or not aibom.components[0].type %}Model Type, {% endif %}
854
+ {% if not aibom.components or not aibom.components[0].version %}Model Version, {% endif %}
855
+ {% if not aibom.components or not aibom.components[0].description %}Model Description{% endif %}
856
+ {% else %}
857
+ All basic information is present.
858
+ {% endif %}
859
+ </td>
860
+ </tr>
861
+ <tr>
862
+ <td>Training Data <span class="score-weight">(25%)</span></td>
863
+ <td>
864
+ {% set training_score = 0 %}
865
+ {% if aibom.components and aibom.components[0].trainingData and aibom.components[0].trainingData.datasets %}{% set training_score = training_score + 15 %}{% endif %}
866
+ {% if aibom.components and aibom.components[0].trainingData and aibom.components[0].trainingData.preprocessing %}{% set training_score = training_score + 10 %}{% endif %}
867
+ {{ training_score }}/25
868
+ {% if training_score >= 20 %}
869
+ <span class="score-label label-excellent">Excellent</span>
870
+ {% elif training_score >= 15 %}
871
+ <span class="score-label label-good">Good</span>
872
+ {% elif training_score >= 10 %}
873
+ <span class="score-label label-fair">Fair</span>
874
+ {% else %}
875
+ <span class="score-label label-poor">Poor</span>
876
+ {% endif %}
877
+ </td>
878
+ <td>
879
+ {% if training_score < 25 %}
880
+ Missing:
881
+ {% if not aibom.components or not aibom.components[0].trainingData or not aibom.components[0].trainingData.datasets %}Training Datasets, {% endif %}
882
+ {% if not aibom.components or not aibom.components[0].trainingData or not aibom.components[0].trainingData.preprocessing %}Data Preprocessing{% endif %}
883
+ {% else %}
884
+ All training data information is present.
885
+ {% endif %}
886
+ </td>
887
+ </tr>
888
+ <tr>
889
+ <td>Training Process <span class="score-weight">(20%)</span></td>
890
+ <td>
891
+ {% set process_score = 0 %}
892
+ {% if aibom.components and aibom.components[0].trainingProcess and aibom.components[0].trainingProcess.trainingMethod %}{% set process_score = process_score + 8 %}{% endif %}
893
+ {% if aibom.components and aibom.components[0].trainingProcess and aibom.components[0].trainingProcess.hyperparameters %}{% set process_score = process_score + 8 %}{% endif %}
894
+ {% if aibom.components and aibom.components[0].trainingProcess and aibom.components[0].trainingProcess.computeInfrastructure %}{% set process_score = process_score + 4 %}{% endif %}
895
+ {{ process_score }}/20
896
+ {% if process_score >= 16 %}
897
+ <span class="score-label label-excellent">Excellent</span>
898
+ {% elif process_score >= 12 %}
899
+ <span class="score-label label-good">Good</span>
900
+ {% elif process_score >= 8 %}
901
+ <span class="score-label label-fair">Fair</span>
902
+ {% else %}
903
+ <span class="score-label label-poor">Poor</span>
904
+ {% endif %}
905
+ </td>
906
+ <td>
907
+ {% if process_score < 20 %}
908
+ Missing:
909
+ {% if not aibom.components or not aibom.components[0].trainingProcess or not aibom.components[0].trainingProcess.trainingMethod %}Training Method, {% endif %}
910
+ {% if not aibom.components or not aibom.components[0].trainingProcess or not aibom.components[0].trainingProcess.hyperparameters %}Hyperparameters, {% endif %}
911
+ {% if not aibom.components or not aibom.components[0].trainingProcess or not aibom.components[0].trainingProcess.computeInfrastructure %}Compute Infrastructure{% endif %}
912
+ {% else %}
913
+ All training process information is present.
914
+ {% endif %}
915
+ </td>
916
+ </tr>
917
+ <tr>
918
+ <td>Evaluation <span class="score-weight">(15%)</span></td>
919
+ <td>
920
+ {% set eval_score = 0 %}
921
+ {% if aibom.components and aibom.components[0].evaluation and aibom.components[0].evaluation.metrics %}{% set eval_score = eval_score + 8 %}{% endif %}
922
+ {% if aibom.components and aibom.components[0].evaluation and aibom.components[0].evaluation.datasets %}{% set eval_score = eval_score + 7 %}{% endif %}
923
+ {{ eval_score }}/15
924
+ {% if eval_score >= 12 %}
925
+ <span class="score-label label-excellent">Excellent</span>
926
+ {% elif eval_score >= 8 %}
927
+ <span class="score-label label-good">Good</span>
928
+ {% elif eval_score >= 4 %}
929
+ <span class="score-label label-fair">Fair</span>
930
+ {% else %}
931
+ <span class="score-label label-poor">Poor</span>
932
+ {% endif %}
933
+ </td>
934
+ <td>
935
+ {% if eval_score < 15 %}
936
+ Missing:
937
+ {% if not aibom.components or not aibom.components[0].evaluation or not aibom.components[0].evaluation.metrics %}Evaluation Metrics, {% endif %}
938
+ {% if not aibom.components or not aibom.components[0].evaluation or not aibom.components[0].evaluation.datasets %}Evaluation Datasets{% endif %}
939
+ {% else %}
940
+ All evaluation information is present.
941
+ {% endif %}
942
+ </td>
943
+ </tr>
944
+ <tr>
945
+ <td>Usage & Licensing <span class="score-weight">(20%)</span></td>
946
+ <td>
947
+ {% set usage_score = 0 %}
948
+ {% if aibom.components and aibom.components[0].usage and aibom.components[0].usage.intendedUse %}{% set usage_score = usage_score + 8 %}{% endif %}
949
+ {% if aibom.components and aibom.components[0].usage and aibom.components[0].usage.outOfScopeUses %}{% set usage_score = usage_score + 2 %}{% endif %}
950
+ {% if aibom.components and aibom.components[0].licenses %}{% set usage_score = usage_score + 10 %}{% endif %}
951
+ {{ usage_score }}/20
952
+ {% if usage_score >= 16 %}
953
+ <span class="score-label label-excellent">Excellent</span>
954
+ {% elif usage_score >= 12 %}
955
+ <span class="score-label label-good">Good</span>
956
+ {% elif usage_score >= 8 %}
957
+ <span class="score-label label-fair">Fair</span>
958
+ {% else %}
959
+ <span class="score-label label-poor">Poor</span>
960
+ {% endif %}
961
+ </td>
962
+ <td>
963
+ {% if usage_score < 20 %}
964
+ Missing:
965
+ {% if not aibom.components or not aibom.components[0].usage or not aibom.components[0].usage.intendedUse %}Intended Use, {% endif %}
966
+ {% if not aibom.components or not aibom.components[0].usage or not aibom.components[0].usage.outOfScopeUses %}Out of Scope Uses, {% endif %}
967
+ {% if not aibom.components or not aibom.components[0].licenses %}Licenses{% endif %}
968
+ {% else %}
969
+ All usage and licensing information is present.
970
+ {% endif %}
971
+ </td>
972
+ </tr>
973
+ </table>
974
+
975
+ <div class="recommendations">
976
+ <h4>Recommendations for Improvement</h4>
977
+ <ul>
978
+ {% if not aibom.components or not aibom.components[0].name or not aibom.components[0].type or not aibom.components[0].version %}
979
+ <li><span class="importance-indicator high-importance">β˜…β˜…β˜…</span> Add basic model information (name, type, version)</li>
980
+ {% endif %}
981
 
982
+ {% if not aibom.components or not aibom.components[0].trainingData or not aibom.components[0].trainingData.datasets %}
983
+ <li><span class="importance-indicator high-importance">β˜…β˜…β˜…</span> Add information about training datasets</li>
984
+ {% endif %}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
985
 
986
+ {% if not aibom.components or not aibom.components[0].licenses %}
987
+ <li><span class="importance-indicator high-importance">β˜…β˜…β˜…</span> Add licensing information</li>
988
+ {% endif %}
989
+
990
+ {% if not aibom.components or not aibom.components[0].trainingProcess or not aibom.components[0].trainingProcess.trainingMethod or not aibom.components[0].trainingProcess.hyperparameters %}
991
+ <li><span class="importance-indicator medium-importance">β˜…β˜…β˜†</span> Add training process details (method, hyperparameters)</li>
992
+ {% endif %}
993
+
994
+ {% if not aibom.components or not aibom.components[0].evaluation or not aibom.components[0].evaluation.metrics %}
995
+ <li><span class="importance-indicator medium-importance">β˜…β˜…β˜†</span> Add evaluation metrics</li>
996
+ {% endif %}
997
+
998
+ {% if not aibom.components or not aibom.components[0].usage or not aibom.components[0].usage.intendedUse %}
999
+ <li><span class="importance-indicator medium-importance">β˜…β˜…β˜†</span> Add intended use information</li>
1000
+ {% endif %}
1001
+
1002
+ {% if not aibom.components or not aibom.components[0].modelCard or not aibom.components[0].modelCard.considerations or not aibom.components[0].modelCard.considerations.ethicalConsiderations %}
1003
+ <li><span class="importance-indicator low-importance">β˜…β˜†β˜†</span> Add ethical considerations</li>
1004
+ {% endif %}
1005
+ </ul>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1006
  </div>
1007
  </div>
1008
 
1009
  <script>
1010
+ function downloadJSON() {
1011
+ const a = document.createElement('a');
1012
+ a.href = '{{ download_url }}';
1013
+ a.download = '{{ model_id|replace("/", "_") }}_aibom.json';
1014
+ document.body.appendChild(a);
1015
+ a.click();
1016
+ document.body.removeChild(a);
1017
+ }
1018
+
1019
  function switchTab(tabId) {
1020
  // Hide all tab contents
1021
+ const tabContents = document.getElementsByClassName('tab-content');
1022
+ for (let i = 0; i < tabContents.length; i++) {
1023
  tabContents[i].classList.remove('active');
1024
  }
1025
 
1026
  // Deactivate all tabs
1027
+ const tabs = document.getElementsByClassName('aibom-tab');
1028
+ for (let i = 0; i < tabs.length; i++) {
1029
  tabs[i].classList.remove('active');
1030
  }
1031
 
1032
  // Activate the selected tab and content
1033
  document.getElementById(tabId).classList.add('active');
1034
+ document.querySelector('.aibom-tab[onclick="switchTab(\'' + tabId + '\')"]').classList.add('active');
 
1035
  }
1036
 
1037
  function toggleCollapsible(element) {
1038
  element.classList.toggle('active');
1039
+ const content = element.nextElementSibling;
 
 
1040
  if (content.classList.contains('active')) {
1041
+ content.classList.remove('active');
1042
  } else {
1043
+ content.classList.add('active');
1044
  }
1045
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1046
  </script>
1047
  </body>
1048
  </html>