wandb 0.17.6__py3-none-macosx_11_0_arm64.whl → 0.17.7__py3-none-macosx_11_0_arm64.whl
Sign up to get free protection for your applications and to get access to all the features.
- wandb/__init__.py +3 -16
- wandb/agents/pyagent.py +1 -2
- wandb/bin/apple_gpu_stats +0 -0
- wandb/bin/wandb-core +0 -0
- wandb/cli/cli.py +21 -0
- wandb/data_types.py +3 -3
- wandb/integration/kfp/wandb_logging.py +1 -1
- wandb/integration/lightning/fabric/logger.py +1 -1
- wandb/integration/openai/fine_tuning.py +13 -5
- wandb/integration/ultralytics/pose_utils.py +0 -1
- wandb/sdk/artifacts/artifact.py +1 -1
- wandb/sdk/data_types/_dtypes.py +5 -5
- wandb/sdk/data_types/base_types/media.py +3 -1
- wandb/sdk/data_types/helper_types/bounding_boxes_2d.py +3 -1
- wandb/sdk/data_types/helper_types/image_mask.py +3 -1
- wandb/sdk/data_types/image.py +3 -1
- wandb/sdk/data_types/saved_model.py +3 -1
- wandb/sdk/interface/interface.py +17 -16
- wandb/sdk/interface/interface_shared.py +6 -9
- wandb/sdk/internal/datastore.py +1 -1
- wandb/sdk/internal/handler.py +0 -2
- wandb/sdk/internal/internal.py +1 -1
- wandb/sdk/internal/job_builder.py +5 -2
- wandb/sdk/internal/tb_watcher.py +2 -2
- wandb/sdk/internal/update.py +2 -2
- wandb/sdk/launch/builder/kaniko_builder.py +13 -5
- wandb/sdk/launch/create_job.py +2 -0
- wandb/sdk/lib/apikey.py +1 -1
- wandb/sdk/service/streams.py +2 -4
- wandb/sdk/wandb_config.py +1 -1
- wandb/sdk/wandb_init.py +55 -7
- wandb/sdk/wandb_run.py +109 -68
- wandb/sdk/wandb_settings.py +1 -1
- wandb/sdk/wandb_setup.py +66 -3
- wandb/sdk/wandb_sweep.py +5 -2
- {wandb-0.17.6.dist-info → wandb-0.17.7.dist-info}/METADATA +1 -1
- {wandb-0.17.6.dist-info → wandb-0.17.7.dist-info}/RECORD +40 -40
- {wandb-0.17.6.dist-info → wandb-0.17.7.dist-info}/WHEEL +0 -0
- {wandb-0.17.6.dist-info → wandb-0.17.7.dist-info}/entry_points.txt +0 -0
- {wandb-0.17.6.dist-info → wandb-0.17.7.dist-info}/licenses/LICENSE +0 -0
wandb/__init__.py
CHANGED
@@ -1,9 +1,6 @@
|
|
1
1
|
"""Use wandb to track machine learning work.
|
2
2
|
|
3
|
-
|
4
|
-
- wandb.init — initialize a new run at the top of your training script
|
5
|
-
- wandb.config — track hyperparameters and metadata
|
6
|
-
- wandb.log — log metrics and media over time within your training loop
|
3
|
+
Train and fine-tune models, manage models from experimentation to production.
|
7
4
|
|
8
5
|
For guides and examples, see https://docs.wandb.ai.
|
9
6
|
|
@@ -11,11 +8,7 @@ For scripts and interactive notebooks, see https://github.com/wandb/examples.
|
|
11
8
|
|
12
9
|
For reference documentation, see https://docs.wandb.com/ref/python.
|
13
10
|
"""
|
14
|
-
__version__ = "0.17.
|
15
|
-
|
16
|
-
|
17
|
-
# Used with pypi checks and other messages related to pip
|
18
|
-
_wandb_module = "wandb"
|
11
|
+
__version__ = "0.17.7"
|
19
12
|
|
20
13
|
from typing import Optional
|
21
14
|
|
@@ -118,13 +111,6 @@ def _assert_is_user_process():
|
|
118
111
|
assert not _IS_INTERNAL_PROCESS
|
119
112
|
|
120
113
|
|
121
|
-
# toplevel:
|
122
|
-
# save()
|
123
|
-
# restore()
|
124
|
-
# login()
|
125
|
-
# sweep()
|
126
|
-
# agent()
|
127
|
-
|
128
114
|
# globals
|
129
115
|
Api = PublicApi
|
130
116
|
api = InternalApi()
|
@@ -254,4 +240,5 @@ __all__ = (
|
|
254
240
|
"log_model",
|
255
241
|
"use_model",
|
256
242
|
"link_model",
|
243
|
+
"define_metric",
|
257
244
|
)
|
wandb/agents/pyagent.py
CHANGED
@@ -14,7 +14,6 @@ import time
|
|
14
14
|
import traceback
|
15
15
|
|
16
16
|
import wandb
|
17
|
-
from wandb import wandb_sdk
|
18
17
|
from wandb.apis import InternalApi
|
19
18
|
from wandb.sdk.launch.sweeps import utils as sweep_utils
|
20
19
|
|
@@ -298,7 +297,7 @@ class Agent:
|
|
298
297
|
sweep_param_path, job.config
|
299
298
|
)
|
300
299
|
os.environ[wandb.env.SWEEP_ID] = self._sweep_id
|
301
|
-
|
300
|
+
wandb.sdk.wandb_setup._setup(_reset=True)
|
302
301
|
|
303
302
|
wandb.termlog(f"Agent Starting Run: {run_id} with config:")
|
304
303
|
for k, v in job.config.items():
|
wandb/bin/apple_gpu_stats
CHANGED
Binary file
|
wandb/bin/wandb-core
CHANGED
Binary file
|
wandb/cli/cli.py
CHANGED
@@ -1417,6 +1417,13 @@ def launch_sweep(
|
|
1417
1417
|
help="""Specific docker image you'd like to use. In the form name:tag.
|
1418
1418
|
If passed in, will override the docker image value passed in using a config file.""",
|
1419
1419
|
)
|
1420
|
+
@click.option(
|
1421
|
+
"--base-image",
|
1422
|
+
"-B",
|
1423
|
+
default=None,
|
1424
|
+
metavar="BASE IMAGE",
|
1425
|
+
help="""Docker image to run job code in. Incompatible with --docker-image.""",
|
1426
|
+
)
|
1420
1427
|
@click.option(
|
1421
1428
|
"--config",
|
1422
1429
|
"-c",
|
@@ -1508,6 +1515,7 @@ def launch(
|
|
1508
1515
|
entity,
|
1509
1516
|
project,
|
1510
1517
|
docker_image,
|
1518
|
+
base_image,
|
1511
1519
|
config,
|
1512
1520
|
cli_template_vars,
|
1513
1521
|
queue,
|
@@ -1604,6 +1612,7 @@ def launch(
|
|
1604
1612
|
git_hash=git_version,
|
1605
1613
|
name=job_name,
|
1606
1614
|
project=project,
|
1615
|
+
base_image=base_image,
|
1607
1616
|
build_context=build_context,
|
1608
1617
|
dockerfile=dockerfile,
|
1609
1618
|
entity=entity,
|
@@ -2001,6 +2010,12 @@ def describe(job):
|
|
2001
2010
|
help="Path to the build context from the root of the job source code. If "
|
2002
2011
|
"provided, this is used as the base path for the Dockerfile and entrypoint.",
|
2003
2012
|
)
|
2013
|
+
@click.option(
|
2014
|
+
"--base-image",
|
2015
|
+
"-B",
|
2016
|
+
type=str,
|
2017
|
+
help="Base image to use for the job. Incompatible with image jobs.",
|
2018
|
+
)
|
2004
2019
|
@click.option(
|
2005
2020
|
"--dockerfile",
|
2006
2021
|
"-D",
|
@@ -2025,6 +2040,7 @@ def create(
|
|
2025
2040
|
git_hash,
|
2026
2041
|
runtime,
|
2027
2042
|
build_context,
|
2043
|
+
base_image,
|
2028
2044
|
dockerfile,
|
2029
2045
|
):
|
2030
2046
|
"""Create a job from a source, without a wandb run.
|
@@ -2056,6 +2072,10 @@ def create(
|
|
2056
2072
|
)
|
2057
2073
|
entrypoint = "main.py"
|
2058
2074
|
|
2075
|
+
if job_type == "image" and base_image:
|
2076
|
+
wandb.termerror("Cannot provide --base-image/-B for an `image` job")
|
2077
|
+
return
|
2078
|
+
|
2059
2079
|
artifact, action, aliases = _create_job(
|
2060
2080
|
api=api,
|
2061
2081
|
path=path,
|
@@ -2069,6 +2089,7 @@ def create(
|
|
2069
2089
|
git_hash=git_hash,
|
2070
2090
|
runtime=runtime,
|
2071
2091
|
build_context=build_context,
|
2092
|
+
base_image=base_image,
|
2072
2093
|
dockerfile=dockerfile,
|
2073
2094
|
)
|
2074
2095
|
if not artifact:
|
wandb/data_types.py
CHANGED
@@ -104,7 +104,7 @@ class _TableIndex(int, _TableLinkMixin):
|
|
104
104
|
def _json_helper(val, artifact):
|
105
105
|
if isinstance(val, WBValue):
|
106
106
|
return val.to_json(artifact)
|
107
|
-
elif val.__class__
|
107
|
+
elif val.__class__ is dict:
|
108
108
|
res = {}
|
109
109
|
for key in val:
|
110
110
|
res[key] = _json_helper(val[key], artifact)
|
@@ -270,10 +270,10 @@ class Table(Media):
|
|
270
270
|
if dtype is None:
|
271
271
|
dtype = _dtypes.UnknownType()
|
272
272
|
|
273
|
-
if optional.__class__
|
273
|
+
if optional.__class__ is not list:
|
274
274
|
optional = [optional for _ in range(len(self.columns))]
|
275
275
|
|
276
|
-
if dtype.__class__
|
276
|
+
if dtype.__class__ is not list:
|
277
277
|
dtype = [dtype for _ in range(len(self.columns))]
|
278
278
|
|
279
279
|
self._column_types = _dtypes.TypedDictType({})
|
@@ -312,7 +312,7 @@ class WandbLogger(Logger):
|
|
312
312
|
self._prefix = prefix
|
313
313
|
self._experiment = experiment
|
314
314
|
self._logged_model_time: Dict[str, float] = {}
|
315
|
-
self._checkpoint_callback: Optional[
|
315
|
+
self._checkpoint_callback: Optional[ModelCheckpoint] = None
|
316
316
|
|
317
317
|
# paths are processed as strings
|
318
318
|
if save_dir is not None:
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import base64
|
1
2
|
import datetime
|
2
3
|
import io
|
3
4
|
import json
|
@@ -16,13 +17,13 @@ from wandb.util import parse_version
|
|
16
17
|
|
17
18
|
openai = util.get_module(
|
18
19
|
name="openai",
|
19
|
-
required="
|
20
|
-
lazy=
|
20
|
+
required="This integration requires `openai`. To install, please run `pip install openai`",
|
21
|
+
lazy=False,
|
21
22
|
)
|
22
23
|
|
23
|
-
if parse_version(openai.__version__) < parse_version("1.0
|
24
|
+
if parse_version(openai.__version__) < parse_version("1.12.0"):
|
24
25
|
raise wandb.Error(
|
25
|
-
f"This integration requires openai version 1.0
|
26
|
+
f"This integration requires openai version 1.12.0 and above. Your current version is {openai.__version__} "
|
26
27
|
"To fix, please `pip install -U openai`"
|
27
28
|
)
|
28
29
|
|
@@ -228,7 +229,14 @@ class WandbLogger:
|
|
228
229
|
# check results are present
|
229
230
|
try:
|
230
231
|
results_id = fine_tune.result_files[0]
|
231
|
-
|
232
|
+
try:
|
233
|
+
encoded_results = cls.openai_client.files.content(
|
234
|
+
file_id=results_id
|
235
|
+
).read()
|
236
|
+
results = base64.b64decode(encoded_results).decode("utf-8")
|
237
|
+
except Exception:
|
238
|
+
# attempt to read as text, works for older jobs
|
239
|
+
results = cls.openai_client.files.content(file_id=results_id).text
|
232
240
|
except openai.NotFoundError:
|
233
241
|
if show_individual_warnings:
|
234
242
|
wandb.termwarn(
|
@@ -23,7 +23,6 @@ def annotate_keypoint_results(result: Results, visualize_skeleton: bool):
|
|
23
23
|
|
24
24
|
|
25
25
|
def annotate_keypoint_batch(image_path: str, keypoints: Any, visualize_skeleton: bool):
|
26
|
-
original_image = None
|
27
26
|
with Image.open(image_path) as original_image:
|
28
27
|
original_image = np.ascontiguousarray(original_image)
|
29
28
|
annotator = Annotator(original_image)
|
wandb/sdk/artifacts/artifact.py
CHANGED
@@ -751,7 +751,7 @@ class Artifact:
|
|
751
751
|
def save(
|
752
752
|
self,
|
753
753
|
project: Optional[str] = None,
|
754
|
-
settings: Optional["wandb.
|
754
|
+
settings: Optional["wandb.sdk.wandb_settings.Settings"] = None,
|
755
755
|
) -> None:
|
756
756
|
"""Persist any changes made to the artifact.
|
757
757
|
|
wandb/sdk/data_types/_dtypes.py
CHANGED
@@ -56,7 +56,7 @@ class TypeRegistry:
|
|
56
56
|
# but will be ultimately treated as a None. Ignoring type since
|
57
57
|
# mypy does not trust that py_obj is a float by the time it is
|
58
58
|
# passed to isnan.
|
59
|
-
if py_obj.__class__
|
59
|
+
if py_obj.__class__ is float and math.isnan(py_obj): # type: ignore
|
60
60
|
return NoneType()
|
61
61
|
|
62
62
|
# TODO: generalize this to handle other config input types
|
@@ -134,7 +134,7 @@ def _params_obj_to_json_obj(
|
|
134
134
|
artifact: t.Optional["Artifact"] = None,
|
135
135
|
) -> t.Any:
|
136
136
|
"""Helper method."""
|
137
|
-
if params_obj.__class__
|
137
|
+
if params_obj.__class__ is dict:
|
138
138
|
return {
|
139
139
|
key: _params_obj_to_json_obj(params_obj[key], artifact)
|
140
140
|
for key in params_obj
|
@@ -151,7 +151,7 @@ def _json_obj_to_params_obj(
|
|
151
151
|
json_obj: t.Any, artifact: t.Optional["Artifact"] = None
|
152
152
|
) -> t.Any:
|
153
153
|
"""Helper method."""
|
154
|
-
if json_obj.__class__
|
154
|
+
if json_obj.__class__ is dict:
|
155
155
|
if "wb_type" in json_obj:
|
156
156
|
return TypeRegistry.type_from_dict(json_obj, artifact)
|
157
157
|
else:
|
@@ -159,7 +159,7 @@ def _json_obj_to_params_obj(
|
|
159
159
|
key: _json_obj_to_params_obj(json_obj[key], artifact)
|
160
160
|
for key in json_obj
|
161
161
|
}
|
162
|
-
elif json_obj.__class__
|
162
|
+
elif json_obj.__class__ is list:
|
163
163
|
return [_json_obj_to_params_obj(item, artifact) for item in json_obj]
|
164
164
|
else:
|
165
165
|
return json_obj
|
@@ -533,7 +533,7 @@ class UnionType(Type):
|
|
533
533
|
self,
|
534
534
|
allowed_types: t.Optional[t.Sequence[ConvertibleToType]] = None,
|
535
535
|
):
|
536
|
-
assert allowed_types is None or (allowed_types.__class__
|
536
|
+
assert allowed_types is None or (allowed_types.__class__ is list)
|
537
537
|
if allowed_types is None:
|
538
538
|
wb_types = []
|
539
539
|
else:
|
@@ -159,9 +159,11 @@ class Media(WBValue):
|
|
159
159
|
# into Media itself we should get rid of them
|
160
160
|
from wandb import Image
|
161
161
|
from wandb.data_types import Audio
|
162
|
+
from wandb.sdk.wandb_run import Run
|
162
163
|
|
163
164
|
json_obj = {}
|
164
|
-
|
165
|
+
|
166
|
+
if isinstance(run, Run):
|
165
167
|
json_obj.update(
|
166
168
|
{
|
167
169
|
"_type": "file", # TODO(adrian): This isn't (yet) a real media type we support on the frontend.
|
@@ -276,7 +276,9 @@ class BoundingBoxes2D(JSONMetadata):
|
|
276
276
|
return True
|
277
277
|
|
278
278
|
def to_json(self, run_or_artifact: Union["LocalRun", "Artifact"]) -> dict:
|
279
|
-
|
279
|
+
from wandb.sdk.wandb_run import Run
|
280
|
+
|
281
|
+
if isinstance(run_or_artifact, Run):
|
280
282
|
return super().to_json(run_or_artifact)
|
281
283
|
elif isinstance(run_or_artifact, wandb.Artifact):
|
282
284
|
# TODO (tim): I would like to log out a proper dictionary representing this object, but don't
|
@@ -191,9 +191,11 @@ class ImageMask(Media):
|
|
191
191
|
)
|
192
192
|
|
193
193
|
def to_json(self, run_or_artifact: Union["LocalRun", "Artifact"]) -> dict:
|
194
|
+
from wandb.sdk.wandb_run import Run
|
195
|
+
|
194
196
|
json_dict = super().to_json(run_or_artifact)
|
195
197
|
|
196
|
-
if isinstance(run_or_artifact,
|
198
|
+
if isinstance(run_or_artifact, Run):
|
197
199
|
json_dict["_type"] = self.type_name()
|
198
200
|
return json_dict
|
199
201
|
elif isinstance(run_or_artifact, wandb.Artifact):
|
wandb/sdk/data_types/image.py
CHANGED
@@ -418,6 +418,8 @@ class Image(BatchableMedia):
|
|
418
418
|
)
|
419
419
|
|
420
420
|
def to_json(self, run_or_artifact: Union["LocalRun", "Artifact"]) -> dict:
|
421
|
+
from wandb.sdk.wandb_run import Run
|
422
|
+
|
421
423
|
json_dict = super().to_json(run_or_artifact)
|
422
424
|
json_dict["_type"] = Image._log_type
|
423
425
|
json_dict["format"] = self.format
|
@@ -456,7 +458,7 @@ class Image(BatchableMedia):
|
|
456
458
|
"digest": classes_entry.digest,
|
457
459
|
}
|
458
460
|
|
459
|
-
elif not isinstance(run_or_artifact,
|
461
|
+
elif not isinstance(run_or_artifact, Run):
|
460
462
|
raise ValueError("to_json accepts wandb_run.Run or wandb_artifact.Artifact")
|
461
463
|
|
462
464
|
if self._boxes:
|
@@ -148,7 +148,9 @@ class _SavedModel(WBValue, Generic[SavedModelObjType]):
|
|
148
148
|
# bit of tech debt in the other data types which requires the input to `to_json`
|
149
149
|
# to accept a Run or Artifact. However, Run additions should be deprecated in the future.
|
150
150
|
# This check helps ensure we do not add to the debt.
|
151
|
-
|
151
|
+
from wandb.sdk.wandb_run import Run
|
152
|
+
|
153
|
+
if isinstance(run_or_artifact, Run):
|
152
154
|
raise ValueError("SavedModel cannot be added to run - must use artifact")
|
153
155
|
artifact = run_or_artifact
|
154
156
|
json_obj = {
|
wandb/sdk/interface/interface.py
CHANGED
@@ -54,18 +54,20 @@ MANIFEST_FILE_SIZE_THRESHOLD = 100_000
|
|
54
54
|
|
55
55
|
GlobStr = NewType("GlobStr", str)
|
56
56
|
|
57
|
-
if
|
58
|
-
from
|
57
|
+
if sys.version_info >= (3, 8):
|
58
|
+
from typing import Literal, TypedDict
|
59
|
+
else:
|
60
|
+
from typing_extensions import Literal, TypedDict
|
61
|
+
|
62
|
+
PolicyName = Literal["now", "live", "end"]
|
59
63
|
|
60
|
-
if sys.version_info >= (3, 8):
|
61
|
-
from typing import Literal, TypedDict
|
62
|
-
else:
|
63
|
-
from typing_extensions import Literal, TypedDict
|
64
64
|
|
65
|
-
|
65
|
+
class FilesDict(TypedDict):
|
66
|
+
files: Iterable[Tuple[GlobStr, PolicyName]]
|
66
67
|
|
67
|
-
|
68
|
-
|
68
|
+
|
69
|
+
if TYPE_CHECKING:
|
70
|
+
from ..wandb_run import Run
|
69
71
|
|
70
72
|
|
71
73
|
logger = logging.getLogger("wandb")
|
@@ -112,15 +114,14 @@ class InterfaceBase:
|
|
112
114
|
def _publish_header(self, header: pb.HeaderRecord) -> None:
|
113
115
|
raise NotImplementedError
|
114
116
|
|
115
|
-
def
|
116
|
-
|
117
|
-
resp = self._communicate_status(status)
|
118
|
-
return resp
|
117
|
+
def deliver_status(self) -> MailboxHandle:
|
118
|
+
return self._deliver_status(pb.StatusRequest())
|
119
119
|
|
120
120
|
@abstractmethod
|
121
|
-
def
|
122
|
-
self,
|
123
|
-
|
121
|
+
def _deliver_status(
|
122
|
+
self,
|
123
|
+
status: pb.StatusRequest,
|
124
|
+
) -> MailboxHandle:
|
124
125
|
raise NotImplementedError
|
125
126
|
|
126
127
|
def _make_config(
|
@@ -299,7 +299,7 @@ class InterfaceShared(InterfaceBase):
|
|
299
299
|
raise NotImplementedError
|
300
300
|
|
301
301
|
def _communicate(
|
302
|
-
self, rec: pb.Record, timeout: Optional[int] =
|
302
|
+
self, rec: pb.Record, timeout: Optional[int] = 30, local: Optional[bool] = None
|
303
303
|
) -> Optional[pb.Result]:
|
304
304
|
return self._communicate_async(rec, local=local).get(timeout=timeout)
|
305
305
|
|
@@ -421,15 +421,12 @@ class InterfaceShared(InterfaceBase):
|
|
421
421
|
rec = self._make_record(alert=proto_alert)
|
422
422
|
self._publish(rec)
|
423
423
|
|
424
|
-
def
|
425
|
-
self,
|
426
|
-
|
424
|
+
def _deliver_status(
|
425
|
+
self,
|
426
|
+
status: pb.StatusRequest,
|
427
|
+
) -> MailboxHandle:
|
427
428
|
req = self._make_request(status=status)
|
428
|
-
|
429
|
-
if resp is None:
|
430
|
-
return None
|
431
|
-
assert resp.response.status_response
|
432
|
-
return resp.response.status_response
|
429
|
+
return self._deliver_record(req)
|
433
430
|
|
434
431
|
def _publish_exit(self, exit_data: pb.RunExitRecord) -> None:
|
435
432
|
rec = self._make_record(exit=exit_data)
|
wandb/sdk/internal/datastore.py
CHANGED
wandb/sdk/internal/handler.py
CHANGED
@@ -745,8 +745,6 @@ class HandleManager:
|
|
745
745
|
self._respond_result(result)
|
746
746
|
|
747
747
|
def handle_request_status(self, record: Record) -> None:
|
748
|
-
# TODO(mempressure): do something better?
|
749
|
-
assert record.control.req_resp
|
750
748
|
result = proto_util._result_from_record(record)
|
751
749
|
self._respond_result(result)
|
752
750
|
|
wandb/sdk/internal/internal.py
CHANGED
@@ -423,15 +423,18 @@ class JobBuilder:
|
|
423
423
|
api: Api,
|
424
424
|
build_context: Optional[str] = None,
|
425
425
|
dockerfile: Optional[str] = None,
|
426
|
+
base_image: Optional[str] = None,
|
426
427
|
) -> Optional[Artifact]:
|
427
428
|
"""Build a job artifact from the current run.
|
428
429
|
|
429
430
|
Arguments:
|
431
|
+
api (Api): The API object to use to create the job artifact.
|
430
432
|
build_context (Optional[str]): Path within the job source code to
|
431
433
|
the image build context. Saved as part of the job for future
|
432
434
|
builds.
|
433
435
|
dockerfile (Optional[str]): Path within the build context the
|
434
436
|
Dockerfile. Saved as part of the job for future builds.
|
437
|
+
base_image (Optional[str]): The base image used to run the job code.
|
435
438
|
|
436
439
|
Returns:
|
437
440
|
Optional[Artifact]: The job artifact if it was successfully built,
|
@@ -467,8 +470,6 @@ class JobBuilder:
|
|
467
470
|
"warn",
|
468
471
|
)
|
469
472
|
return None
|
470
|
-
metadata["dockerfile"] = dockerfile
|
471
|
-
metadata["build_context"] = build_context
|
472
473
|
|
473
474
|
runtime: Optional[str] = metadata.get("python")
|
474
475
|
# can't build a job without a python version
|
@@ -520,6 +521,8 @@ class JobBuilder:
|
|
520
521
|
source["build_context"] = build_context # type: ignore[typeddict-item]
|
521
522
|
if dockerfile:
|
522
523
|
source["dockerfile"] = dockerfile # type: ignore[typeddict-item]
|
524
|
+
if base_image:
|
525
|
+
source["base_image"] = base_image # type: ignore[typeddict-item]
|
523
526
|
|
524
527
|
# Pop any keys that are initialized to None. The current TypedDict
|
525
528
|
# system for source dicts requires all keys to be present, but we
|
wandb/sdk/internal/tb_watcher.py
CHANGED
@@ -123,7 +123,7 @@ class TBWatcher:
|
|
123
123
|
self._force = force
|
124
124
|
# TODO(jhr): do we need locking in this queue?
|
125
125
|
self._watcher_queue = queue.PriorityQueue()
|
126
|
-
wandb.tensorboard.reset_state()
|
126
|
+
wandb.tensorboard.reset_state() # type: ignore
|
127
127
|
|
128
128
|
def _calculate_namespace(self, logdir: str, rootdir: str) -> Optional[str]:
|
129
129
|
namespace: Optional[str]
|
@@ -430,7 +430,7 @@ class TBEventConsumer:
|
|
430
430
|
def _handle_event(
|
431
431
|
self, event: "ProtoEvent", history: Optional["TBHistory"] = None
|
432
432
|
) -> None:
|
433
|
-
wandb.tensorboard._log(
|
433
|
+
wandb.tensorboard._log( # type: ignore
|
434
434
|
event.event,
|
435
435
|
step=event.event.step,
|
436
436
|
namespace=event.namespace,
|
wandb/sdk/internal/update.py
CHANGED
@@ -10,7 +10,7 @@ def _find_available(
|
|
10
10
|
) -> Optional[Tuple[str, bool, bool, bool, Optional[str]]]:
|
11
11
|
from wandb.util import parse_version
|
12
12
|
|
13
|
-
pypi_url =
|
13
|
+
pypi_url = "https://pypi.org/pypi/wandb/json"
|
14
14
|
|
15
15
|
yanked_dict = {}
|
16
16
|
try:
|
@@ -78,7 +78,7 @@ def check_available(current_version: str) -> Optional[Dict[str, Optional[str]]]:
|
|
78
78
|
if not package_info:
|
79
79
|
return None
|
80
80
|
|
81
|
-
wandb_module_name = wandb
|
81
|
+
wandb_module_name = "wandb"
|
82
82
|
|
83
83
|
latest_version, pip_prerelease, deleted, yanked, yanked_reason = package_info
|
84
84
|
upgrade_message = (
|
@@ -63,6 +63,13 @@ else:
|
|
63
63
|
NAMESPACE = "wandb"
|
64
64
|
|
65
65
|
|
66
|
+
def get_pod_name_safe(job: client.V1Job):
|
67
|
+
try:
|
68
|
+
return job.spec.template.metadata.name
|
69
|
+
except AttributeError:
|
70
|
+
return None
|
71
|
+
|
72
|
+
|
66
73
|
async def _wait_for_completion(
|
67
74
|
batch_client: client.BatchV1Api, job_name: str, deadline_secs: Optional[int] = None
|
68
75
|
) -> bool:
|
@@ -319,17 +326,18 @@ class KanikoBuilder(AbstractBuilder):
|
|
319
326
|
await self._create_docker_ecr_config_map(
|
320
327
|
build_job_name, core_v1, repo_uri
|
321
328
|
)
|
322
|
-
await batch_v1.create_namespaced_job(NAMESPACE, build_job)
|
323
|
-
|
329
|
+
k8s_job = await batch_v1.create_namespaced_job(NAMESPACE, build_job)
|
324
330
|
# wait for double the job deadline since it might take time to schedule
|
325
331
|
if not await _wait_for_completion(
|
326
332
|
batch_v1, build_job_name, 3 * _DEFAULT_BUILD_TIMEOUT_SECS
|
327
333
|
):
|
328
334
|
if job_tracker:
|
329
335
|
job_tracker.set_err_stage("build")
|
330
|
-
|
331
|
-
|
332
|
-
|
336
|
+
msg = f"Failed to build image in kaniko for job {run_id}."
|
337
|
+
pod_name = get_pod_name_safe(k8s_job)
|
338
|
+
if pod_name:
|
339
|
+
msg += f" View logs with `kubectl logs -n {NAMESPACE} {pod_name}`."
|
340
|
+
raise Exception(msg)
|
333
341
|
try:
|
334
342
|
pods_from_job = await core_v1.list_namespaced_pod(
|
335
343
|
namespace=NAMESPACE, label_selector=f"job-name={build_job_name}"
|
wandb/sdk/launch/create_job.py
CHANGED
@@ -114,6 +114,7 @@ def _create_job(
|
|
114
114
|
git_hash: Optional[str] = None,
|
115
115
|
build_context: Optional[str] = None,
|
116
116
|
dockerfile: Optional[str] = None,
|
117
|
+
base_image: Optional[str] = None,
|
117
118
|
) -> Tuple[Optional[Artifact], str, List[str]]:
|
118
119
|
wandb.termlog(f"Creating launch job of type: {job_type}...")
|
119
120
|
|
@@ -188,6 +189,7 @@ def _create_job(
|
|
188
189
|
api.api,
|
189
190
|
dockerfile=dockerfile,
|
190
191
|
build_context=build_context,
|
192
|
+
base_image=base_image,
|
191
193
|
)
|
192
194
|
if not artifact:
|
193
195
|
wandb.termerror("JobBuilder failed to build a job")
|
wandb/sdk/lib/apikey.py
CHANGED
@@ -107,7 +107,7 @@ def prompt_api_key( # noqa: C901
|
|
107
107
|
|
108
108
|
if jupyter and "google.colab" in sys.modules:
|
109
109
|
log_string = term.LOG_STRING_NOCOLOR
|
110
|
-
key = wandb.jupyter.attempt_colab_login(app_url)
|
110
|
+
key = wandb.jupyter.attempt_colab_login(app_url) # type: ignore
|
111
111
|
if key is not None:
|
112
112
|
write_key(settings, key, api=api)
|
113
113
|
return key # type: ignore
|
wandb/sdk/service/streams.py
CHANGED
@@ -81,9 +81,7 @@ class StreamRecord:
|
|
81
81
|
self._wait_thread_active()
|
82
82
|
|
83
83
|
def _wait_thread_active(self) -> None:
|
84
|
-
|
85
|
-
# TODO: using the default communicate timeout, is that enough? retries?
|
86
|
-
assert result
|
84
|
+
self._iface.deliver_status().wait(timeout=-1)
|
87
85
|
|
88
86
|
def join(self) -> None:
|
89
87
|
self._iface.join()
|
@@ -212,7 +210,7 @@ class StreamMux:
|
|
212
210
|
# run_id = action.stream_id # will want to fix if a streamid != runid
|
213
211
|
settings = action._data
|
214
212
|
thread = StreamThread(
|
215
|
-
target=wandb.wandb_sdk.internal.internal.wandb_internal,
|
213
|
+
target=wandb.wandb_sdk.internal.internal.wandb_internal, # type: ignore
|
216
214
|
kwargs=dict(
|
217
215
|
settings=settings,
|
218
216
|
record_q=stream._record_q,
|
wandb/sdk/wandb_config.py
CHANGED
@@ -61,7 +61,7 @@ class Config:
|
|
61
61
|
|
62
62
|
Using absl flags
|
63
63
|
```
|
64
|
-
flags.DEFINE_string(
|
64
|
+
flags.DEFINE_string("model", None, "model to run") # name, default, help
|
65
65
|
wandb.config.update(flags.FLAGS) # adds all absl flags to config
|
66
66
|
```
|
67
67
|
|