mlrun 1.10.0rc13__py3-none-any.whl → 1.10.0rc14__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 mlrun might be problematic. Click here for more details.
- mlrun/artifacts/llm_prompt.py +106 -20
- mlrun/common/constants.py +0 -1
- mlrun/common/schemas/workflow.py +0 -1
- mlrun/execution.py +16 -7
- mlrun/model.py +15 -0
- mlrun/projects/project.py +12 -6
- mlrun/serving/__init__.py +2 -0
- mlrun/serving/states.py +114 -10
- mlrun/utils/version/version.json +2 -2
- {mlrun-1.10.0rc13.dist-info → mlrun-1.10.0rc14.dist-info}/METADATA +2 -2
- {mlrun-1.10.0rc13.dist-info → mlrun-1.10.0rc14.dist-info}/RECORD +15 -15
- {mlrun-1.10.0rc13.dist-info → mlrun-1.10.0rc14.dist-info}/WHEEL +0 -0
- {mlrun-1.10.0rc13.dist-info → mlrun-1.10.0rc14.dist-info}/entry_points.txt +0 -0
- {mlrun-1.10.0rc13.dist-info → mlrun-1.10.0rc14.dist-info}/licenses/LICENSE +0 -0
- {mlrun-1.10.0rc13.dist-info → mlrun-1.10.0rc14.dist-info}/top_level.txt +0 -0
mlrun/artifacts/llm_prompt.py
CHANGED
|
@@ -11,12 +11,13 @@
|
|
|
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
|
+
import json
|
|
14
15
|
import tempfile
|
|
15
16
|
from typing import Optional, Union
|
|
16
17
|
|
|
17
18
|
import mlrun
|
|
18
19
|
import mlrun.artifacts.model as model_art
|
|
19
|
-
import mlrun.common
|
|
20
|
+
import mlrun.common.schemas
|
|
20
21
|
from mlrun.artifacts import Artifact, ArtifactMetadata, ArtifactSpec
|
|
21
22
|
from mlrun.utils import StorePrefix, logger
|
|
22
23
|
|
|
@@ -25,16 +26,18 @@ MAX_PROMPT_LENGTH = 1024
|
|
|
25
26
|
|
|
26
27
|
class LLMPromptArtifactSpec(ArtifactSpec):
|
|
27
28
|
_dict_fields = ArtifactSpec._dict_fields + [
|
|
28
|
-
"
|
|
29
|
+
"prompt_template",
|
|
29
30
|
"prompt_legend",
|
|
30
31
|
"model_configuration",
|
|
31
32
|
"description",
|
|
32
33
|
]
|
|
34
|
+
PROMPT_TEMPLATE_KEYS = ("content", "role")
|
|
35
|
+
PROMPT_LEGENDS_KEYS = ("field", "description")
|
|
33
36
|
|
|
34
37
|
def __init__(
|
|
35
38
|
self,
|
|
36
39
|
model_artifact: Union[model_art.ModelArtifact, str] = None,
|
|
37
|
-
|
|
40
|
+
prompt_template: Optional[list[dict]] = None,
|
|
38
41
|
prompt_path: Optional[str] = None,
|
|
39
42
|
prompt_legend: Optional[dict] = None,
|
|
40
43
|
model_configuration: Optional[dict] = None,
|
|
@@ -42,22 +45,26 @@ class LLMPromptArtifactSpec(ArtifactSpec):
|
|
|
42
45
|
target_path: Optional[str] = None,
|
|
43
46
|
**kwargs,
|
|
44
47
|
):
|
|
45
|
-
if
|
|
48
|
+
if prompt_template and prompt_path:
|
|
46
49
|
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
47
|
-
"Cannot specify both '
|
|
50
|
+
"Cannot specify both 'prompt_template' and 'prompt_path'"
|
|
48
51
|
)
|
|
49
|
-
|
|
52
|
+
if prompt_legend:
|
|
53
|
+
self._verify_prompt_legend(prompt_legend)
|
|
54
|
+
if prompt_path:
|
|
55
|
+
self._verify_prompt_path(prompt_path)
|
|
56
|
+
if prompt_template:
|
|
57
|
+
self._verify_prompt_template(prompt_template)
|
|
50
58
|
super().__init__(
|
|
51
59
|
src_path=prompt_path,
|
|
52
60
|
target_path=target_path,
|
|
53
61
|
parent_uri=model_artifact.uri
|
|
54
62
|
if isinstance(model_artifact, model_art.ModelArtifact)
|
|
55
63
|
else model_artifact,
|
|
56
|
-
body=prompt_string,
|
|
57
64
|
**kwargs,
|
|
58
65
|
)
|
|
59
66
|
|
|
60
|
-
self.
|
|
67
|
+
self.prompt_template = prompt_template
|
|
61
68
|
self.prompt_legend = prompt_legend
|
|
62
69
|
self.model_configuration = model_configuration
|
|
63
70
|
self.description = description
|
|
@@ -67,10 +74,78 @@ class LLMPromptArtifactSpec(ArtifactSpec):
|
|
|
67
74
|
else None
|
|
68
75
|
)
|
|
69
76
|
|
|
77
|
+
def _verify_prompt_template(self, prompt_template):
|
|
78
|
+
if not (
|
|
79
|
+
isinstance(prompt_template, list)
|
|
80
|
+
and all(isinstance(item, dict) for item in prompt_template)
|
|
81
|
+
):
|
|
82
|
+
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
83
|
+
"Expected prompt_template to be a list of dicts"
|
|
84
|
+
)
|
|
85
|
+
keys_to_pop = []
|
|
86
|
+
for message in prompt_template:
|
|
87
|
+
for key in message.keys():
|
|
88
|
+
if isinstance(key, str):
|
|
89
|
+
if key.lower() not in self.PROMPT_TEMPLATE_KEYS:
|
|
90
|
+
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
91
|
+
f"Expected prompt_template to contain dict that "
|
|
92
|
+
f"only has keys from {self.PROMPT_TEMPLATE_KEYS}"
|
|
93
|
+
)
|
|
94
|
+
else:
|
|
95
|
+
if not key.islower():
|
|
96
|
+
message[key.lower()] = message[key]
|
|
97
|
+
keys_to_pop.append(key)
|
|
98
|
+
else:
|
|
99
|
+
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
100
|
+
f"Expected prompt_template to contain dict that only"
|
|
101
|
+
f" has str keys got {key} of type {type(key)}"
|
|
102
|
+
)
|
|
103
|
+
for key_to_pop in keys_to_pop:
|
|
104
|
+
message.pop(key_to_pop)
|
|
105
|
+
|
|
70
106
|
@property
|
|
71
107
|
def model_uri(self):
|
|
72
108
|
return self.parent_uri
|
|
73
109
|
|
|
110
|
+
@staticmethod
|
|
111
|
+
def _verify_prompt_legend(prompt_legend: dict):
|
|
112
|
+
if prompt_legend is None:
|
|
113
|
+
return True
|
|
114
|
+
for place_holder, body_map in prompt_legend.items():
|
|
115
|
+
if isinstance(body_map, dict):
|
|
116
|
+
if body_map.get("field") is None:
|
|
117
|
+
body_map["field"] = place_holder
|
|
118
|
+
body_map["description"] = body_map.get("description")
|
|
119
|
+
if diff := set(body_map.keys()) - set(
|
|
120
|
+
LLMPromptArtifactSpec.PROMPT_LEGENDS_KEYS
|
|
121
|
+
):
|
|
122
|
+
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
123
|
+
"prompt_legend values must contain only 'field' and "
|
|
124
|
+
f"'description' keys, got extra fields: {diff}"
|
|
125
|
+
)
|
|
126
|
+
else:
|
|
127
|
+
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
128
|
+
f"Wrong prompt_legend format, {place_holder} is not mapped to dict"
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
@staticmethod
|
|
132
|
+
def _verify_prompt_path(prompt_path: str):
|
|
133
|
+
with mlrun.datastore.store_manager.object(prompt_path).open(mode="r") as p_file:
|
|
134
|
+
try:
|
|
135
|
+
json.load(p_file)
|
|
136
|
+
except json.JSONDecodeError:
|
|
137
|
+
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
138
|
+
f"Failed on decoding str in path "
|
|
139
|
+
f"{prompt_path} expected file to contain a "
|
|
140
|
+
f"json format."
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
def get_body(self):
|
|
144
|
+
if self.prompt_template:
|
|
145
|
+
return json.dumps(self.prompt_template)
|
|
146
|
+
else:
|
|
147
|
+
return None
|
|
148
|
+
|
|
74
149
|
|
|
75
150
|
class LLMPromptArtifact(Artifact):
|
|
76
151
|
"""
|
|
@@ -90,7 +165,7 @@ class LLMPromptArtifact(Artifact):
|
|
|
90
165
|
model_artifact: Union[
|
|
91
166
|
model_art.ModelArtifact, str
|
|
92
167
|
] = None, # TODO support partial model uri
|
|
93
|
-
|
|
168
|
+
prompt_template: Optional[list[dict]] = None,
|
|
94
169
|
prompt_path: Optional[str] = None,
|
|
95
170
|
prompt_legend: Optional[dict] = None,
|
|
96
171
|
model_configuration: Optional[dict] = None,
|
|
@@ -99,7 +174,7 @@ class LLMPromptArtifact(Artifact):
|
|
|
99
174
|
**kwargs,
|
|
100
175
|
):
|
|
101
176
|
llm_prompt_spec = LLMPromptArtifactSpec(
|
|
102
|
-
|
|
177
|
+
prompt_template=prompt_template,
|
|
103
178
|
prompt_path=prompt_path,
|
|
104
179
|
prompt_legend=prompt_legend,
|
|
105
180
|
model_artifact=model_artifact,
|
|
@@ -137,33 +212,44 @@ class LLMPromptArtifact(Artifact):
|
|
|
137
212
|
return self.spec._model_artifact
|
|
138
213
|
return None
|
|
139
214
|
|
|
140
|
-
def read_prompt(self) -> Optional[str]:
|
|
215
|
+
def read_prompt(self) -> Optional[Union[str, list[dict]]]:
|
|
141
216
|
"""
|
|
142
|
-
Read the prompt
|
|
217
|
+
Read the prompt json from the artifact or if provided prompt template.
|
|
218
|
+
@:param as_str: True to return the prompt string or a list of dicts.
|
|
219
|
+
@:return prompt string or list of dicts
|
|
143
220
|
"""
|
|
144
|
-
if self.spec.
|
|
145
|
-
return self.spec.
|
|
221
|
+
if self.spec.prompt_template:
|
|
222
|
+
return self.spec.prompt_template
|
|
146
223
|
if self.spec.target_path:
|
|
147
224
|
with mlrun.datastore.store_manager.object(url=self.spec.target_path).open(
|
|
148
225
|
mode="r"
|
|
149
226
|
) as p_file:
|
|
150
|
-
|
|
227
|
+
try:
|
|
228
|
+
return json.load(p_file)
|
|
229
|
+
except json.JSONDecodeError:
|
|
230
|
+
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
231
|
+
f"Failed on decoding str in path "
|
|
232
|
+
f"{self.spec.target_path} expected file to contain a "
|
|
233
|
+
f"json format."
|
|
234
|
+
)
|
|
151
235
|
|
|
152
236
|
def before_log(self):
|
|
153
237
|
"""
|
|
154
238
|
Prepare the artifact before logging.
|
|
155
239
|
This method is called before the artifact is logged.
|
|
156
240
|
"""
|
|
157
|
-
if
|
|
241
|
+
if (
|
|
242
|
+
self.spec.prompt_template
|
|
243
|
+
and len(str(self.spec.prompt_template)) > MAX_PROMPT_LENGTH
|
|
244
|
+
):
|
|
158
245
|
logger.debug(
|
|
159
246
|
"Prompt string exceeds maximum length, saving to a temporary file."
|
|
160
247
|
)
|
|
161
248
|
with tempfile.NamedTemporaryFile(
|
|
162
|
-
delete=False, mode="w", suffix=".
|
|
249
|
+
delete=False, mode="w", suffix=".json"
|
|
163
250
|
) as temp_file:
|
|
164
|
-
temp_file.write(self.spec.
|
|
251
|
+
temp_file.write(json.dumps(self.spec.prompt_template))
|
|
165
252
|
self.spec.src_path = temp_file.name
|
|
166
|
-
self.spec.
|
|
253
|
+
self.spec.prompt_template = None
|
|
167
254
|
self._src_is_temp = True
|
|
168
|
-
|
|
169
255
|
super().before_log()
|
mlrun/common/constants.py
CHANGED
mlrun/common/schemas/workflow.py
CHANGED
|
@@ -49,7 +49,6 @@ class WorkflowRequest(pydantic.v1.BaseModel):
|
|
|
49
49
|
class RerunWorkflowRequest(pydantic.v1.BaseModel):
|
|
50
50
|
run_name: typing.Optional[str] = None
|
|
51
51
|
run_id: typing.Optional[str] = None
|
|
52
|
-
original_workflow_id: typing.Optional[str] = None
|
|
53
52
|
notifications: typing.Optional[list[Notification]] = None
|
|
54
53
|
workflow_runner_node_selector: typing.Optional[dict[str, str]] = None
|
|
55
54
|
|
mlrun/execution.py
CHANGED
|
@@ -94,6 +94,7 @@ class MLClientCtx:
|
|
|
94
94
|
self._state_thresholds = {}
|
|
95
95
|
self._retry_spec = {}
|
|
96
96
|
self._retry_count = None
|
|
97
|
+
self._retries = []
|
|
97
98
|
|
|
98
99
|
self._labels = {}
|
|
99
100
|
self._annotations = {}
|
|
@@ -468,6 +469,7 @@ class MLClientCtx:
|
|
|
468
469
|
for key, uri in status.get("artifact_uris", {}).items():
|
|
469
470
|
self._artifacts_manager.artifact_uris[key] = uri
|
|
470
471
|
self._retry_count = status.get("retry_count", self._retry_count)
|
|
472
|
+
self._retries = status.get("retries", self._retries)
|
|
471
473
|
# if run is a retry, the state needs to move to running
|
|
472
474
|
if include_status:
|
|
473
475
|
self._state = status.get("state", self._state)
|
|
@@ -911,7 +913,7 @@ class MLClientCtx:
|
|
|
911
913
|
def log_llm_prompt(
|
|
912
914
|
self,
|
|
913
915
|
key,
|
|
914
|
-
|
|
916
|
+
prompt_template: Optional[list[dict]] = None,
|
|
915
917
|
prompt_path: Optional[str] = None,
|
|
916
918
|
prompt_legend: Optional[dict] = None,
|
|
917
919
|
model_artifact: Union[ModelArtifact, str] = None,
|
|
@@ -935,7 +937,7 @@ class MLClientCtx:
|
|
|
935
937
|
# Log an inline prompt
|
|
936
938
|
context.log_llm_prompt(
|
|
937
939
|
key="qa-prompt",
|
|
938
|
-
|
|
940
|
+
prompt_template=[{"role: "user", "content": "question with {place_holder}"}],
|
|
939
941
|
model_artifact=model,
|
|
940
942
|
prompt_legend={"question": "user_input"},
|
|
941
943
|
model_configuration={"temperature": 0.7, "max_tokens": 128},
|
|
@@ -943,10 +945,16 @@ class MLClientCtx:
|
|
|
943
945
|
)
|
|
944
946
|
|
|
945
947
|
:param key: Unique name of the artifact.
|
|
946
|
-
:param
|
|
948
|
+
:param prompt_template: Raw prompt list of dicts -
|
|
949
|
+
[{"role": "system", "content": "You are a {profession} advisor"},
|
|
950
|
+
"role": "user", "content": "I need your help with {profession}"]. only "role" and "content" keys allow in any
|
|
951
|
+
str format (upper/lower case), keys will be modified to lower case.
|
|
952
|
+
Cannot be used with `prompt_path`.
|
|
947
953
|
:param prompt_path: Path to a file containing the prompt content. Cannot be used with `prompt_string`.
|
|
948
954
|
:param prompt_legend: A dictionary where each key is a placeholder in the prompt (e.g., ``{user_name}``)
|
|
949
|
-
and the value is a description
|
|
955
|
+
and the value is a dictionary holding two keys, "field", "description". "field" points to the field in
|
|
956
|
+
the event where the value of the place-holder inside the event, if None or not exist will be replaced
|
|
957
|
+
with the place-holder name. "description" will point to explanation of what that placeholder represents.
|
|
950
958
|
Useful for documenting and clarifying dynamic parts of the prompt.
|
|
951
959
|
:param model_artifact: Reference to the parent model (either `ModelArtifact` or model URI string).
|
|
952
960
|
:param model_configuration: Dictionary of generation parameters (e.g., temperature, max_tokens).
|
|
@@ -961,15 +969,15 @@ class MLClientCtx:
|
|
|
961
969
|
:returns: The logged `LLMPromptArtifact` object.
|
|
962
970
|
"""
|
|
963
971
|
|
|
964
|
-
if not
|
|
972
|
+
if not prompt_template and not prompt_path:
|
|
965
973
|
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
966
|
-
"Either '
|
|
974
|
+
"Either 'prompt_template' or 'prompt_path' must be provided"
|
|
967
975
|
)
|
|
968
976
|
|
|
969
977
|
llm_prompt = LLMPromptArtifact(
|
|
970
978
|
key=key,
|
|
971
979
|
project=self.project or "",
|
|
972
|
-
|
|
980
|
+
prompt_template=prompt_template,
|
|
973
981
|
prompt_path=prompt_path,
|
|
974
982
|
prompt_legend=prompt_legend,
|
|
975
983
|
model_artifact=model_artifact,
|
|
@@ -1267,6 +1275,7 @@ class MLClientCtx:
|
|
|
1267
1275
|
"start_time": to_date_str(self._start_time),
|
|
1268
1276
|
"last_update": to_date_str(self._last_update),
|
|
1269
1277
|
"retry_count": self._retry_count,
|
|
1278
|
+
"retries": self._retries,
|
|
1270
1279
|
},
|
|
1271
1280
|
}
|
|
1272
1281
|
|
mlrun/model.py
CHANGED
|
@@ -1375,6 +1375,7 @@ class RunStatus(ModelObj):
|
|
|
1375
1375
|
notifications: Optional[dict[str, Notification]] = None,
|
|
1376
1376
|
artifact_uris: Optional[dict[str, str]] = None,
|
|
1377
1377
|
retry_count: Optional[int] = None,
|
|
1378
|
+
retries: Optional[list[dict]] = None,
|
|
1378
1379
|
):
|
|
1379
1380
|
self.state = state or "created"
|
|
1380
1381
|
self.status_text = status_text
|
|
@@ -1393,6 +1394,7 @@ class RunStatus(ModelObj):
|
|
|
1393
1394
|
# Artifact key -> URI mapping, since the full artifacts are not stored in the runs DB table
|
|
1394
1395
|
self._artifact_uris = artifact_uris or {}
|
|
1395
1396
|
self._retry_count = retry_count or None
|
|
1397
|
+
self._retries = retries or []
|
|
1396
1398
|
|
|
1397
1399
|
@classmethod
|
|
1398
1400
|
def from_dict(
|
|
@@ -1461,6 +1463,19 @@ class RunStatus(ModelObj):
|
|
|
1461
1463
|
"""
|
|
1462
1464
|
self._retry_count = retry_count
|
|
1463
1465
|
|
|
1466
|
+
@property
|
|
1467
|
+
def retries(self) -> list[dict]:
|
|
1468
|
+
"""List of metadata for each retry attempt."""
|
|
1469
|
+
return self._retries
|
|
1470
|
+
|
|
1471
|
+
@retries.setter
|
|
1472
|
+
def retries(self, retries: list[dict]):
|
|
1473
|
+
"""
|
|
1474
|
+
Set the list of retry attempt metadata.
|
|
1475
|
+
:param retries: A list of dictionaries, each representing a retry attempt.
|
|
1476
|
+
"""
|
|
1477
|
+
self._retries = retries
|
|
1478
|
+
|
|
1464
1479
|
def is_failed(self) -> Optional[bool]:
|
|
1465
1480
|
"""
|
|
1466
1481
|
This method returns whether a run has failed.
|
mlrun/projects/project.py
CHANGED
|
@@ -1889,7 +1889,7 @@ class MlrunProject(ModelObj):
|
|
|
1889
1889
|
def log_llm_prompt(
|
|
1890
1890
|
self,
|
|
1891
1891
|
key,
|
|
1892
|
-
|
|
1892
|
+
prompt_template: Optional[list[dict]] = None,
|
|
1893
1893
|
prompt_path: Optional[str] = None,
|
|
1894
1894
|
prompt_legend: Optional[dict] = None,
|
|
1895
1895
|
model_artifact: Union[ModelArtifact, str] = None,
|
|
@@ -1923,10 +1923,16 @@ class MlrunProject(ModelObj):
|
|
|
1923
1923
|
)
|
|
1924
1924
|
|
|
1925
1925
|
:param key: Unique key for the prompt artifact.
|
|
1926
|
-
:param
|
|
1926
|
+
:param prompt_template: Raw prompt list of dicts -
|
|
1927
|
+
[{"role": "system", "content": "You are a {profession} advisor"},
|
|
1928
|
+
"role": "user", "content": "I need your help with {profession}"]. only "role" and "content" keys allow in any
|
|
1929
|
+
str format (upper/lower case), keys will be modified to lower case.
|
|
1930
|
+
Cannot be used with `prompt_path`.
|
|
1927
1931
|
:param prompt_path: Path to a file containing the prompt. Mutually exclusive with `prompt_string`.
|
|
1928
1932
|
:param prompt_legend: A dictionary where each key is a placeholder in the prompt (e.g., ``{user_name}``)
|
|
1929
|
-
and the value is a description
|
|
1933
|
+
and the value is a dictionary holding two keys, "field", "description". "field" points to the field in
|
|
1934
|
+
the event where the value of the place-holder inside the event, if None or not exist will be replaced
|
|
1935
|
+
with the place-holder name. "description" will point to explanation of what that placeholder represents.
|
|
1930
1936
|
Useful for documenting and clarifying dynamic parts of the prompt.
|
|
1931
1937
|
:param model_artifact: Reference to the parent model (either `ModelArtifact` or model URI string).
|
|
1932
1938
|
:param model_configuration: Configuration dictionary for model generation parameters
|
|
@@ -1942,15 +1948,15 @@ class MlrunProject(ModelObj):
|
|
|
1942
1948
|
:returns: The logged `LLMPromptArtifact` object.
|
|
1943
1949
|
"""
|
|
1944
1950
|
|
|
1945
|
-
if not
|
|
1951
|
+
if not prompt_template and not prompt_path:
|
|
1946
1952
|
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
1947
|
-
"Either '
|
|
1953
|
+
"Either 'prompt_template' or 'prompt_path' must be provided"
|
|
1948
1954
|
)
|
|
1949
1955
|
|
|
1950
1956
|
llm_prompt = LLMPromptArtifact(
|
|
1951
1957
|
key=key,
|
|
1952
1958
|
project=self.name,
|
|
1953
|
-
|
|
1959
|
+
prompt_template=prompt_template,
|
|
1954
1960
|
prompt_path=prompt_path,
|
|
1955
1961
|
prompt_legend=prompt_legend,
|
|
1956
1962
|
model_artifact=model_artifact,
|
mlrun/serving/__init__.py
CHANGED
|
@@ -28,6 +28,7 @@ __all__ = [
|
|
|
28
28
|
"Model",
|
|
29
29
|
"ModelSelector",
|
|
30
30
|
"MonitoredStep",
|
|
31
|
+
"LLModel",
|
|
31
32
|
]
|
|
32
33
|
|
|
33
34
|
from .routers import ModelRouter, VotingEnsemble # noqa
|
|
@@ -47,6 +48,7 @@ from .states import (
|
|
|
47
48
|
Model,
|
|
48
49
|
ModelSelector,
|
|
49
50
|
MonitoredStep,
|
|
51
|
+
LLModel,
|
|
50
52
|
) # noqa
|
|
51
53
|
from .v1_serving import MLModelServer, new_v1_model_server # noqa
|
|
52
54
|
from .v2_serving import V2ModelServer # noqa
|
mlrun/serving/states.py
CHANGED
|
@@ -1081,6 +1081,7 @@ class Model(storey.ParallelExecutionRunnable, ModelObj):
|
|
|
1081
1081
|
"raise_exception",
|
|
1082
1082
|
"artifact_uri",
|
|
1083
1083
|
"shared_runnable_name",
|
|
1084
|
+
"shared_proxy_mapping",
|
|
1084
1085
|
]
|
|
1085
1086
|
kind = "model"
|
|
1086
1087
|
|
|
@@ -1089,12 +1090,16 @@ class Model(storey.ParallelExecutionRunnable, ModelObj):
|
|
|
1089
1090
|
name: str,
|
|
1090
1091
|
raise_exception: bool = True,
|
|
1091
1092
|
artifact_uri: Optional[str] = None,
|
|
1093
|
+
shared_proxy_mapping: Optional[dict] = None,
|
|
1092
1094
|
**kwargs,
|
|
1093
1095
|
):
|
|
1094
1096
|
super().__init__(name=name, raise_exception=raise_exception, **kwargs)
|
|
1095
1097
|
if artifact_uri is not None and not isinstance(artifact_uri, str):
|
|
1096
1098
|
raise MLRunInvalidArgumentError("'artifact_uri' argument must be a string")
|
|
1097
1099
|
self.artifact_uri = artifact_uri
|
|
1100
|
+
self.shared_proxy_mapping: dict[
|
|
1101
|
+
str : Union[str, ModelArtifact, LLMPromptArtifact]
|
|
1102
|
+
] = shared_proxy_mapping
|
|
1098
1103
|
self.invocation_artifact: Optional[LLMPromptArtifact] = None
|
|
1099
1104
|
self.model_artifact: Optional[ModelArtifact] = None
|
|
1100
1105
|
self.model_provider: Optional[ModelProvider] = None
|
|
@@ -1125,10 +1130,13 @@ class Model(storey.ParallelExecutionRunnable, ModelObj):
|
|
|
1125
1130
|
else:
|
|
1126
1131
|
self.model_artifact = artifact
|
|
1127
1132
|
|
|
1128
|
-
def _get_artifact_object(
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1133
|
+
def _get_artifact_object(
|
|
1134
|
+
self, proxy_uri: Optional[str] = None
|
|
1135
|
+
) -> Union[ModelArtifact, LLMPromptArtifact, None]:
|
|
1136
|
+
uri = proxy_uri or self.artifact_uri
|
|
1137
|
+
if uri:
|
|
1138
|
+
if mlrun.datastore.is_store_uri(uri):
|
|
1139
|
+
artifact, _ = mlrun.store_manager.get_store_artifact(uri)
|
|
1132
1140
|
return artifact
|
|
1133
1141
|
else:
|
|
1134
1142
|
raise ValueError(
|
|
@@ -1148,10 +1156,12 @@ class Model(storey.ParallelExecutionRunnable, ModelObj):
|
|
|
1148
1156
|
"""Override to implement prediction logic if the logic requires asyncio."""
|
|
1149
1157
|
return body
|
|
1150
1158
|
|
|
1151
|
-
def run(self, body: Any, path: str) -> Any:
|
|
1159
|
+
def run(self, body: Any, path: str, origin_name: Optional[str] = None) -> Any:
|
|
1152
1160
|
return self.predict(body)
|
|
1153
1161
|
|
|
1154
|
-
async def run_async(
|
|
1162
|
+
async def run_async(
|
|
1163
|
+
self, body: Any, path: str, origin_name: Optional[str] = None
|
|
1164
|
+
) -> Any:
|
|
1155
1165
|
return await self.predict_async(body)
|
|
1156
1166
|
|
|
1157
1167
|
def get_local_model_path(self, suffix="") -> (str, dict):
|
|
@@ -1186,6 +1196,65 @@ class Model(storey.ParallelExecutionRunnable, ModelObj):
|
|
|
1186
1196
|
return None, None
|
|
1187
1197
|
|
|
1188
1198
|
|
|
1199
|
+
class LLModel(Model):
|
|
1200
|
+
def __init__(self, name: str, **kwargs):
|
|
1201
|
+
super().__init__(name, **kwargs)
|
|
1202
|
+
|
|
1203
|
+
def predict(
|
|
1204
|
+
self, body: Any, messages: list[dict], model_configuration: dict
|
|
1205
|
+
) -> Any:
|
|
1206
|
+
return body
|
|
1207
|
+
|
|
1208
|
+
async def predict_async(
|
|
1209
|
+
self, body: Any, messages: list[dict], model_configuration: dict
|
|
1210
|
+
) -> Any:
|
|
1211
|
+
return body
|
|
1212
|
+
|
|
1213
|
+
def run(self, body: Any, path: str, origin_name: Optional[str] = None) -> Any:
|
|
1214
|
+
messages, model_configuration = self.enrich_prompt(body, origin_name)
|
|
1215
|
+
return self.predict(
|
|
1216
|
+
body, messages=messages, model_configuration=model_configuration
|
|
1217
|
+
)
|
|
1218
|
+
|
|
1219
|
+
async def run_async(
|
|
1220
|
+
self, body: Any, path: str, origin_name: Optional[str] = None
|
|
1221
|
+
) -> Any:
|
|
1222
|
+
messages, model_configuration = self.enrich_prompt(body, origin_name)
|
|
1223
|
+
return await self.predict_async(
|
|
1224
|
+
body, messages=messages, model_configuration=model_configuration
|
|
1225
|
+
)
|
|
1226
|
+
|
|
1227
|
+
def enrich_prompt(
|
|
1228
|
+
self, body: dict, origin_name: str
|
|
1229
|
+
) -> Union[tuple[list[dict], dict], tuple[None, None]]:
|
|
1230
|
+
if origin_name and self.shared_proxy_mapping:
|
|
1231
|
+
llm_prompt_artifact = self.shared_proxy_mapping.get(origin_name)
|
|
1232
|
+
if isinstance(llm_prompt_artifact, str):
|
|
1233
|
+
llm_prompt_artifact = self._get_artifact_object(llm_prompt_artifact)
|
|
1234
|
+
self.shared_proxy_mapping[origin_name] = llm_prompt_artifact
|
|
1235
|
+
else:
|
|
1236
|
+
llm_prompt_artifact = (
|
|
1237
|
+
self.invocation_artifact or self._get_artifact_object()
|
|
1238
|
+
)
|
|
1239
|
+
if not (
|
|
1240
|
+
llm_prompt_artifact and isinstance(llm_prompt_artifact, LLMPromptArtifact)
|
|
1241
|
+
):
|
|
1242
|
+
logger.warning(
|
|
1243
|
+
"LLMModel must be provided with LLMPromptArtifact",
|
|
1244
|
+
llm_prompt_artifact=llm_prompt_artifact,
|
|
1245
|
+
)
|
|
1246
|
+
return None, None
|
|
1247
|
+
prompt_legend = llm_prompt_artifact.spec.prompt_legend
|
|
1248
|
+
prompt_template = deepcopy(llm_prompt_artifact.read_prompt())
|
|
1249
|
+
kwargs = {
|
|
1250
|
+
place_holder: body.get(body_map["field"])
|
|
1251
|
+
for place_holder, body_map in prompt_legend.items()
|
|
1252
|
+
}
|
|
1253
|
+
for d in prompt_template:
|
|
1254
|
+
d["content"] = d["content"].format(**kwargs)
|
|
1255
|
+
return prompt_template, llm_prompt_artifact.spec.model_configuration
|
|
1256
|
+
|
|
1257
|
+
|
|
1189
1258
|
class ModelSelector:
|
|
1190
1259
|
"""Used to select which models to run on each event."""
|
|
1191
1260
|
|
|
@@ -1292,6 +1361,7 @@ class ModelRunnerStep(MonitoredStep):
|
|
|
1292
1361
|
"""
|
|
1293
1362
|
|
|
1294
1363
|
kind = "model_runner"
|
|
1364
|
+
_dict_fields = MonitoredStep._dict_fields + ["_shared_proxy_mapping"]
|
|
1295
1365
|
|
|
1296
1366
|
def __init__(
|
|
1297
1367
|
self,
|
|
@@ -1311,6 +1381,7 @@ class ModelRunnerStep(MonitoredStep):
|
|
|
1311
1381
|
)
|
|
1312
1382
|
self.raise_exception = raise_exception
|
|
1313
1383
|
self.shape = "folder"
|
|
1384
|
+
self._shared_proxy_mapping = {}
|
|
1314
1385
|
|
|
1315
1386
|
def add_shared_model_proxy(
|
|
1316
1387
|
self,
|
|
@@ -1360,9 +1431,9 @@ class ModelRunnerStep(MonitoredStep):
|
|
|
1360
1431
|
in path.
|
|
1361
1432
|
:param override: bool allow override existing model on the current ModelRunnerStep.
|
|
1362
1433
|
"""
|
|
1363
|
-
model_class =
|
|
1364
|
-
|
|
1365
|
-
shared_runnable_name
|
|
1434
|
+
model_class, model_params = (
|
|
1435
|
+
"mlrun.serving.Model",
|
|
1436
|
+
{"name": endpoint_name, "shared_runnable_name": shared_model_name},
|
|
1366
1437
|
)
|
|
1367
1438
|
if isinstance(model_artifact, str):
|
|
1368
1439
|
model_artifact_uri = model_artifact
|
|
@@ -1389,6 +1460,20 @@ class ModelRunnerStep(MonitoredStep):
|
|
|
1389
1460
|
f"ModelRunnerStep can only add proxy models that were added to the root flow step, "
|
|
1390
1461
|
f"model {shared_model_name} is not in the shared models."
|
|
1391
1462
|
)
|
|
1463
|
+
if shared_model_name not in self._shared_proxy_mapping:
|
|
1464
|
+
self._shared_proxy_mapping[shared_model_name] = {
|
|
1465
|
+
endpoint_name: model_artifact.uri
|
|
1466
|
+
if isinstance(model_artifact, (ModelArtifact, LLMPromptArtifact))
|
|
1467
|
+
else model_artifact
|
|
1468
|
+
}
|
|
1469
|
+
else:
|
|
1470
|
+
self._shared_proxy_mapping[shared_model_name].update(
|
|
1471
|
+
{
|
|
1472
|
+
endpoint_name: model_artifact.uri
|
|
1473
|
+
if isinstance(model_artifact, (ModelArtifact, LLMPromptArtifact))
|
|
1474
|
+
else model_artifact
|
|
1475
|
+
}
|
|
1476
|
+
)
|
|
1392
1477
|
self.add_model(
|
|
1393
1478
|
endpoint_name=endpoint_name,
|
|
1394
1479
|
model_class=model_class,
|
|
@@ -1401,6 +1486,7 @@ class ModelRunnerStep(MonitoredStep):
|
|
|
1401
1486
|
outputs=outputs,
|
|
1402
1487
|
input_path=input_path,
|
|
1403
1488
|
result_path=result_path,
|
|
1489
|
+
**model_params,
|
|
1404
1490
|
)
|
|
1405
1491
|
|
|
1406
1492
|
def add_model(
|
|
@@ -1659,6 +1745,7 @@ class ModelRunnerStep(MonitoredStep):
|
|
|
1659
1745
|
model_selector=model_selector,
|
|
1660
1746
|
runnables=model_objects,
|
|
1661
1747
|
execution_mechanism_by_runnable_name=execution_mechanism_by_model_name,
|
|
1748
|
+
shared_proxy_mapping=self._shared_proxy_mapping or None,
|
|
1662
1749
|
name=self.name,
|
|
1663
1750
|
context=context,
|
|
1664
1751
|
)
|
|
@@ -2494,7 +2581,24 @@ class RootFlowStep(FlowStep):
|
|
|
2494
2581
|
max_threads=self.shared_max_threads,
|
|
2495
2582
|
pool_factor=self.pool_factor,
|
|
2496
2583
|
)
|
|
2497
|
-
|
|
2584
|
+
monitored_steps = self.get_monitored_steps().values()
|
|
2585
|
+
for monitored_step in monitored_steps:
|
|
2586
|
+
if isinstance(monitored_step, ModelRunnerStep):
|
|
2587
|
+
for model, model_params in self.shared_models.values():
|
|
2588
|
+
if "shared_proxy_mapping" in model_params:
|
|
2589
|
+
model_params["shared_proxy_mapping"].update(
|
|
2590
|
+
deepcopy(
|
|
2591
|
+
monitored_step._shared_proxy_mapping.get(
|
|
2592
|
+
model_params.get("name"), {}
|
|
2593
|
+
)
|
|
2594
|
+
)
|
|
2595
|
+
)
|
|
2596
|
+
else:
|
|
2597
|
+
model_params["shared_proxy_mapping"] = deepcopy(
|
|
2598
|
+
monitored_step._shared_proxy_mapping.get(
|
|
2599
|
+
model_params.get("name"), {}
|
|
2600
|
+
)
|
|
2601
|
+
)
|
|
2498
2602
|
for model, model_params in self.shared_models.values():
|
|
2499
2603
|
model = get_class(model, namespace).from_dict(
|
|
2500
2604
|
model_params, init_with_params=True
|
mlrun/utils/version/version.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mlrun
|
|
3
|
-
Version: 1.10.
|
|
3
|
+
Version: 1.10.0rc14
|
|
4
4
|
Summary: Tracking and config of machine learning runs
|
|
5
5
|
Home-page: https://github.com/mlrun/mlrun
|
|
6
6
|
Author: Yaron Haviv
|
|
@@ -44,7 +44,7 @@ Requires-Dist: semver~=3.0
|
|
|
44
44
|
Requires-Dist: dependency-injector~=4.41
|
|
45
45
|
Requires-Dist: fsspec<2024.7,>=2023.9.2
|
|
46
46
|
Requires-Dist: v3iofs~=0.1.17
|
|
47
|
-
Requires-Dist: storey~=1.10.
|
|
47
|
+
Requires-Dist: storey~=1.10.8
|
|
48
48
|
Requires-Dist: inflection~=0.5.0
|
|
49
49
|
Requires-Dist: python-dotenv~=1.0
|
|
50
50
|
Requires-Dist: setuptools>=75.2
|
|
@@ -2,11 +2,11 @@ mlrun/__init__.py,sha256=Y_AFhZV1hEx4vfiO-cyjup0aLGcp6R0SeL75GqLFQrc,7514
|
|
|
2
2
|
mlrun/__main__.py,sha256=wQNaxW7QsqFBtWffnPkw-497fnpsrQzUnscBQQAP_UM,48364
|
|
3
3
|
mlrun/config.py,sha256=dmJj0Yzd0ZpNf10gsjS-19UqJhuBkoOfhf2SoQTNqcg,72398
|
|
4
4
|
mlrun/errors.py,sha256=bAk0t_qmCxQSPNK0TugOAfA5R6f0G6OYvEvXUWSJ_5U,9062
|
|
5
|
-
mlrun/execution.py,sha256=
|
|
5
|
+
mlrun/execution.py,sha256=dJ4PFwg5AlDHbCL2Q9dVDjWA_i64UTq2qBiF8kTU9tw,56922
|
|
6
6
|
mlrun/features.py,sha256=jMEXo6NB36A6iaxNEJWzdtYwUmglYD90OIKTIEeWhE8,15841
|
|
7
7
|
mlrun/k8s_utils.py,sha256=mMnGyouHoJC93ZD2KGf9neJM1pD7mR9IXLnHOEwYVTQ,21469
|
|
8
8
|
mlrun/lists.py,sha256=OlaV2QIFUzmenad9kxNJ3k4whlDyxI3zFbGwr6vpC5Y,8561
|
|
9
|
-
mlrun/model.py,sha256=
|
|
9
|
+
mlrun/model.py,sha256=wHtM8LylSOEFk6Hxl95CVm8DOPhofjsANYdIvKHH6dw,88956
|
|
10
10
|
mlrun/render.py,sha256=5DlhD6JtzHgmj5RVlpaYiHGhX84Q7qdi4RCEUj2UMgw,13195
|
|
11
11
|
mlrun/run.py,sha256=_ban8NoNWfQHps3QIVyWh_Hn2S6usNrFBTUMObaeueo,46904
|
|
12
12
|
mlrun/secrets.py,sha256=dZPdkc_zzfscVQepOHUwmzFqnBavDCBXV9DQoH_eIYM,7800
|
|
@@ -18,12 +18,12 @@ mlrun/artifacts/base.py,sha256=G6t1HMAQW9Ct24EQnENMYglRPbNUfhoHkKxWdq0YQcI,29683
|
|
|
18
18
|
mlrun/artifacts/dataset.py,sha256=bhb5Kfbs8P28yjnpN76th5lLEUl5nAqD4VqVzHEVPrM,16421
|
|
19
19
|
mlrun/artifacts/document.py,sha256=p5HsWdmIIJ0NahS7y3EEQN2tfHtUrUmUG-8BEEyi_Jc,17373
|
|
20
20
|
mlrun/artifacts/helpers.py,sha256=ejTEC9vkI2w5FHn5Gopw3VEIxuni0bazWUnR6BBWZfU,1662
|
|
21
|
-
mlrun/artifacts/llm_prompt.py,sha256=
|
|
21
|
+
mlrun/artifacts/llm_prompt.py,sha256=uP_uq-SpbVs9uV9fFG3yF9e_X4XuXYt_EHAu4feaBfQ,9414
|
|
22
22
|
mlrun/artifacts/manager.py,sha256=DEIQBfQhaondfChjmEN-zt-dBvV90yHLzIVqd4oGh00,16827
|
|
23
23
|
mlrun/artifacts/model.py,sha256=8EVaD70SOkTohQIWqkDk0MEwskdofxs3wJTgspa2sho,25615
|
|
24
24
|
mlrun/artifacts/plots.py,sha256=wmaxVXiAPSCyn3M7pIlcBu9pP3O8lrq0Ewx6iHRDF9s,4238
|
|
25
25
|
mlrun/common/__init__.py,sha256=kXGBqhLN0rlAx0kTXhozGzFsIdSqW0uTSKMmsLgq_is,569
|
|
26
|
-
mlrun/common/constants.py,sha256=
|
|
26
|
+
mlrun/common/constants.py,sha256=tWqaog0fe3ZU6sIGToB8Joo7AY_3QjpnxA2GkiiAtj8,4033
|
|
27
27
|
mlrun/common/helpers.py,sha256=DIdqs_eN3gO5bZ8iFobIvx8cEiOxYxhFIyut6-O69T0,1385
|
|
28
28
|
mlrun/common/secrets.py,sha256=8g9xtIw-9DGcwiZRT62a5ozSQM-aYo8yK5Ghey9WM0g,5179
|
|
29
29
|
mlrun/common/types.py,sha256=1gxThbmC0Vd0U1ffIkEwz4T4S7JOgHt70rvw8TCO21c,1073
|
|
@@ -73,7 +73,7 @@ mlrun/common/schemas/schedule.py,sha256=L7z9Lp06-xmFmdp0q5PypCU_DCl6zZIyQTVoJa01
|
|
|
73
73
|
mlrun/common/schemas/secret.py,sha256=Td2UAeWHSAdA4nIP3rQv_PIVKVqcBnCnK6xjr528tS8,1486
|
|
74
74
|
mlrun/common/schemas/serving.py,sha256=-3U45YLtmVWMZrx4R8kaPgFGoJ4JmD7RE3nydpYNTz8,1359
|
|
75
75
|
mlrun/common/schemas/tag.py,sha256=1wqEiAujsElojWb3qmuyfcaLFjXSNAAQdafkDx7fkn0,891
|
|
76
|
-
mlrun/common/schemas/workflow.py,sha256=
|
|
76
|
+
mlrun/common/schemas/workflow.py,sha256=4KeTUIZCkIgEIKNDbMeJqyhUmIKvLdX1bQSNsmYMCwg,2378
|
|
77
77
|
mlrun/common/schemas/model_monitoring/__init__.py,sha256=K9XumcIsTxdp8oNvCSluBGCS07rbJibHcA1DSg8Xe4w,1877
|
|
78
78
|
mlrun/common/schemas/model_monitoring/constants.py,sha256=yjTaSGiRs0zYIE20QSuJuMNnS5iuJpnV1wBiq7leVpg,13238
|
|
79
79
|
mlrun/common/schemas/model_monitoring/functions.py,sha256=VvbsW8UxD-Raj3gaLpHzEierXl_yA9PO11r1ps4fJZ4,2204
|
|
@@ -277,7 +277,7 @@ mlrun/platforms/iguazio.py,sha256=6VBTq8eQ3mzT96tzjYhAtcMQ2VjF4x8LpIPW5DAcX2Q,13
|
|
|
277
277
|
mlrun/projects/__init__.py,sha256=hdCOA6_fp8X4qGGGT7Bj7sPbkM1PayWuaVZL0DkpuZw,1240
|
|
278
278
|
mlrun/projects/operations.py,sha256=Rc__P5ucNAY2G-lHc2LrnZs15PUbNFt8-NqNNT2Bjpk,20623
|
|
279
279
|
mlrun/projects/pipelines.py,sha256=kY5BUHAjNri-9KjWZiCZ9Wo5XwZFqpvqctWy5j8va60,51611
|
|
280
|
-
mlrun/projects/project.py,sha256=
|
|
280
|
+
mlrun/projects/project.py,sha256=QaMjKRHh2nQtb-VrTtQTUQ-1KaYegebiTSDAoRicrA4,252950
|
|
281
281
|
mlrun/runtimes/__init__.py,sha256=8cqrYKy1a0_87XG7V_p96untQ4t8RocadM4LVEEN1JM,9029
|
|
282
282
|
mlrun/runtimes/base.py,sha256=FVEooeQMpwxIK2iW1R0FNbC5P1sZ_efKtJcsdNSYNmc,38266
|
|
283
283
|
mlrun/runtimes/daskjob.py,sha256=zuWnFLgiPoYFMRSLYiwwG2MpFYKK662_ekbvu2VKvdQ,19906
|
|
@@ -307,13 +307,13 @@ mlrun/runtimes/nuclio/application/application.py,sha256=3WeVCeVUb6U5wJDVJSuTDzJ-
|
|
|
307
307
|
mlrun/runtimes/nuclio/application/reverse_proxy.go,sha256=lEHH74vr2PridIHp1Jkc_NjkrWb5b6zawRrNxHQhwGU,2913
|
|
308
308
|
mlrun/runtimes/sparkjob/__init__.py,sha256=GPP_ekItxiU9Ydn3mJa4Obph02Bg6DO-JYs791_MV58,607
|
|
309
309
|
mlrun/runtimes/sparkjob/spark3job.py,sha256=5TdmQy5yDBtaq9y9fQGrNYTJ_0UqR9VnV7-SGiZEOyc,41287
|
|
310
|
-
mlrun/serving/__init__.py,sha256=
|
|
310
|
+
mlrun/serving/__init__.py,sha256=nriJAcVn5aatwU03T7SsE6ngJEGTxr3wIGt4WuvCCzY,1392
|
|
311
311
|
mlrun/serving/merger.py,sha256=pfOQoozUyObCTpqXAMk94PmhZefn4bBrKufO3MKnkAc,6193
|
|
312
312
|
mlrun/serving/remote.py,sha256=Igha2FipK3-6rV_PZ1K464kTbiTu8rhc6SMm-HiEJ6o,18817
|
|
313
313
|
mlrun/serving/routers.py,sha256=SmBOlHn7rT2gWTa-W8f16UB0UthgIFc4D1cPOZAA9ss,54003
|
|
314
314
|
mlrun/serving/server.py,sha256=NXqpuNMiIjavwhG8lwBKLVLh9QarP6DJm_0qB4pStfY,32523
|
|
315
315
|
mlrun/serving/serving_wrapper.py,sha256=UL9hhWCfMPcTJO_XrkvNaFvck1U1E7oS8trTZyak0cA,835
|
|
316
|
-
mlrun/serving/states.py,sha256=
|
|
316
|
+
mlrun/serving/states.py,sha256=ScjJ7hecu-PptrN8jSN06i6NrjjHS0P0AV1c6SdhhIY,120093
|
|
317
317
|
mlrun/serving/system_steps.py,sha256=9AqSQwv6nVljGKZoWJbksnuqsl3VqETcytEwjEVLmA4,16446
|
|
318
318
|
mlrun/serving/utils.py,sha256=Zbfqm8TKNcTE8zRBezVBzpvR2WKeKeIRN7otNIaiYEc,4170
|
|
319
319
|
mlrun/serving/v1_serving.py,sha256=c6J_MtpE-Tqu00-6r4eJOCO6rUasHDal9W2eBIcrl50,11853
|
|
@@ -347,11 +347,11 @@ mlrun/utils/notifications/notification/mail.py,sha256=ZyJ3eqd8simxffQmXzqd3bgbAq
|
|
|
347
347
|
mlrun/utils/notifications/notification/slack.py,sha256=kfhogR5keR7Zjh0VCjJNK3NR5_yXT7Cv-x9GdOUW4Z8,7294
|
|
348
348
|
mlrun/utils/notifications/notification/webhook.py,sha256=zxh8CAlbPnTazsk6r05X5TKwqUZVOH5KBU2fJbzQlG4,5330
|
|
349
349
|
mlrun/utils/version/__init__.py,sha256=YnzE6tlf24uOQ8y7Z7l96QLAI6-QEii7-77g8ynmzy0,613
|
|
350
|
-
mlrun/utils/version/version.json,sha256=
|
|
350
|
+
mlrun/utils/version/version.json,sha256=tQy-mD_fOGta6_Eg7aN0kFOHik3ux1rqs6L2E8cyYXE,90
|
|
351
351
|
mlrun/utils/version/version.py,sha256=M2hVhRrgkN3SxacZHs3ZqaOsqAA7B6a22ne324IQ1HE,1877
|
|
352
|
-
mlrun-1.10.
|
|
353
|
-
mlrun-1.10.
|
|
354
|
-
mlrun-1.10.
|
|
355
|
-
mlrun-1.10.
|
|
356
|
-
mlrun-1.10.
|
|
357
|
-
mlrun-1.10.
|
|
352
|
+
mlrun-1.10.0rc14.dist-info/licenses/LICENSE,sha256=zTiv1CxWNkOk1q8eJS1G_8oD4gWpWLwWxj_Agcsi8Os,11337
|
|
353
|
+
mlrun-1.10.0rc14.dist-info/METADATA,sha256=IxvfEPLAicKlw4neullhNBCn0p9_IYmpULcZA_iyPOA,26411
|
|
354
|
+
mlrun-1.10.0rc14.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
355
|
+
mlrun-1.10.0rc14.dist-info/entry_points.txt,sha256=1Owd16eAclD5pfRCoJpYC2ZJSyGNTtUr0nCELMioMmU,46
|
|
356
|
+
mlrun-1.10.0rc14.dist-info/top_level.txt,sha256=NObLzw3maSF9wVrgSeYBv-fgnHkAJ1kEkh12DLdd5KM,6
|
|
357
|
+
mlrun-1.10.0rc14.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|