xinference 1.7.1__py3-none-any.whl → 1.8.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of xinference might be problematic. Click here for more details.

Files changed (136) hide show
  1. xinference/_version.py +3 -3
  2. xinference/client/restful/async_restful_client.py +8 -13
  3. xinference/client/restful/restful_client.py +6 -2
  4. xinference/core/chat_interface.py +6 -4
  5. xinference/core/media_interface.py +5 -0
  6. xinference/core/model.py +1 -5
  7. xinference/core/supervisor.py +117 -68
  8. xinference/core/worker.py +49 -37
  9. xinference/deploy/test/test_cmdline.py +2 -6
  10. xinference/model/audio/__init__.py +26 -23
  11. xinference/model/audio/chattts.py +3 -2
  12. xinference/model/audio/core.py +49 -98
  13. xinference/model/audio/cosyvoice.py +3 -2
  14. xinference/model/audio/custom.py +28 -73
  15. xinference/model/audio/f5tts.py +3 -2
  16. xinference/model/audio/f5tts_mlx.py +3 -2
  17. xinference/model/audio/fish_speech.py +3 -2
  18. xinference/model/audio/funasr.py +17 -4
  19. xinference/model/audio/kokoro.py +3 -2
  20. xinference/model/audio/megatts.py +3 -2
  21. xinference/model/audio/melotts.py +3 -2
  22. xinference/model/audio/model_spec.json +572 -171
  23. xinference/model/audio/utils.py +0 -6
  24. xinference/model/audio/whisper.py +3 -2
  25. xinference/model/audio/whisper_mlx.py +3 -2
  26. xinference/model/cache_manager.py +141 -0
  27. xinference/model/core.py +6 -49
  28. xinference/model/custom.py +174 -0
  29. xinference/model/embedding/__init__.py +67 -56
  30. xinference/model/embedding/cache_manager.py +35 -0
  31. xinference/model/embedding/core.py +104 -84
  32. xinference/model/embedding/custom.py +55 -78
  33. xinference/model/embedding/embed_family.py +80 -31
  34. xinference/model/embedding/flag/core.py +21 -5
  35. xinference/model/embedding/llama_cpp/__init__.py +0 -0
  36. xinference/model/embedding/llama_cpp/core.py +234 -0
  37. xinference/model/embedding/model_spec.json +968 -103
  38. xinference/model/embedding/sentence_transformers/core.py +30 -20
  39. xinference/model/embedding/vllm/core.py +11 -5
  40. xinference/model/flexible/__init__.py +8 -2
  41. xinference/model/flexible/core.py +26 -119
  42. xinference/model/flexible/custom.py +69 -0
  43. xinference/model/flexible/launchers/image_process_launcher.py +1 -0
  44. xinference/model/flexible/launchers/modelscope_launcher.py +5 -1
  45. xinference/model/flexible/launchers/transformers_launcher.py +15 -3
  46. xinference/model/flexible/launchers/yolo_launcher.py +5 -1
  47. xinference/model/image/__init__.py +20 -20
  48. xinference/model/image/cache_manager.py +62 -0
  49. xinference/model/image/core.py +70 -182
  50. xinference/model/image/custom.py +28 -72
  51. xinference/model/image/model_spec.json +402 -119
  52. xinference/model/image/ocr/got_ocr2.py +3 -2
  53. xinference/model/image/stable_diffusion/core.py +22 -7
  54. xinference/model/image/stable_diffusion/mlx.py +6 -6
  55. xinference/model/image/utils.py +2 -2
  56. xinference/model/llm/__init__.py +71 -94
  57. xinference/model/llm/cache_manager.py +292 -0
  58. xinference/model/llm/core.py +37 -111
  59. xinference/model/llm/custom.py +88 -0
  60. xinference/model/llm/llama_cpp/core.py +5 -7
  61. xinference/model/llm/llm_family.json +16260 -8151
  62. xinference/model/llm/llm_family.py +138 -839
  63. xinference/model/llm/lmdeploy/core.py +5 -7
  64. xinference/model/llm/memory.py +3 -4
  65. xinference/model/llm/mlx/core.py +6 -8
  66. xinference/model/llm/reasoning_parser.py +3 -1
  67. xinference/model/llm/sglang/core.py +32 -14
  68. xinference/model/llm/transformers/chatglm.py +3 -7
  69. xinference/model/llm/transformers/core.py +49 -27
  70. xinference/model/llm/transformers/deepseek_v2.py +2 -2
  71. xinference/model/llm/transformers/gemma3.py +2 -2
  72. xinference/model/llm/transformers/multimodal/cogagent.py +2 -2
  73. xinference/model/llm/transformers/multimodal/deepseek_vl2.py +2 -2
  74. xinference/model/llm/transformers/multimodal/gemma3.py +2 -2
  75. xinference/model/llm/transformers/multimodal/glm4_1v.py +167 -0
  76. xinference/model/llm/transformers/multimodal/glm4v.py +2 -2
  77. xinference/model/llm/transformers/multimodal/intern_vl.py +2 -2
  78. xinference/model/llm/transformers/multimodal/minicpmv26.py +3 -3
  79. xinference/model/llm/transformers/multimodal/ovis2.py +2 -2
  80. xinference/model/llm/transformers/multimodal/qwen-omni.py +2 -2
  81. xinference/model/llm/transformers/multimodal/qwen2_audio.py +2 -2
  82. xinference/model/llm/transformers/multimodal/qwen2_vl.py +2 -2
  83. xinference/model/llm/transformers/opt.py +3 -7
  84. xinference/model/llm/utils.py +34 -49
  85. xinference/model/llm/vllm/core.py +77 -27
  86. xinference/model/llm/vllm/xavier/engine.py +5 -3
  87. xinference/model/llm/vllm/xavier/scheduler.py +10 -6
  88. xinference/model/llm/vllm/xavier/transfer.py +1 -1
  89. xinference/model/rerank/__init__.py +26 -25
  90. xinference/model/rerank/core.py +47 -87
  91. xinference/model/rerank/custom.py +25 -71
  92. xinference/model/rerank/model_spec.json +158 -33
  93. xinference/model/rerank/utils.py +2 -2
  94. xinference/model/utils.py +115 -54
  95. xinference/model/video/__init__.py +13 -17
  96. xinference/model/video/core.py +44 -102
  97. xinference/model/video/diffusers.py +4 -3
  98. xinference/model/video/model_spec.json +90 -21
  99. xinference/types.py +5 -3
  100. xinference/web/ui/build/asset-manifest.json +3 -3
  101. xinference/web/ui/build/index.html +1 -1
  102. xinference/web/ui/build/static/js/main.7d24df53.js +3 -0
  103. xinference/web/ui/build/static/js/main.7d24df53.js.map +1 -0
  104. xinference/web/ui/node_modules/.cache/babel-loader/2704ff66a5f73ca78b341eb3edec60154369df9d87fbc8c6dd60121abc5e1b0a.json +1 -0
  105. xinference/web/ui/node_modules/.cache/babel-loader/607dfef23d33e6b594518c0c6434567639f24f356b877c80c60575184ec50ed0.json +1 -0
  106. xinference/web/ui/node_modules/.cache/babel-loader/9be3d56173aacc3efd0b497bcb13c4f6365de30069176ee9403b40e717542326.json +1 -0
  107. xinference/web/ui/node_modules/.cache/babel-loader/9f9dd6c32c78a222d07da5987ae902effe16bcf20aac00774acdccc4de3c9ff2.json +1 -0
  108. xinference/web/ui/node_modules/.cache/babel-loader/b2ab5ee972c60d15eb9abf5845705f8ab7e1d125d324d9a9b1bcae5d6fd7ffb2.json +1 -0
  109. xinference/web/ui/src/locales/en.json +0 -1
  110. xinference/web/ui/src/locales/ja.json +0 -1
  111. xinference/web/ui/src/locales/ko.json +0 -1
  112. xinference/web/ui/src/locales/zh.json +0 -1
  113. {xinference-1.7.1.dist-info → xinference-1.8.0.dist-info}/METADATA +9 -11
  114. {xinference-1.7.1.dist-info → xinference-1.8.0.dist-info}/RECORD +119 -119
  115. xinference/model/audio/model_spec_modelscope.json +0 -231
  116. xinference/model/embedding/model_spec_modelscope.json +0 -293
  117. xinference/model/embedding/utils.py +0 -18
  118. xinference/model/image/model_spec_modelscope.json +0 -375
  119. xinference/model/llm/llama_cpp/memory.py +0 -457
  120. xinference/model/llm/llm_family_csghub.json +0 -56
  121. xinference/model/llm/llm_family_modelscope.json +0 -8700
  122. xinference/model/llm/llm_family_openmind_hub.json +0 -1019
  123. xinference/model/rerank/model_spec_modelscope.json +0 -85
  124. xinference/model/video/model_spec_modelscope.json +0 -184
  125. xinference/web/ui/build/static/js/main.9b12b7f9.js +0 -3
  126. xinference/web/ui/build/static/js/main.9b12b7f9.js.map +0 -1
  127. xinference/web/ui/node_modules/.cache/babel-loader/1460361af6975e63576708039f1cb732faf9c672d97c494d4055fc6331460be0.json +0 -1
  128. xinference/web/ui/node_modules/.cache/babel-loader/4efd8dda58fda83ed9546bf2f587df67f8d98e639117bee2d9326a9a1d9bebb2.json +0 -1
  129. xinference/web/ui/node_modules/.cache/babel-loader/55b9fb40b57fa926e8f05f31c2f96467e76e5ad62f033dca97c03f9e8c4eb4fe.json +0 -1
  130. xinference/web/ui/node_modules/.cache/babel-loader/5b2dafe5aa9e1105e0244a2b6751807342fa86aa0144b4e84d947a1686102715.json +0 -1
  131. xinference/web/ui/node_modules/.cache/babel-loader/611fa2c6c53b66039991d06dfb0473b5ab37fc63b4564e0f6e1718523768a045.json +0 -1
  132. /xinference/web/ui/build/static/js/{main.9b12b7f9.js.LICENSE.txt → main.7d24df53.js.LICENSE.txt} +0 -0
  133. {xinference-1.7.1.dist-info → xinference-1.8.0.dist-info}/WHEEL +0 -0
  134. {xinference-1.7.1.dist-info → xinference-1.8.0.dist-info}/entry_points.txt +0 -0
  135. {xinference-1.7.1.dist-info → xinference-1.8.0.dist-info}/licenses/LICENSE +0 -0
  136. {xinference-1.7.1.dist-info → xinference-1.8.0.dist-info}/top_level.txt +0 -0
@@ -11,29 +11,26 @@
11
11
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
-
15
14
  import logging
16
- import os
17
- from threading import Lock
18
15
  from typing import Any, List, Optional
19
16
 
20
17
  from ..._compat import (
21
18
  ROOT_KEY,
22
19
  ErrorWrapper,
20
+ Literal,
23
21
  Protocol,
24
22
  StrBytes,
25
23
  ValidationError,
26
24
  load_str_bytes,
27
25
  )
28
- from ...constants import XINFERENCE_CACHE_DIR, XINFERENCE_MODEL_DIR
29
- from .core import AudioModelFamilyV1
26
+ from ..custom import ModelRegistry
27
+ from .core import AudioModelFamilyV2
30
28
 
31
29
  logger = logging.getLogger(__name__)
32
30
 
33
- UD_AUDIO_LOCK = Lock()
34
-
35
31
 
36
- class CustomAudioModelFamilyV1(AudioModelFamilyV1):
32
+ class CustomAudioModelFamilyV2(AudioModelFamilyV2):
33
+ version: Literal[2] = 2
37
34
  model_id: Optional[str] # type: ignore
38
35
  model_revision: Optional[str] # type: ignore
39
36
  model_uri: Optional[str]
@@ -47,7 +44,7 @@ class CustomAudioModelFamilyV1(AudioModelFamilyV1):
47
44
  encoding: str = "utf8",
48
45
  proto: Protocol = None,
49
46
  allow_pickle: bool = False,
50
- ) -> AudioModelFamilyV1:
47
+ ) -> AudioModelFamilyV2:
51
48
  # See source code of BaseModel.parse_raw
52
49
  try:
53
50
  obj = load_str_bytes(
@@ -61,7 +58,7 @@ class CustomAudioModelFamilyV1(AudioModelFamilyV1):
61
58
  except (ValueError, TypeError, UnicodeDecodeError) as e:
62
59
  raise ValidationError([ErrorWrapper(e, loc=ROOT_KEY)], cls)
63
60
 
64
- audio_spec: AudioModelFamilyV1 = cls.parse_obj(obj)
61
+ audio_spec: AudioModelFamilyV2 = cls.parse_obj(obj)
65
62
 
66
63
  # check model_family
67
64
  if audio_spec.model_family is None:
@@ -72,78 +69,36 @@ class CustomAudioModelFamilyV1(AudioModelFamilyV1):
72
69
  return audio_spec
73
70
 
74
71
 
75
- UD_AUDIOS: List[CustomAudioModelFamilyV1] = []
72
+ UD_AUDIOS: List[CustomAudioModelFamilyV2] = []
73
+
76
74
 
75
+ class AudioModelRegistry(ModelRegistry):
76
+ model_type = "audio"
77
77
 
78
- def get_user_defined_audios() -> List[CustomAudioModelFamilyV1]:
79
- with UD_AUDIO_LOCK:
80
- return UD_AUDIOS.copy()
78
+ def __init__(self):
79
+ from . import BUILTIN_AUDIO_MODELS
81
80
 
81
+ super().__init__()
82
+ self.models = UD_AUDIOS
83
+ self.builtin_models = list(BUILTIN_AUDIO_MODELS.keys())
82
84
 
83
- def register_audio(model_spec: CustomAudioModelFamilyV1, persist: bool):
84
- from ...constants import XINFERENCE_MODEL_DIR
85
- from ..utils import is_valid_model_name, is_valid_model_uri
86
- from . import BUILTIN_AUDIO_MODELS, MODELSCOPE_AUDIO_MODELS
87
85
 
88
- if not is_valid_model_name(model_spec.model_name):
89
- raise ValueError(f"Invalid model name {model_spec.model_name}.")
86
+ def get_user_defined_audios() -> List[CustomAudioModelFamilyV2]:
87
+ from ..custom import RegistryManager
90
88
 
91
- model_uri = model_spec.model_uri
92
- if model_uri and not is_valid_model_uri(model_uri):
93
- raise ValueError(f"Invalid model URI {model_uri}.")
89
+ registry = RegistryManager.get_registry("audio")
90
+ return registry.get_custom_models()
94
91
 
95
- with UD_AUDIO_LOCK:
96
- for model_name in (
97
- list(BUILTIN_AUDIO_MODELS.keys())
98
- + list(MODELSCOPE_AUDIO_MODELS.keys())
99
- + [spec.model_name for spec in UD_AUDIOS]
100
- ):
101
- if model_spec.model_name == model_name:
102
- raise ValueError(
103
- f"Model name conflicts with existing model {model_spec.model_name}"
104
- )
105
92
 
106
- UD_AUDIOS.append(model_spec)
93
+ def register_audio(model_spec: CustomAudioModelFamilyV2, persist: bool):
94
+ from ..custom import RegistryManager
107
95
 
108
- if persist:
109
- persist_path = os.path.join(
110
- XINFERENCE_MODEL_DIR, "audio", f"{model_spec.model_name}.json"
111
- )
112
- os.makedirs(os.path.dirname(persist_path), exist_ok=True)
113
- with open(persist_path, mode="w") as fd:
114
- fd.write(model_spec.json())
96
+ registry = RegistryManager.get_registry("audio")
97
+ registry.register(model_spec, persist)
115
98
 
116
99
 
117
100
  def unregister_audio(model_name: str, raise_error: bool = True):
118
- with UD_AUDIO_LOCK:
119
- model_spec = None
120
- for i, f in enumerate(UD_AUDIOS):
121
- if f.model_name == model_name:
122
- model_spec = f
123
- break
124
- if model_spec:
125
- UD_AUDIOS.remove(model_spec)
126
-
127
- persist_path = os.path.join(
128
- XINFERENCE_MODEL_DIR, "audio", f"{model_spec.model_name}.json"
129
- )
130
- if os.path.exists(persist_path):
131
- os.remove(persist_path)
132
-
133
- cache_dir = os.path.join(XINFERENCE_CACHE_DIR, model_spec.model_name)
134
- if os.path.exists(cache_dir):
135
- logger.warning(
136
- f"Remove the cache of user-defined model {model_spec.model_name}. "
137
- f"Cache directory: {cache_dir}"
138
- )
139
- if os.path.isdir(cache_dir):
140
- os.rmdir(cache_dir)
141
- else:
142
- logger.warning(
143
- f"Cache directory is not a soft link, please remove it manually."
144
- )
145
- else:
146
- if raise_error:
147
- raise ValueError(f"Model {model_name} not found")
148
- else:
149
- logger.warning(f"Custom audio model {model_name} not found")
101
+ from ..custom import RegistryManager
102
+
103
+ registry = RegistryManager.get_registry("audio")
104
+ registry.unregister(model_name, raise_error)
@@ -19,7 +19,7 @@ from io import BytesIO
19
19
  from typing import TYPE_CHECKING, Optional, Union
20
20
 
21
21
  if TYPE_CHECKING:
22
- from .core import AudioModelFamilyV1
22
+ from .core import AudioModelFamilyV2
23
23
 
24
24
  logger = logging.getLogger(__name__)
25
25
 
@@ -29,10 +29,11 @@ class F5TTSModel:
29
29
  self,
30
30
  model_uid: str,
31
31
  model_path: str,
32
- model_spec: "AudioModelFamilyV1",
32
+ model_spec: "AudioModelFamilyV2",
33
33
  device: Optional[str] = None,
34
34
  **kwargs,
35
35
  ):
36
+ self.model_family = model_spec
36
37
  self._model_uid = model_uid
37
38
  self._model_path = model_path
38
39
  self._model_spec = model_spec
@@ -24,7 +24,7 @@ import numpy as np
24
24
  from tqdm import tqdm
25
25
 
26
26
  if TYPE_CHECKING:
27
- from .core import AudioModelFamilyV1
27
+ from .core import AudioModelFamilyV2
28
28
 
29
29
  logger = logging.getLogger(__name__)
30
30
 
@@ -34,10 +34,11 @@ class F5TTSMLXModel:
34
34
  self,
35
35
  model_uid: str,
36
36
  model_path: str,
37
- model_spec: "AudioModelFamilyV1",
37
+ model_spec: "AudioModelFamilyV2",
38
38
  device: Optional[str] = None,
39
39
  **kwargs,
40
40
  ):
41
+ self.model_family = model_spec
41
42
  self._model_uid = model_uid
42
43
  self._model_path = model_path
43
44
  self._model_spec = model_spec
@@ -23,7 +23,7 @@ import torch
23
23
  from ...device_utils import get_available_device, is_device_available
24
24
 
25
25
  if TYPE_CHECKING:
26
- from .core import AudioModelFamilyV1
26
+ from .core import AudioModelFamilyV2
27
27
 
28
28
  logger = logging.getLogger(__name__)
29
29
 
@@ -48,10 +48,11 @@ class FishSpeechModel:
48
48
  self,
49
49
  model_uid: str,
50
50
  model_path: str,
51
- model_spec: "AudioModelFamilyV1",
51
+ model_spec: "AudioModelFamilyV2",
52
52
  device: Optional[str] = None,
53
53
  **kwargs,
54
54
  ):
55
+ self.model_family = model_spec
55
56
  self._model_uid = model_uid
56
57
  self._model_path = model_path
57
58
  self._model_spec = model_spec
@@ -19,7 +19,7 @@ from typing import TYPE_CHECKING, List, Optional
19
19
  from ...device_utils import get_available_device, is_device_available
20
20
 
21
21
  if TYPE_CHECKING:
22
- from .core import AudioModelFamilyV1
22
+ from .core import AudioModelFamilyV2
23
23
 
24
24
  logger = logging.getLogger(__name__)
25
25
 
@@ -29,10 +29,11 @@ class FunASRModel:
29
29
  self,
30
30
  model_uid: str,
31
31
  model_path: str,
32
- model_spec: "AudioModelFamilyV1",
32
+ model_spec: "AudioModelFamilyV2",
33
33
  device: Optional[str] = None,
34
34
  **kwargs,
35
35
  ):
36
+ self.model_family = model_spec
36
37
  self._model_uid = model_uid
37
38
  self._model_path = model_path
38
39
  self._model_spec = model_spec
@@ -100,7 +101,11 @@ class FunASRModel:
100
101
  if not is_device_available(self._device):
101
102
  raise ValueError(f"Device {self._device} is not available!")
102
103
 
103
- kwargs = self._model_spec.default_model_config.copy()
104
+ kwargs = (
105
+ self._model_spec.default_model_config.copy()
106
+ if getattr(self._model_spec, "default_model_config", None)
107
+ else {}
108
+ )
104
109
  kwargs.update(self._kwargs)
105
110
  logger.debug("Loading FunASR model with kwargs: %s", kwargs)
106
111
  self._model = AutoModel(model=self._model_path, device=self._device, **kwargs)
@@ -131,12 +136,20 @@ class FunASRModel:
131
136
  with tempfile.NamedTemporaryFile(buffering=0) as f:
132
137
  f.write(audio)
133
138
 
134
- kw = self._model_spec.default_transcription_config.copy() # type: ignore
139
+ kw = (
140
+ self._model_spec.default_transcription_config.copy() # type: ignore
141
+ if getattr(self._model_spec, "default_transcription_config", None)
142
+ else {}
143
+ )
135
144
  kw.update(kwargs)
136
145
  logger.debug("Calling FunASR model with kwargs: %s", kw)
137
146
  result = self._model.generate( # type: ignore
138
147
  input=f.name, cache={}, language=language, **kw
139
148
  )
149
+ if not result or not isinstance(result, list):
150
+ raise RuntimeError(f"FunASR returned empty or invalid result: {result}")
151
+ if "text" not in result[0]:
152
+ raise RuntimeError(f"Missing 'text' field in result[0]: {result[0]}")
140
153
  text = rich_transcription_postprocess(result[0]["text"])
141
154
 
142
155
  if response_format == "json":
@@ -20,7 +20,7 @@ import numpy as np
20
20
  from ...device_utils import get_available_device, is_device_available
21
21
 
22
22
  if TYPE_CHECKING:
23
- from .core import AudioModelFamilyV1
23
+ from .core import AudioModelFamilyV2
24
24
 
25
25
  logger = logging.getLogger(__name__)
26
26
 
@@ -30,10 +30,11 @@ class KokoroModel:
30
30
  self,
31
31
  model_uid: str,
32
32
  model_path: str,
33
- model_spec: "AudioModelFamilyV1",
33
+ model_spec: "AudioModelFamilyV2",
34
34
  device: Optional[str] = None,
35
35
  **kwargs,
36
36
  ):
37
+ self.model_family = model_spec
37
38
  self._model_uid = model_uid
38
39
  self._model_path = model_path
39
40
  self._model_spec = model_spec
@@ -17,7 +17,7 @@ from io import BytesIO
17
17
  from typing import TYPE_CHECKING, Optional
18
18
 
19
19
  if TYPE_CHECKING:
20
- from .core import AudioModelFamilyV1
20
+ from .core import AudioModelFamilyV2
21
21
 
22
22
  logger = logging.getLogger(__name__)
23
23
 
@@ -27,10 +27,11 @@ class MegaTTSModel:
27
27
  self,
28
28
  model_uid: str,
29
29
  model_path: str,
30
- model_spec: "AudioModelFamilyV1",
30
+ model_spec: "AudioModelFamilyV2",
31
31
  device: Optional[str] = None,
32
32
  **kwargs,
33
33
  ):
34
+ self.model_family = model_spec
34
35
  self._model_uid = model_uid
35
36
  self._model_path = model_path
36
37
  self._model_spec = model_spec
@@ -18,7 +18,7 @@ from typing import TYPE_CHECKING, Optional
18
18
  from ...device_utils import get_available_device, is_device_available
19
19
 
20
20
  if TYPE_CHECKING:
21
- from .core import AudioModelFamilyV1
21
+ from .core import AudioModelFamilyV2
22
22
 
23
23
  logger = logging.getLogger(__name__)
24
24
 
@@ -28,10 +28,11 @@ class MeloTTSModel:
28
28
  self,
29
29
  model_uid: str,
30
30
  model_path: str,
31
- model_spec: "AudioModelFamilyV1",
31
+ model_spec: "AudioModelFamilyV2",
32
32
  device: Optional[str] = None,
33
33
  **kwargs,
34
34
  ):
35
+ self.model_family = model_spec
35
36
  self._model_uid = model_uid
36
37
  self._model_path = model_path
37
38
  self._model_spec = model_spec