Download src/templates/result.html from GenAISecurityProject/OWASP-AIBOM-Generator: direct link, hf CLI and curl.
- Browser
- Download file 48.9 kB
-
https://huggingface.co/spaces/GenAISecurityProject/OWASP-AIBOM-Generator/resolve/main/src/templates/result.html
- Command line
-
hf download hf://spaces/GenAISecurityProject/OWASP-AIBOM-Generator/src/templates/result.html
-
curl -L -o result.html https://huggingface.co/spaces/GenAISecurityProject/OWASP-AIBOM-Generator/resolve/main/src/templates/result.html
48.9 kB
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>AIBOM Generated</title> | |
| <link rel="stylesheet" href="{{ static_root|default('/static') }}/css/style.css?v=2.0"> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <!-- Header --> | |
| {% include 'includes/header.html' %} | |
| <!-- Success Message | |
| <div class="success-message"> | |
| <h2>β AIBOM is Generated Successfully for <span class="model-name">{{ model_id }}</span></h2> | |
| </div> --> | |
| <!-- Key Information --> | |
| <div class="key-info"> | |
| <h3>π AIBOM Summary</h3> | |
| <div class="aibom-property"> | |
| <span class="property-name">Model:</span> | |
| <span class="property-value"><a href="https://huggingface.co/{{ model_id }}" target="_blank">{{ model_id | |
| }}</a></span> | |
| </div> | |
| <div class="aibom-property"> | |
| <span class="property-name">Generated:</span> | |
| <span class="property-value">{{ aibom.metadata.timestamp }}</span> | |
| </div> | |
| <div class="aibom-property"> | |
| <span class="property-name">SBOM Format:</span> | |
| <span class="property-value"> | |
| <a href="https://cyclonedx.org/docs/1.6/json/#components_items_modelCard" target="_blank">{{ | |
| aibom.bomFormat }} {{ aibom.specVersion }}</a>, | |
| <a href="https://cyclonedx.org/docs/1.7/json/#components_items_modelCard" target="_blank">{{ | |
| aibom.bomFormat }} 1.7</a> | |
| </span> | |
| </div> | |
| <div class="aibom-property"> | |
| <span class="property-name">Serial Number:</span> | |
| <span class="property-value">{{ aibom.serialNumber }}</span> | |
| </div> | |
| </div> | |
| <!-- Calculate Shared Score State --> | |
| {% set score_percent = (completeness_score.total_score if completeness_score.total_score != 'Undefined' else 0) | |
| | float %} | |
| {% if score_percent >= 90 %} | |
| {% set score_class = 'progress-excellent' %} | |
| {% set score_label = 'Excellent' %} | |
| {% elif score_percent >= 70 %} | |
| {% set score_class = 'progress-good' %} | |
| {% set score_label = 'Good' %} | |
| {% elif score_percent >= 50 %} | |
| {% set score_class = 'progress-fair' %} | |
| {% set score_label = 'Fair' %} | |
| {% else %} | |
| {% set score_class = 'progress-poor' %} | |
| {% set score_label = 'Poor' %} | |
| {% endif %} | |
| <!-- Completeness Profile & Download Section --> | |
| <div class="completeness-profile {{ score_class }}-border" | |
| style="display: flex; flex-wrap: wrap; gap: 0; align-items: center;"> | |
| <div class="completeness-left" | |
| style="flex: 1 1 50%; min-width: 300px; padding-right: 20px; box-sizing: border-box;"> | |
| {% if completeness_score.completeness_profile %} | |
| <h3 style="margin-top:0; margin-bottom:15px;">π Completeness Assessment</h3> | |
| <div style="display: flex; gap: 15px; align-items: center;"> | |
| <span class="profile-badge profile-{{ completeness_score.completeness_profile.name|lower }}"> | |
| {{ completeness_score.completeness_profile.name }} | |
| </span> | |
| <span>{{ completeness_score.completeness_profile.description }}</span> | |
| </div> | |
| {% endif %} | |
| </div> | |
| <div class="completeness-right" style="flex: 1 1 50%; min-width: 300px; box-sizing: border-box;"> | |
| <div class="download-section-inner"> | |
| <h3 style="margin-top:0; margin-bottom:15px;">πΎ Download your AIBOM</h3> | |
| <div class="download-buttons" style="display: flex; gap: 10px;"> | |
| <button onclick="downloadJSON(AIBOM_CDX_JSON_1_6, FILENAME_BASE + '_aibom_1_6.json')"> | |
| <img src="{{ static_root|default('/static') }}/images/cdx.webp" alt="CycloneDX Logo" | |
| width="16" height="16" style="filter: brightness(0) invert(1);"> | |
| CycloneDX 1.6 | |
| </button> | |
| <button onclick="downloadJSON(AIBOM_CDX_JSON_1_7, FILENAME_BASE + '_aibom_1_7.json')"> | |
| <img src="{{ static_root|default('/static') }}/images/cdx.webp" alt="CycloneDX Logo" | |
| width="16" height="16" style="filter: brightness(0) invert(1);"> | |
| CycloneDX 1.7 | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Tabbed Content --> | |
| <div class="aibom-viewer"> | |
| <div class="aibom-tabs"> | |
| <div class="aibom-tab active" onclick="switchTab('human-view')">Human-Friendly View</div> | |
| <div class="aibom-tab" onclick="switchTab('field-checklist')">Field Checklist</div> | |
| <div class="aibom-tab" onclick="switchTab('score-view')">Score Report</div> | |
| <div class="aibom-tab" onclick="switchTab('json-view')">JSON View</div> | |
| </div> | |
| <!-- Human-Friendly View Tab --> | |
| <div id="human-view" class="tab-content active"> | |
| <div class="aibom-section"> | |
| <h4>π€ AI Model Information</h4> | |
| <div class="aibom-property"> | |
| <span class="property-name">Name:</span> | |
| <span class="property-value"> | |
| {{ aibom.components[0].name if aibom.components else 'Not specified' }} | |
| </span> | |
| </div> | |
| <div class="aibom-property"> | |
| <span class="property-name">Type:</span> | |
| <span class="property-value"> | |
| {{ aibom.components[0].type if aibom.components else 'Not specified' }} | |
| </span> | |
| </div> | |
| <div class="aibom-property"> | |
| <span class="property-name">Version:</span> | |
| <span class="property-value">{{ aibom.components[0].version if aibom.components else 'Not | |
| specified' }}</span> | |
| </div> | |
| <div class="aibom-property"> | |
| <span class="property-name">Description:</span> | |
| <span class="property-value">{{ aibom.components[0].description if aibom.components and | |
| aibom.components[0].description else 'Not specified' }}</span> | |
| </div> | |
| <div class="aibom-property"> | |
| <span class="property-name">PURL:</span> | |
| <span class="property-value">{{ aibom.components[0].purl if aibom.components and | |
| aibom.components[0].purl else 'Not specified' }}</span> | |
| </div> | |
| {% if aibom.components and aibom.components[0].licenses %} | |
| <div class="aibom-property"> | |
| <span class="property-name">Licenses:</span> | |
| <span class="property-value"> | |
| {% for license in aibom.components[0].licenses %} | |
| <span class="tag"> | |
| {% if license.license %} | |
| {{ license.license.id if license.license.id else license.license.name }} | |
| {% else %} | |
| Unknown | |
| {% endif %} | |
| </span> | |
| {% endfor %} | |
| </span> | |
| </div> | |
| {% endif %} | |
| </div> | |
| {% if aibom.components and aibom.components[0].modelCard %} | |
| <div class="aibom-section"> | |
| <h4>π Model Card</h4> | |
| {% if aibom.components[0].modelCard.modelParameters %} | |
| <div class="aibom-property"> | |
| <span class="property-name">Architecture:</span> | |
| <span class="property-value"> | |
| {{ aibom.components[0].modelCard.modelParameters.modelArchitecture if | |
| aibom.components[0].modelCard.modelParameters.modelArchitecture else 'Not specified' }} | |
| </span> | |
| </div> | |
| <div class="aibom-property"> | |
| <span class="property-name">Task:</span> | |
| <span class="property-value">{{ aibom.components[0].modelCard.modelParameters.task if | |
| aibom.components[0].modelCard.modelParameters.task else 'Not specified' }}</span> | |
| </div> | |
| {% endif %} | |
| {% if aibom.components[0].modelCard.properties %} | |
| <div class="aibom-property"> | |
| <span class="property-name">Additional Properties:</span> | |
| <span class="property-value"> | |
| {% for prop in aibom.components[0].modelCard.properties %} | |
| <span class="tag">{{ prop.name }}: {{ prop.value }}</span> | |
| {% endfor %} | |
| </span> | |
| </div> | |
| {% endif %} | |
| {% set hp_props = [] %} | |
| {% set quant_props = [] %} | |
| {% if aibom.components[0].properties %} | |
| {% for prop in aibom.components[0].properties %} | |
| {% if prop.name.startswith('hyperparameter:') %}{% if hp_props.append(prop) %}{% endif %}{% endif %} | |
| {% if prop.name.startswith('quantization:') %}{% if quant_props.append(prop) %}{% endif %}{% endif | |
| %} | |
| {% endfor %} | |
| {% endif %} | |
| {% if hp_props %} | |
| <div class="aibom-property"> | |
| <span class="property-name">Hyperparameters:</span> | |
| <span class="property-value"> | |
| {% for prop in hp_props %} | |
| <span class="tag">{{ prop.name.split(':')[1] | replace('_', ' ') | title }}: {{ prop.value | |
| }}</span> | |
| {% endfor %} | |
| </span> | |
| </div> | |
| {% endif %} | |
| {% if quant_props %} | |
| <div class="aibom-property"> | |
| <span class="property-name">Quantization:</span> | |
| <span class="property-value"> | |
| {% for prop in quant_props %} | |
| <span class="tag">{{ prop.name.split(':')[1] | replace('_', ' ') | title }}: {{ prop.value | |
| }}</span> | |
| {% endfor %} | |
| </span> | |
| </div> | |
| {% endif %} | |
| </div> | |
| {% endif %} | |
| {% if aibom.externalReferences %} | |
| <div class="aibom-section"> | |
| <h4>π External References</h4> | |
| {% for ref in aibom.externalReferences %} | |
| <div class="aibom-property"> | |
| <span class="property-name">{{ ref.type|title }}:</span> | |
| <span class="property-value"><a href="{{ ref.url }}" target="_blank">{{ ref.url }}</a></span> | |
| </div> | |
| {% endfor %} | |
| </div> | |
| {% endif %} | |
| <div class="aibom-section"> | |
| <h4>π οΈ Generation Metadata</h4> | |
| <div class="aibom-property"> | |
| <span class="property-name">Generated by:</span> | |
| <span class="property-value">{{ aibom.metadata.tools.components[0].name if aibom.metadata.tools | |
| and aibom.metadata.tools.components else 'Unknown' }}</span> | |
| </div> | |
| <div class="aibom-property"> | |
| <span class="property-name">Timestamp:</span> | |
| <span class="property-value">{{ aibom.metadata.timestamp }}</span> | |
| </div> | |
| {% if aibom.components and aibom.components[0].purl %} | |
| <div class="aibom-property"> | |
| <span class="property-name">Component PURL:</span> | |
| <span class="property-value"><a href="https://huggingface.co/{{ model_id }}" target="_blank">{{ | |
| aibom.components[0].purl }}</a></span> | |
| </div> | |
| {% elif aibom.metadata.component %} | |
| <div class="aibom-property"> | |
| <span class="property-name">Component PURL:</span> | |
| <span class="property-value">{{ aibom.metadata.component['bom-ref'] }}</span> | |
| </div> | |
| {% endif %} | |
| </div> | |
| </div> | |
| <!-- Field Checklist Tab --> | |
| <div id="field-checklist" class="tab-content"> | |
| <div class="content-section"> | |
| <h3>Field Checklist & Mapping</h3> | |
| <!-- Field Type Legend --> | |
| <div class="field-type-legend"> | |
| <h4>Legend</h4> | |
| <div class="legend-item"> | |
| <span class="field-tier tier-critical"></span> | |
| <span>Critical</span> | |
| </div> | |
| <div class="legend-item"> | |
| <span class="field-tier tier-important"></span> | |
| <span>Important</span> | |
| </div> | |
| <div class="legend-item"> | |
| <span class="field-tier tier-supplementary"></span> | |
| <span>Supplementary</span> | |
| </div> | |
| <div class="legend-item"> | |
| <strong>CDX</strong> = CycloneDX Standard | |
| </div> | |
| <div class="legend-item"> | |
| <strong>AI</strong> = AI-Specific Extension | |
| </div> | |
| </div> | |
| <p>This breakdown outlines field categories and statuses in the AIBOM generated for model <strong><a | |
| href="https://huggingface.co/{{ model_id }}" target="_blank">{{ model_id | |
| }}</a></strong>, showing how each field impacts the completeness score.</p> | |
| {% if completeness_score.field_checklist %} | |
| <!-- Required Fields Category --> | |
| <div class="category-table"> | |
| <h4>Required Fields Category</h4> | |
| <table> | |
| <thead> | |
| <tr> | |
| <th>Status</th> | |
| <th>Field Name</th> | |
| <th>Actual Location</th> | |
| <th>Tier</th> | |
| <th>Type</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| {% set required_fields = ['bomFormat', 'specVersion', 'serialNumber', 'version'] %} | |
| {% for field in required_fields %} | |
| <tr> | |
| <td> | |
| {% if completeness_score.field_checklist.get(field, '').startswith('β') %} | |
| <span class="check-mark">β</span> | |
| {% else %} | |
| <span class="x-mark">β</span> | |
| {% endif %} | |
| </td> | |
| <td>{{ field }}</td> | |
| <td> | |
| {% if completeness_score.field_checklist.get(field, '').startswith('β') %} | |
| $.{{ field }} | |
| {% else %} | |
| Not found | |
| {% endif %} | |
| </td> | |
| <td><span class="field-tier tier-critical"></span> Critical</td> | |
| <td> | |
| {% set f_type = completeness_score.field_types.get(field, 'Unknown') %} | |
| {% set f_url = completeness_score.reference_urls.get(field, '') if | |
| completeness_score.reference_urls else '' %} | |
| {% if f_url %} | |
| <a href="{{ f_url }}" target="_blank">{{ f_type }}</a> | |
| {% else %} | |
| {{ f_type }} | |
| {% endif %} | |
| </td> | |
| </tr> | |
| {% endfor %} | |
| </tbody> | |
| </table> | |
| <div class="category-result"> | |
| Result: {{ completeness_score.category_details.required_fields.present_fields if | |
| completeness_score.category_details else 'N/A' }}/{{ | |
| completeness_score.category_details.required_fields.total_fields if | |
| completeness_score.category_details else 'N/A' }} present | |
| ({{ completeness_score.category_details.required_fields.percentage if | |
| completeness_score.category_details else 'N/A' }}%) = | |
| {{ completeness_score.section_scores.required_fields if completeness_score.section_scores | |
| else 'N/A' }}/20 points | |
| </div> | |
| </div> | |
| <!-- Metadata Category --> | |
| <div class="category-table"> | |
| <h4>Metadata Category</h4> | |
| <table> | |
| <thead> | |
| <tr> | |
| <th>Status</th> | |
| <th>Field Name</th> | |
| <th>Actual Location</th> | |
| <th>Tier</th> | |
| <th>Type</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| {% set metadata_fields = [ | |
| ('primaryPurpose', 'Critical'), | |
| ('suppliedBy', 'Critical'), | |
| ('standardCompliance', 'Supplementary'), | |
| ('domain', 'Supplementary'), | |
| ('autonomyType', 'Supplementary') | |
| ] %} | |
| {% for field, tier in metadata_fields %} | |
| <tr> | |
| <td> | |
| {% if completeness_score.field_checklist.get(field, '').startswith('β') %} | |
| <span class="check-mark">β</span> | |
| {% else %} | |
| <span class="x-mark">β</span> | |
| {% endif %} | |
| </td> | |
| <td>{{ field }}</td> | |
| <td> | |
| {% if completeness_score.field_checklist.get(field, '').startswith('β') %} | |
| {% if field == 'primaryPurpose' %} | |
| $.components[0].modelCard.modelParameters.task | |
| {% elif field == 'suppliedBy' %} | |
| $.components[0].supplier.name | |
| {% else %} | |
| $.components[0].modelCard.properties[name="{{ field }}"] | |
| {% endif %} | |
| {% else %} | |
| Not found | |
| {% endif %} | |
| </td> | |
| <td><span class="field-tier tier-{{ tier|lower }}"></span> {{ tier }}</td> | |
| <td> | |
| {% set f_type = completeness_score.field_types.get(field, 'Unknown') %} | |
| {% set f_url = completeness_score.reference_urls.get(field, '') if | |
| completeness_score.reference_urls else '' %} | |
| {% if f_url %} | |
| <a href="{{ f_url }}" target="_blank">{{ f_type }}</a> | |
| {% else %} | |
| {{ f_type }} | |
| {% endif %} | |
| </td> | |
| </tr> | |
| {% endfor %} | |
| </tbody> | |
| </table> | |
| <div class="category-result"> | |
| Result: {{ completeness_score.category_details.metadata.present_fields if | |
| completeness_score.category_details else 'N/A' }}/{{ | |
| completeness_score.category_details.metadata.total_fields if | |
| completeness_score.category_details else 'N/A' }} present | |
| ({{ completeness_score.category_details.metadata.percentage if | |
| completeness_score.category_details else 'N/A' }}%) = | |
| {{ completeness_score.section_scores.metadata if completeness_score.section_scores else | |
| 'N/A' }}/20 points | |
| </div> | |
| </div> | |
| <!-- Component Basic Category --> | |
| <div class="category-table"> | |
| <h4>Component Basic Category</h4> | |
| <table> | |
| <thead> | |
| <tr> | |
| <th>Status</th> | |
| <th>Field Name</th> | |
| <th>Actual Location</th> | |
| <th>Tier</th> | |
| <th>Type</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| {% set component_basic_fields = [ | |
| ('name', 'Critical'), | |
| ('type', 'Critical'), | |
| ('component_version', 'Critical'), | |
| ('purl', 'Important'), | |
| ('description', 'Important'), | |
| ('licenses', 'Important') | |
| ] %} | |
| {% for field, tier in component_basic_fields %} | |
| <tr> | |
| <td> | |
| {% if completeness_score.field_checklist.get(field, '').startswith('β') %} | |
| <span class="check-mark">β</span> | |
| {% else %} | |
| <span class="x-mark">β</span> | |
| {% endif %} | |
| </td> | |
| <td>{% if field == 'component_version' %}version{% else %}{{ field }}{% endif %} | |
| </td> | |
| <td> | |
| {% if completeness_score.field_checklist.get(field, '').startswith('β') %} | |
| {% if field == 'component_version' %} | |
| $.components[0].version | |
| {% else %} | |
| $.components[0].{{ field }} | |
| {% endif %} | |
| {% else %} | |
| {% if field == 'description' %} | |
| Not found in component level | |
| {% else %} | |
| Not found | |
| {% endif %} | |
| {% endif %} | |
| </td> | |
| <td><span class="field-tier tier-{{ tier|lower }}"></span> {{ tier }}</td> | |
| <td> | |
| {% set f_type = completeness_score.field_types.get(field, 'Unknown') %} | |
| {% set f_url = completeness_score.reference_urls.get(field, '') if | |
| completeness_score.reference_urls else '' %} | |
| {% if f_url %} | |
| <a href="{{ f_url }}" target="_blank">{{ f_type }}</a> | |
| {% else %} | |
| {{ f_type }} | |
| {% endif %} | |
| </td> | |
| </tr> | |
| {% endfor %} | |
| </tbody> | |
| </table> | |
| <div class="category-result"> | |
| Result: {{ completeness_score.category_details.component_basic.present_fields if | |
| completeness_score.category_details else 'N/A' }}/{{ | |
| completeness_score.category_details.component_basic.total_fields if | |
| completeness_score.category_details else 'N/A' }} present | |
| ({{ completeness_score.category_details.component_basic.percentage if | |
| completeness_score.category_details else 'N/A' }}%) = | |
| {{ completeness_score.section_scores.component_basic if completeness_score.section_scores | |
| else 'N/A' }}/20 points | |
| </div> | |
| </div> | |
| <!-- Component Model Card Category --> | |
| <div class="category-table"> | |
| <h4>Component Model Card Category</h4> | |
| <table> | |
| <thead> | |
| <tr> | |
| <th>Status</th> | |
| <th>Field Name</th> | |
| <th>Actual Location</th> | |
| <th>Tier</th> | |
| <th>Type</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| {% set model_card_fields = completeness_score.category_fields_list.component_model_card | |
| if completeness_score and completeness_score.category_fields_list else [] %} | |
| {% for field_item in model_card_fields %} | |
| {% set field = field_item.name %} | |
| {% set tier = field_item.tier %} | |
| <tr> | |
| <td> | |
| {% if completeness_score.field_checklist.get(field, '').startswith('β') %} | |
| <span class="check-mark">β</span> | |
| {% else %} | |
| <span class="x-mark">β</span> | |
| {% endif %} | |
| </td> | |
| <td>{{ field }}</td> | |
| <td> | |
| {% if completeness_score.field_checklist.get(field, '').startswith('β') %} | |
| {{ field_item.path }} | |
| {% else %} | |
| Not found | |
| {% endif %} | |
| </td> | |
| <td><span class="field-tier tier-{{ tier|lower }}"></span> {{ tier }}</td> | |
| <td> | |
| {% set f_type = completeness_score.field_types.get(field, 'Unknown') %} | |
| {% set f_url = completeness_score.reference_urls.get(field, '') if | |
| completeness_score.reference_urls else '' %} | |
| {% if f_url %} | |
| <a href="{{ f_url }}" target="_blank">{{ f_type }}</a> | |
| {% else %} | |
| {{ f_type }} | |
| {% endif %} | |
| </td> | |
| </tr> | |
| {% endfor %} | |
| </tbody> | |
| </table> | |
| <div class="category-result"> | |
| Result: {{ completeness_score.category_details.component_model_card.present_fields if | |
| completeness_score.category_details else 'N/A' }}/{{ | |
| completeness_score.category_details.component_model_card.total_fields if | |
| completeness_score.category_details else 'N/A' }} present | |
| ({{ completeness_score.category_details.component_model_card.percentage if | |
| completeness_score.category_details else 'N/A' }}%) = | |
| {{ completeness_score.section_scores.component_model_card if | |
| completeness_score.section_scores else 'N/A' }}/30 points | |
| </div> | |
| </div> | |
| <!-- External References Category --> | |
| <div class="category-table"> | |
| <h4>External References Category</h4> | |
| <table> | |
| <thead> | |
| <tr> | |
| <th>Status</th> | |
| <th>Field Name</th> | |
| <th>Actual Location</th> | |
| <th>Tier</th> | |
| <th>Type</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| {% set external_ref_fields = completeness_score.category_fields_list.external_references | |
| if completeness_score and completeness_score.category_fields_list else [] %} | |
| {% for field_item in external_ref_fields %} | |
| {% set field = field_item.name %} | |
| {% set tier = field_item.tier %} | |
| <tr> | |
| <td> | |
| {% if completeness_score.field_checklist.get(field, '').startswith('β') %} | |
| <span class="check-mark">β</span> | |
| {% else %} | |
| <span class="x-mark">β</span> | |
| {% endif %} | |
| </td> | |
| <td>{{ field }}</td> | |
| <td> | |
| {% if completeness_score.field_checklist.get(field, '').startswith('β') %} | |
| {{ field_item.path }} | |
| {% else %} | |
| Not found | |
| {% endif %} | |
| </td> | |
| <td><span class="field-tier tier-{{ tier|lower }}"></span> {{ tier }}</td> | |
| <td> | |
| {% set f_type = completeness_score.field_types.get(field, 'Unknown') %} | |
| {% set f_url = completeness_score.reference_urls.get(field, '') if | |
| completeness_score.reference_urls else '' %} | |
| {% if f_url %} | |
| <a href="{{ f_url }}" target="_blank">{{ f_type }}</a> | |
| {% else %} | |
| {{ f_type }} | |
| {% endif %} | |
| </td> | |
| </tr> | |
| {% endfor %} | |
| </tbody> | |
| </table> | |
| <div class="category-result"> | |
| Result: {{ completeness_score.category_details.external_references.present_fields if | |
| completeness_score.category_details else 'N/A' }}/{{ | |
| completeness_score.category_details.external_references.total_fields if | |
| completeness_score.category_details else 'N/A' }} present | |
| ({{ completeness_score.category_details.external_references.percentage if | |
| completeness_score.category_details else 'N/A' }}%) = | |
| {{ completeness_score.section_scores.external_references if | |
| completeness_score.section_scores else 'N/A' }}/10 points | |
| </div> | |
| </div> | |
| {% else %} | |
| <p>Field checklist data not available.</p> | |
| {% endif %} | |
| </div> | |
| </div> | |
| <!-- Score Report Tab --> | |
| <div id="score-view" class="tab-content"> | |
| <div class="content-section"> | |
| <h3>π Completeness Score Report</h3> | |
| <!-- Total Score Display --> | |
| <div class="total-score-container"> | |
| <div class="total-score">{{ (completeness_score.total_score if completeness_score.total_score != | |
| "Undefined" else 0)|round(1) }}/100</div> | |
| <div class="total-progress"> | |
| <div class="progress-container"> | |
| <div class="progress-bar {{ score_class }}" | |
| style="width: {{ score_percent|round|int }}%"> | |
| {{ score_percent|int }}% {{ score_label }} | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Specific Breakdown for This SBOM --> | |
| <div class="note-box"> | |
| <h4>Your AIBOM Breakdown</h4> | |
| <p><strong>Model:</strong> <a href="https://huggingface.co/{{ model_id }}" target="_blank">{{ | |
| model_id }}</a></p> | |
| <table class="score-table"> | |
| <thead> | |
| <tr> | |
| <th>Category</th> | |
| <th>Fields Present</th> | |
| <th>Score</th> | |
| <th>Progress</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| {% if completeness_score.category_details and completeness_score.section_scores %} | |
| {% set categories = [ | |
| ('Required Fields', 'required_fields', 20), | |
| ('Metadata', 'metadata', 20), | |
| ('Component Basic', 'component_basic', 20), | |
| ('Model Card', 'component_model_card', 30), | |
| ('External References', 'external_references', 10) | |
| ] %} | |
| {% for display_name, key, max_score in categories %} | |
| <tr> | |
| <td>{{ display_name }}</td> | |
| <td>{{ completeness_score.category_details[key].present_fields }}/{{ | |
| completeness_score.category_details[key].total_fields }}</td> | |
| <td>{{ completeness_score.section_scores[key]|round(1) }}/{{ max_score }}</td> | |
| <td> | |
| <div class="progress-container"> | |
| {% set percentage = completeness_score.category_details[key].percentage %} | |
| {% if percentage >= 80 %} | |
| {% set progress_class = "progress-excellent" %} | |
| {% elif percentage >= 60 %} | |
| {% set progress_class = "progress-good" %} | |
| {% elif percentage >= 40 %} | |
| {% set progress_class = "progress-fair" %} | |
| {% else %} | |
| {% set progress_class = "progress-poor" %} | |
| {% endif %} | |
| <div class="progress-bar {{ progress_class }}" | |
| style="width: {{ percentage|round|int }}%">{{ percentage|round|int }}% | |
| </div> | |
| </div> | |
| </td> | |
| </tr> | |
| {% endfor %} | |
| {% else %} | |
| <tr> | |
| <td colspan="4">Breakdown data not available</td> | |
| </tr> | |
| {% endif %} | |
| </tbody> | |
| </table> | |
| </div> | |
| <p><strong>Calculation:</strong></p> | |
| <p>Subtotal: | |
| {% if completeness_score.section_scores %} | |
| {% for category, score in completeness_score.section_scores.items() %} | |
| {{ score|round(1) }}{% if not loop.last %} + {% endif %} | |
| {% endfor %} | |
| = <strong>{{ completeness_score.subtotal_score|round(1) }}/100</strong> | |
| {% else %} | |
| <strong>{{ completeness_score.subtotal_score|round(1) }}/100</strong> | |
| {% endif %} | |
| </p> | |
| {% if completeness_score.penalty_applied %} | |
| <p>Penalty Applied: <strong>-{{ completeness_score.penalty_percentage }}%</strong> ({{ | |
| completeness_score.penalty_reason }})</p> | |
| <p>Final Score: {{ completeness_score.subtotal_score|round(1) }} Γ {{ | |
| completeness_score.penalty_factor }} = <strong>{{ completeness_score.total_score|round(1) | |
| }}/100</strong></p> | |
| {% else %} | |
| <p>No penalties applied</p> | |
| <p>Final Score: <strong>{{ completeness_score.total_score|round(1) }}/100</strong></p> | |
| {% endif %} | |
| </div> | |
| <!-- Missing Fields Analysis --> | |
| {% if completeness_score.missing_counts %} | |
| <div class="missing-fields"> | |
| <h4>Missing Fields Summary</h4> | |
| <ul> | |
| <li><strong>Critical:</strong> {{ completeness_score.missing_counts.critical }} missing</li> | |
| <li><strong>Important:</strong> {{ completeness_score.missing_counts.important }} missing</li> | |
| <li><strong>Supplementary:</strong> {{ completeness_score.missing_counts.supplementary }} | |
| missing</li> | |
| </ul> | |
| {% if completeness_score.missing_counts.important >= 5 %} | |
| <p><strong>Impact:</strong> Missing multiple critical and/or important fields will incur penalties | |
| according to the Penalty Structure.</p> | |
| {% endif %} | |
| </div> | |
| {% endif %} | |
| <!-- Recommendations --> | |
| {% if completeness_score.recommendations %} | |
| <div class="recommendations"> | |
| <h4>General Recommendations to Improve AIBOM Completeness</h4> | |
| <ul> | |
| <li><strong>Required Fields:</strong> Ensure the model is published with a clear name, version, | |
| and hosting platform information to allow proper SBOM structuring.</li> | |
| <li><strong>Metadata:</strong> Include author or organization name, purpose of the model, and | |
| relevant timestamps in the model repository or card.</li> | |
| <li><strong>Component Basic:</strong> Provide a descriptive model title, a meaningful | |
| description, a valid license, and a consistent version reference (e.g., tags or commits). | |
| </li> | |
| <li><strong>Model Card:</strong> Fill out structured sections for model parameters, evaluation | |
| metrics, limitations, and ethical considerations to enable full transparency.</li> | |
| <li><strong>External References:</strong> Add links to source code, datasets, documentation, and | |
| versioned download locations to support traceability and reproducibility.</li> | |
| </ul> | |
| </div> | |
| <!-- Generic Scoring Explanation --> | |
| <div class="scoring-rubric"> | |
| <h4>How AIBOM Completeness is Scored</h4> | |
| <p>The completeness score evaluates how well your AIBOM documents the model across five key | |
| categories:</p> | |
| <ul> | |
| <li><strong>Required Fields ({{ completeness_score.category_details.required_fields.max_points | |
| if completeness_score.category_details else 'N/A' }} points):</strong> Basic SBOM | |
| structure mandated by CycloneDX | |
| </li> | |
| <li><strong>Metadata ({{ completeness_score.category_details.metadata.max_points if | |
| completeness_score.category_details else 'N/A' }} points):</strong> Information about | |
| the SBOM generation and model | |
| purpose</li> | |
| <li><strong>Component Basic ({{ completeness_score.category_details.component_basic.max_points | |
| if completeness_score.category_details else 'N/A' }} points):</strong> Essential model | |
| identification and licensing | |
| </li> | |
| <li><strong>Model Card ({{ completeness_score.category_details.component_model_card.max_points | |
| if completeness_score.category_details else 'N/A' }} points):</strong> Detailed | |
| AI-specific documentation for transparency | |
| </li> | |
| <li><strong>External References ({{ | |
| completeness_score.category_details.external_references.max_points if | |
| completeness_score.category_details else 'N/A' }} points):</strong> Links to model | |
| resources and documentation | |
| </li> | |
| </ul> | |
| <p><strong>Calculation Method:</strong></p> | |
| <p>Each category score = (Present Fields Γ· Total Fields) Γ Maximum Points</p> | |
| <p>Subtotal = Sum of all category scores</p> | |
| <p>Final Score = Subtotal Γ Penalty Factor (if applicable)</p> | |
| <h4>Penalty Structure:</h4> | |
| <p><strong>Critical Fields Missing:</strong></p> | |
| <ul> | |
| <li>0-1 missing: No penalty</li> | |
| <li>2-3 missing: 10% penalty (Γ0.9)</li> | |
| <li>4+ missing: 20% penalty (Γ0.8)</li> | |
| </ul> | |
| <p><strong>Important Fields Missing:</strong></p> | |
| <ul> | |
| <li>0-4 missing: No penalty</li> | |
| <li>5+ missing: 5% penalty (Γ0.95)</li> | |
| </ul> | |
| <p><strong>Note:</strong> Penalties are cumulative and applied to the subtotal. For example, if you | |
| have 3 critical fields missing AND 5 important fields missing, both penalties apply: Subtotal Γ | |
| 0.9 Γ 0.95 = Final Score.</p> | |
| </div> | |
| {% endif %} | |
| </div> | |
| </div> | |
| <!-- JSON View Tab --> | |
| <div id="json-view" class="tab-content"> | |
| <div class="content-section"> | |
| <h3>π Raw JSON View</h3> | |
| <p>This is the complete AIBOM components array in CycloneDX JSON format:</p> | |
| <div class="json-view"> | |
| <pre>{{ components_json }}</pre> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Modern Footer --> | |
| {% include 'includes/footer.html' %} | |
| </div> | |
| <script> | |
| </script> | |
| <script src="{{ static_root|default('/static') }}/js/script.js"></script> | |
| </body> | |
| </html> |