Skip to content

Overview

ModelCards are cards for storing, versioning, and tracking model objects.

Features

  • shareable: All cards including ModelCards are shareable and searchable.
  • auto-onnx: Automatic conversion of trained model into onnx model format.
  • auto-schema: Auto-infer data schema and input and output signature.
  • versioning: SemVer for your model.

Create a Card

# load data card from earlier
from sklearn.linear_model import LinearRegression

# Opsml
from opsml import CardRegistry, ModelCard, CardInfo

# set up registries
data_registry = CardRegistry(registry_name="data")
model_registry = CardRegistry(registry_name="model")

card_info = CardInfo(name="linnerrud", repository="opsml", contact="user@email.com")


# load datacard
datacard = data_registry.load_card(name=card_info.name, version="1.0.0")

# data is not loaded by default (helps when sharing cards with large data)
datacard.load_data()
data_splits = datacard.split_data()


X_train = data_splits["train"].X
y_train = data_splits["train"].y

# fit model
linreg = LinearRegression()
linreg = linreg.fit(X=X_train, y=y_train)
model_interface = SklearnModel(model=linreg, sample_data=X_train)

# lets test the onnx model before registering
modelcard = ModelCard(
    info=card_info,
    interface = model_interface,
    datacard_uid=datacard.uid,
    to_onnx=True,
)

# if you'd like to convert to onnx before registering, you can do that as well
modelcard.convert_to_onnx()

# custom onnx testing logic
...

# everything looks good
model_registry.register_card(modelcard)

ModelCard Args

name: str
Name for the data (Required)
repository: str
repository data belongs to (Required)
contact: str
Email to associate with data (Required)
interface: ModelInterface
ModelInterface used to interact with model. See ModelInterface for more information
datacard_uid
uid of DataCard that contains training data. This is not required to instantiate a ModelCard, but it is required to register a ModelCard
to_onnx
Whether to convert model to onnx or not. Default is True
metadata: ModelCardMetadata
Optional ModelCardMetadata used to store metadata about the model. See ModelCardMetadata for more information. If not provided, a default object is created. When registering a card, the metadata is updated with the latest information.

Docs

opsml.ModelCard

Bases: ArtifactCard

Create a ModelCard from your trained machine learning model. This Card is used in conjunction with the ModelCardCreator class.

Parameters:

Name Type Description Default
interface
Trained model interface.
required
name

Name for the model specific to your current project

required
repository

Repository that this model is associated with

required
contact

Contact to associate with card

required
info

CardInfo object containing additional metadata. If provided, it will override any values provided for name, repository, contact, and version.

Name, repository, and contact are required arguments for all cards. They can be provided directly or through a CardInfo object.

required
uid

Unique id (assigned if card has been registered)

required
version

Current version (assigned if card has been registered)

required
datacard_uid

Uid of the DataCard associated with training the model

required
to_onnx

Whether to convert the model to onnx or not

required
metadata

ModelCardMetadata associated with the model

required
Source code in opsml/cards/model.py
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
class ModelCard(ArtifactCard):
    """Create a ModelCard from your trained machine learning model.
    This Card is used in conjunction with the ModelCardCreator class.

    Args:
        interface:
                Trained model interface.
        name:
            Name for the model specific to your current project
        repository:
            Repository that this model is associated with
        contact:
            Contact to associate with card
        info:
            `CardInfo` object containing additional metadata. If provided, it will override any
            values provided for `name`, `repository`, `contact`, and `version`.

            Name, repository, and contact are required arguments for all cards. They can be provided
            directly or through a `CardInfo` object.

        uid:
            Unique id (assigned if card has been registered)
        version:
            Current version (assigned if card has been registered)
        datacard_uid:
            Uid of the DataCard associated with training the model
        to_onnx:
            Whether to convert the model to onnx or not
        metadata:
            `ModelCardMetadata` associated with the model
    """

    model_config = ConfigDict(
        arbitrary_types_allowed=True,
        protected_namespaces=("protect_",),
        validate_assignment=True,
    )

    interface: SerializeAsAny[ModelInterface]
    datacard_uid: Optional[str] = None
    to_onnx: bool = False
    metadata: ModelCardMetadata = ModelCardMetadata()

    @field_validator("datacard_uid", mode="before")
    @classmethod
    def check_uid(cls, datacard_uid: Optional[str] = None) -> Optional[str]:
        if datacard_uid is None:
            return datacard_uid

        try:
            UUID(datacard_uid, version=4)  # we use uuid4
            return datacard_uid

        except ValueError as exc:
            raise ValueError("Datacard uid is not a valid uuid") from exc

    def load_model(self, **kwargs: Any) -> None:
        """Loads model, preprocessor and sample data to interface"""

        from opsml.storage.card_loader import ModelCardLoader

        ModelCardLoader(self).load_model(**kwargs)

    def download_model(self, path: Path, **kwargs: Any) -> None:
        """Downloads model, preprocessor and metadata to path

        Args:
            path:
                Path to download model

            kwargs:
                load_preprocessor:
                    Whether to load preprocessor or not. Default is True
                load_onnx:
                    Whether to load onnx model or not. Default is False
                quantize:
                    Whether to quantize onnx model or not. Default is False
        """

        from opsml.storage.card_loader import ModelCardLoader

        # set path to download model
        kwargs["lpath"] = path

        ModelCardLoader(self).download_model(**kwargs)

    def load_onnx_model(self, **kwargs: Any) -> None:
        """Loads onnx model to interface"""

        from opsml.storage.card_loader import ModelCardLoader

        ModelCardLoader(self).load_onnx_model(**kwargs)

    def load_preprocessor(self, **kwargs: Any) -> None:
        """Loads onnx model to interface"""

        if self.preprocessor is not None:
            return

        from opsml.storage.card_loader import ModelCardLoader

        ModelCardLoader(self).load_preprocessor(**kwargs)

    def create_registry_record(self) -> Dict[str, Any]:
        """Creates a registry record from the current ModelCard"""

        exclude_vars = {"interface": {"model", "preprocessor", "sample_data", "onnx_model"}}
        dumped_model = self.model_dump(exclude=exclude_vars)

        return dumped_model

    @property
    def model(self) -> Any:
        """Quick access to model from interface"""
        return self.interface.model

    @property
    def sample_data(self) -> Any:
        """Quick access to sample data from interface"""
        return self.interface.sample_data

    @property
    def preprocessor(self) -> Any:
        """Quick access to preprocessor from interface"""

        if hasattr(self.interface, "preprocessor"):
            return self.interface.preprocessor

        if hasattr(self.interface, "tokenizer"):
            if self.interface.tokenizer is not None:
                return self.interface.tokenizer

        if hasattr(self.interface, "feature_extractor"):
            if self.interface.feature_extractor is not None:
                return self.interface.feature_extractor

        return None

    @property
    def onnx_model(self) -> Optional[OnnxModel]:
        """Quick access to onnx model from interface"""
        return self.interface.onnx_model

    @property
    def model_metadata(self) -> ModelMetadata:
        """Loads `ModelMetadata` class"""

        from opsml.storage.card_loader import ModelCardLoader

        return ModelCardLoader(self).load_model_metadata()

    @property
    def card_type(self) -> str:
        return CardType.MODELCARD.value

onnx_model: Optional[OnnxModel] property

Quick access to onnx model from interface