wandb 0.16.3__py3-none-any.whl → 0.16.5__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.
- wandb/__init__.py +2 -2
- wandb/agents/pyagent.py +1 -1
- wandb/apis/importers/__init__.py +1 -4
- wandb/apis/importers/internals/internal.py +386 -0
- wandb/apis/importers/internals/protocols.py +125 -0
- wandb/apis/importers/internals/util.py +78 -0
- wandb/apis/importers/mlflow.py +125 -88
- wandb/apis/importers/validation.py +108 -0
- wandb/apis/importers/wandb.py +1604 -0
- wandb/apis/public/api.py +7 -10
- wandb/apis/public/artifacts.py +38 -0
- wandb/apis/public/files.py +11 -2
- wandb/apis/reports/v2/__init__.py +0 -19
- wandb/apis/reports/v2/expr_parsing.py +0 -1
- wandb/apis/reports/v2/interface.py +15 -18
- wandb/apis/reports/v2/internal.py +12 -45
- wandb/cli/cli.py +52 -55
- wandb/integration/gym/__init__.py +2 -1
- wandb/integration/keras/callbacks/model_checkpoint.py +1 -1
- wandb/integration/keras/keras.py +6 -4
- wandb/integration/kfp/kfp_patch.py +2 -2
- wandb/integration/openai/fine_tuning.py +1 -2
- wandb/integration/ultralytics/callback.py +0 -1
- wandb/proto/v3/wandb_internal_pb2.py +332 -312
- wandb/proto/v3/wandb_settings_pb2.py +13 -3
- wandb/proto/v3/wandb_telemetry_pb2.py +10 -10
- wandb/proto/v4/wandb_internal_pb2.py +316 -312
- wandb/proto/v4/wandb_settings_pb2.py +5 -3
- wandb/proto/v4/wandb_telemetry_pb2.py +10 -10
- wandb/sdk/artifacts/artifact.py +75 -31
- wandb/sdk/artifacts/artifact_manifest.py +5 -2
- wandb/sdk/artifacts/artifact_manifest_entry.py +6 -1
- wandb/sdk/artifacts/artifact_manifests/artifact_manifest_v1.py +8 -2
- wandb/sdk/artifacts/artifact_saver.py +19 -47
- wandb/sdk/artifacts/storage_handler.py +2 -1
- wandb/sdk/artifacts/storage_policies/wandb_storage_policy.py +22 -9
- wandb/sdk/artifacts/storage_policy.py +4 -1
- wandb/sdk/data_types/base_types/wb_value.py +1 -1
- wandb/sdk/data_types/image.py +2 -2
- wandb/sdk/interface/interface.py +49 -13
- wandb/sdk/interface/interface_shared.py +17 -11
- wandb/sdk/internal/file_stream.py +20 -1
- wandb/sdk/internal/handler.py +1 -4
- wandb/sdk/internal/internal_api.py +3 -1
- wandb/sdk/internal/job_builder.py +49 -19
- wandb/sdk/internal/profiler.py +1 -1
- wandb/sdk/internal/sender.py +96 -124
- wandb/sdk/internal/sender_config.py +197 -0
- wandb/sdk/internal/settings_static.py +9 -0
- wandb/sdk/internal/system/system_info.py +5 -3
- wandb/sdk/internal/update.py +1 -1
- wandb/sdk/launch/_launch.py +3 -3
- wandb/sdk/launch/_launch_add.py +28 -29
- wandb/sdk/launch/_project_spec.py +148 -136
- wandb/sdk/launch/agent/agent.py +3 -7
- wandb/sdk/launch/agent/config.py +0 -27
- wandb/sdk/launch/builder/build.py +54 -28
- wandb/sdk/launch/builder/docker_builder.py +4 -15
- wandb/sdk/launch/builder/kaniko_builder.py +72 -45
- wandb/sdk/launch/create_job.py +6 -40
- wandb/sdk/launch/loader.py +10 -0
- wandb/sdk/launch/registry/anon.py +29 -0
- wandb/sdk/launch/registry/local_registry.py +4 -1
- wandb/sdk/launch/runner/kubernetes_runner.py +20 -2
- wandb/sdk/launch/runner/local_container.py +15 -10
- wandb/sdk/launch/runner/sagemaker_runner.py +1 -1
- wandb/sdk/launch/sweeps/scheduler.py +11 -3
- wandb/sdk/launch/utils.py +14 -0
- wandb/sdk/lib/__init__.py +2 -5
- wandb/sdk/lib/_settings_toposort_generated.py +4 -1
- wandb/sdk/lib/apikey.py +0 -5
- wandb/sdk/lib/config_util.py +0 -31
- wandb/sdk/lib/filesystem.py +11 -1
- wandb/sdk/lib/run_moment.py +72 -0
- wandb/sdk/service/service.py +7 -2
- wandb/sdk/service/streams.py +1 -6
- wandb/sdk/verify/verify.py +2 -1
- wandb/sdk/wandb_init.py +12 -1
- wandb/sdk/wandb_login.py +43 -26
- wandb/sdk/wandb_run.py +164 -110
- wandb/sdk/wandb_settings.py +58 -16
- wandb/testing/relay.py +5 -6
- wandb/util.py +50 -7
- {wandb-0.16.3.dist-info → wandb-0.16.5.dist-info}/METADATA +8 -1
- {wandb-0.16.3.dist-info → wandb-0.16.5.dist-info}/RECORD +89 -82
- {wandb-0.16.3.dist-info → wandb-0.16.5.dist-info}/WHEEL +1 -1
- wandb/apis/importers/base.py +0 -400
- {wandb-0.16.3.dist-info → wandb-0.16.5.dist-info}/LICENSE +0 -0
- {wandb-0.16.3.dist-info → wandb-0.16.5.dist-info}/entry_points.txt +0 -0
- {wandb-0.16.3.dist-info → wandb-0.16.5.dist-info}/top_level.txt +0 -0
wandb/apis/importers/base.py
DELETED
@@ -1,400 +0,0 @@
|
|
1
|
-
import json
|
2
|
-
import os
|
3
|
-
import queue
|
4
|
-
import sys
|
5
|
-
from dataclasses import dataclass
|
6
|
-
from typing import Any, Dict, Iterable, List, Optional, Tuple
|
7
|
-
from unittest.mock import patch
|
8
|
-
|
9
|
-
from google.protobuf.json_format import ParseDict
|
10
|
-
from tqdm import tqdm
|
11
|
-
|
12
|
-
import wandb
|
13
|
-
from wandb.proto import wandb_internal_pb2 as pb
|
14
|
-
from wandb.proto import wandb_settings_pb2
|
15
|
-
from wandb.proto import wandb_telemetry_pb2 as telem_pb
|
16
|
-
from wandb.sdk.interface.interface import file_policy_to_enum
|
17
|
-
from wandb.sdk.interface.interface_queue import InterfaceQueue
|
18
|
-
from wandb.sdk.internal import context
|
19
|
-
from wandb.sdk.internal.sender import SendManager
|
20
|
-
from wandb.sdk.internal.settings_static import SettingsStatic
|
21
|
-
from wandb.util import cast_dictlike_to_dict, coalesce
|
22
|
-
|
23
|
-
if sys.version_info >= (3, 8):
|
24
|
-
from typing import Protocol
|
25
|
-
else:
|
26
|
-
from typing_extensions import Protocol
|
27
|
-
|
28
|
-
|
29
|
-
with patch("click.echo"):
|
30
|
-
from wandb.apis.reports import Report
|
31
|
-
|
32
|
-
|
33
|
-
class ImporterRun(Protocol):
|
34
|
-
def run_id(self) -> str:
|
35
|
-
...
|
36
|
-
|
37
|
-
def entity(self) -> str:
|
38
|
-
...
|
39
|
-
|
40
|
-
def project(self) -> str:
|
41
|
-
...
|
42
|
-
|
43
|
-
def config(self) -> Dict[str, Any]:
|
44
|
-
...
|
45
|
-
|
46
|
-
def summary(self) -> Dict[str, float]:
|
47
|
-
...
|
48
|
-
|
49
|
-
def metrics(self) -> Iterable[Dict[str, float]]:
|
50
|
-
"""Metrics for the run.
|
51
|
-
|
52
|
-
We expect metrics in this shape:
|
53
|
-
|
54
|
-
[
|
55
|
-
{'metric1': 1, 'metric2': 1, '_step': 0},
|
56
|
-
{'metric1': 2, 'metric2': 4, '_step': 1},
|
57
|
-
{'metric1': 3, 'metric2': 9, '_step': 2},
|
58
|
-
...
|
59
|
-
]
|
60
|
-
|
61
|
-
You can also submit metrics in this shape:
|
62
|
-
[
|
63
|
-
{'metric1': 1, '_step': 0},
|
64
|
-
{'metric2': 1, '_step': 0},
|
65
|
-
{'metric1': 2, '_step': 1},
|
66
|
-
{'metric2': 4, '_step': 1},
|
67
|
-
...
|
68
|
-
]
|
69
|
-
"""
|
70
|
-
...
|
71
|
-
|
72
|
-
def run_group(self) -> Optional[str]:
|
73
|
-
...
|
74
|
-
|
75
|
-
def job_type(self) -> Optional[str]:
|
76
|
-
...
|
77
|
-
|
78
|
-
def display_name(self) -> str:
|
79
|
-
...
|
80
|
-
|
81
|
-
def notes(self) -> Optional[str]:
|
82
|
-
...
|
83
|
-
|
84
|
-
def tags(self) -> Optional[List[str]]:
|
85
|
-
...
|
86
|
-
|
87
|
-
def artifacts(self) -> Optional[Iterable[wandb.Artifact]]: # type: ignore
|
88
|
-
...
|
89
|
-
|
90
|
-
def used_artifacts(self) -> Optional[Iterable[wandb.Artifact]]: # type: ignore
|
91
|
-
...
|
92
|
-
|
93
|
-
def os_version(self) -> Optional[str]:
|
94
|
-
...
|
95
|
-
|
96
|
-
def python_version(self) -> Optional[str]:
|
97
|
-
...
|
98
|
-
|
99
|
-
def cuda_version(self) -> Optional[str]:
|
100
|
-
...
|
101
|
-
|
102
|
-
def program(self) -> Optional[str]:
|
103
|
-
...
|
104
|
-
|
105
|
-
def host(self) -> Optional[str]:
|
106
|
-
...
|
107
|
-
|
108
|
-
def username(self) -> Optional[str]:
|
109
|
-
...
|
110
|
-
|
111
|
-
def executable(self) -> Optional[str]:
|
112
|
-
...
|
113
|
-
|
114
|
-
def gpus_used(self) -> Optional[str]:
|
115
|
-
...
|
116
|
-
|
117
|
-
def cpus_used(self) -> Optional[int]: # can we get the model?
|
118
|
-
...
|
119
|
-
|
120
|
-
def memory_used(self) -> Optional[int]:
|
121
|
-
...
|
122
|
-
|
123
|
-
def runtime(self) -> Optional[int]:
|
124
|
-
...
|
125
|
-
|
126
|
-
def start_time(self) -> Optional[int]:
|
127
|
-
...
|
128
|
-
|
129
|
-
def code_path(self) -> Optional[str]:
|
130
|
-
...
|
131
|
-
|
132
|
-
def cli_version(self) -> Optional[str]:
|
133
|
-
...
|
134
|
-
|
135
|
-
def files(self) -> Optional[Iterable[Tuple[str, str]]]:
|
136
|
-
...
|
137
|
-
|
138
|
-
def logs(self) -> Optional[Iterable[str]]:
|
139
|
-
...
|
140
|
-
|
141
|
-
|
142
|
-
class Importer(Protocol):
|
143
|
-
def collect_runs(self, *args, **kwargs) -> Iterable[ImporterRun]:
|
144
|
-
...
|
145
|
-
|
146
|
-
def collect_reports(self, *args, **kwargs) -> Iterable[Report]:
|
147
|
-
...
|
148
|
-
|
149
|
-
def import_run(self, run: ImporterRun) -> None:
|
150
|
-
...
|
151
|
-
|
152
|
-
def import_report(self, report: Report) -> None:
|
153
|
-
...
|
154
|
-
|
155
|
-
|
156
|
-
@dataclass
|
157
|
-
class RecordMaker:
|
158
|
-
run: ImporterRun
|
159
|
-
interface: InterfaceQueue = InterfaceQueue()
|
160
|
-
|
161
|
-
@property
|
162
|
-
def run_dir(self) -> str:
|
163
|
-
return f"./wandb-importer/{self.run.run_id()}"
|
164
|
-
|
165
|
-
def _make_run_record(self) -> pb.Record:
|
166
|
-
run = pb.RunRecord()
|
167
|
-
run.run_id = self.run.run_id()
|
168
|
-
run.entity = self.run.entity()
|
169
|
-
run.project = self.run.project()
|
170
|
-
run.display_name = coalesce(self.run.display_name())
|
171
|
-
run.notes = coalesce(self.run.notes(), "")
|
172
|
-
run.tags.extend(coalesce(self.run.tags(), []))
|
173
|
-
run.start_time.FromMilliseconds(self.run.start_time())
|
174
|
-
|
175
|
-
host = self.run.host()
|
176
|
-
if host is not None:
|
177
|
-
run.host = host
|
178
|
-
|
179
|
-
runtime = self.run.runtime()
|
180
|
-
if runtime is not None:
|
181
|
-
run.runtime = runtime
|
182
|
-
|
183
|
-
run_group = self.run.run_group()
|
184
|
-
if run_group is not None:
|
185
|
-
run.run_group = run_group
|
186
|
-
|
187
|
-
config = self.run.config()
|
188
|
-
if "_wandb" not in config:
|
189
|
-
config["_wandb"] = {}
|
190
|
-
|
191
|
-
# how do I get this automatically?
|
192
|
-
config["_wandb"]["code_path"] = self.run.code_path()
|
193
|
-
config["_wandb"]["python_version"] = self.run.python_version()
|
194
|
-
config["_wandb"]["cli_version"] = self.run.cli_version()
|
195
|
-
|
196
|
-
self.interface._make_config(
|
197
|
-
data=config,
|
198
|
-
obj=run.config,
|
199
|
-
) # is there a better way?
|
200
|
-
return self.interface._make_record(run=run)
|
201
|
-
|
202
|
-
def _make_output_record(self, line) -> pb.Record:
|
203
|
-
output_raw = pb.OutputRawRecord()
|
204
|
-
output_raw.output_type = pb.OutputRawRecord.OutputType.STDOUT
|
205
|
-
output_raw.line = line
|
206
|
-
return self.interface._make_record(output_raw=output_raw)
|
207
|
-
|
208
|
-
def _make_summary_record(self) -> pb.Record:
|
209
|
-
d: dict = {
|
210
|
-
**self.run.summary(),
|
211
|
-
"_runtime": self.run.runtime(), # quirk of runtime -- it has to be here!
|
212
|
-
# '_timestamp': self.run.start_time()/1000,
|
213
|
-
}
|
214
|
-
d = cast_dictlike_to_dict(d)
|
215
|
-
summary = self.interface._make_summary_from_dict(d)
|
216
|
-
return self.interface._make_record(summary=summary)
|
217
|
-
|
218
|
-
def _make_history_records(self) -> Iterable[pb.Record]:
|
219
|
-
for _, metrics in enumerate(self.run.metrics()):
|
220
|
-
history = pb.HistoryRecord()
|
221
|
-
for k, v in metrics.items():
|
222
|
-
item = history.item.add()
|
223
|
-
item.key = k
|
224
|
-
item.value_json = json.dumps(v)
|
225
|
-
yield self.interface._make_record(history=history)
|
226
|
-
|
227
|
-
def _make_files_record(
|
228
|
-
self,
|
229
|
-
files_dict,
|
230
|
-
) -> pb.Record:
|
231
|
-
files_record = pb.FilesRecord()
|
232
|
-
for path, policy in files_dict["files"]:
|
233
|
-
f = files_record.files.add()
|
234
|
-
f.path = path
|
235
|
-
f.policy = file_policy_to_enum(policy) # is this always "end"?
|
236
|
-
return self.interface._make_record(files=files_record)
|
237
|
-
|
238
|
-
def _make_metadata_files_record(self) -> pb.Record:
|
239
|
-
files = self.run.files()
|
240
|
-
if files is None:
|
241
|
-
metadata_fname = self._make_metadata_file()
|
242
|
-
files = [(metadata_fname, "end")]
|
243
|
-
|
244
|
-
files_dict = {"files": files}
|
245
|
-
return self._make_files_record(files_dict)
|
246
|
-
|
247
|
-
def _make_artifact_record(self, artifact, use_artifact=False) -> pb.Record:
|
248
|
-
proto = self.interface._make_artifact(artifact)
|
249
|
-
proto.run_id = self.run.run_id()
|
250
|
-
proto.project = self.run.project()
|
251
|
-
proto.entity = self.run.entity()
|
252
|
-
proto.user_created = use_artifact
|
253
|
-
proto.use_after_commit = use_artifact
|
254
|
-
proto.finalize = True
|
255
|
-
for tag in ["latest", "imported"]:
|
256
|
-
proto.aliases.append(tag)
|
257
|
-
return self.interface._make_record(artifact=proto)
|
258
|
-
|
259
|
-
def _make_telem_record(self) -> pb.Record:
|
260
|
-
telem = telem_pb.TelemetryRecord()
|
261
|
-
|
262
|
-
feature = telem_pb.Feature()
|
263
|
-
feature.importer_mlflow = True
|
264
|
-
telem.feature.CopyFrom(feature)
|
265
|
-
|
266
|
-
cli_version = self.run.cli_version()
|
267
|
-
if cli_version:
|
268
|
-
telem.cli_version = cli_version
|
269
|
-
|
270
|
-
python_version = self.run.python_version()
|
271
|
-
if python_version:
|
272
|
-
telem.python_version = python_version
|
273
|
-
|
274
|
-
return self.interface._make_record(telemetry=telem)
|
275
|
-
|
276
|
-
def _make_metadata_file(self) -> str:
|
277
|
-
missing_text = "This data was not captured"
|
278
|
-
|
279
|
-
d = {}
|
280
|
-
d["os"] = coalesce(self.run.os_version(), missing_text)
|
281
|
-
d["python"] = coalesce(self.run.python_version(), missing_text)
|
282
|
-
d["program"] = coalesce(self.run.program(), missing_text)
|
283
|
-
d["cuda"] = coalesce(self.run.cuda_version(), missing_text)
|
284
|
-
d["host"] = coalesce(self.run.host(), missing_text)
|
285
|
-
d["username"] = coalesce(self.run.username(), missing_text)
|
286
|
-
d["executable"] = coalesce(self.run.executable(), missing_text)
|
287
|
-
|
288
|
-
gpus_used = self.run.gpus_used()
|
289
|
-
if gpus_used is not None:
|
290
|
-
d["gpu_devices"] = json.dumps(gpus_used)
|
291
|
-
d["gpu_count"] = json.dumps(len(gpus_used))
|
292
|
-
|
293
|
-
cpus_used = self.run.cpus_used()
|
294
|
-
if cpus_used is not None:
|
295
|
-
d["cpu_count"] = json.dumps(self.run.cpus_used())
|
296
|
-
|
297
|
-
mem_used = self.run.memory_used()
|
298
|
-
if mem_used is not None:
|
299
|
-
d["memory"] = json.dumps({"total": self.run.memory_used()})
|
300
|
-
|
301
|
-
fname = f"{self.run_dir}/files/wandb-metadata.json"
|
302
|
-
with open(fname, "w") as f:
|
303
|
-
f.write(json.dumps(d))
|
304
|
-
return fname
|
305
|
-
|
306
|
-
|
307
|
-
def send_run_with_send_manager(
|
308
|
-
run: ImporterRun,
|
309
|
-
overrides: Optional[Dict[str, Any]] = None,
|
310
|
-
settings_override: Optional[SettingsStatic] = None,
|
311
|
-
) -> None:
|
312
|
-
# does this need to be here for pmap?
|
313
|
-
if overrides:
|
314
|
-
for k, v in overrides.items():
|
315
|
-
# `lambda: v` won't work!
|
316
|
-
# https://stackoverflow.com/questions/10802002/why-deepcopy-doesnt-create-new-references-to-lambda-function
|
317
|
-
setattr(run, k, lambda v=v: v)
|
318
|
-
_settings_override = coalesce(settings_override, {})
|
319
|
-
rm = RecordMaker(run)
|
320
|
-
|
321
|
-
root_dir = rm.run_dir
|
322
|
-
default_settings = {
|
323
|
-
"files_dir": os.path.join(root_dir, "files"),
|
324
|
-
"root_dir": root_dir,
|
325
|
-
"_start_time": 0,
|
326
|
-
"git_remote": None,
|
327
|
-
"resume": False,
|
328
|
-
"program": None,
|
329
|
-
"ignore_globs": (),
|
330
|
-
"run_id": None,
|
331
|
-
"entity": None,
|
332
|
-
"project": None,
|
333
|
-
"run_group": None,
|
334
|
-
"job_type": None,
|
335
|
-
"run_tags": None,
|
336
|
-
"run_name": None,
|
337
|
-
"run_notes": None,
|
338
|
-
"save_code": None,
|
339
|
-
"email": None,
|
340
|
-
"silent": None,
|
341
|
-
"_offline": None,
|
342
|
-
"_sync": True,
|
343
|
-
"_live_policy_rate_limit": None,
|
344
|
-
"_live_policy_wait_time": None,
|
345
|
-
"disable_job_creation": False,
|
346
|
-
"_async_upload_concurrency_limit": None,
|
347
|
-
}
|
348
|
-
combined_settings = {**default_settings, **_settings_override}
|
349
|
-
settings_message = wandb_settings_pb2.Settings()
|
350
|
-
ParseDict(combined_settings, settings_message)
|
351
|
-
|
352
|
-
settings = SettingsStatic(settings_message)
|
353
|
-
|
354
|
-
record_q: queue.Queue = queue.Queue()
|
355
|
-
result_q: queue.Queue = queue.Queue()
|
356
|
-
interface = InterfaceQueue(record_q=record_q)
|
357
|
-
context_keeper = context.ContextKeeper()
|
358
|
-
|
359
|
-
with SendManager(settings, record_q, result_q, interface, context_keeper) as sm:
|
360
|
-
wandb.termlog(">> Make run record")
|
361
|
-
sm.send(rm._make_run_record())
|
362
|
-
|
363
|
-
wandb.termlog(">> Use Artifacts")
|
364
|
-
used_artifacts = run.used_artifacts()
|
365
|
-
if used_artifacts is not None:
|
366
|
-
for artifact in tqdm(
|
367
|
-
used_artifacts, desc="Used artifacts", unit="artifacts", leave=False
|
368
|
-
):
|
369
|
-
sm.send(rm._make_artifact_record(artifact, use_artifact=True))
|
370
|
-
|
371
|
-
wandb.termlog(">> Log Artifacts")
|
372
|
-
artifacts = run.artifacts()
|
373
|
-
if artifacts is not None:
|
374
|
-
for artifact in tqdm(
|
375
|
-
artifacts, desc="Logged artifacts", unit="artifacts", leave=False
|
376
|
-
):
|
377
|
-
sm.send(rm._make_artifact_record(artifact))
|
378
|
-
|
379
|
-
wandb.termlog(">> Log Metadata")
|
380
|
-
sm.send(rm._make_metadata_files_record())
|
381
|
-
|
382
|
-
wandb.termlog(">> Log History")
|
383
|
-
for history_record in tqdm(
|
384
|
-
rm._make_history_records(), desc="History", unit="steps", leave=False
|
385
|
-
):
|
386
|
-
sm.send(history_record)
|
387
|
-
|
388
|
-
wandb.termlog(">> Log Summary")
|
389
|
-
sm.send(rm._make_summary_record())
|
390
|
-
|
391
|
-
wandb.termlog(">> Log Output")
|
392
|
-
# if hasattr(run, "_logs"):
|
393
|
-
# lines = run._logs
|
394
|
-
lines = run.logs()
|
395
|
-
if lines is not None:
|
396
|
-
for line in tqdm(lines, desc="Stdout", unit="lines", leave=False):
|
397
|
-
sm.send(rm._make_output_record(line))
|
398
|
-
|
399
|
-
wandb.termlog(">> Log Telem")
|
400
|
-
sm.send(rm._make_telem_record())
|
File without changes
|
File without changes
|
File without changes
|