wandb 0.21.0__py3-none-win32.whl → 0.21.2__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 +525 -360
- wandb/apis/public/artifacts.py +207 -13
- 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/_utils.py +14 -16
- wandb/apis/public/registries/registries_search.py +183 -304
- wandb/apis/public/reports.py +96 -15
- 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/automations/_generated/delete_automation.py +1 -3
- wandb/automations/_generated/enums.py +13 -11
- wandb/beta/workflows.py +66 -30
- wandb/bin/gpu_stats.exe +0 -0
- wandb/bin/wandb-core +0 -0
- wandb/cli/cli.py +127 -3
- 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/data_pytorch.py +75 -0
- wandb/integration/metaflow/data_sklearn.py +76 -0
- wandb/integration/metaflow/errors.py +13 -0
- wandb/integration/metaflow/metaflow.py +167 -223
- wandb/integration/openai/fine_tuning.py +1 -2
- wandb/integration/weave/__init__.py +6 -0
- wandb/integration/weave/interface.py +49 -0
- wandb/integration/weave/weave.py +63 -0
- wandb/jupyter.py +5 -5
- wandb/plot/custom_chart.py +30 -7
- wandb/proto/v3/wandb_internal_pb2.py +281 -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/_factories.py +17 -0
- wandb/sdk/artifacts/_generated/__init__.py +221 -13
- wandb/sdk/artifacts/_generated/artifact_by_id.py +17 -0
- wandb/sdk/artifacts/_generated/artifact_by_name.py +22 -0
- wandb/sdk/artifacts/_generated/artifact_collection_membership_file_urls.py +43 -0
- wandb/sdk/artifacts/_generated/artifact_created_by.py +47 -0
- wandb/sdk/artifacts/_generated/artifact_file_urls.py +22 -0
- wandb/sdk/artifacts/_generated/artifact_type.py +31 -0
- wandb/sdk/artifacts/_generated/artifact_used_by.py +43 -0
- wandb/sdk/artifacts/_generated/artifact_via_membership_by_name.py +26 -0
- wandb/sdk/artifacts/_generated/delete_artifact.py +28 -0
- wandb/sdk/artifacts/_generated/enums.py +5 -0
- wandb/sdk/artifacts/_generated/fetch_artifact_manifest.py +38 -0
- wandb/sdk/artifacts/_generated/fetch_registries.py +32 -0
- wandb/sdk/artifacts/_generated/fragments.py +279 -41
- wandb/sdk/artifacts/_generated/link_artifact.py +6 -0
- wandb/sdk/artifacts/_generated/operations.py +654 -51
- wandb/sdk/artifacts/_generated/registry_collections.py +34 -0
- wandb/sdk/artifacts/_generated/registry_versions.py +34 -0
- wandb/sdk/artifacts/_generated/unlink_artifact.py +25 -0
- wandb/sdk/artifacts/_graphql_fragments.py +3 -86
- wandb/sdk/artifacts/_internal_artifact.py +19 -8
- wandb/sdk/artifacts/_validators.py +14 -4
- wandb/sdk/artifacts/artifact.py +512 -618
- wandb/sdk/artifacts/artifact_file_cache.py +10 -6
- wandb/sdk/artifacts/artifact_manifest.py +10 -9
- wandb/sdk/artifacts/artifact_manifest_entry.py +9 -10
- wandb/sdk/artifacts/artifact_manifests/artifact_manifest_v1.py +5 -3
- wandb/sdk/artifacts/storage_handlers/http_handler.py +1 -1
- wandb/sdk/artifacts/storage_handlers/s3_handler.py +1 -1
- wandb/sdk/artifacts/storage_policies/wandb_storage_policy.py +1 -1
- 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/interface/interface_queue.py +1 -4
- wandb/sdk/interface/interface_shared.py +26 -37
- wandb/sdk/interface/interface_sock.py +24 -14
- wandb/sdk/internal/internal_api.py +6 -0
- wandb/sdk/internal/job_builder.py +6 -0
- wandb/sdk/internal/settings_static.py +2 -3
- 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 +15 -2
- 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 +323 -1
- wandb/sdk/launch/sweeps/scheduler.py +2 -3
- wandb/sdk/lib/asyncio_compat.py +19 -16
- wandb/sdk/lib/asyncio_manager.py +252 -0
- wandb/sdk/lib/deprecate.py +1 -7
- wandb/sdk/lib/disabled.py +1 -1
- wandb/sdk/lib/hashutil.py +27 -5
- wandb/sdk/lib/module.py +7 -13
- wandb/sdk/lib/printer.py +2 -2
- wandb/sdk/lib/printer_asyncio.py +3 -1
- wandb/sdk/lib/progress.py +0 -19
- wandb/sdk/lib/retry.py +185 -78
- wandb/sdk/lib/service/service_client.py +106 -0
- wandb/sdk/lib/service/service_connection.py +20 -26
- wandb/sdk/lib/service/service_token.py +30 -13
- wandb/sdk/mailbox/mailbox.py +13 -5
- wandb/sdk/mailbox/mailbox_handle.py +22 -13
- wandb/sdk/mailbox/response_handle.py +42 -106
- wandb/sdk/mailbox/wait_with_progress.py +7 -42
- wandb/sdk/wandb_init.py +77 -116
- wandb/sdk/wandb_login.py +19 -15
- wandb/sdk/wandb_metric.py +2 -0
- wandb/sdk/wandb_run.py +497 -469
- wandb/sdk/wandb_settings.py +145 -4
- wandb/sdk/wandb_setup.py +204 -124
- wandb/sdk/wandb_sweep.py +14 -13
- wandb/sdk/wandb_watch.py +4 -6
- wandb/sync/sync.py +10 -0
- wandb/util.py +58 -1
- wandb/wandb_run.py +1 -2
- {wandb-0.21.0.dist-info → wandb-0.21.2.dist-info}/METADATA +1 -1
- {wandb-0.21.0.dist-info → wandb-0.21.2.dist-info}/RECORD +145 -129
- wandb/sdk/interface/interface_relay.py +0 -38
- wandb/sdk/interface/router.py +0 -89
- wandb/sdk/interface/router_queue.py +0 -43
- wandb/sdk/interface/router_relay.py +0 -50
- wandb/sdk/interface/router_sock.py +0 -32
- wandb/sdk/lib/sock_client.py +0 -236
- wandb/vendor/pynvml/__init__.py +0 -0
- wandb/vendor/pynvml/pynvml.py +0 -4779
- {wandb-0.21.0.dist-info → wandb-0.21.2.dist-info}/WHEEL +0 -0
- {wandb-0.21.0.dist-info → wandb-0.21.2.dist-info}/entry_points.txt +0 -0
- {wandb-0.21.0.dist-info → wandb-0.21.2.dist-info}/licenses/LICENSE +0 -0
@@ -23,7 +23,6 @@ if TYPE_CHECKING:
|
|
23
23
|
from typing_extensions import Self
|
24
24
|
|
25
25
|
from wandb.sdk.artifacts.artifact import Artifact
|
26
|
-
from wandb.sdk.wandb_run import Run as LocalRun
|
27
26
|
|
28
27
|
|
29
28
|
DEBUG_MODE = False
|
@@ -137,15 +136,14 @@ class _SavedModel(WBValue, Generic[SavedModelObjType]):
|
|
137
136
|
# and specified adapter.
|
138
137
|
return cls(dl_path)
|
139
138
|
|
140
|
-
def to_json(self, run_or_artifact:
|
139
|
+
def to_json(self, run_or_artifact: wandb.Run | Artifact) -> dict:
|
141
140
|
# Unlike other data types, we do not allow adding to a Run directly. There is a
|
142
141
|
# bit of tech debt in the other data types which requires the input to `to_json`
|
143
142
|
# to accept a Run or Artifact. However, Run additions should be deprecated in the future.
|
144
143
|
# This check helps ensure we do not add to the debt.
|
145
|
-
|
146
|
-
|
147
|
-
if isinstance(run_or_artifact, Run):
|
144
|
+
if isinstance(run_or_artifact, wandb.Run):
|
148
145
|
raise TypeError("SavedModel cannot be added to run - must use artifact")
|
146
|
+
|
149
147
|
artifact = run_or_artifact
|
150
148
|
json_obj = {
|
151
149
|
"type": self._log_type,
|
@@ -329,7 +327,7 @@ class _PicklingSavedModel(_SavedModel[SavedModelObjType]):
|
|
329
327
|
|
330
328
|
return inst # type: ignore
|
331
329
|
|
332
|
-
def to_json(self, run_or_artifact:
|
330
|
+
def to_json(self, run_or_artifact: wandb.Run | Artifact) -> dict:
|
333
331
|
json_obj = super().to_json(run_or_artifact)
|
334
332
|
assert isinstance(run_or_artifact, wandb.Artifact)
|
335
333
|
if self._dep_py_files_path is not None:
|
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
|
+
settings = wandb_setup.singleton().settings_if_loaded
|
29
|
+
if settings and (settings.quiet or 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
|
@@ -8,8 +8,6 @@ import logging
|
|
8
8
|
from multiprocessing.process import BaseProcess
|
9
9
|
from typing import TYPE_CHECKING, Optional
|
10
10
|
|
11
|
-
from wandb.sdk.mailbox import Mailbox
|
12
|
-
|
13
11
|
from .interface_shared import InterfaceShared
|
14
12
|
|
15
13
|
if TYPE_CHECKING:
|
@@ -27,12 +25,11 @@ class InterfaceQueue(InterfaceShared):
|
|
27
25
|
record_q: Optional["Queue[pb.Record]"] = None,
|
28
26
|
result_q: Optional["Queue[pb.Result]"] = None,
|
29
27
|
process: Optional[BaseProcess] = None,
|
30
|
-
mailbox: Optional[Mailbox] = None,
|
31
28
|
) -> None:
|
32
29
|
self.record_q = record_q
|
33
30
|
self.result_q = result_q
|
34
31
|
self._process = process
|
35
|
-
super().__init__(
|
32
|
+
super().__init__()
|
36
33
|
|
37
34
|
def _publish(self, record: "pb.Record", local: Optional[bool] = None) -> None:
|
38
35
|
if self._process and not self._process.is_alive():
|
@@ -10,7 +10,7 @@ from typing import Any, Optional, cast
|
|
10
10
|
|
11
11
|
from wandb.proto import wandb_internal_pb2 as pb
|
12
12
|
from wandb.proto import wandb_telemetry_pb2 as tpb
|
13
|
-
from wandb.sdk.mailbox import
|
13
|
+
from wandb.sdk.mailbox import MailboxHandle
|
14
14
|
from wandb.util import json_dumps_safer, json_friendly
|
15
15
|
|
16
16
|
from .interface import InterfaceBase
|
@@ -19,9 +19,8 @@ logger = logging.getLogger("wandb")
|
|
19
19
|
|
20
20
|
|
21
21
|
class InterfaceShared(InterfaceBase):
|
22
|
-
def __init__(self
|
22
|
+
def __init__(self) -> None:
|
23
23
|
super().__init__()
|
24
|
-
self._mailbox = mailbox
|
25
24
|
|
26
25
|
def _publish_output(self, outdata: pb.OutputRecord) -> None:
|
27
26
|
rec = pb.Record()
|
@@ -67,7 +66,7 @@ class InterfaceShared(InterfaceBase):
|
|
67
66
|
self, job_input: pb.JobInputRequest
|
68
67
|
) -> MailboxHandle[pb.Result]:
|
69
68
|
record = self._make_request(job_input=job_input)
|
70
|
-
return self.
|
69
|
+
return self._deliver(record)
|
71
70
|
|
72
71
|
def _make_stats(self, stats_dict: dict) -> pb.StatsRecord:
|
73
72
|
stats = pb.StatsRecord()
|
@@ -263,6 +262,9 @@ class InterfaceShared(InterfaceBase):
|
|
263
262
|
def _publish(self, record: pb.Record, local: Optional[bool] = None) -> None:
|
264
263
|
raise NotImplementedError
|
265
264
|
|
265
|
+
def _deliver(self, record: pb.Record) -> "MailboxHandle[pb.Result]":
|
266
|
+
raise NotImplementedError
|
267
|
+
|
266
268
|
def _publish_defer(self, state: "pb.DeferRequest.DeferState.V") -> None:
|
267
269
|
defer = pb.DeferRequest(state=state)
|
268
270
|
rec = self._make_request(defer=defer)
|
@@ -333,19 +335,19 @@ class InterfaceShared(InterfaceBase):
|
|
333
335
|
log_artifact: pb.LogArtifactRequest,
|
334
336
|
) -> MailboxHandle[pb.Result]:
|
335
337
|
rec = self._make_request(log_artifact=log_artifact)
|
336
|
-
return self.
|
338
|
+
return self._deliver(rec)
|
337
339
|
|
338
340
|
def _deliver_download_artifact(
|
339
341
|
self, download_artifact: pb.DownloadArtifactRequest
|
340
342
|
) -> MailboxHandle[pb.Result]:
|
341
343
|
rec = self._make_request(download_artifact=download_artifact)
|
342
|
-
return self.
|
344
|
+
return self._deliver(rec)
|
343
345
|
|
344
346
|
def _deliver_link_artifact(
|
345
347
|
self, link_artifact: pb.LinkArtifactRequest
|
346
348
|
) -> MailboxHandle[pb.Result]:
|
347
349
|
rec = self._make_request(link_artifact=link_artifact)
|
348
|
-
return self.
|
350
|
+
return self._deliver(rec)
|
349
351
|
|
350
352
|
def _publish_artifact(self, proto_artifact: pb.ArtifactRecord) -> None:
|
351
353
|
rec = self._make_record(artifact=proto_artifact)
|
@@ -360,7 +362,7 @@ class InterfaceShared(InterfaceBase):
|
|
360
362
|
status: pb.StatusRequest,
|
361
363
|
) -> MailboxHandle[pb.Result]:
|
362
364
|
req = self._make_request(status=status)
|
363
|
-
return self.
|
365
|
+
return self._deliver(req)
|
364
366
|
|
365
367
|
def _publish_exit(self, exit_data: pb.RunExitRecord) -> None:
|
366
368
|
rec = self._make_record(exit=exit_data)
|
@@ -373,110 +375,97 @@ class InterfaceShared(InterfaceBase):
|
|
373
375
|
def _deliver_shutdown(self) -> MailboxHandle[pb.Result]:
|
374
376
|
request = pb.Request(shutdown=pb.ShutdownRequest())
|
375
377
|
record = self._make_record(request=request)
|
376
|
-
return self.
|
377
|
-
|
378
|
-
def _get_mailbox(self) -> Mailbox:
|
379
|
-
mailbox = self._mailbox
|
380
|
-
assert mailbox
|
381
|
-
return mailbox
|
382
|
-
|
383
|
-
def _deliver_record(self, record: pb.Record) -> MailboxHandle[pb.Result]:
|
384
|
-
mailbox = self._get_mailbox()
|
385
|
-
|
386
|
-
handle = mailbox.require_response(record)
|
387
|
-
self._publish(record)
|
388
|
-
|
389
|
-
return handle.map(lambda resp: resp.result_communicate)
|
378
|
+
return self._deliver(record)
|
390
379
|
|
391
380
|
def _deliver_run(self, run: pb.RunRecord) -> MailboxHandle[pb.Result]:
|
392
381
|
record = self._make_record(run=run)
|
393
|
-
return self.
|
382
|
+
return self._deliver(record)
|
394
383
|
|
395
384
|
def _deliver_finish_sync(
|
396
385
|
self,
|
397
386
|
sync_finish: pb.SyncFinishRequest,
|
398
387
|
) -> MailboxHandle[pb.Result]:
|
399
388
|
record = self._make_request(sync_finish=sync_finish)
|
400
|
-
return self.
|
389
|
+
return self._deliver(record)
|
401
390
|
|
402
391
|
def _deliver_run_start(
|
403
392
|
self,
|
404
393
|
run_start: pb.RunStartRequest,
|
405
394
|
) -> MailboxHandle[pb.Result]:
|
406
395
|
record = self._make_request(run_start=run_start)
|
407
|
-
return self.
|
396
|
+
return self._deliver(record)
|
408
397
|
|
409
398
|
def _deliver_get_summary(
|
410
399
|
self,
|
411
400
|
get_summary: pb.GetSummaryRequest,
|
412
401
|
) -> MailboxHandle[pb.Result]:
|
413
402
|
record = self._make_request(get_summary=get_summary)
|
414
|
-
return self.
|
403
|
+
return self._deliver(record)
|
415
404
|
|
416
405
|
def _deliver_get_system_metrics(
|
417
406
|
self, get_system_metrics: pb.GetSystemMetricsRequest
|
418
407
|
) -> MailboxHandle[pb.Result]:
|
419
408
|
record = self._make_request(get_system_metrics=get_system_metrics)
|
420
|
-
return self.
|
409
|
+
return self._deliver(record)
|
421
410
|
|
422
411
|
def _deliver_exit(
|
423
412
|
self,
|
424
413
|
exit_data: pb.RunExitRecord,
|
425
414
|
) -> MailboxHandle[pb.Result]:
|
426
415
|
record = self._make_record(exit=exit_data)
|
427
|
-
return self.
|
416
|
+
return self._deliver(record)
|
428
417
|
|
429
418
|
def deliver_operation_stats(self):
|
430
419
|
record = self._make_request(operation_stats=pb.OperationStatsRequest())
|
431
|
-
return self.
|
420
|
+
return self._deliver(record)
|
432
421
|
|
433
422
|
def _deliver_poll_exit(
|
434
423
|
self,
|
435
424
|
poll_exit: pb.PollExitRequest,
|
436
425
|
) -> MailboxHandle[pb.Result]:
|
437
426
|
record = self._make_request(poll_exit=poll_exit)
|
438
|
-
return self.
|
427
|
+
return self._deliver(record)
|
439
428
|
|
440
429
|
def _deliver_finish_without_exit(
|
441
430
|
self, run_finish_without_exit: pb.RunFinishWithoutExitRequest
|
442
431
|
) -> MailboxHandle[pb.Result]:
|
443
432
|
record = self._make_request(run_finish_without_exit=run_finish_without_exit)
|
444
|
-
return self.
|
433
|
+
return self._deliver(record)
|
445
434
|
|
446
435
|
def _deliver_stop_status(
|
447
436
|
self,
|
448
437
|
stop_status: pb.StopStatusRequest,
|
449
438
|
) -> MailboxHandle[pb.Result]:
|
450
439
|
record = self._make_request(stop_status=stop_status)
|
451
|
-
return self.
|
440
|
+
return self._deliver(record)
|
452
441
|
|
453
442
|
def _deliver_attach(
|
454
443
|
self,
|
455
444
|
attach: pb.AttachRequest,
|
456
445
|
) -> MailboxHandle[pb.Result]:
|
457
446
|
record = self._make_request(attach=attach)
|
458
|
-
return self.
|
447
|
+
return self._deliver(record)
|
459
448
|
|
460
449
|
def _deliver_network_status(
|
461
450
|
self, network_status: pb.NetworkStatusRequest
|
462
451
|
) -> MailboxHandle[pb.Result]:
|
463
452
|
record = self._make_request(network_status=network_status)
|
464
|
-
return self.
|
453
|
+
return self._deliver(record)
|
465
454
|
|
466
455
|
def _deliver_internal_messages(
|
467
456
|
self, internal_message: pb.InternalMessagesRequest
|
468
457
|
) -> MailboxHandle[pb.Result]:
|
469
458
|
record = self._make_request(internal_messages=internal_message)
|
470
|
-
return self.
|
459
|
+
return self._deliver(record)
|
471
460
|
|
472
461
|
def _deliver_request_sampled_history(
|
473
462
|
self, sampled_history: pb.SampledHistoryRequest
|
474
463
|
) -> MailboxHandle[pb.Result]:
|
475
464
|
record = self._make_request(sampled_history=sampled_history)
|
476
|
-
return self.
|
465
|
+
return self._deliver(record)
|
477
466
|
|
478
467
|
def _deliver_request_run_status(
|
479
468
|
self, run_status: pb.RunStatusRequest
|
480
469
|
) -> MailboxHandle[pb.Result]:
|
481
470
|
record = self._make_request(run_status=run_status)
|
482
|
-
return self.
|
471
|
+
return self._deliver(record)
|