databricks-sdk 0.54.0__py3-none-any.whl → 0.56.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 databricks-sdk might be problematic. Click here for more details.
- databricks/sdk/__init__.py +304 -278
- databricks/sdk/config.py +15 -4
- databricks/sdk/credentials_provider.py +101 -55
- databricks/sdk/oauth.py +0 -5
- databricks/sdk/oidc.py +206 -0
- databricks/sdk/service/aibuilder.py +364 -0
- databricks/sdk/service/billing.py +150 -169
- databricks/sdk/service/catalog.py +263 -835
- databricks/sdk/service/cleanrooms.py +15 -10
- databricks/sdk/service/compute.py +12 -22
- databricks/sdk/service/dashboards.py +59 -451
- databricks/sdk/service/database.py +1256 -0
- databricks/sdk/service/files.py +2 -0
- databricks/sdk/service/iam.py +6 -6
- databricks/sdk/service/jobs.py +238 -0
- databricks/sdk/service/ml.py +8 -271
- databricks/sdk/service/pipelines.py +45 -1
- databricks/sdk/service/provisioning.py +0 -3
- databricks/sdk/service/qualitymonitorv2.py +275 -0
- databricks/sdk/service/serving.py +76 -4
- databricks/sdk/service/settings.py +982 -99
- databricks/sdk/service/sharing.py +3 -2
- databricks/sdk/service/sql.py +218 -1
- databricks/sdk/version.py +1 -1
- {databricks_sdk-0.54.0.dist-info → databricks_sdk-0.56.0.dist-info}/METADATA +1 -1
- {databricks_sdk-0.54.0.dist-info → databricks_sdk-0.56.0.dist-info}/RECORD +30 -26
- {databricks_sdk-0.54.0.dist-info → databricks_sdk-0.56.0.dist-info}/WHEEL +1 -1
- {databricks_sdk-0.54.0.dist-info → databricks_sdk-0.56.0.dist-info}/licenses/LICENSE +0 -0
- {databricks_sdk-0.54.0.dist-info → databricks_sdk-0.56.0.dist-info}/licenses/NOTICE +0 -0
- {databricks_sdk-0.54.0.dist-info → databricks_sdk-0.56.0.dist-info}/top_level.txt +0 -0
databricks/sdk/oidc.py
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Package oidc provides utilities for working with OIDC ID tokens.
|
|
3
|
+
|
|
4
|
+
This package is experimental and subject to change.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
import os
|
|
9
|
+
from abc import ABC, abstractmethod
|
|
10
|
+
from dataclasses import dataclass
|
|
11
|
+
from typing import Optional
|
|
12
|
+
|
|
13
|
+
from . import oauth
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclass
|
|
19
|
+
class IdToken:
|
|
20
|
+
"""Represents an OIDC ID token that can be exchanged for a Databricks access token.
|
|
21
|
+
|
|
22
|
+
Parameters
|
|
23
|
+
----------
|
|
24
|
+
jwt : str
|
|
25
|
+
The signed JWT token string.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
jwt: str
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class IdTokenSource(ABC):
|
|
32
|
+
"""Abstract base class representing anything that returns an IDToken.
|
|
33
|
+
|
|
34
|
+
This class defines the interface for token sources that can provide OIDC ID tokens.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
@abstractmethod
|
|
38
|
+
def id_token(self) -> IdToken:
|
|
39
|
+
"""Get an ID token.
|
|
40
|
+
|
|
41
|
+
Returns
|
|
42
|
+
-------
|
|
43
|
+
IdToken
|
|
44
|
+
An ID token.
|
|
45
|
+
|
|
46
|
+
Raises
|
|
47
|
+
------
|
|
48
|
+
Exception
|
|
49
|
+
Implementation specific exceptions.
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class EnvIdTokenSource(IdTokenSource):
|
|
54
|
+
"""IDTokenSource that reads the ID token from an environment variable.
|
|
55
|
+
|
|
56
|
+
Parameters
|
|
57
|
+
----------
|
|
58
|
+
env_var : str
|
|
59
|
+
The name of the environment variable containing the ID token.
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
def __init__(self, env_var: str):
|
|
63
|
+
self.env_var = env_var
|
|
64
|
+
|
|
65
|
+
def id_token(self) -> IdToken:
|
|
66
|
+
"""Get an ID token from an environment variable.
|
|
67
|
+
|
|
68
|
+
Returns
|
|
69
|
+
-------
|
|
70
|
+
IdToken
|
|
71
|
+
An ID token.
|
|
72
|
+
|
|
73
|
+
Raises
|
|
74
|
+
------
|
|
75
|
+
ValueError
|
|
76
|
+
If the environment variable is not set.
|
|
77
|
+
"""
|
|
78
|
+
token = os.getenv(self.env_var)
|
|
79
|
+
if not token:
|
|
80
|
+
raise ValueError(f"Missing env var {self.env_var!r}")
|
|
81
|
+
return IdToken(jwt=token)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class FileIdTokenSource(IdTokenSource):
|
|
85
|
+
"""IDTokenSource that reads the ID token from a file.
|
|
86
|
+
|
|
87
|
+
Parameters
|
|
88
|
+
----------
|
|
89
|
+
path : str
|
|
90
|
+
The path to the file containing the ID token.
|
|
91
|
+
"""
|
|
92
|
+
|
|
93
|
+
def __init__(self, path: str):
|
|
94
|
+
self.path = path
|
|
95
|
+
|
|
96
|
+
def id_token(self) -> IdToken:
|
|
97
|
+
"""Get an ID token from a file.
|
|
98
|
+
|
|
99
|
+
Returns
|
|
100
|
+
-------
|
|
101
|
+
IdToken
|
|
102
|
+
An ID token.
|
|
103
|
+
|
|
104
|
+
Raises
|
|
105
|
+
------
|
|
106
|
+
ValueError
|
|
107
|
+
If the file is empty, does not exist, or cannot be read.
|
|
108
|
+
"""
|
|
109
|
+
if not self.path:
|
|
110
|
+
raise ValueError("Missing path")
|
|
111
|
+
|
|
112
|
+
token = None
|
|
113
|
+
try:
|
|
114
|
+
with open(self.path, "r") as f:
|
|
115
|
+
token = f.read().strip()
|
|
116
|
+
except FileNotFoundError:
|
|
117
|
+
raise ValueError(f"File {self.path!r} does not exist")
|
|
118
|
+
except Exception as e:
|
|
119
|
+
raise ValueError(f"Error reading token file: {str(e)}")
|
|
120
|
+
|
|
121
|
+
if not token:
|
|
122
|
+
raise ValueError(f"File {self.path!r} is empty")
|
|
123
|
+
return IdToken(jwt=token)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
class DatabricksOidcTokenSource(oauth.TokenSource):
|
|
127
|
+
"""A TokenSource which exchanges a token using Workload Identity Federation.
|
|
128
|
+
|
|
129
|
+
Parameters
|
|
130
|
+
----------
|
|
131
|
+
host : str
|
|
132
|
+
The host of the Databricks account or workspace.
|
|
133
|
+
id_token_source : IdTokenSource
|
|
134
|
+
IDTokenSource that returns the IDToken to be used for the token exchange.
|
|
135
|
+
token_endpoint_provider : Callable[[], dict]
|
|
136
|
+
Returns the token endpoint for the Databricks OIDC application.
|
|
137
|
+
client_id : Optional[str], optional
|
|
138
|
+
ClientID of the Databricks OIDC application. It corresponds to the
|
|
139
|
+
Application ID of the Databricks Service Principal. Only required for
|
|
140
|
+
Workload Identity Federation and should be empty for Account-wide token
|
|
141
|
+
federation.
|
|
142
|
+
account_id : Optional[str], optional
|
|
143
|
+
The account ID of the Databricks Account. Only required for
|
|
144
|
+
Account-wide token federation.
|
|
145
|
+
audience : Optional[str], optional
|
|
146
|
+
The audience of the Databricks OIDC application. Only used for
|
|
147
|
+
Workspace level tokens.
|
|
148
|
+
"""
|
|
149
|
+
|
|
150
|
+
def __init__(
|
|
151
|
+
self,
|
|
152
|
+
host: str,
|
|
153
|
+
token_endpoint: str,
|
|
154
|
+
id_token_source: IdTokenSource,
|
|
155
|
+
client_id: Optional[str] = None,
|
|
156
|
+
account_id: Optional[str] = None,
|
|
157
|
+
audience: Optional[str] = None,
|
|
158
|
+
disable_async: bool = False,
|
|
159
|
+
):
|
|
160
|
+
self._host = host
|
|
161
|
+
self._id_token_source = id_token_source
|
|
162
|
+
self._token_endpoint = token_endpoint
|
|
163
|
+
self._client_id = client_id
|
|
164
|
+
self._account_id = account_id
|
|
165
|
+
self._audience = audience
|
|
166
|
+
self._disable_async = disable_async
|
|
167
|
+
|
|
168
|
+
def token(self) -> oauth.Token:
|
|
169
|
+
"""Get a token by exchanging the ID token.
|
|
170
|
+
|
|
171
|
+
Returns
|
|
172
|
+
-------
|
|
173
|
+
dict
|
|
174
|
+
The exchanged token.
|
|
175
|
+
|
|
176
|
+
Raises
|
|
177
|
+
------
|
|
178
|
+
ValueError
|
|
179
|
+
If the host is missing or other configuration errors occur.
|
|
180
|
+
"""
|
|
181
|
+
if not self._host:
|
|
182
|
+
logger.debug("Missing Host")
|
|
183
|
+
raise ValueError("missing Host")
|
|
184
|
+
|
|
185
|
+
if not self._client_id:
|
|
186
|
+
logger.debug("No ClientID provided, authenticating with Account-wide token federation")
|
|
187
|
+
else:
|
|
188
|
+
logger.debug("Client ID provided, authenticating with Workload Identity Federation")
|
|
189
|
+
|
|
190
|
+
id_token = self._id_token_source.id_token()
|
|
191
|
+
|
|
192
|
+
client = oauth.ClientCredentials(
|
|
193
|
+
client_id=self._client_id,
|
|
194
|
+
client_secret="", # we have no (rotatable) secrets in OIDC flow
|
|
195
|
+
token_url=self._token_endpoint,
|
|
196
|
+
endpoint_params={
|
|
197
|
+
"subject_token_type": "urn:ietf:params:oauth:token-type:jwt",
|
|
198
|
+
"subject_token": id_token,
|
|
199
|
+
"grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
|
|
200
|
+
},
|
|
201
|
+
scopes=["all-apis"],
|
|
202
|
+
use_params=True,
|
|
203
|
+
disable_async=self._disable_async,
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
return client.token()
|
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
# Code generated from OpenAPI specs by Databricks SDK Generator. DO NOT EDIT.
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
from enum import Enum
|
|
8
|
+
from typing import Any, Dict, List, Optional
|
|
9
|
+
|
|
10
|
+
from ._internal import _enum, _from_dict, _repeated_dict
|
|
11
|
+
|
|
12
|
+
_LOG = logging.getLogger("databricks.sdk")
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# all definitions in this file are in alphabetical order
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclass
|
|
19
|
+
class CancelCustomLlmOptimizationRunRequest:
|
|
20
|
+
id: Optional[str] = None
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@dataclass
|
|
24
|
+
class CancelResponse:
|
|
25
|
+
def as_dict(self) -> dict:
|
|
26
|
+
"""Serializes the CancelResponse into a dictionary suitable for use as a JSON request body."""
|
|
27
|
+
body = {}
|
|
28
|
+
return body
|
|
29
|
+
|
|
30
|
+
def as_shallow_dict(self) -> dict:
|
|
31
|
+
"""Serializes the CancelResponse into a shallow dictionary of its immediate attributes."""
|
|
32
|
+
body = {}
|
|
33
|
+
return body
|
|
34
|
+
|
|
35
|
+
@classmethod
|
|
36
|
+
def from_dict(cls, d: Dict[str, Any]) -> CancelResponse:
|
|
37
|
+
"""Deserializes the CancelResponse from a dictionary."""
|
|
38
|
+
return cls()
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@dataclass
|
|
42
|
+
class CustomLlm:
|
|
43
|
+
name: str
|
|
44
|
+
"""Name of the custom LLM"""
|
|
45
|
+
|
|
46
|
+
instructions: str
|
|
47
|
+
"""Instructions for the custom LLM to follow"""
|
|
48
|
+
|
|
49
|
+
optimization_state: State
|
|
50
|
+
"""If optimization is kicked off, tracks the state of the custom LLM"""
|
|
51
|
+
|
|
52
|
+
agent_artifact_path: Optional[str] = None
|
|
53
|
+
|
|
54
|
+
creation_time: Optional[str] = None
|
|
55
|
+
"""Creation timestamp of the custom LLM"""
|
|
56
|
+
|
|
57
|
+
creator: Optional[str] = None
|
|
58
|
+
"""Creator of the custom LLM"""
|
|
59
|
+
|
|
60
|
+
datasets: Optional[List[Dataset]] = None
|
|
61
|
+
"""Datasets used for training and evaluating the model, not for inference"""
|
|
62
|
+
|
|
63
|
+
endpoint_name: Optional[str] = None
|
|
64
|
+
"""Name of the endpoint that will be used to serve the custom LLM"""
|
|
65
|
+
|
|
66
|
+
guidelines: Optional[List[str]] = None
|
|
67
|
+
"""Guidelines for the custom LLM to adhere to"""
|
|
68
|
+
|
|
69
|
+
id: Optional[str] = None
|
|
70
|
+
|
|
71
|
+
def as_dict(self) -> dict:
|
|
72
|
+
"""Serializes the CustomLlm into a dictionary suitable for use as a JSON request body."""
|
|
73
|
+
body = {}
|
|
74
|
+
if self.agent_artifact_path is not None:
|
|
75
|
+
body["agent_artifact_path"] = self.agent_artifact_path
|
|
76
|
+
if self.creation_time is not None:
|
|
77
|
+
body["creation_time"] = self.creation_time
|
|
78
|
+
if self.creator is not None:
|
|
79
|
+
body["creator"] = self.creator
|
|
80
|
+
if self.datasets:
|
|
81
|
+
body["datasets"] = [v.as_dict() for v in self.datasets]
|
|
82
|
+
if self.endpoint_name is not None:
|
|
83
|
+
body["endpoint_name"] = self.endpoint_name
|
|
84
|
+
if self.guidelines:
|
|
85
|
+
body["guidelines"] = [v for v in self.guidelines]
|
|
86
|
+
if self.id is not None:
|
|
87
|
+
body["id"] = self.id
|
|
88
|
+
if self.instructions is not None:
|
|
89
|
+
body["instructions"] = self.instructions
|
|
90
|
+
if self.name is not None:
|
|
91
|
+
body["name"] = self.name
|
|
92
|
+
if self.optimization_state is not None:
|
|
93
|
+
body["optimization_state"] = self.optimization_state.value
|
|
94
|
+
return body
|
|
95
|
+
|
|
96
|
+
def as_shallow_dict(self) -> dict:
|
|
97
|
+
"""Serializes the CustomLlm into a shallow dictionary of its immediate attributes."""
|
|
98
|
+
body = {}
|
|
99
|
+
if self.agent_artifact_path is not None:
|
|
100
|
+
body["agent_artifact_path"] = self.agent_artifact_path
|
|
101
|
+
if self.creation_time is not None:
|
|
102
|
+
body["creation_time"] = self.creation_time
|
|
103
|
+
if self.creator is not None:
|
|
104
|
+
body["creator"] = self.creator
|
|
105
|
+
if self.datasets:
|
|
106
|
+
body["datasets"] = self.datasets
|
|
107
|
+
if self.endpoint_name is not None:
|
|
108
|
+
body["endpoint_name"] = self.endpoint_name
|
|
109
|
+
if self.guidelines:
|
|
110
|
+
body["guidelines"] = self.guidelines
|
|
111
|
+
if self.id is not None:
|
|
112
|
+
body["id"] = self.id
|
|
113
|
+
if self.instructions is not None:
|
|
114
|
+
body["instructions"] = self.instructions
|
|
115
|
+
if self.name is not None:
|
|
116
|
+
body["name"] = self.name
|
|
117
|
+
if self.optimization_state is not None:
|
|
118
|
+
body["optimization_state"] = self.optimization_state
|
|
119
|
+
return body
|
|
120
|
+
|
|
121
|
+
@classmethod
|
|
122
|
+
def from_dict(cls, d: Dict[str, Any]) -> CustomLlm:
|
|
123
|
+
"""Deserializes the CustomLlm from a dictionary."""
|
|
124
|
+
return cls(
|
|
125
|
+
agent_artifact_path=d.get("agent_artifact_path", None),
|
|
126
|
+
creation_time=d.get("creation_time", None),
|
|
127
|
+
creator=d.get("creator", None),
|
|
128
|
+
datasets=_repeated_dict(d, "datasets", Dataset),
|
|
129
|
+
endpoint_name=d.get("endpoint_name", None),
|
|
130
|
+
guidelines=d.get("guidelines", None),
|
|
131
|
+
id=d.get("id", None),
|
|
132
|
+
instructions=d.get("instructions", None),
|
|
133
|
+
name=d.get("name", None),
|
|
134
|
+
optimization_state=_enum(d, "optimization_state", State),
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
@dataclass
|
|
139
|
+
class Dataset:
|
|
140
|
+
table: Table
|
|
141
|
+
|
|
142
|
+
def as_dict(self) -> dict:
|
|
143
|
+
"""Serializes the Dataset into a dictionary suitable for use as a JSON request body."""
|
|
144
|
+
body = {}
|
|
145
|
+
if self.table:
|
|
146
|
+
body["table"] = self.table.as_dict()
|
|
147
|
+
return body
|
|
148
|
+
|
|
149
|
+
def as_shallow_dict(self) -> dict:
|
|
150
|
+
"""Serializes the Dataset into a shallow dictionary of its immediate attributes."""
|
|
151
|
+
body = {}
|
|
152
|
+
if self.table:
|
|
153
|
+
body["table"] = self.table
|
|
154
|
+
return body
|
|
155
|
+
|
|
156
|
+
@classmethod
|
|
157
|
+
def from_dict(cls, d: Dict[str, Any]) -> Dataset:
|
|
158
|
+
"""Deserializes the Dataset from a dictionary."""
|
|
159
|
+
return cls(table=_from_dict(d, "table", Table))
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
@dataclass
|
|
163
|
+
class StartCustomLlmOptimizationRunRequest:
|
|
164
|
+
id: Optional[str] = None
|
|
165
|
+
"""The Id of the tile."""
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
class State(Enum):
|
|
169
|
+
"""States of Custom LLM optimization lifecycle."""
|
|
170
|
+
|
|
171
|
+
CANCELLED = "CANCELLED"
|
|
172
|
+
COMPLETED = "COMPLETED"
|
|
173
|
+
CREATED = "CREATED"
|
|
174
|
+
FAILED = "FAILED"
|
|
175
|
+
PENDING = "PENDING"
|
|
176
|
+
RUNNING = "RUNNING"
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
@dataclass
|
|
180
|
+
class Table:
|
|
181
|
+
table_path: str
|
|
182
|
+
"""Full UC table path in catalog.schema.table_name format"""
|
|
183
|
+
|
|
184
|
+
request_col: str
|
|
185
|
+
"""Name of the request column"""
|
|
186
|
+
|
|
187
|
+
response_col: Optional[str] = None
|
|
188
|
+
"""Optional: Name of the response column if the data is labeled"""
|
|
189
|
+
|
|
190
|
+
def as_dict(self) -> dict:
|
|
191
|
+
"""Serializes the Table into a dictionary suitable for use as a JSON request body."""
|
|
192
|
+
body = {}
|
|
193
|
+
if self.request_col is not None:
|
|
194
|
+
body["request_col"] = self.request_col
|
|
195
|
+
if self.response_col is not None:
|
|
196
|
+
body["response_col"] = self.response_col
|
|
197
|
+
if self.table_path is not None:
|
|
198
|
+
body["table_path"] = self.table_path
|
|
199
|
+
return body
|
|
200
|
+
|
|
201
|
+
def as_shallow_dict(self) -> dict:
|
|
202
|
+
"""Serializes the Table into a shallow dictionary of its immediate attributes."""
|
|
203
|
+
body = {}
|
|
204
|
+
if self.request_col is not None:
|
|
205
|
+
body["request_col"] = self.request_col
|
|
206
|
+
if self.response_col is not None:
|
|
207
|
+
body["response_col"] = self.response_col
|
|
208
|
+
if self.table_path is not None:
|
|
209
|
+
body["table_path"] = self.table_path
|
|
210
|
+
return body
|
|
211
|
+
|
|
212
|
+
@classmethod
|
|
213
|
+
def from_dict(cls, d: Dict[str, Any]) -> Table:
|
|
214
|
+
"""Deserializes the Table from a dictionary."""
|
|
215
|
+
return cls(
|
|
216
|
+
request_col=d.get("request_col", None),
|
|
217
|
+
response_col=d.get("response_col", None),
|
|
218
|
+
table_path=d.get("table_path", None),
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
@dataclass
|
|
223
|
+
class UpdateCustomLlmRequest:
|
|
224
|
+
custom_llm: CustomLlm
|
|
225
|
+
"""The CustomLlm containing the fields which should be updated."""
|
|
226
|
+
|
|
227
|
+
update_mask: str
|
|
228
|
+
"""The list of the CustomLlm fields to update. These should correspond to the values (or lack
|
|
229
|
+
thereof) present in `custom_llm`.
|
|
230
|
+
|
|
231
|
+
The field mask must be a single string, with multiple fields separated by commas (no spaces).
|
|
232
|
+
The field path is relative to the resource object, using a dot (`.`) to navigate sub-fields
|
|
233
|
+
(e.g., `author.given_name`). Specification of elements in sequence or map fields is not allowed,
|
|
234
|
+
as only the entire collection field can be specified. Field names must exactly match the
|
|
235
|
+
resource field names.
|
|
236
|
+
|
|
237
|
+
A field mask of `*` indicates full replacement. It’s recommended to always explicitly list the
|
|
238
|
+
fields being updated and avoid using `*` wildcards, as it can lead to unintended results if the
|
|
239
|
+
API changes in the future."""
|
|
240
|
+
|
|
241
|
+
id: Optional[str] = None
|
|
242
|
+
"""The id of the custom llm"""
|
|
243
|
+
|
|
244
|
+
def as_dict(self) -> dict:
|
|
245
|
+
"""Serializes the UpdateCustomLlmRequest into a dictionary suitable for use as a JSON request body."""
|
|
246
|
+
body = {}
|
|
247
|
+
if self.custom_llm:
|
|
248
|
+
body["custom_llm"] = self.custom_llm.as_dict()
|
|
249
|
+
if self.id is not None:
|
|
250
|
+
body["id"] = self.id
|
|
251
|
+
if self.update_mask is not None:
|
|
252
|
+
body["update_mask"] = self.update_mask
|
|
253
|
+
return body
|
|
254
|
+
|
|
255
|
+
def as_shallow_dict(self) -> dict:
|
|
256
|
+
"""Serializes the UpdateCustomLlmRequest into a shallow dictionary of its immediate attributes."""
|
|
257
|
+
body = {}
|
|
258
|
+
if self.custom_llm:
|
|
259
|
+
body["custom_llm"] = self.custom_llm
|
|
260
|
+
if self.id is not None:
|
|
261
|
+
body["id"] = self.id
|
|
262
|
+
if self.update_mask is not None:
|
|
263
|
+
body["update_mask"] = self.update_mask
|
|
264
|
+
return body
|
|
265
|
+
|
|
266
|
+
@classmethod
|
|
267
|
+
def from_dict(cls, d: Dict[str, Any]) -> UpdateCustomLlmRequest:
|
|
268
|
+
"""Deserializes the UpdateCustomLlmRequest from a dictionary."""
|
|
269
|
+
return cls(
|
|
270
|
+
custom_llm=_from_dict(d, "custom_llm", CustomLlm),
|
|
271
|
+
id=d.get("id", None),
|
|
272
|
+
update_mask=d.get("update_mask", None),
|
|
273
|
+
)
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
class CustomLlmsAPI:
|
|
277
|
+
"""The Custom LLMs service manages state and powers the UI for the Custom LLM product."""
|
|
278
|
+
|
|
279
|
+
def __init__(self, api_client):
|
|
280
|
+
self._api = api_client
|
|
281
|
+
|
|
282
|
+
def cancel(self, id: str):
|
|
283
|
+
"""Cancel a Custom LLM Optimization Run.
|
|
284
|
+
|
|
285
|
+
:param id: str
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
"""
|
|
289
|
+
|
|
290
|
+
headers = {
|
|
291
|
+
"Accept": "application/json",
|
|
292
|
+
"Content-Type": "application/json",
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
self._api.do("POST", f"/api/2.0/custom-llms/{id}/optimize/cancel", headers=headers)
|
|
296
|
+
|
|
297
|
+
def create(self, id: str) -> CustomLlm:
|
|
298
|
+
"""Start a Custom LLM Optimization Run.
|
|
299
|
+
|
|
300
|
+
:param id: str
|
|
301
|
+
The Id of the tile.
|
|
302
|
+
|
|
303
|
+
:returns: :class:`CustomLlm`
|
|
304
|
+
"""
|
|
305
|
+
|
|
306
|
+
headers = {
|
|
307
|
+
"Accept": "application/json",
|
|
308
|
+
"Content-Type": "application/json",
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
res = self._api.do("POST", f"/api/2.0/custom-llms/{id}/optimize", headers=headers)
|
|
312
|
+
return CustomLlm.from_dict(res)
|
|
313
|
+
|
|
314
|
+
def get(self, id: str) -> CustomLlm:
|
|
315
|
+
"""Get a Custom LLM.
|
|
316
|
+
|
|
317
|
+
:param id: str
|
|
318
|
+
The id of the custom llm
|
|
319
|
+
|
|
320
|
+
:returns: :class:`CustomLlm`
|
|
321
|
+
"""
|
|
322
|
+
|
|
323
|
+
headers = {
|
|
324
|
+
"Accept": "application/json",
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
res = self._api.do("GET", f"/api/2.0/custom-llms/{id}", headers=headers)
|
|
328
|
+
return CustomLlm.from_dict(res)
|
|
329
|
+
|
|
330
|
+
def update(self, id: str, custom_llm: CustomLlm, update_mask: str) -> CustomLlm:
|
|
331
|
+
"""Update a Custom LLM.
|
|
332
|
+
|
|
333
|
+
:param id: str
|
|
334
|
+
The id of the custom llm
|
|
335
|
+
:param custom_llm: :class:`CustomLlm`
|
|
336
|
+
The CustomLlm containing the fields which should be updated.
|
|
337
|
+
:param update_mask: str
|
|
338
|
+
The list of the CustomLlm fields to update. These should correspond to the values (or lack thereof)
|
|
339
|
+
present in `custom_llm`.
|
|
340
|
+
|
|
341
|
+
The field mask must be a single string, with multiple fields separated by commas (no spaces). The
|
|
342
|
+
field path is relative to the resource object, using a dot (`.`) to navigate sub-fields (e.g.,
|
|
343
|
+
`author.given_name`). Specification of elements in sequence or map fields is not allowed, as only
|
|
344
|
+
the entire collection field can be specified. Field names must exactly match the resource field
|
|
345
|
+
names.
|
|
346
|
+
|
|
347
|
+
A field mask of `*` indicates full replacement. It’s recommended to always explicitly list the
|
|
348
|
+
fields being updated and avoid using `*` wildcards, as it can lead to unintended results if the API
|
|
349
|
+
changes in the future.
|
|
350
|
+
|
|
351
|
+
:returns: :class:`CustomLlm`
|
|
352
|
+
"""
|
|
353
|
+
body = {}
|
|
354
|
+
if custom_llm is not None:
|
|
355
|
+
body["custom_llm"] = custom_llm.as_dict()
|
|
356
|
+
if update_mask is not None:
|
|
357
|
+
body["update_mask"] = update_mask
|
|
358
|
+
headers = {
|
|
359
|
+
"Accept": "application/json",
|
|
360
|
+
"Content-Type": "application/json",
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
res = self._api.do("PATCH", f"/api/2.0/custom-llms/{id}", body=body, headers=headers)
|
|
364
|
+
return CustomLlm.from_dict(res)
|