wandb 0.21.0__py3-none-win32.whl → 0.21.1__py3-none-win32.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.
- wandb/__init__.py +16 -14
- wandb/__init__.pyi +427 -450
- wandb/agents/pyagent.py +41 -12
- wandb/analytics/sentry.py +7 -2
- wandb/apis/importers/mlflow.py +1 -1
- wandb/apis/public/__init__.py +1 -1
- wandb/apis/public/api.py +526 -360
- wandb/apis/public/artifacts.py +204 -8
- wandb/apis/public/automations.py +19 -3
- wandb/apis/public/files.py +172 -33
- wandb/apis/public/history.py +67 -15
- wandb/apis/public/integrations.py +25 -2
- wandb/apis/public/jobs.py +90 -2
- wandb/apis/public/projects.py +130 -79
- wandb/apis/public/query_generator.py +11 -1
- wandb/apis/public/registries/registries_search.py +7 -15
- wandb/apis/public/reports.py +83 -5
- wandb/apis/public/runs.py +299 -105
- wandb/apis/public/sweeps.py +222 -22
- wandb/apis/public/teams.py +41 -4
- wandb/apis/public/users.py +45 -4
- wandb/beta/workflows.py +66 -30
- wandb/bin/gpu_stats.exe +0 -0
- wandb/bin/wandb-core +0 -0
- wandb/cli/cli.py +80 -1
- wandb/env.py +8 -0
- wandb/errors/errors.py +4 -1
- wandb/integration/lightning/fabric/logger.py +3 -4
- wandb/integration/metaflow/__init__.py +6 -0
- wandb/integration/metaflow/data_pandas.py +74 -0
- wandb/integration/metaflow/errors.py +13 -0
- wandb/integration/metaflow/metaflow.py +205 -190
- wandb/integration/openai/fine_tuning.py +1 -2
- wandb/jupyter.py +5 -5
- wandb/plot/custom_chart.py +30 -7
- wandb/proto/v3/wandb_internal_pb2.py +280 -280
- wandb/proto/v3/wandb_telemetry_pb2.py +4 -4
- wandb/proto/v4/wandb_internal_pb2.py +280 -280
- wandb/proto/v4/wandb_telemetry_pb2.py +4 -4
- wandb/proto/v5/wandb_internal_pb2.py +280 -280
- wandb/proto/v5/wandb_telemetry_pb2.py +4 -4
- wandb/proto/v6/wandb_internal_pb2.py +280 -280
- wandb/proto/v6/wandb_telemetry_pb2.py +4 -4
- wandb/proto/wandb_deprecated.py +6 -0
- wandb/sdk/artifacts/_internal_artifact.py +19 -8
- wandb/sdk/artifacts/_validators.py +8 -0
- wandb/sdk/artifacts/artifact.py +106 -75
- wandb/sdk/data_types/audio.py +38 -10
- wandb/sdk/data_types/base_types/media.py +6 -56
- wandb/sdk/data_types/graph.py +48 -14
- wandb/sdk/data_types/helper_types/bounding_boxes_2d.py +1 -3
- wandb/sdk/data_types/helper_types/image_mask.py +1 -3
- wandb/sdk/data_types/histogram.py +34 -21
- wandb/sdk/data_types/html.py +35 -12
- wandb/sdk/data_types/image.py +104 -68
- wandb/sdk/data_types/molecule.py +32 -19
- wandb/sdk/data_types/object_3d.py +36 -17
- wandb/sdk/data_types/plotly.py +18 -5
- wandb/sdk/data_types/saved_model.py +4 -6
- wandb/sdk/data_types/table.py +59 -30
- wandb/sdk/data_types/video.py +53 -26
- wandb/sdk/integration_utils/auto_logging.py +2 -2
- wandb/sdk/internal/internal_api.py +6 -0
- wandb/sdk/internal/job_builder.py +6 -0
- wandb/sdk/launch/agent/agent.py +8 -1
- wandb/sdk/launch/agent/run_queue_item_file_saver.py +2 -2
- wandb/sdk/launch/create_job.py +3 -1
- wandb/sdk/launch/inputs/internal.py +3 -4
- wandb/sdk/launch/inputs/schema.py +1 -0
- wandb/sdk/launch/runner/kubernetes_monitor.py +1 -0
- wandb/sdk/launch/runner/kubernetes_runner.py +328 -1
- wandb/sdk/launch/sweeps/scheduler.py +2 -3
- wandb/sdk/lib/asyncio_compat.py +3 -0
- wandb/sdk/lib/deprecate.py +1 -7
- wandb/sdk/lib/disabled.py +1 -1
- wandb/sdk/lib/hashutil.py +14 -1
- wandb/sdk/lib/module.py +7 -13
- wandb/sdk/lib/progress.py +0 -19
- wandb/sdk/lib/sock_client.py +0 -4
- wandb/sdk/wandb_init.py +66 -91
- wandb/sdk/wandb_login.py +18 -14
- wandb/sdk/wandb_metric.py +2 -0
- wandb/sdk/wandb_run.py +406 -414
- wandb/sdk/wandb_settings.py +130 -2
- wandb/sdk/wandb_setup.py +28 -28
- wandb/sdk/wandb_sweep.py +14 -13
- wandb/sdk/wandb_watch.py +4 -6
- wandb/sync/sync.py +10 -0
- wandb/util.py +57 -0
- wandb/wandb_run.py +1 -2
- {wandb-0.21.0.dist-info → wandb-0.21.1.dist-info}/METADATA +1 -1
- {wandb-0.21.0.dist-info → wandb-0.21.1.dist-info}/RECORD +95 -95
- wandb/vendor/pynvml/__init__.py +0 -0
- wandb/vendor/pynvml/pynvml.py +0 -4779
- {wandb-0.21.0.dist-info → wandb-0.21.1.dist-info}/WHEEL +0 -0
- {wandb-0.21.0.dist-info → wandb-0.21.1.dist-info}/entry_points.txt +0 -0
- {wandb-0.21.0.dist-info → wandb-0.21.1.dist-info}/licenses/LICENSE +0 -0
wandb/sdk/data_types/table.py
CHANGED
@@ -203,7 +203,7 @@ class Table(Media):
|
|
203
203
|
This means you can embed `Images`, `Video`, `Audio`, and other sorts of rich, annotated media
|
204
204
|
directly in Tables, alongside other traditional scalar values.
|
205
205
|
|
206
|
-
This class is the primary class used to generate
|
206
|
+
This class is the primary class used to generate W&B Tables
|
207
207
|
https://docs.wandb.ai/guides/models/tables/.
|
208
208
|
"""
|
209
209
|
|
@@ -236,6 +236,7 @@ class Table(Media):
|
|
236
236
|
data: (List[List[any]]) 2D row-oriented array of values.
|
237
237
|
dataframe: (pandas.DataFrame) DataFrame object used to create the table.
|
238
238
|
When set, `data` and `columns` arguments are ignored.
|
239
|
+
rows: (List[List[any]]) 2D row-oriented array of values.
|
239
240
|
optional: (Union[bool,List[bool]]) Determines if `None` values are allowed. Default to True
|
240
241
|
- If a singular bool value, then the optionality is enforced for all
|
241
242
|
columns specified at construction time
|
@@ -410,13 +411,15 @@ class Table(Media):
|
|
410
411
|
def cast(self, col_name, dtype, optional=False):
|
411
412
|
"""Casts a column to a specific data type.
|
412
413
|
|
413
|
-
This can be one of the normal python classes, an internal W&B type,
|
414
|
-
example object, like an instance of wandb.Image or
|
414
|
+
This can be one of the normal python classes, an internal W&B type,
|
415
|
+
or an example object, like an instance of wandb.Image or
|
416
|
+
wandb.Classes.
|
415
417
|
|
416
418
|
Args:
|
417
|
-
col_name
|
418
|
-
dtype
|
419
|
-
|
419
|
+
col_name (str): The name of the column to cast.
|
420
|
+
dtype (class, wandb.wandb_sdk.interface._dtypes.Type, any): The
|
421
|
+
target dtype.
|
422
|
+
optional (bool): If the column should allow Nones.
|
420
423
|
"""
|
421
424
|
assert col_name in self.columns
|
422
425
|
|
@@ -499,14 +502,17 @@ class Table(Media):
|
|
499
502
|
|
500
503
|
@allow_relogging_after_mutation
|
501
504
|
def add_row(self, *row):
|
502
|
-
"""Deprecated
|
505
|
+
"""Deprecated. Use `Table.add_data` method instead."""
|
503
506
|
logging.warning("add_row is deprecated, use add_data")
|
504
507
|
self.add_data(*row)
|
505
508
|
|
506
509
|
@allow_relogging_after_mutation
|
507
510
|
@allow_incremental_logging_after_append
|
508
511
|
def add_data(self, *data):
|
509
|
-
"""Adds a new row of data to the table.
|
512
|
+
"""Adds a new row of data to the table.
|
513
|
+
|
514
|
+
The maximum amount ofrows in a table is determined by
|
515
|
+
`wandb.Table.MAX_ARTIFACT_ROWS`.
|
510
516
|
|
511
517
|
The length of the data should match the length of the table column.
|
512
518
|
"""
|
@@ -589,6 +595,10 @@ class Table(Media):
|
|
589
595
|
return {"columns": self.columns, "data": self.data[:max_rows]}
|
590
596
|
|
591
597
|
def bind_to_run(self, *args, **kwargs):
|
598
|
+
"""Bind this object to a run.
|
599
|
+
|
600
|
+
<!-- lazydoc-ignore: internal -->
|
601
|
+
"""
|
592
602
|
# We set `warn=False` since Tables will now always be logged to both
|
593
603
|
# files and artifacts. The file limit will never practically matter and
|
594
604
|
# this code path will be ultimately removed. The 10k limit warning confuses
|
@@ -603,10 +613,18 @@ class Table(Media):
|
|
603
613
|
|
604
614
|
@classmethod
|
605
615
|
def get_media_subdir(cls):
|
616
|
+
"""Get media subdirectory.
|
617
|
+
|
618
|
+
<!-- lazydoc-ignore-classmethod: internal -->
|
619
|
+
"""
|
606
620
|
return os.path.join("media", "table")
|
607
621
|
|
608
622
|
@classmethod
|
609
623
|
def from_json(cls, json_obj, source_artifact: "artifact.Artifact"):
|
624
|
+
"""Deserialize JSON object into it's class representation.
|
625
|
+
|
626
|
+
<!-- lazydoc-ignore-classmethod: internal -->
|
627
|
+
"""
|
610
628
|
data = []
|
611
629
|
column_types = None
|
612
630
|
np_deserialized_columns = {}
|
@@ -690,6 +708,10 @@ class Table(Media):
|
|
690
708
|
return new_obj
|
691
709
|
|
692
710
|
def to_json(self, run_or_artifact):
|
711
|
+
"""Returns the JSON representation expected by the backend.
|
712
|
+
|
713
|
+
<!-- lazydoc-ignore: internal -->
|
714
|
+
"""
|
693
715
|
json_dict = super().to_json(run_or_artifact)
|
694
716
|
|
695
717
|
if self.log_mode == "INCREMENTAL":
|
@@ -705,7 +727,7 @@ class Table(Media):
|
|
705
727
|
}
|
706
728
|
)
|
707
729
|
|
708
|
-
if isinstance(run_or_artifact, wandb.
|
730
|
+
if isinstance(run_or_artifact, wandb.Run):
|
709
731
|
if self.log_mode == "INCREMENTAL":
|
710
732
|
wbvalue_type = "incremental-table-file"
|
711
733
|
else:
|
@@ -799,11 +821,11 @@ class Table(Media):
|
|
799
821
|
|
800
822
|
Yields:
|
801
823
|
------
|
802
|
-
index
|
803
|
-
The index of the row. Using this value in other W&B tables
|
824
|
+
index: The index of the row. Using this value in other W&B tables
|
804
825
|
will automatically build a relationship between the tables
|
805
|
-
row
|
806
|
-
|
826
|
+
row: The data of the row.
|
827
|
+
|
828
|
+
<!-- lazydoc-ignore: internal -->
|
807
829
|
"""
|
808
830
|
for ndx in range(len(self.data)):
|
809
831
|
index = _TableIndex(ndx)
|
@@ -812,12 +834,20 @@ class Table(Media):
|
|
812
834
|
|
813
835
|
@allow_relogging_after_mutation
|
814
836
|
def set_pk(self, col_name):
|
837
|
+
"""Set primary key type for Table object.
|
838
|
+
|
839
|
+
<!-- lazydoc-ignore: internal -->
|
840
|
+
"""
|
815
841
|
# TODO: Docs
|
816
842
|
assert col_name in self.columns
|
817
843
|
self.cast(col_name, _PrimaryKeyType())
|
818
844
|
|
819
845
|
@allow_relogging_after_mutation
|
820
846
|
def set_fk(self, col_name, table, table_col):
|
847
|
+
"""Set foreign key type for Table object.
|
848
|
+
|
849
|
+
<!-- lazydoc-ignore: internal -->
|
850
|
+
"""
|
821
851
|
# TODO: Docs
|
822
852
|
assert col_name in self.columns
|
823
853
|
assert col_name != self._pk_col
|
@@ -1003,7 +1033,10 @@ class Table(Media):
|
|
1003
1033
|
return pd.DataFrame.from_records(self.data, columns=self.columns)
|
1004
1034
|
|
1005
1035
|
def index_ref(self, index):
|
1006
|
-
"""Gets a reference of the index of a row in the table.
|
1036
|
+
"""Gets a reference of the index of a row in the table.
|
1037
|
+
|
1038
|
+
<!-- lazydoc-ignore: internal -->
|
1039
|
+
"""
|
1007
1040
|
assert index < len(self.data)
|
1008
1041
|
_index = _TableIndex(index)
|
1009
1042
|
_index.set_table(self)
|
@@ -1015,14 +1048,12 @@ class Table(Media):
|
|
1015
1048
|
"""Adds one or more computed columns based on existing data.
|
1016
1049
|
|
1017
1050
|
Args:
|
1018
|
-
fn: A function which accepts one or two parameters, ndx (int) and
|
1019
|
-
which is expected to return a dict representing
|
1020
|
-
by the new column names.
|
1021
|
-
|
1022
|
-
`ndx` is an integer representing the index of the row. Only included if `include_ndx`
|
1051
|
+
fn: A function which accepts one or two parameters, ndx (int) and
|
1052
|
+
row (dict), which is expected to return a dict representing
|
1053
|
+
new columns for that row, keyed by the new column names.
|
1054
|
+
- `ndx` is an integer representing the index of the row. Only included if `include_ndx`
|
1023
1055
|
is set to `True`.
|
1024
|
-
|
1025
|
-
`row` is a dictionary keyed by existing columns
|
1056
|
+
- `row` is a dictionary keyed by existing columns
|
1026
1057
|
"""
|
1027
1058
|
new_columns = {}
|
1028
1059
|
for ndx, row in self.iterrows():
|
@@ -1056,7 +1087,8 @@ class _PartitionTablePartEntry:
|
|
1056
1087
|
class PartitionedTable(Media):
|
1057
1088
|
"""A table which is composed of multiple sub-tables.
|
1058
1089
|
|
1059
|
-
Currently, PartitionedTable is designed to point to a directory within an
|
1090
|
+
Currently, PartitionedTable is designed to point to a directory within an
|
1091
|
+
artifact.
|
1060
1092
|
"""
|
1061
1093
|
|
1062
1094
|
_log_type = "partitioned-table"
|
@@ -1075,7 +1107,7 @@ class PartitionedTable(Media):
|
|
1075
1107
|
json_obj = {
|
1076
1108
|
"_type": PartitionedTable._log_type,
|
1077
1109
|
}
|
1078
|
-
if isinstance(artifact_or_run, wandb.
|
1110
|
+
if isinstance(artifact_or_run, wandb.Run):
|
1079
1111
|
artifact_entry_url = self._get_artifact_entry_ref_url()
|
1080
1112
|
if artifact_entry_url is None:
|
1081
1113
|
raise ValueError(
|
@@ -1099,12 +1131,9 @@ class PartitionedTable(Media):
|
|
1099
1131
|
def iterrows(self):
|
1100
1132
|
"""Iterate over rows as (ndx, row).
|
1101
1133
|
|
1102
|
-
|
1103
|
-
|
1104
|
-
|
1105
|
-
The index of the row.
|
1106
|
-
row : List[any]
|
1107
|
-
The data of the row.
|
1134
|
+
Args:
|
1135
|
+
index (int): The index of the row.
|
1136
|
+
row (List[any]): The data of the row.
|
1108
1137
|
"""
|
1109
1138
|
columns = None
|
1110
1139
|
ndx = 0
|
@@ -1233,7 +1262,7 @@ class JoinedTable(Media):
|
|
1233
1262
|
json_obj = {
|
1234
1263
|
"_type": JoinedTable._log_type,
|
1235
1264
|
}
|
1236
|
-
if isinstance(artifact_or_run, wandb.
|
1265
|
+
if isinstance(artifact_or_run, wandb.Run):
|
1237
1266
|
artifact_entry_url = self._get_artifact_entry_ref_url()
|
1238
1267
|
if artifact_entry_url is None:
|
1239
1268
|
raise ValueError(
|
wandb/sdk/data_types/video.py
CHANGED
@@ -6,7 +6,8 @@ from io import BytesIO
|
|
6
6
|
from typing import TYPE_CHECKING, Any, Literal, Optional, Sequence, Type, Union
|
7
7
|
|
8
8
|
import wandb
|
9
|
-
from wandb import util
|
9
|
+
from wandb import env, util
|
10
|
+
from wandb.sdk import wandb_setup
|
10
11
|
from wandb.sdk.lib import filesystem, printer, printer_asyncio, runid
|
11
12
|
|
12
13
|
from . import _dtypes
|
@@ -23,6 +24,14 @@ if TYPE_CHECKING: # pragma: no cover
|
|
23
24
|
from ..wandb_run import Run as LocalRun
|
24
25
|
|
25
26
|
|
27
|
+
def _should_print_spinner() -> bool:
|
28
|
+
singleton = wandb_setup.singleton_if_setup()
|
29
|
+
if singleton and (singleton.settings.quiet or singleton.settings.silent):
|
30
|
+
return False
|
31
|
+
|
32
|
+
return not env.is_quiet() and not env.is_silent()
|
33
|
+
|
34
|
+
|
26
35
|
# This helper function is a workaround for the issue discussed here:
|
27
36
|
# https://github.com/wandb/wandb/issues/3472
|
28
37
|
#
|
@@ -80,40 +89,38 @@ class Video(BatchableMedia):
|
|
80
89
|
"""Initialize a W&B Video object.
|
81
90
|
|
82
91
|
Args:
|
83
|
-
data_or_path:
|
84
|
-
Video can be initialized with a
|
85
|
-
|
86
|
-
The numpy tensor must be either 4 dimensional or 5 dimensional.
|
92
|
+
data_or_path: Video can be initialized with a path to a file or an io object.
|
93
|
+
Video can be initialized with a numpy tensor. The numpy tensor
|
94
|
+
must be either 4 dimensional or 5 dimensional.
|
87
95
|
The dimensions should be (number of frames, channel, height, width) or
|
88
96
|
(batch, number of frames, channel, height, width)
|
89
97
|
The format parameter must be specified with the format argument
|
90
98
|
when initializing with a numpy array
|
91
99
|
or io object.
|
92
100
|
caption: Caption associated with the video for display.
|
93
|
-
fps:
|
94
|
-
The frame rate to use when encoding raw video frames.
|
101
|
+
fps: The frame rate to use when encoding raw video frames.
|
95
102
|
Default value is 4.
|
96
103
|
This parameter has no effect when data_or_path is a string, or bytes.
|
97
|
-
format:
|
98
|
-
Format of video, necessary if initializing with a numpy array
|
104
|
+
format: Format of video, necessary if initializing with a numpy array
|
99
105
|
or io object. This parameter will be used to determine the format
|
100
106
|
to use when encoding the video data. Accepted values are "gif",
|
101
107
|
"mp4", "webm", or "ogg".
|
102
108
|
If no value is provided, the default format will be "gif".
|
103
109
|
|
104
110
|
Examples:
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
)
|
115
|
-
|
116
|
-
|
111
|
+
Log a numpy array as a video
|
112
|
+
|
113
|
+
```python
|
114
|
+
import numpy as np
|
115
|
+
import wandb
|
116
|
+
|
117
|
+
with wandb.init() as run:
|
118
|
+
# axes are (number of frames, channel, height, width)
|
119
|
+
frames = np.random.randint(
|
120
|
+
low=0, high=256, size=(10, 3, 100, 100), dtype=np.uint8
|
121
|
+
)
|
122
|
+
run.log({"video": wandb.Video(frames, format="mp4", fps=4)})
|
123
|
+
```
|
117
124
|
"""
|
118
125
|
super().__init__(caption=caption)
|
119
126
|
|
@@ -167,13 +174,21 @@ class Video(BatchableMedia):
|
|
167
174
|
"wandb.Video accepts a file path or numpy like data as input"
|
168
175
|
)
|
169
176
|
fps = fps or 4
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
177
|
+
|
178
|
+
if _should_print_spinner():
|
179
|
+
printer_asyncio.run_async_with_spinner(
|
180
|
+
printer.new_printer(),
|
181
|
+
"Encoding video...",
|
182
|
+
functools.partial(self.encode, fps=fps),
|
183
|
+
)
|
184
|
+
else:
|
185
|
+
self.encode(fps=fps)
|
175
186
|
|
176
187
|
def encode(self, fps: int = 4) -> None:
|
188
|
+
"""Encode the video data to a file.
|
189
|
+
|
190
|
+
<!-- lazydoc-ignore: internal -->
|
191
|
+
"""
|
177
192
|
# import ImageSequenceClip from the appropriate MoviePy module
|
178
193
|
mpy = util.get_module(
|
179
194
|
"moviepy.video.io.ImageSequenceClip",
|
@@ -199,9 +214,17 @@ class Video(BatchableMedia):
|
|
199
214
|
|
200
215
|
@classmethod
|
201
216
|
def get_media_subdir(cls: Type["Video"]) -> str:
|
217
|
+
"""Get media subdirectory for video files.
|
218
|
+
|
219
|
+
<!-- lazydoc-ignore-classmethod: internal -->
|
220
|
+
"""
|
202
221
|
return os.path.join("media", "videos")
|
203
222
|
|
204
223
|
def to_json(self, run_or_artifact: Union["LocalRun", "Artifact"]) -> dict:
|
224
|
+
"""Returns the JSON representation expected by the backend.
|
225
|
+
|
226
|
+
<!-- lazydoc-ignore: internal -->
|
227
|
+
"""
|
205
228
|
json_dict = super().to_json(run_or_artifact)
|
206
229
|
json_dict["_type"] = self._log_type
|
207
230
|
|
@@ -256,6 +279,10 @@ class Video(BatchableMedia):
|
|
256
279
|
key: str,
|
257
280
|
step: Union[int, str],
|
258
281
|
) -> dict:
|
282
|
+
"""Convert a sequence of Video objects to a JSON representation.
|
283
|
+
|
284
|
+
<!-- lazydoc-ignore-classmethod: internal -->
|
285
|
+
"""
|
259
286
|
base_path = os.path.join(run.dir, cls.get_media_subdir())
|
260
287
|
filesystem.mkdir_exists_ok(base_path)
|
261
288
|
|
@@ -71,7 +71,7 @@ class PatchAPI:
|
|
71
71
|
)
|
72
72
|
return self._api
|
73
73
|
|
74
|
-
def patch(self, run: "wandb.
|
74
|
+
def patch(self, run: "wandb.Run") -> None:
|
75
75
|
"""Patches the API to log media or metrics to W&B."""
|
76
76
|
for symbol in self.symbols:
|
77
77
|
# split on dots, e.g. "Client.generate" -> ["Client", "generate"]
|
@@ -163,7 +163,7 @@ class AutologAPI:
|
|
163
163
|
resolver=resolver,
|
164
164
|
)
|
165
165
|
self._name = self._patch_api.name
|
166
|
-
self._run: Optional[wandb.
|
166
|
+
self._run: Optional[wandb.Run] = None
|
167
167
|
self.__run_created_by_autolog: bool = False
|
168
168
|
|
169
169
|
@property
|
@@ -284,6 +284,7 @@ class Api:
|
|
284
284
|
self._extra_http_headers.update(_thread_local_api_settings.headers or {})
|
285
285
|
|
286
286
|
auth = None
|
287
|
+
api_key = api_key or self.default_settings.get("api_key")
|
287
288
|
if api_key:
|
288
289
|
auth = ("api", api_key)
|
289
290
|
elif self.access_token is not None:
|
@@ -3234,6 +3235,7 @@ class Api:
|
|
3234
3235
|
entity: Optional[str] = None,
|
3235
3236
|
state: Optional[str] = None,
|
3236
3237
|
prior_runs: Optional[List[str]] = None,
|
3238
|
+
display_name: Optional[str] = None,
|
3237
3239
|
template_variable_values: Optional[Dict[str, Any]] = None,
|
3238
3240
|
) -> Tuple[str, List[str]]:
|
3239
3241
|
"""Upsert a sweep object.
|
@@ -3248,6 +3250,7 @@ class Api:
|
|
3248
3250
|
entity (str): entity to use
|
3249
3251
|
state (str): state
|
3250
3252
|
prior_runs (list): IDs of existing runs to add to the sweep
|
3253
|
+
display_name (str): display name for the sweep
|
3251
3254
|
template_variable_values (dict): template variable values
|
3252
3255
|
"""
|
3253
3256
|
project_query = """
|
@@ -3271,6 +3274,7 @@ class Api:
|
|
3271
3274
|
$scheduler: JSONString,
|
3272
3275
|
$state: String,
|
3273
3276
|
$priorRunsFilters: JSONString,
|
3277
|
+
$displayName: String,
|
3274
3278
|
) {
|
3275
3279
|
upsertSweep(input: {
|
3276
3280
|
id: $id,
|
@@ -3282,6 +3286,7 @@ class Api:
|
|
3282
3286
|
scheduler: $scheduler,
|
3283
3287
|
state: $state,
|
3284
3288
|
priorRunsFilters: $priorRunsFilters,
|
3289
|
+
displayName: $displayName,
|
3285
3290
|
}) {
|
3286
3291
|
sweep {
|
3287
3292
|
name
|
@@ -3358,6 +3363,7 @@ class Api:
|
|
3358
3363
|
"templateVariableValues": json.dumps(template_variable_values),
|
3359
3364
|
"scheduler": scheduler,
|
3360
3365
|
"priorRunsFilters": filters,
|
3366
|
+
"displayName": display_name,
|
3361
3367
|
}
|
3362
3368
|
if state:
|
3363
3369
|
variables["state"] = state
|
@@ -109,6 +109,7 @@ class JobSourceDict(TypedDict, total=False):
|
|
109
109
|
input_types: Dict[str, Any]
|
110
110
|
output_types: Dict[str, Any]
|
111
111
|
runtime: Optional[str]
|
112
|
+
services: Dict[str, str]
|
112
113
|
|
113
114
|
|
114
115
|
class ArtifactInfoForJob(TypedDict):
|
@@ -143,6 +144,7 @@ class JobBuilder:
|
|
143
144
|
_job_version_alias: Optional[str]
|
144
145
|
_is_notebook_run: bool
|
145
146
|
_verbose: bool
|
147
|
+
_services: Dict[str, str]
|
146
148
|
|
147
149
|
def __init__(self, settings: SettingsStatic, verbose: bool = False):
|
148
150
|
self._settings = settings
|
@@ -162,6 +164,7 @@ class JobBuilder:
|
|
162
164
|
self._is_notebook_run = self._get_is_notebook_run()
|
163
165
|
self._verbose = verbose
|
164
166
|
self._partial = False
|
167
|
+
self._services = {}
|
165
168
|
|
166
169
|
def set_config(self, config: Dict[str, Any]) -> None:
|
167
170
|
self._config = config
|
@@ -544,6 +547,9 @@ class JobBuilder:
|
|
544
547
|
"runtime": runtime,
|
545
548
|
}
|
546
549
|
|
550
|
+
if self._services:
|
551
|
+
source_info["services"] = self._services
|
552
|
+
|
547
553
|
assert source_info is not None
|
548
554
|
assert name is not None
|
549
555
|
|
wandb/sdk/launch/agent/agent.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
"""Implementation of launch agent."""
|
2
2
|
|
3
3
|
import asyncio
|
4
|
+
import copy
|
4
5
|
import logging
|
5
6
|
import os
|
6
7
|
import pprint
|
@@ -421,6 +422,7 @@ class LaunchAgent:
|
|
421
422
|
"""Removes the job from our list for now."""
|
422
423
|
with self._jobs_lock:
|
423
424
|
job_and_run_status = self._jobs[thread_id]
|
425
|
+
|
424
426
|
if (
|
425
427
|
job_and_run_status.entity is not None
|
426
428
|
and job_and_run_status.entity != self._entity
|
@@ -516,7 +518,11 @@ class LaunchAgent:
|
|
516
518
|
Arguments:
|
517
519
|
job: Job to run.
|
518
520
|
"""
|
519
|
-
|
521
|
+
job_copy = copy.deepcopy(job)
|
522
|
+
if "runSpec" in job_copy and "_wandb_api_key" in job_copy["runSpec"]:
|
523
|
+
job_copy["runSpec"]["_wandb_api_key"] = "<redacted>"
|
524
|
+
|
525
|
+
_msg = f"{LOG_PREFIX}Launch agent received job:\n{pprint.pformat(job_copy)}\n"
|
520
526
|
wandb.termlog(_msg)
|
521
527
|
_logger.info(_msg)
|
522
528
|
# update agent status
|
@@ -727,6 +733,7 @@ class LaunchAgent:
|
|
727
733
|
backend = loader.runner_from_config(
|
728
734
|
resource, api, backend_config, environment, registry
|
729
735
|
)
|
736
|
+
|
730
737
|
if not (
|
731
738
|
project.docker_image
|
732
739
|
or project.job_base_image
|
@@ -11,7 +11,7 @@ FileSubtypes = Literal["warning", "error"]
|
|
11
11
|
class RunQueueItemFileSaver:
|
12
12
|
def __init__(
|
13
13
|
self,
|
14
|
-
agent_run: Optional["wandb.
|
14
|
+
agent_run: Optional["wandb.Run"],
|
15
15
|
run_queue_item_id: str,
|
16
16
|
):
|
17
17
|
self.run_queue_item_id = run_queue_item_id
|
@@ -20,7 +20,7 @@ class RunQueueItemFileSaver:
|
|
20
20
|
def save_contents(
|
21
21
|
self, contents: str, fname: str, file_sub_type: FileSubtypes
|
22
22
|
) -> Optional[List[str]]:
|
23
|
-
if not isinstance(self.run, wandb.
|
23
|
+
if not isinstance(self.run, wandb.Run):
|
24
24
|
wandb.termwarn("Not saving file contents because agent has no run")
|
25
25
|
return None
|
26
26
|
root_dir = self.run._settings.files_dir
|
wandb/sdk/launch/create_job.py
CHANGED
@@ -115,6 +115,7 @@ def _create_job(
|
|
115
115
|
build_context: Optional[str] = None,
|
116
116
|
dockerfile: Optional[str] = None,
|
117
117
|
base_image: Optional[str] = None,
|
118
|
+
services: Optional[Dict[str, str]] = None,
|
118
119
|
) -> Tuple[Optional[Artifact], str, List[str]]:
|
119
120
|
wandb.termlog(f"Creating launch job of type: {job_type}...")
|
120
121
|
|
@@ -169,6 +170,7 @@ def _create_job(
|
|
169
170
|
|
170
171
|
job_builder = _configure_job_builder_for_partial(tempdir.name, job_source=job_type)
|
171
172
|
job_builder._settings.job_name = name
|
173
|
+
job_builder._services = services or {}
|
172
174
|
if job_type == "code":
|
173
175
|
assert entrypoint is not None
|
174
176
|
job_name = _make_code_artifact(
|
@@ -421,7 +423,7 @@ def _configure_job_builder_for_partial(tmpdir: str, job_source: str) -> JobBuild
|
|
421
423
|
def _make_code_artifact(
|
422
424
|
api: Api,
|
423
425
|
job_builder: JobBuilder,
|
424
|
-
run: "wandb.
|
426
|
+
run: "wandb.Run",
|
425
427
|
path: str,
|
426
428
|
entrypoint: str,
|
427
429
|
entity: Optional[str],
|
@@ -17,7 +17,6 @@ import wandb
|
|
17
17
|
import wandb.data_types
|
18
18
|
from wandb.sdk.launch.errors import LaunchError
|
19
19
|
from wandb.sdk.launch.inputs.schema import META_SCHEMA
|
20
|
-
from wandb.sdk.wandb_run import Run
|
21
20
|
from wandb.util import get_module
|
22
21
|
|
23
22
|
from .files import config_path_is_valid, override_file
|
@@ -93,7 +92,7 @@ class StagedLaunchInputs:
|
|
93
92
|
):
|
94
93
|
self._staged_inputs.append(input_arguments)
|
95
94
|
|
96
|
-
def apply(self, run: Run):
|
95
|
+
def apply(self, run: wandb.Run):
|
97
96
|
"""Apply the staged inputs to the given run."""
|
98
97
|
for input in self._staged_inputs:
|
99
98
|
_publish_job_input(input, run)
|
@@ -101,13 +100,13 @@ class StagedLaunchInputs:
|
|
101
100
|
|
102
101
|
def _publish_job_input(
|
103
102
|
input: JobInputArguments,
|
104
|
-
run: Run,
|
103
|
+
run: wandb.Run,
|
105
104
|
) -> None:
|
106
105
|
"""Publish a job input to the backend interface of the given run.
|
107
106
|
|
108
107
|
Arguments:
|
109
108
|
input (JobInputArguments): The arguments for the job input.
|
110
|
-
run (Run): The run to publish the job input to.
|
109
|
+
run (wandb.Run): The run to publish the job input to.
|
111
110
|
"""
|
112
111
|
assert run._backend is not None
|
113
112
|
assert run._backend.interface is not None
|
@@ -7,6 +7,7 @@ META_SCHEMA = {
|
|
7
7
|
},
|
8
8
|
"title": {"type": "string"},
|
9
9
|
"description": {"type": "string"},
|
10
|
+
"format": {"type": "string"},
|
10
11
|
"enum": {"type": "array", "items": {"type": ["integer", "number", "string"]}},
|
11
12
|
"properties": {"type": "object", "patternProperties": {".*": {"$ref": "#"}}},
|
12
13
|
"allOf": {"type": "array", "items": {"$ref": "#"}},
|
@@ -27,6 +27,7 @@ WANDB_K8S_LABEL_NAMESPACE = "wandb.ai"
|
|
27
27
|
WANDB_K8S_RUN_ID = f"{WANDB_K8S_LABEL_NAMESPACE}/run-id"
|
28
28
|
WANDB_K8S_LABEL_AGENT = f"{WANDB_K8S_LABEL_NAMESPACE}/agent"
|
29
29
|
WANDB_K8S_LABEL_MONITOR = f"{WANDB_K8S_LABEL_NAMESPACE}/monitor"
|
30
|
+
WANDB_K8S_LABEL_AUXILIARY_RESOURCE = f"{WANDB_K8S_LABEL_NAMESPACE}/auxiliary-resource"
|
30
31
|
|
31
32
|
|
32
33
|
class Resources:
|