truefoundry 0.4.1__py3-none-any.whl → 0.4.2__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 truefoundry might be problematic. Click here for more details.
- truefoundry/common/auth_service_client.py +14 -5
- truefoundry/common/constants.py +2 -1
- truefoundry/common/credential_file_manager.py +4 -3
- truefoundry/common/credential_provider.py +4 -5
- truefoundry/common/servicefoundry_client.py +14 -7
- truefoundry/common/utils.py +59 -10
- truefoundry/deploy/auto_gen/models.py +11 -5
- truefoundry/deploy/builder/__init__.py +2 -2
- truefoundry/deploy/builder/builders/tfy_notebook_buildpack/__init__.py +7 -1
- truefoundry/deploy/builder/builders/tfy_notebook_buildpack/dockerfile_template.py +25 -12
- truefoundry/deploy/builder/builders/tfy_python_buildpack/__init__.py +8 -2
- truefoundry/deploy/builder/builders/tfy_python_buildpack/dockerfile_template.py +26 -3
- truefoundry/deploy/builder/constants.py +7 -0
- truefoundry/deploy/builder/utils.py +32 -0
- truefoundry/deploy/cli/commands/deploy_command.py +46 -2
- truefoundry/deploy/cli/util.py +4 -1
- truefoundry/deploy/lib/auth/servicefoundry_session.py +4 -2
- truefoundry/deploy/lib/clients/servicefoundry_client.py +3 -1
- truefoundry/deploy/lib/session.py +6 -6
- truefoundry/deploy/v2/lib/patched_models.py +4 -0
- truefoundry/ml/autogen/client/__init__.py +3 -0
- truefoundry/ml/autogen/client/api/mlfoundry_artifacts_api.py +163 -0
- truefoundry/ml/autogen/client/models/__init__.py +3 -0
- truefoundry/ml/autogen/client/models/delete_files_for_dataset_request_dto.py +68 -0
- truefoundry/ml/autogen/client_README.md +2 -0
- truefoundry/ml/autogen/entities/artifacts.py +286 -0
- truefoundry/ml/clients/servicefoundry_client.py +2 -4
- truefoundry/ml/log_types/artifacts/artifact.py +59 -1
- truefoundry/ml/mlfoundry_api.py +48 -3
- truefoundry/ml/mlfoundry_run.py +33 -16
- truefoundry/ml/run_utils.py +0 -14
- truefoundry/ml/session.py +9 -8
- truefoundry/workflow/example/hello_world_package/workflow.py +2 -2
- truefoundry/workflow/example/package/test_workflow.py +14 -15
- {truefoundry-0.4.1.dist-info → truefoundry-0.4.2.dist-info}/METADATA +1 -2
- {truefoundry-0.4.1.dist-info → truefoundry-0.4.2.dist-info}/RECORD +38 -34
- {truefoundry-0.4.1.dist-info → truefoundry-0.4.2.dist-info}/WHEEL +0 -0
- {truefoundry-0.4.1.dist-info → truefoundry-0.4.2.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
# generated by datamodel-codegen:
|
|
2
|
+
# filename: artifacts.json
|
|
3
|
+
# timestamp: 2024-09-12T13:40:36+00:00
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from enum import Enum
|
|
8
|
+
from typing import Any, Dict, List, Literal, Optional, Union
|
|
9
|
+
|
|
10
|
+
from truefoundry.pydantic_v1 import BaseModel, Field, constr
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Agent(BaseModel):
|
|
14
|
+
type: Literal["agent"] = Field(..., description="+value=agent")
|
|
15
|
+
name: constr(regex=r"^[a-zA-Z][a-zA-Z0-9\-]{1,30}[a-zA-Z0-9]$") = Field(
|
|
16
|
+
..., description="Names cannot repeat accross agent\n+uiType=Hidden"
|
|
17
|
+
)
|
|
18
|
+
available_tools: List[constr(min_length=1)] = Field(
|
|
19
|
+
..., description="+sort=30\n+uiType=Hidden"
|
|
20
|
+
)
|
|
21
|
+
goal: constr(min_length=1, max_length=128) = Field(
|
|
22
|
+
..., description="+sort=10\n+uiType=TextArea"
|
|
23
|
+
)
|
|
24
|
+
instruction: constr(min_length=1, max_length=2620) = Field(
|
|
25
|
+
...,
|
|
26
|
+
description='`instruction` is the system prompt for now. (2.5 * 1024)\n+sort=20\n+uiType=AgentInstructions\n+uiProps={"helpText":"Use the syntax ${Tool FQN} to reference a tool, and ${AGENT FQN} to reference another agent"}',
|
|
27
|
+
)
|
|
28
|
+
model_id: constr(min_length=1) = Field(
|
|
29
|
+
...,
|
|
30
|
+
description='+sort=40\n+uiType=EnabledModelSelector\n+uiProps={"searchable":true,"modelType":"chat","providerType":"openai"}',
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class Method(str, Enum):
|
|
35
|
+
"""
|
|
36
|
+
+sort=50
|
|
37
|
+
+uiType=Hidden
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
get = "get"
|
|
41
|
+
post = "post"
|
|
42
|
+
put = "put"
|
|
43
|
+
delete = "delete"
|
|
44
|
+
patch = "patch"
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class AgentWithFQN(Agent):
|
|
48
|
+
id: str
|
|
49
|
+
fqn: str
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class MimeType(str, Enum):
|
|
53
|
+
"""
|
|
54
|
+
+label=MIME Type
|
|
55
|
+
+usage=MIME type of the content
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
text_plain = "text/plain"
|
|
59
|
+
application_json = "application/json"
|
|
60
|
+
image_png = "image/png"
|
|
61
|
+
image_jpeg = "image/jpeg"
|
|
62
|
+
application_x_directory = "application/x-directory"
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class BlobStorageReference(BaseModel):
|
|
66
|
+
"""
|
|
67
|
+
+usage=Blob Storage Location
|
|
68
|
+
+label=Blob Storage Location
|
|
69
|
+
+docs=Defines the structure for blob storage content references, including type, path, and mime_type
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
type: Literal["blob-storage"]
|
|
73
|
+
path: constr(regex=r"^.{1,}$") = Field(
|
|
74
|
+
..., description="+label=Path\n+usage=Path to the content in blob storage"
|
|
75
|
+
)
|
|
76
|
+
mime_type: MimeType = Field(
|
|
77
|
+
..., description="+label=MIME Type\n+usage=MIME type of the content"
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class ImageUrl(BaseModel):
|
|
82
|
+
"""
|
|
83
|
+
+label=URL for the image
|
|
84
|
+
+usage=The URL for the image, must be a non-empty valid HTTPS URL or a data URL
|
|
85
|
+
"""
|
|
86
|
+
|
|
87
|
+
url: Union[
|
|
88
|
+
constr(
|
|
89
|
+
regex=r"^\b((https?://)?(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}(?:[-a-zA-Z0-9()@:%_\+.~#?&/=]*)|data:image/[a-zA-Z]+;base64,[a-zA-Z0-9+/=\s]+)$"
|
|
90
|
+
),
|
|
91
|
+
BlobStorageReference,
|
|
92
|
+
] = Field(
|
|
93
|
+
...,
|
|
94
|
+
description="+label=URL for the image\n+usage=The URL for the image, must be a non-empty valid HTTPS URL or a data URL",
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class ImageContentPart(BaseModel):
|
|
99
|
+
"""
|
|
100
|
+
+usage=Image URL
|
|
101
|
+
+label=Image URL
|
|
102
|
+
"""
|
|
103
|
+
|
|
104
|
+
type: Literal["image_url"]
|
|
105
|
+
image_url: ImageUrl = Field(
|
|
106
|
+
...,
|
|
107
|
+
description="+label=URL for the image\n+usage=The URL for the image, must be a non-empty valid HTTPS URL or a data URL",
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
class Parameters(BaseModel):
|
|
112
|
+
"""
|
|
113
|
+
+usage=Parameters for the provider
|
|
114
|
+
+label=Parameters
|
|
115
|
+
+docs=Key-value pairs to store additional parameters for the provider
|
|
116
|
+
"""
|
|
117
|
+
|
|
118
|
+
max_tokens: Optional[int] = None
|
|
119
|
+
temperature: Optional[float] = None
|
|
120
|
+
top_k: Optional[float] = None
|
|
121
|
+
top_p: Optional[float] = None
|
|
122
|
+
stop: Optional[Union[List[str], str]] = None
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
class ModelConfiguration(BaseModel):
|
|
126
|
+
"""
|
|
127
|
+
+label=Model Configuration
|
|
128
|
+
+icon=fa-cogs:#326ce5
|
|
129
|
+
+message=Configuration details for the provider and corresponding config
|
|
130
|
+
+usage=Define the provider and its configuration
|
|
131
|
+
+docs=Configuration settings specific to the provider, including model settings and other parameters.
|
|
132
|
+
"""
|
|
133
|
+
|
|
134
|
+
provider: str = Field(
|
|
135
|
+
...,
|
|
136
|
+
description='+label=Provider Name\n+usage=Name of the provider, must be non-empty, e.g., "openai", "google_gemini"',
|
|
137
|
+
)
|
|
138
|
+
model: constr(regex=r"^[a-zA-Z][a-zA-Z0-9\-]{1,30}[a-zA-Z0-9]$") = Field(
|
|
139
|
+
..., description="+label=Model name\n+usage=Model name, must be non-empty"
|
|
140
|
+
)
|
|
141
|
+
parameters: Optional[Parameters] = Field(
|
|
142
|
+
None,
|
|
143
|
+
description="+usage=Parameters for the provider\n+label=Parameters\n+docs=Key-value pairs to store additional parameters for the provider",
|
|
144
|
+
)
|
|
145
|
+
extra_parameters: Optional[Dict[str, Any]] = Field(
|
|
146
|
+
None,
|
|
147
|
+
description="+usage=Extra parameters for the provider\n+label=Extra Parameters\n+docs=Additional parameters for the provider",
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
class SystemMessage(BaseModel):
|
|
152
|
+
"""
|
|
153
|
+
+usage=System message
|
|
154
|
+
+docs=Defines the structure of a system message, including role and content
|
|
155
|
+
+label=System Message
|
|
156
|
+
"""
|
|
157
|
+
|
|
158
|
+
role: Literal["system"]
|
|
159
|
+
content: Union[constr(regex=r"^.[\s\S]*$"), BlobStorageReference] = Field(
|
|
160
|
+
..., description="+label=Content\n+usage=Text content for the system message"
|
|
161
|
+
)
|
|
162
|
+
name: Optional[str] = Field(
|
|
163
|
+
None, description="+label=Name\n+usage=Name of the system"
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
class TextContentPart(BaseModel):
|
|
168
|
+
"""
|
|
169
|
+
+usage=Text content
|
|
170
|
+
+label=Text content
|
|
171
|
+
"""
|
|
172
|
+
|
|
173
|
+
type: Literal["text"]
|
|
174
|
+
text: Union[constr(regex=r"^.[\s\S]*$"), BlobStorageReference]
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
class UserMessage(BaseModel):
|
|
178
|
+
"""
|
|
179
|
+
+usage=User message
|
|
180
|
+
+docs=Defines the structure of a user message, including role and content
|
|
181
|
+
+label=User Message
|
|
182
|
+
"""
|
|
183
|
+
|
|
184
|
+
role: Literal["user"]
|
|
185
|
+
content: Union[
|
|
186
|
+
constr(regex=r"^.[\s\S]*$"),
|
|
187
|
+
BlobStorageReference,
|
|
188
|
+
List[Union[TextContentPart, ImageContentPart]],
|
|
189
|
+
] = Field(
|
|
190
|
+
..., description="+label=Content\n+usage=Text content for the user message"
|
|
191
|
+
)
|
|
192
|
+
name: Optional[str] = Field(
|
|
193
|
+
None, description="+label=Name\n+usage=Name of the user message"
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
class AgentOpenAPITool(BaseModel):
|
|
198
|
+
type: Literal["openapi-tool"] = Field(..., description="+value=openapi-tool")
|
|
199
|
+
name: constr(regex=r"^[a-zA-Z][a-zA-Z0-9\-]{1,30}[a-zA-Z0-9]$") = Field(
|
|
200
|
+
..., description="Names cannot repeat accross tools\n+uiType=Hidden"
|
|
201
|
+
)
|
|
202
|
+
description: constr(min_length=1, max_length=128) = Field(
|
|
203
|
+
..., description="+sort=10\n+uiType=TextArea"
|
|
204
|
+
)
|
|
205
|
+
openapi_spec: Union[BlobStorageReference, Dict[str, Any]] = Field(
|
|
206
|
+
..., description="+sort=20\n+uiType=OpenapiSchema"
|
|
207
|
+
)
|
|
208
|
+
base_url: constr(
|
|
209
|
+
regex=r"^(https?://)?(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}(?:[-a-zA-Z0-9()@:%_\+.~#?&/=]*)$"
|
|
210
|
+
) = Field(..., description="+sort=30")
|
|
211
|
+
path: constr(min_length=1) = Field(
|
|
212
|
+
...,
|
|
213
|
+
description="+sort=40\n+uiType=MethodPathSelector\n+label=Method + Path\n+usage=Select one Method and Path for this tool",
|
|
214
|
+
)
|
|
215
|
+
method: Method = Field(..., description="+sort=50\n+uiType=Hidden")
|
|
216
|
+
headers: Optional[Dict[str, str]] = Field(
|
|
217
|
+
None,
|
|
218
|
+
description='+sort=60\n+uiType=KV\n+uiProps={"allowSecrets":true,"secretConfig":{"enableNew":true,"hideOptions":true}}',
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
class AgentOpenAPIToolWithFQN(AgentOpenAPITool):
|
|
223
|
+
id: str
|
|
224
|
+
fqn: str
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
class AssistantMessage(BaseModel):
|
|
228
|
+
"""
|
|
229
|
+
+usage=Assistant message
|
|
230
|
+
+docs=Defines the structure of an assistant message, including role and content
|
|
231
|
+
+label=Assistant Message
|
|
232
|
+
"""
|
|
233
|
+
|
|
234
|
+
role: Literal["assistant"]
|
|
235
|
+
content: Union[constr(regex=r"^.[\s\S]*$"), BlobStorageReference] = Field(
|
|
236
|
+
..., description="+label=Content\n+usage=Text content for the assistant message"
|
|
237
|
+
)
|
|
238
|
+
name: Optional[str] = Field(
|
|
239
|
+
None, description="+label=Name\n+usage=Name of the assistant message"
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
class BasePrompt(BaseModel):
|
|
244
|
+
"""
|
|
245
|
+
Main prompt structure
|
|
246
|
+
"""
|
|
247
|
+
|
|
248
|
+
name: constr(regex=r"^[a-zA-Z][a-zA-Z0-9-_]{0,254}[a-zA-Z0-9]$") = Field(
|
|
249
|
+
...,
|
|
250
|
+
description="+label=Prompt Name\n+icon=fa-desktop:#326ce5\n+message=Alphanumeric word, may contain '-' with a maximum length of 256 characters\n+sort=1000\n+usage=Name of the Prompt. This uniquely identifies it in the workspace.\n+docs=The unique name for the prompt, consisting of alphanumeric characters and dashes, max length 100.",
|
|
251
|
+
)
|
|
252
|
+
description: Optional[constr(min_length=1, max_length=512)] = Field(
|
|
253
|
+
None,
|
|
254
|
+
description="+label=Description\n+icon=fa-desktop:#326ce5\n+message=Description in a maximum of 512 characters\n+sort=2000\n+usage=Description of the prompt\n+docs=An optional description for the prompt, with a maximum length of 512 characters.\n+optional",
|
|
255
|
+
)
|
|
256
|
+
model_configuration: ModelConfiguration
|
|
257
|
+
metadata: Dict[str, str] = Field(
|
|
258
|
+
...,
|
|
259
|
+
description="+label=Metadata\n+icon=fa-info-circle:#326ce5\n+message=Additional metadata for the prompt\n+sort=7000\n+usage=Define additional metadata for the prompt\n+docs=Key-value pairs to store additional metadata related to the prompt.",
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
class ChatPrompt(BasePrompt):
|
|
264
|
+
type: Literal["chat_prompt"] = Field(
|
|
265
|
+
...,
|
|
266
|
+
description='+label=Type\n+icon=fa-desktop:#326ce5\n+message=Type of the prompt\n+sort=3000\n+usage=Type of the prompt\n+docs=Type of the prompt, set to "chat_prompt"\n+default="chat_prompt"',
|
|
267
|
+
)
|
|
268
|
+
messages: List[Union[SystemMessage, AssistantMessage, UserMessage]] = Field(
|
|
269
|
+
...,
|
|
270
|
+
description="+sort=4000\n+usage=Chat completion messages\n+label=Messages in the chat conversation\n+message=Chat completion messages\n+usage=List of messages in the chat conversation, must be non-empty\n+docs=Messages that define the chat conversation, including system, assistant, and user messages.",
|
|
271
|
+
)
|
|
272
|
+
variables: Optional[Dict[str, Optional[str]]] = Field(
|
|
273
|
+
None,
|
|
274
|
+
description="+label=Variables\n+usage=Variables for the chat completion messages to be used in the prompt messages\n+sort=5000",
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
class AgentApp(BaseModel):
|
|
279
|
+
type: Literal["agent-app"] = Field(..., description="+value=agent-app")
|
|
280
|
+
tools: List[AgentOpenAPIToolWithFQN]
|
|
281
|
+
agents: List[AgentWithFQN]
|
|
282
|
+
root_agent: constr(min_length=1)
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
class Artifacts(BaseModel):
|
|
286
|
+
__root__: Union[ChatPrompt, AgentOpenAPITool, Agent, AgentApp]
|
|
@@ -12,15 +12,13 @@ from truefoundry.ml.clients.entities import (
|
|
|
12
12
|
)
|
|
13
13
|
from truefoundry.ml.clients.utils import http_request_safe
|
|
14
14
|
from truefoundry.ml.exceptions import MlFoundryException
|
|
15
|
-
from truefoundry.ml.run_utils import append_servicefoundry_path_to_tracking_uri
|
|
16
15
|
|
|
17
16
|
|
|
18
17
|
class ServiceFoundryServiceClient(BaseServiceFoundryServiceClient):
|
|
18
|
+
# TODO (chiragjn): Rename tracking_uri to tfy_host
|
|
19
19
|
def __init__(self, tracking_uri: str, token: Optional[str] = None):
|
|
20
20
|
super().__init__(base_url=tracking_uri)
|
|
21
|
-
self.host_creds = HostCreds(
|
|
22
|
-
host=append_servicefoundry_path_to_tracking_uri(tracking_uri), token=token
|
|
23
|
-
)
|
|
21
|
+
self.host_creds = HostCreds(host=self._api_server_url, token=token)
|
|
24
22
|
|
|
25
23
|
def get_integration_from_id(self, integration_id: str):
|
|
26
24
|
integration_id = integration_id or ""
|
|
@@ -5,7 +5,7 @@ import os
|
|
|
5
5
|
import tempfile
|
|
6
6
|
import uuid
|
|
7
7
|
from pathlib import Path
|
|
8
|
-
from typing import TYPE_CHECKING, Any, Dict, NamedTuple, Optional, Tuple, Union
|
|
8
|
+
from typing import TYPE_CHECKING, Any, Dict, List, NamedTuple, Optional, Tuple, Union
|
|
9
9
|
|
|
10
10
|
from truefoundry.ml.artifact.truefoundry_artifact_repo import (
|
|
11
11
|
ArtifactIdentifier,
|
|
@@ -25,6 +25,7 @@ from truefoundry.ml.autogen.client import ( # type: ignore[attr-defined]
|
|
|
25
25
|
from truefoundry.ml.autogen.client import ( # type: ignore[attr-defined]
|
|
26
26
|
InternalMetadata as InternalMetadataDto,
|
|
27
27
|
)
|
|
28
|
+
from truefoundry.ml.autogen.entities.artifacts import ChatPrompt
|
|
28
29
|
from truefoundry.ml.exceptions import MlFoundryException
|
|
29
30
|
from truefoundry.ml.log_types.artifacts.constants import INTERNAL_METADATA_PATH
|
|
30
31
|
from truefoundry.ml.log_types.artifacts.utils import (
|
|
@@ -351,6 +352,63 @@ class ArtifactVersion:
|
|
|
351
352
|
self._set_mutable_attrs()
|
|
352
353
|
|
|
353
354
|
|
|
355
|
+
class ChatPromptVersion(ArtifactVersion):
|
|
356
|
+
def __init__(self, artifact_version: ArtifactVersionDto, artifact: ArtifactDto):
|
|
357
|
+
if artifact.type != ArtifactType.CHAT_PROMPT:
|
|
358
|
+
raise ValueError(
|
|
359
|
+
f"{artifact_version.fqn!r} is not a chat prompt type artifact"
|
|
360
|
+
)
|
|
361
|
+
super().__init__(
|
|
362
|
+
artifact_version=artifact_version,
|
|
363
|
+
artifact=artifact,
|
|
364
|
+
)
|
|
365
|
+
self._chat_prompt = ChatPrompt.parse_obj(
|
|
366
|
+
artifact_version.internal_metadata.to_dict()
|
|
367
|
+
)
|
|
368
|
+
|
|
369
|
+
@classmethod
|
|
370
|
+
def from_fqn(cls, fqn: str) -> "ChatPromptVersion":
|
|
371
|
+
api_client = _get_api_client()
|
|
372
|
+
mlfoundry_artifacts_api = MlfoundryArtifactsApi(api_client=api_client)
|
|
373
|
+
_artifact_version = mlfoundry_artifacts_api.get_artifact_version_by_fqn_get(
|
|
374
|
+
fqn=fqn
|
|
375
|
+
)
|
|
376
|
+
artifact_version = _artifact_version.artifact_version
|
|
377
|
+
_artifact = mlfoundry_artifacts_api.get_artifact_by_id_get(
|
|
378
|
+
id=artifact_version.artifact_id
|
|
379
|
+
)
|
|
380
|
+
return cls(
|
|
381
|
+
artifact_version=_artifact_version.artifact_version,
|
|
382
|
+
artifact=_artifact.artifact,
|
|
383
|
+
)
|
|
384
|
+
|
|
385
|
+
@property
|
|
386
|
+
def model(self) -> str:
|
|
387
|
+
return self._chat_prompt.model_configuration.model
|
|
388
|
+
|
|
389
|
+
@property
|
|
390
|
+
def provider(self) -> str:
|
|
391
|
+
return self._chat_prompt.model_configuration.provider
|
|
392
|
+
|
|
393
|
+
@property
|
|
394
|
+
def messages(self) -> List[Dict[str, Any]]:
|
|
395
|
+
return [message.dict() for message in self._chat_prompt.messages]
|
|
396
|
+
|
|
397
|
+
@property
|
|
398
|
+
def parameters(self) -> Dict[str, Any]:
|
|
399
|
+
_parameters = self._chat_prompt.model_configuration.parameters
|
|
400
|
+
return _parameters.dict(exclude_unset=True) if _parameters else {}
|
|
401
|
+
|
|
402
|
+
@property
|
|
403
|
+
def extra_parameters(self) -> Dict[str, Any]:
|
|
404
|
+
_extra_parameters = self._chat_prompt.model_configuration.extra_parameters
|
|
405
|
+
return _extra_parameters.dict(exclude_unset=True) if _extra_parameters else {}
|
|
406
|
+
|
|
407
|
+
@property
|
|
408
|
+
def variables(self) -> Dict[str, Any]:
|
|
409
|
+
return self._chat_prompt.variables or {}
|
|
410
|
+
|
|
411
|
+
|
|
354
412
|
def _log_artifact_version_helper(
|
|
355
413
|
run: "MlFoundryRun",
|
|
356
414
|
name: str,
|
truefoundry/ml/mlfoundry_api.py
CHANGED
|
@@ -7,6 +7,7 @@ from typing import Any, Dict, Iterator, List, Optional, Sequence, Tuple, Union
|
|
|
7
7
|
import coolname
|
|
8
8
|
import pandas as pd
|
|
9
9
|
|
|
10
|
+
from truefoundry.common.utils import relogin_error_message
|
|
10
11
|
from truefoundry.ml import constants, env_vars
|
|
11
12
|
from truefoundry.ml.autogen.client import ( # type: ignore[attr-defined]
|
|
12
13
|
ArtifactDto,
|
|
@@ -34,7 +35,11 @@ from truefoundry.ml.clients.servicefoundry_client import ServiceFoundryServiceCl
|
|
|
34
35
|
from truefoundry.ml.enums import ModelFramework, ViewType
|
|
35
36
|
from truefoundry.ml.exceptions import MlFoundryException
|
|
36
37
|
from truefoundry.ml.internal_namespace import NAMESPACE
|
|
37
|
-
from truefoundry.ml.log_types.artifacts.artifact import
|
|
38
|
+
from truefoundry.ml.log_types.artifacts.artifact import (
|
|
39
|
+
ArtifactPath,
|
|
40
|
+
ArtifactVersion,
|
|
41
|
+
ChatPromptVersion,
|
|
42
|
+
)
|
|
38
43
|
from truefoundry.ml.log_types.artifacts.dataset import DataDirectory
|
|
39
44
|
from truefoundry.ml.log_types.artifacts.general_artifact import _log_artifact_version
|
|
40
45
|
from truefoundry.ml.log_types.artifacts.model import ModelVersion, _log_model_version
|
|
@@ -209,8 +214,9 @@ class MlFoundry:
|
|
|
209
214
|
session = get_active_session()
|
|
210
215
|
if session is None:
|
|
211
216
|
raise MlFoundryException(
|
|
212
|
-
|
|
213
|
-
|
|
217
|
+
relogin_error_message(
|
|
218
|
+
"No active session found. Perhaps you are not logged in?",
|
|
219
|
+
)
|
|
214
220
|
)
|
|
215
221
|
servicefoundry_client = ServiceFoundryServiceClient(
|
|
216
222
|
tracking_uri=self.get_tracking_uri(),
|
|
@@ -1554,6 +1560,45 @@ class MlFoundry:
|
|
|
1554
1560
|
if not datasets or not page_token:
|
|
1555
1561
|
done = True
|
|
1556
1562
|
|
|
1563
|
+
def get_chat_prompt_version_by_fqn(self, fqn: str) -> ChatPromptVersion:
|
|
1564
|
+
"""
|
|
1565
|
+
Get the prompt by prompt version FQN
|
|
1566
|
+
Args:
|
|
1567
|
+
fqn (str): Fully qualified name of the chat prompt version.
|
|
1568
|
+
Returns:
|
|
1569
|
+
ChatPromptVersion: An instance of the ChatPromptVersion class with the fetched prompt details.
|
|
1570
|
+
|
|
1571
|
+
Examples:
|
|
1572
|
+
```python
|
|
1573
|
+
from truefoundry.ml import get_client
|
|
1574
|
+
client = get_client()
|
|
1575
|
+
|
|
1576
|
+
# Get the chat prompt by FQN
|
|
1577
|
+
fqn = 'chat_prompt:truefoundry/prompt-demo/demo-prompt-1:2'
|
|
1578
|
+
chat_prompt = client.get_chat_prompt_version_by_fqn(fqn=fqn)
|
|
1579
|
+
|
|
1580
|
+
# Check the chat prompt values
|
|
1581
|
+
print(chat_prompt)
|
|
1582
|
+
|
|
1583
|
+
# Use with OpenAI client
|
|
1584
|
+
from openai import OpenAI
|
|
1585
|
+
openai_client = OpenAI(api_key="api_key")
|
|
1586
|
+
|
|
1587
|
+
# Make the OpenAI call
|
|
1588
|
+
response = openai_client.chat.completions.create(
|
|
1589
|
+
model=chat_prompt.model,
|
|
1590
|
+
messages=chat_prompt.messages,
|
|
1591
|
+
**chat_prompt.parameters,
|
|
1592
|
+
**chat_prompt.extra_parameters
|
|
1593
|
+
)
|
|
1594
|
+
|
|
1595
|
+
# Extract the content from the response
|
|
1596
|
+
response_content = response.choices[0].message.content
|
|
1597
|
+
print(response_content)
|
|
1598
|
+
```
|
|
1599
|
+
"""
|
|
1600
|
+
return ChatPromptVersion.from_fqn(fqn=fqn)
|
|
1601
|
+
|
|
1557
1602
|
|
|
1558
1603
|
def get_client() -> MlFoundry:
|
|
1559
1604
|
"""Initializes and returns the mlfoundry client.
|
truefoundry/ml/mlfoundry_run.py
CHANGED
|
@@ -19,6 +19,7 @@ from typing import (
|
|
|
19
19
|
from urllib.parse import urljoin, urlsplit
|
|
20
20
|
|
|
21
21
|
from truefoundry import version
|
|
22
|
+
from truefoundry.common.utils import relogin_error_message
|
|
22
23
|
from truefoundry.ml import constants, enums
|
|
23
24
|
from truefoundry.ml.autogen.client import ( # type: ignore[attr-defined]
|
|
24
25
|
ArtifactType,
|
|
@@ -51,6 +52,8 @@ from truefoundry.ml.run_utils import ParamsType, flatten_dict, process_params
|
|
|
51
52
|
from truefoundry.ml.session import ACTIVE_RUNS, _get_api_client, get_active_session
|
|
52
53
|
from truefoundry.ml.validation_utils import (
|
|
53
54
|
MAX_ENTITY_KEY_LENGTH,
|
|
55
|
+
MAX_METRICS_PER_BATCH,
|
|
56
|
+
MAX_PARAMS_TAGS_PER_BATCH,
|
|
54
57
|
_validate_batch_log_data,
|
|
55
58
|
)
|
|
56
59
|
|
|
@@ -222,8 +225,9 @@ class MlFoundryRun:
|
|
|
222
225
|
session = get_active_session()
|
|
223
226
|
if session is None:
|
|
224
227
|
raise MlFoundryException(
|
|
225
|
-
|
|
226
|
-
|
|
228
|
+
relogin_error_message(
|
|
229
|
+
"No active session found. Perhaps you are not logged in?",
|
|
230
|
+
)
|
|
227
231
|
)
|
|
228
232
|
base_url = "{uri.scheme}://{uri.netloc}/".format(
|
|
229
233
|
uri=urlsplit(session.tracking_uri)
|
|
@@ -636,12 +640,16 @@ class MlFoundryRun:
|
|
|
636
640
|
return
|
|
637
641
|
|
|
638
642
|
try:
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
+
for i in range(0, len(metrics), MAX_METRICS_PER_BATCH):
|
|
644
|
+
metrics_batch = metrics[i : i + MAX_METRICS_PER_BATCH]
|
|
645
|
+
|
|
646
|
+
_validate_batch_log_data(metrics=metrics_batch, params=[], tags=[])
|
|
647
|
+
|
|
648
|
+
self._runs_api.log_run_batch_post(
|
|
649
|
+
log_batch_request_dto=LogBatchRequestDto(
|
|
650
|
+
run_id=self.run_id, metrics=metrics_batch, params=[], tags=[]
|
|
651
|
+
)
|
|
643
652
|
)
|
|
644
|
-
)
|
|
645
653
|
except Exception as e:
|
|
646
654
|
raise MlFoundryException(str(e)) from e
|
|
647
655
|
|
|
@@ -723,12 +731,17 @@ class MlFoundryRun:
|
|
|
723
731
|
if len(params) == 0:
|
|
724
732
|
logger.warning("Cannot log empty params dictionary")
|
|
725
733
|
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
734
|
+
for i in range(0, len(params), MAX_PARAMS_TAGS_PER_BATCH):
|
|
735
|
+
params_batch = params[i : i + MAX_PARAMS_TAGS_PER_BATCH]
|
|
736
|
+
|
|
737
|
+
_validate_batch_log_data(metrics=[], params=params_batch, tags=[])
|
|
738
|
+
logger.debug("Logging parameters: %s", params_batch)
|
|
739
|
+
|
|
740
|
+
self._runs_api.log_run_batch_post(
|
|
741
|
+
log_batch_request_dto=LogBatchRequestDto(
|
|
742
|
+
run_id=self.run_id, metrics=[], params=params_batch, tags=[]
|
|
743
|
+
)
|
|
730
744
|
)
|
|
731
|
-
)
|
|
732
745
|
except Exception as e:
|
|
733
746
|
raise MlFoundryException(str(e)) from e
|
|
734
747
|
logger.info("Parameters logged successfully")
|
|
@@ -765,11 +778,15 @@ class MlFoundryRun:
|
|
|
765
778
|
tags_arr = [
|
|
766
779
|
RunTagDto(key=key, value=str(value)) for key, value in tags.items()
|
|
767
780
|
]
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
781
|
+
for i in range(0, len(tags_arr), MAX_PARAMS_TAGS_PER_BATCH):
|
|
782
|
+
tags_batch = tags_arr[i : i + MAX_PARAMS_TAGS_PER_BATCH]
|
|
783
|
+
|
|
784
|
+
_validate_batch_log_data(metrics=[], params=[], tags=tags_batch)
|
|
785
|
+
self._runs_api.log_run_batch_post(
|
|
786
|
+
log_batch_request_dto=LogBatchRequestDto(
|
|
787
|
+
run_id=self.run_id, metrics=[], params=[], tags=tags_batch
|
|
788
|
+
)
|
|
771
789
|
)
|
|
772
|
-
)
|
|
773
790
|
except Exception as e:
|
|
774
791
|
raise MlFoundryException(str(e)) from e
|
|
775
792
|
logger.info("Tags set successfully")
|
truefoundry/ml/run_utils.py
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import argparse
|
|
2
2
|
import importlib
|
|
3
3
|
import json
|
|
4
|
-
import os
|
|
5
4
|
from typing import Any, Dict, List, Mapping, Optional, Tuple, Union
|
|
6
|
-
from urllib.parse import urljoin, urlsplit
|
|
7
5
|
|
|
8
6
|
import numpy as np
|
|
9
7
|
|
|
@@ -21,18 +19,6 @@ def get_module(
|
|
|
21
19
|
raise MlFoundryException(msg) from ex
|
|
22
20
|
|
|
23
21
|
|
|
24
|
-
def append_path_to_rest_tracking_uri(tracking_uri: str):
|
|
25
|
-
if urlsplit(tracking_uri).netloc.startswith("localhost"):
|
|
26
|
-
return tracking_uri
|
|
27
|
-
return urljoin(tracking_uri, "/api/ml")
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
def append_servicefoundry_path_to_tracking_uri(tracking_uri: str):
|
|
31
|
-
if urlsplit(tracking_uri).netloc.startswith("localhost"):
|
|
32
|
-
return os.getenv("SERVICEFOUNDRY_SERVER_URL")
|
|
33
|
-
return urljoin(tracking_uri, "/api/svc")
|
|
34
|
-
|
|
35
|
-
|
|
36
22
|
class NumpyEncoder(json.JSONEncoder):
|
|
37
23
|
"""Special json encoder for numpy types"""
|
|
38
24
|
|
truefoundry/ml/session.py
CHANGED
|
@@ -10,6 +10,7 @@ from truefoundry.common.credential_provider import (
|
|
|
10
10
|
)
|
|
11
11
|
from truefoundry.common.entities import Token, UserInfo
|
|
12
12
|
from truefoundry.common.request_utils import urllib3_retry
|
|
13
|
+
from truefoundry.common.utils import get_tfy_servers_config, relogin_error_message
|
|
13
14
|
from truefoundry.ml.autogen.client import ( # type: ignore[attr-defined]
|
|
14
15
|
ApiClient,
|
|
15
16
|
Configuration,
|
|
@@ -17,9 +18,6 @@ from truefoundry.ml.autogen.client import ( # type: ignore[attr-defined]
|
|
|
17
18
|
from truefoundry.ml.clients.entities import HostCreds
|
|
18
19
|
from truefoundry.ml.exceptions import MlFoundryException
|
|
19
20
|
from truefoundry.ml.logger import logger
|
|
20
|
-
from truefoundry.ml.run_utils import (
|
|
21
|
-
append_path_to_rest_tracking_uri,
|
|
22
|
-
)
|
|
23
21
|
|
|
24
22
|
if TYPE_CHECKING:
|
|
25
23
|
from truefoundry.ml.mlfoundry_run import MlFoundryRun
|
|
@@ -83,6 +81,7 @@ class Session:
|
|
|
83
81
|
self._assert_not_closed()
|
|
84
82
|
return self._user_info
|
|
85
83
|
|
|
84
|
+
# TODO (chiragjn): Rename tracking_uri to tfy_host
|
|
86
85
|
@property
|
|
87
86
|
def tracking_uri(self) -> str:
|
|
88
87
|
return self._cred_provider.base_url
|
|
@@ -97,7 +96,7 @@ class Session:
|
|
|
97
96
|
)
|
|
98
97
|
|
|
99
98
|
def get_host_creds(self) -> HostCreds:
|
|
100
|
-
tracking_uri =
|
|
99
|
+
tracking_uri = get_tfy_servers_config(self.tracking_uri).mlfoundry_server_url
|
|
101
100
|
return HostCreds(
|
|
102
101
|
host=tracking_uri, token=self._cred_provider.token.access_token
|
|
103
102
|
)
|
|
@@ -120,8 +119,9 @@ def _get_api_client(
|
|
|
120
119
|
return ApiClient()
|
|
121
120
|
else:
|
|
122
121
|
raise MlFoundryException(
|
|
123
|
-
|
|
124
|
-
|
|
122
|
+
relogin_error_message(
|
|
123
|
+
"No active session found. Perhaps you are not logged in?",
|
|
124
|
+
)
|
|
125
125
|
)
|
|
126
126
|
|
|
127
127
|
creds = session.get_host_creds()
|
|
@@ -144,8 +144,9 @@ def init_session() -> Session:
|
|
|
144
144
|
break
|
|
145
145
|
if final_cred_provider is None:
|
|
146
146
|
raise MlFoundryException(
|
|
147
|
-
|
|
148
|
-
|
|
147
|
+
relogin_error_message(
|
|
148
|
+
"No active session found. Perhaps you are not logged in?",
|
|
149
|
+
)
|
|
149
150
|
)
|
|
150
151
|
new_session = Session(cred_provider=final_cred_provider)
|
|
151
152
|
|
|
@@ -5,9 +5,9 @@ from truefoundry.workflow import PythonTaskConfig, TaskPythonBuild, task, workfl
|
|
|
5
5
|
task_config=PythonTaskConfig(
|
|
6
6
|
image=TaskPythonBuild(
|
|
7
7
|
python_version="3.9",
|
|
8
|
-
pip_packages=["truefoundry[workflow]
|
|
8
|
+
pip_packages=["truefoundry[workflow]"],
|
|
9
9
|
),
|
|
10
|
-
service_account="tfy-
|
|
10
|
+
service_account="tfy-workflows-sa",
|
|
11
11
|
)
|
|
12
12
|
)
|
|
13
13
|
def say_hello() -> str:
|