wallaroo.model_config

  1from typing import TYPE_CHECKING, List, cast
  2
  3from .object import *
  4
  5if TYPE_CHECKING:
  6    # Imports that happen below in methods to fix circular import dependency
  7    # issues need to also be specified here to satisfy mypy type checking.
  8    from .client import Client
  9    from .model import Model
 10
 11import gql  # type: ignore
 12import yaml
 13
 14
 15class ModelConfig(Object):
 16    """Wraps a backend ModelConfig object."""
 17
 18    def __init__(
 19        self, client: Optional["Client"], data: Dict[str, Any], standalone=False
 20    ) -> None:
 21        self.client = client
 22        super().__init__(
 23            gql_client=client._gql_client if client is not None else None,
 24            data=data,
 25            standalone=standalone,
 26        )
 27
 28    @staticmethod
 29    def as_standalone(
 30        model: "Model",
 31        filter_threshold: Optional[float] = None,
 32        runtime: Optional[str] = None,
 33        tensor_fields: Optional[List[str]] = None,
 34    ) -> "ModelConfig":
 35        """Creates a ModelConfig intended for use in generating standalone configurations"""
 36        constructor_dict = {
 37            "id": -1,
 38            "model": model,
 39            "filter_threshold": filter_threshold,
 40            "runtime": runtime,
 41            "tensor_fields": tensor_fields,
 42        }
 43        return ModelConfig(None, data=constructor_dict, standalone=True)
 44
 45    @property
 46    def inputs(self):
 47        return self.model().inputs
 48
 49    @property
 50    def outputs(self):
 51        return self.model().outputs
 52
 53    def to_yaml(self):
 54        """Generates a yaml file for standalone engines"""
 55        extra = {
 56            "model_id": self.model().name(),
 57            "model_version": self.model().version(),
 58        }
 59        return self._yaml(extra)
 60
 61    def to_k8s_yaml(self):
 62        # XXX - the deployment manager currently stitches this together
 63        extra = {
 64            "name": self.model().name(),
 65            "version": self.model().version(),
 66            "sha": self.model().sha(),
 67        }
 68        return self._yaml(extra)
 69
 70    def _yaml(self, yaml_dict):
 71        if self.filter_threshold():
 72            yaml_dict["filter_threshold"] = self.filter_threshold()
 73        if self.runtime():
 74            yaml_dict["runtime"] = self.runtime()
 75        if self.tensor_fields():
 76            yaml_dict["tensor_fields"] = self.tensor_fields()
 77        if type(self._input_schema) == str:
 78            yaml_dict["input_schema"] = self._input_schema
 79        if type(self._output_schema) == str:
 80            yaml_dict["output_schema"] = self._output_schema
 81        return yaml.dump(yaml_dict)
 82
 83    def _fill(self, data: Dict[str, Any]) -> None:
 84        """Fills an object given a response dictionary from the GraphQL API.
 85
 86        Only the primary key member must be present; other members will be
 87        filled in via rehydration if their corresponding member function is
 88        called.
 89        """
 90        from .model import Model  # Avoids circular imports
 91
 92        for required_attribute in ["id"]:
 93            if required_attribute not in data:
 94                raise RequiredAttributeMissing(
 95                    self.__class__.__name__, required_attribute
 96                )
 97        # Required
 98        self._id = data["id"]
 99
100        # Optional
101        self._filter_threshold = value_if_present(data, "filter_threshold")
102        self._model = (
103            (
104                data["model"]
105                if isinstance(data["model"], Model)
106                else Model(
107                    client=self.client,
108                    data=data["model"],
109                    standalone=self._standalone,
110                )
111            )
112            if "model" in data
113            else DehydratedValue()
114        )
115        self._runtime = value_if_present(data, "runtime")
116        self._tensor_fields = value_if_present(data, "tensor_fields")
117        self._input_schema = value_if_present(data, "input_schema")
118        self._output_schema = value_if_present(data, "output_schema")
119
120    def _fetch_attributes(self) -> Dict[str, Any]:
121        """Fetches all member data from the GraphQL API."""
122        assert self.client is not None
123        return self.client._gql_client.execute(
124            gql.gql(
125                """
126                query ModelConfigById($model_config_id: bigint!) {
127                  model_config_by_pk(id: $model_config_id) {
128                    id
129                    filter_threshold
130                    model {
131                      id
132                    }
133                    runtime
134                    tensor_fields
135                  }
136                }
137            """
138            ),
139            variable_values={
140                "model_config_id": self._id,
141            },
142        )["model_config_by_pk"]
143
144    def id(self) -> int:
145        return self._id
146
147    @rehydrate("_filter_threshold")
148    def filter_threshold(self) -> float:
149        return cast(float, self._filter_threshold)
150
151    @rehydrate("_model")
152    def model(self) -> "Model":
153        from .model import Model  # Avoids circular imports
154
155        return cast(Model, self._model)
156
157    @rehydrate("_runtime")
158    def runtime(self) -> str:
159        return cast(str, self._runtime)
160
161    @rehydrate("_tensor_fields")
162    def tensor_fields(self) -> List[str]:
163        return cast(List[str], self._tensor_fields)
class ModelConfig(wallaroo.object.Object):
 16class ModelConfig(Object):
 17    """Wraps a backend ModelConfig object."""
 18
 19    def __init__(
 20        self, client: Optional["Client"], data: Dict[str, Any], standalone=False
 21    ) -> None:
 22        self.client = client
 23        super().__init__(
 24            gql_client=client._gql_client if client is not None else None,
 25            data=data,
 26            standalone=standalone,
 27        )
 28
 29    @staticmethod
 30    def as_standalone(
 31        model: "Model",
 32        filter_threshold: Optional[float] = None,
 33        runtime: Optional[str] = None,
 34        tensor_fields: Optional[List[str]] = None,
 35    ) -> "ModelConfig":
 36        """Creates a ModelConfig intended for use in generating standalone configurations"""
 37        constructor_dict = {
 38            "id": -1,
 39            "model": model,
 40            "filter_threshold": filter_threshold,
 41            "runtime": runtime,
 42            "tensor_fields": tensor_fields,
 43        }
 44        return ModelConfig(None, data=constructor_dict, standalone=True)
 45
 46    @property
 47    def inputs(self):
 48        return self.model().inputs
 49
 50    @property
 51    def outputs(self):
 52        return self.model().outputs
 53
 54    def to_yaml(self):
 55        """Generates a yaml file for standalone engines"""
 56        extra = {
 57            "model_id": self.model().name(),
 58            "model_version": self.model().version(),
 59        }
 60        return self._yaml(extra)
 61
 62    def to_k8s_yaml(self):
 63        # XXX - the deployment manager currently stitches this together
 64        extra = {
 65            "name": self.model().name(),
 66            "version": self.model().version(),
 67            "sha": self.model().sha(),
 68        }
 69        return self._yaml(extra)
 70
 71    def _yaml(self, yaml_dict):
 72        if self.filter_threshold():
 73            yaml_dict["filter_threshold"] = self.filter_threshold()
 74        if self.runtime():
 75            yaml_dict["runtime"] = self.runtime()
 76        if self.tensor_fields():
 77            yaml_dict["tensor_fields"] = self.tensor_fields()
 78        if type(self._input_schema) == str:
 79            yaml_dict["input_schema"] = self._input_schema
 80        if type(self._output_schema) == str:
 81            yaml_dict["output_schema"] = self._output_schema
 82        return yaml.dump(yaml_dict)
 83
 84    def _fill(self, data: Dict[str, Any]) -> None:
 85        """Fills an object given a response dictionary from the GraphQL API.
 86
 87        Only the primary key member must be present; other members will be
 88        filled in via rehydration if their corresponding member function is
 89        called.
 90        """
 91        from .model import Model  # Avoids circular imports
 92
 93        for required_attribute in ["id"]:
 94            if required_attribute not in data:
 95                raise RequiredAttributeMissing(
 96                    self.__class__.__name__, required_attribute
 97                )
 98        # Required
 99        self._id = data["id"]
100
101        # Optional
102        self._filter_threshold = value_if_present(data, "filter_threshold")
103        self._model = (
104            (
105                data["model"]
106                if isinstance(data["model"], Model)
107                else Model(
108                    client=self.client,
109                    data=data["model"],
110                    standalone=self._standalone,
111                )
112            )
113            if "model" in data
114            else DehydratedValue()
115        )
116        self._runtime = value_if_present(data, "runtime")
117        self._tensor_fields = value_if_present(data, "tensor_fields")
118        self._input_schema = value_if_present(data, "input_schema")
119        self._output_schema = value_if_present(data, "output_schema")
120
121    def _fetch_attributes(self) -> Dict[str, Any]:
122        """Fetches all member data from the GraphQL API."""
123        assert self.client is not None
124        return self.client._gql_client.execute(
125            gql.gql(
126                """
127                query ModelConfigById($model_config_id: bigint!) {
128                  model_config_by_pk(id: $model_config_id) {
129                    id
130                    filter_threshold
131                    model {
132                      id
133                    }
134                    runtime
135                    tensor_fields
136                  }
137                }
138            """
139            ),
140            variable_values={
141                "model_config_id": self._id,
142            },
143        )["model_config_by_pk"]
144
145    def id(self) -> int:
146        return self._id
147
148    @rehydrate("_filter_threshold")
149    def filter_threshold(self) -> float:
150        return cast(float, self._filter_threshold)
151
152    @rehydrate("_model")
153    def model(self) -> "Model":
154        from .model import Model  # Avoids circular imports
155
156        return cast(Model, self._model)
157
158    @rehydrate("_runtime")
159    def runtime(self) -> str:
160        return cast(str, self._runtime)
161
162    @rehydrate("_tensor_fields")
163    def tensor_fields(self) -> List[str]:
164        return cast(List[str], self._tensor_fields)

Wraps a backend ModelConfig object.

ModelConfig( client: Optional[wallaroo.client.Client], data: Dict[str, Any], standalone=False)
19    def __init__(
20        self, client: Optional["Client"], data: Dict[str, Any], standalone=False
21    ) -> None:
22        self.client = client
23        super().__init__(
24            gql_client=client._gql_client if client is not None else None,
25            data=data,
26            standalone=standalone,
27        )

Base constructor.

Each object requires:

  • a GraphQL client - in order to fill its missing members dynamically
  • an initial data blob - typically from unserialized JSON, contains at
  • least the data for required members (typically the object's primary key) and optionally other data members.
@staticmethod
def as_standalone( model: wallaroo.model.Model, filter_threshold: Optional[float] = None, runtime: Optional[str] = None, tensor_fields: Optional[List[str]] = None) -> wallaroo.model_config.ModelConfig:
29    @staticmethod
30    def as_standalone(
31        model: "Model",
32        filter_threshold: Optional[float] = None,
33        runtime: Optional[str] = None,
34        tensor_fields: Optional[List[str]] = None,
35    ) -> "ModelConfig":
36        """Creates a ModelConfig intended for use in generating standalone configurations"""
37        constructor_dict = {
38            "id": -1,
39            "model": model,
40            "filter_threshold": filter_threshold,
41            "runtime": runtime,
42            "tensor_fields": tensor_fields,
43        }
44        return ModelConfig(None, data=constructor_dict, standalone=True)

Creates a ModelConfig intended for use in generating standalone configurations

inputs
outputs
def to_yaml(self):
54    def to_yaml(self):
55        """Generates a yaml file for standalone engines"""
56        extra = {
57            "model_id": self.model().name(),
58            "model_version": self.model().version(),
59        }
60        return self._yaml(extra)

Generates a yaml file for standalone engines

def to_k8s_yaml(self):
62    def to_k8s_yaml(self):
63        # XXX - the deployment manager currently stitches this together
64        extra = {
65            "name": self.model().name(),
66            "version": self.model().version(),
67            "sha": self.model().sha(),
68        }
69        return self._yaml(extra)
def id(self) -> int:
145    def id(self) -> int:
146        return self._id
def filter_threshold(*args, **kwargs):
41        def wrapper(*args, **kwargs):
42            obj = args[0]
43            if not getattr(obj, "_standalone", None):
44                present = getattr(obj, attr) != DehydratedValue()
45                # Uncomment to debug while testing
46                # print(
47                #    "rehydrate: {} -> {}".format(
48                #        attr, "present" if present else "not present"
49                #    )
50                # )
51                if not present:
52                    obj._rehydrate()
53            result = fn(*args, **kwargs)
54            return result
def model(*args, **kwargs):
41        def wrapper(*args, **kwargs):
42            obj = args[0]
43            if not getattr(obj, "_standalone", None):
44                present = getattr(obj, attr) != DehydratedValue()
45                # Uncomment to debug while testing
46                # print(
47                #    "rehydrate: {} -> {}".format(
48                #        attr, "present" if present else "not present"
49                #    )
50                # )
51                if not present:
52                    obj._rehydrate()
53            result = fn(*args, **kwargs)
54            return result
def runtime(*args, **kwargs):
41        def wrapper(*args, **kwargs):
42            obj = args[0]
43            if not getattr(obj, "_standalone", None):
44                present = getattr(obj, attr) != DehydratedValue()
45                # Uncomment to debug while testing
46                # print(
47                #    "rehydrate: {} -> {}".format(
48                #        attr, "present" if present else "not present"
49                #    )
50                # )
51                if not present:
52                    obj._rehydrate()
53            result = fn(*args, **kwargs)
54            return result
def tensor_fields(*args, **kwargs):
41        def wrapper(*args, **kwargs):
42            obj = args[0]
43            if not getattr(obj, "_standalone", None):
44                present = getattr(obj, attr) != DehydratedValue()
45                # Uncomment to debug while testing
46                # print(
47                #    "rehydrate: {} -> {}".format(
48                #        attr, "present" if present else "not present"
49                #    )
50                # )
51                if not present:
52                    obj._rehydrate()
53            result = fn(*args, **kwargs)
54            return result