# SPDX 3.0 AI and Dataset Profiles, With Example > SPDX 3.0.1 AIPackage and DatasetPackage fields explained with a worked JSON-LD example, a field table, and the gaps you will hit modelling an AI system. Source: https://playciso.com/blog/spdx-3-ai-dataset-profile-example · Published: 2026-10-29 · Publisher: PlayCISO (https://playciso.com) --- SPDX 3.0 describes an AI model as an `AIPackage` from the AI profile and each dataset as a `DatasetPackage` from the Dataset profile. Both are software packages, so they carry the usual name, version, supplier and download location. They are joined by separate Relationship elements: `trainedOn` and `testedOn` from the model to its data, `descendantOf` to the base model. The current version is 3.0.1. **Who this is for:** AppSec engineers whose SBOM pipeline already speaks SPDX and now has to cover models, and GRC teams who receive SPDX files as evidence and need to know what each AI field claims. For the general idea, start with [what an AIBOM is](/blog/what-is-an-aibom-ai-bill-of-materials); for a format-neutral field list, see the [AIBOM parameters checklist](/blog/aibom-parameters-checklist). _Fictional example. Northwind Health, Triage Assistant and its datasets, services, scores and URLs are invented for illustration; the base model and open-source libraries are real._ ## How an SPDX 3.0 AIBOM is laid out An SPDX 3.0 file in JSON-LD is one `@context` and one flat `@graph` of elements. Five things to know before reading one: - Everything is an element with an spdxId, a URI. Northwind uses https://northwind-health.example/spdx/triage-assistant-2.3.0#…. - One shared CreationInfo says who produced the data and when (spec version 3.0.1). Every element points at it. - Profiles are declared. The SpdxDocument lists profileConformance: core, software, ai, dataset and simpleLicensing for Northwind. - Property names carry the profile as a prefix in JSON-LD: ai_limitation, dataset_datasetType, software_packageVersion. Core properties such as name have none. - Links are elements too. “The model was trained on this dataset” is a Relationship node with from, relationshipType and to, not a field inside the model. Licences work the same way, through hasDeclaredLicense. If you know SPDX 2.x, note that 3.0 is a new model, not an extension of 2.x documents. Tools written for 2.x will not read it. ## AIPackage: the AI profile An AIPackage must have the six package properties in the first rows. Every `ai_` property is optional. Cardinality is from the SPDX 3.0.1 class page. PropertyCardinalityWhat it recordsNorthwind `name, software_packageVersion`1 eachModel identitynorthwind/triage-assistant, 2.3.0 `software_downloadLocation`1Where the weights areInternal model store URL `software_primaryPurpose`1What kind of package this is`model` `suppliedBy, releaseTime`1 eachAccountable supplier and release dateNorthwind Health, 2026-02-16 `ai_typeOfModel`0..*Free-text model typedecoder-only transformer (causal language model) `ai_domain`0..*Where the model is meant to be usedcustomer support `ai_informationAboutTraining`0..1How it was trained, in wordsLoRA fine-tune on the ticket dataset `ai_informationAboutApplication`0..1Intended applicationDrafts for human approval `ai_limitation`0..1Known limits and out-of-scope uses, as one stringMedical advice; sending without approval `ai_metric, ai_metricDecisionThreshold`0..* eachMetric results, and thresholds, as key/value DictionaryEntry pairsanswer-accuracy 0.87; toxicity-rate 0.002 (fictional). No thresholds. `ai_hyperparameter`0..*Training settings as key/value pairsfinetuning_method = LoRA; task `ai_modelDataPreprocessing`0..*Data preparation before trainingDe-identification `ai_autonomyType`0..1Whether it acts without a human in the loop: `yes`, `no`, `noAssertion``no` `ai_safetyRiskAssessment`0..1Self-assessed risk: `serious`, `high`, `medium`, `low``medium` `ai_useSensitivePersonalInformation`0..1Whether sensitive personal data was used`no` `ai_modelExplainability, ai_standardCompliance, ai_energyConsumption`0..* / 0..* / 0..1Explainability notes, standards complied with, energy used in training, fine-tuning and inferenceNot recorded Two of these are judgements, not facts. `ai_safetyRiskAssessment` is the supplier’s own rating on a four-level scale, and `ai_useSensitivePersonalInformation` is the supplier’s claim after its own de-identification. Read both as claims to test. ## DatasetPackage: the Dataset profile A DatasetPackage must have at least one `dataset_datasetType`, plus `builtTime`, `releaseTime`, `originatedBy`, a download location and a primary purpose (`data`). PropertyCardinalityWhat it recordsNorthwind training set `dataset_datasetType`1..*`text`, `image`, `audio`, `structured` and ten more`text` `builtTime, releaseTime, originatedBy`1 each (originatedBy at most 1)When the data was built and released, and who created it2025-12-31, 2026-01-20, Northwind Health `dataset_dataCollectionProcess`0..1How the data was collectedExport from the ticketing system `dataset_dataPreprocessing`0..*Steps between raw data and training dataDropped no-reply tickets; de-identified `dataset_anonymizationMethodUsed`0..*How identifiers were removedNER plus pattern rules, sample review `dataset_hasSensitivePersonalInformation`0..1`yes`, `no`, `noAssertion``no` `dataset_confidentialityLevel`0..1Traffic Light Protocol style: `clear`, `green`, `amber`, `red``amber` `dataset_intendedUse, dataset_knownBias`0..1 / 0..*What the data is for, and known biasesFine-tuning the model; written channels only `dataset_datasetUpdateMechanism`0..1How the data is updatedNone: static 2025 snapshot `dataset_datasetSize`0..1Size in bytes (not records)Left out; record count is in the description `dataset_datasetAvailability, dataset_datasetNoise, dataset_sensor`0..1 / 0..1 / 0..*How it can be obtained, known noise, sensors usedNot recorded (internal text data) ## Relationships that make it an AIBOM - describes: the SBOM element describes the application. - dependsOn: the application depends on the model, vLLM 0.6.3, the RAG index and the MCP server; vLLM depends on its libraries. - descendantOf: the fine-tune is a descendant of mistralai/Mistral-7B-Instruct-v0.3. - trainedOn and testedOn: the model was trained on northwind/support-tickets-2025 and tested on northwind/triage-eval-v4. The direction is always from the model to the data. - hasDeclaredLicense: each package to a simplelicensing_LicenseExpression element. The base model gets Apache-2.0; Northwind’s own model and data get a LicenseRef- identifier mapped to a licence URL. ## The Northwind field table FieldNorthwind valueWhat it tells you `@context`https://spdx.org/rdf/3.0.1/spdx-context.jsonldDeclares SPDX 3.0.1 JSON-LD. Every node lives in one @graph. `CreationInfo (specVersion, created, createdBy)`3.0.1, 2026-02-16T09:00:00Z, Northwind HealthWho produced the SPDX data and when. Shared by every element. `SpdxDocument.profileConformance`core, software, ai, dataset, simpleLicensingWhich SPDX profiles the document uses. "ai" and "dataset" are the AIBOM parts. `software_Sbom.software_sbomType`buildGenerated at build time. `ai_AIPackage name / software_packageVersion`northwind/triage-assistant / 2.3.0Model identity. AIPackage requires name, version, download location, supplier, release time and primary purpose. `software_primaryPurpose`modelSays this package is a model (datasets use "data"). `suppliedBy / releaseTime`Northwind Health / 2026-02-16T09:00:00ZAccountable supplier and release date. `verifiedUsing (Hash sha256)`3bad18cc9805… (placeholder)Integrity check of the weights file. `ai_typeOfModel / ai_domain`decoder-only transformer / customer supportFree-text model type and the domain it is meant for. `ai_informationAboutTraining`LoRA fine-tune on northwind/support-tickets-2025How the model was trained, in words. `ai_informationAboutApplication`Draft replies to customer support tickets for a human support agent to review, edit and approve before sending.Intended application. `ai_limitation`Medical advice or clinical triage of symptoms; Sending any reply to a customer without human approvalKnown limitations and out-of-scope uses. One string in SPDX 3.0.1. `ai_metric (DictionaryEntry)`answer-accuracy 0.87; toxicity-rate 0.002 (fictional)Metric name and value as key/value pairs. `ai_hyperparameter`finetuning_method = LoRA; task = text-generationTraining settings worth recording. `ai_autonomyType`noNo: a human approves every output before it has effect. `ai_safetyRiskAssessment`mediumNorthwind Health's own risk rating on SPDX's four-level scale (serious, high, medium, low). Fictional. `ai_useSensitivePersonalInformation`noPublisher asserts no sensitive personal data was used in training, after de-identification. `dataset_DatasetPackage (training)`northwind/support-tickets-2025, datasetType text, confidentialityLevel amberThe training data as its own element. datasetType is the one Dataset-profile field that is required. `dataset_anonymizationMethodUsed / dataset_hasSensitivePersonalInformation`NER plus pattern rules, sample review / noHow identifiers were removed, and the resulting claim. De-identified is not the same as anonymous. `dataset_datasetSize`(omitted)Size in bytes, not records. The record count (48,210) goes in the description. `Relationship descendantOf`triage-assistant → mistralai/Mistral-7B-Instruct-v0.3Lineage to the base model. `Relationship trainedOn / testedOn`northwind/support-tickets-2025 / northwind/triage-eval-v4Which data trained the model and which tested it. `Relationship dependsOn`Triage Assistant → model, vllm 0.6.3, northwind-helpcentre-index, ticketing-mcpRun-time dependencies. SPDX 3.0.1 has no service class, so the RAG index is a dataset and the MCP server a package. `Relationship hasDeclaredLicense`Apache-2.0 (base model); LicenseRef proprietary (model, data)Licences, as simplelicensing_LicenseExpression elements. `externalRef (model)`documentation (model card); other: Sigstore bundle; other: in-toto provenanceLinks to the signature and provenance. SPDX 3.0.1 has no dedicated signature or SLSA ref type, so these use "other" with a contentType. ## The example file, excerpted The model with its signature link, the training dataset, and the two relationships that say where the model came from and what it learned from. `{ "@context": "https://spdx.org/rdf/3.0.1/spdx-context.jsonld", "@graph": [ { "type": "ai_AIPackage", "spdxId": "https://northwind-health.example/spdx/triage-assistant-2.3.0#model", "name": "northwind/triage-assistant", "software_packageVersion": "2.3.0", "software_primaryPurpose": "model", "suppliedBy": "https://northwind-health.example/spdx/triage-assistant-2.3.0#org-northwind-health", "releaseTime": "2026-02-16T09:00:00Z", "ai_typeOfModel": ["decoder-only transformer (causal language model)"], "ai_limitation": "Out of scope: Medical advice or clinical triage of symptoms; Sending any reply to a customer without human approval.", "ai_autonomyType": "no", "ai_safetyRiskAssessment": "medium", "ai_useSensitivePersonalInformation": "no", "externalRef": [ { "type": "ExternalRef", "externalRefType": "other", "locator": [ "https://models.northwind-health.example/northwind/triage-assistant/2.3.0/model.sig" ], "contentType": "application/vnd.dev.sigstore.bundle.v0.3+json", "comment": "Sigstore model signature (OpenSSF model signing), produced in CI." } ] }, { "type": "dataset_DatasetPackage", "spdxId": "https://northwind-health.example/spdx/triage-assistant-2.3.0#dataset-support-tickets-2025", "name": "northwind/support-tickets-2025", "builtTime": "2025-12-31T23:59:59Z", "originatedBy": [ "https://northwind-health.example/spdx/triage-assistant-2.3.0#org-northwind-health" ], "dataset_datasetType": ["text"], "dataset_anonymizationMethodUsed": [ "Named-entity detection plus pattern rules to remove names, email addresses, phone numbers, postal addresses and account or member numbers; manual review of a sample." ], "dataset_confidentialityLevel": "amber", "dataset_hasSensitivePersonalInformation": "no" }, { "type": "Relationship", "from": "https://northwind-health.example/spdx/triage-assistant-2.3.0#model", "relationshipType": "descendantOf", "to": ["https://northwind-health.example/spdx/triage-assistant-2.3.0#base-model"] }, { "type": "Relationship", "from": "https://northwind-health.example/spdx/triage-assistant-2.3.0#model", "relationshipType": "trainedOn", "to": [ "https://northwind-health.example/spdx/triage-assistant-2.3.0#dataset-support-tickets-2025" ] } ] }` _Excerpt, 59 lines: the AIPackage (metrics and two of its three external references left out), the training DatasetPackage, and the descendantOf and trainedOn relationships. Keys and list entries not shown are left out; every value shown is exactly as in the full file, which runs to 608 lines pretty-printed._ The complete file, with the application, the base model, the evaluation set, the RAG index, the MCP server, the libraries, the licences and every relationship, is in the [AIBOM Template Library](/tools/aibom-template-library?format=spdx) (Pro). ## Gaps we hit, and what we did Building the Northwind file in SPDX 3.0.1 ran into five places where the model has no field for something an AI system needs. None makes the file invalid. All of them push facts into free text. GapWhyWhat the Northwind file does No service classCycloneDX has services for things called at run time. SPDX 3.0.1 does not.The RAG index is a `dataset_DatasetPackage` with `software_primaryPurpose: data` and a weekly update mechanism; the MCP server is a `software_Package` with `primaryPurpose: application`. Authentication, trust boundary and tool permissions go into the description, where tools cannot query them. No reference type for a model signature or SLSA provenance`ExternalRefType` has 46 values but none for a signature bundle or build provenance. `secureSoftwareAttestation` exists, but it means an SSDF or CISA secure-development attestation form.Both links use `externalRefType: other` with a `contentType`: `application/vnd.dev.sigstore.bundle.v0.3+json` for the signature and `application/vnd.in-toto+json` for the provenance, plus a comment. datasetSize is bytesThe spec says the size “is to be measured in bytes”. Writing 48210 there would claim a 48 KB dataset.`dataset_datasetSize` is left out; “48,210 de-identified support tickets” goes in the description. ai_limitation holds one stringMaximum cardinality is 1.The two out-of-scope uses are joined into one sentence. Metrics have no slice`ai_metric` is a key/value pair; there is no slot for the dataset a metric was measured on.The dataset goes into the key (`answer-accuracy (northwind/triage-eval-v4)`), and a `testedOn` relationship links the model to the evaluation set. ## SPDX or CycloneDX? Neither is better in general. Pick by what you need to express and who reads it. If…ChooseWhy Your SBOM pipeline and your customers already use SPDXSPDXThe AIBOM should come out of the same pipeline as the SBOM. You need to show RAG indexes, tool servers and trust boundariesCycloneDXCycloneDX has services with endpoints, authentication, trust boundary and data flows. SPDX 3.0.1 has no service class. Dataset facts matter most (anonymisation, confidentiality, bias, collection)SPDXThe Dataset profile has named fields for these. CycloneDX data components have classification and sensitive-data notes only. You want a structured model card inside the BOMCycloneDXmodelCard has separate lists for use cases, limitations, trade-offs, ethical, environmental and fairness considerations. SPDX has free-text strings. Licence compliance is the main useSPDXLicence expressions are first-class elements, linked by hasDeclaredLicense. You need autonomy, safety-risk or energy fieldsSPDXautonomyType, safetyRiskAssessment and energyConsumption have no direct CycloneDX equivalent. You want PlayCISO’s validator and diffCycloneDXThe AIBOM Validator and AIBOM Diff read CycloneDX. The [CycloneDX ML-BOM guide](/blog/cyclonedx-ml-bom-example) uses the same Northwind system, so you can compare the two files field by field. The [AIBOM Format Field Map](/tools/aibom-field-map) (Pro) does that comparison for every field. For how the three bill-of-materials ideas differ, see [SBOM vs AIBOM vs MLBOM](/blog/sbom-vs-aibom-vs-mlbom). ## How to validate it - Structure: the official SPDX 3.0.1 JSON schema checks that the JSON-LD has the right shape. - Meaning: the SHACL shapes in the SPDX model file (spdx-model.ttl) check required properties, cardinalities and enumerated values, for example with pySHACL. This is what catches a DatasetPackage without a datasetType. - Both at once: the community tool spdx3-validate runs the schema and SHACL checks together, with some extra checks for documents that reference each other. The Northwind file passes the official SPDX 3.0.1 JSON schema and the SHACL shapes (checked with pySHACL). As with any format, valid only means well-formed. The facts inside, such as the de-identification claim, still need evidence. ## Where to go next This guide is part of the [AIBOM Library](/aibom). The same Northwind system in the other formats: [CycloneDX ML-BOM](/blog/cyclonedx-ml-bom-example) and [Croissant RAI](/blog/croissant-rai-dataset-metadata-example). To choose between formats, start with [AIBOM standards and templates compared](/blog/aibom-standards-templates-compared); to see one field across every format, use the [AIBOM Format Field Map](/tools/aibom-field-map) (Pro). ## Frequently asked questions ### What is the SPDX AI profile? The part of SPDX 3.0 that describes AI models. It adds the AIPackage class, a software package with properties such as typeOfModel, informationAboutTraining, informationAboutApplication, limitation, metric, hyperparameter, autonomyType, safetyRiskAssessment, useSensitivePersonalInformation and energyConsumption. The Dataset profile adds DatasetPackage for training and test data. ### What fields does an SPDX AIPackage require? In SPDX 3.0.1 every AIPackage needs a name, packageVersion, downloadLocation, primaryPurpose, suppliedBy and releaseTime, plus the spdxId and creationInfo every element has. All the ai_ properties are optional. A DatasetPackage needs datasetType, builtTime, releaseTime, originatedBy, downloadLocation and primaryPurpose. ### How do you link a model to its training data in SPDX 3.0? With Relationship elements. A relationship from the model to a dataset with relationshipType trainedOn says the model was trained on it; testedOn says it was tested on it; descendantOf from the fine-tune to the base model records lineage. Relationships are separate nodes in the @graph, not properties nested inside the model. ### Can SPDX 3.0 describe a RAG pipeline or an MCP server? Only partly. SPDX 3.0.1 has no class for a service called at run time. You can model a retrieval index as a DatasetPackage and a tool server as a software Package, linked with dependsOn, but authentication, trust boundaries and tool permissions end up in free text. CycloneDX services hold them as fields. ### Is SPDX 3.0 an ISO standard? No. ISO/IEC 5962:2021 is SPDX 2.2.1. The AI and Dataset profiles are new in SPDX 3.0, so they are not part of that ISO text. The current SPDX version is 3.0.1; SPDX 3.1 was at release-candidate stage in October 2026. ### Should I use SPDX or CycloneDX for an AIBOM? Use the format your SBOM pipeline and your customers already use. Choose CycloneDX if you need run-time services with trust boundaries or a structured model card. Choose SPDX if your focus is licence compliance or detailed dataset facts such as anonymisation method and confidentiality level. You can produce both from one source. ## Sources - SPDX 3.0.1: AIPackage - SPDX 3.0.1: DatasetPackage - SPDX 3.0.1: RelationshipType (trainedOn, testedOn, descendantOf) - SPDX 3.0.1: ExternalRefType - SPDX 3.0.1: datasetSize (“measured in bytes”) - SPDX 3.0.1 JSON schema - spdx3-validate (JSON schema plus SHACL checks for SPDX 3) - SPDX 3.1 release candidate 1 - Mistral-7B-Instruct-v0.3 on Hugging Face (the real base model in the example) _Checked on 29 October 2026. PlayCISO is not affiliated with OWASP, Ecma, the Linux Foundation or MLCommons. This is general information, not legal advice._