wandb 0.19.9__py3-none-win32.whl → 0.19.11__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.
Files changed (156) hide show
  1. wandb/__init__.py +1 -1
  2. wandb/__init__.pyi +6 -3
  3. wandb/_pydantic/__init__.py +14 -8
  4. wandb/_pydantic/base.py +51 -36
  5. wandb/_pydantic/utils.py +73 -0
  6. wandb/_pydantic/v1_compat.py +79 -57
  7. wandb/apis/public/__init__.py +2 -2
  8. wandb/apis/public/api.py +684 -4
  9. wandb/apis/public/artifacts.py +377 -677
  10. wandb/apis/public/automations.py +69 -0
  11. wandb/apis/public/integrations.py +180 -0
  12. wandb/apis/public/projects.py +29 -0
  13. wandb/apis/public/registries/__init__.py +0 -0
  14. wandb/apis/public/registries/_freezable_list.py +179 -0
  15. wandb/apis/public/{registries.py → registries/registries_search.py} +22 -129
  16. wandb/apis/public/registries/registry.py +357 -0
  17. wandb/apis/public/registries/utils.py +140 -0
  18. wandb/apis/public/runs.py +58 -56
  19. wandb/apis/public/utils.py +107 -1
  20. wandb/automations/__init__.py +73 -0
  21. wandb/automations/_filters/__init__.py +40 -0
  22. wandb/automations/_filters/expressions.py +181 -0
  23. wandb/automations/_filters/operators.py +258 -0
  24. wandb/automations/_filters/run_metrics.py +332 -0
  25. wandb/automations/_generated/__init__.py +177 -0
  26. wandb/automations/_generated/create_automation.py +17 -0
  27. wandb/automations/_generated/create_generic_webhook_integration.py +43 -0
  28. wandb/automations/_generated/delete_automation.py +17 -0
  29. wandb/automations/_generated/enums.py +33 -0
  30. wandb/automations/_generated/fragments.py +358 -0
  31. wandb/automations/_generated/generic_webhook_integrations_by_entity.py +22 -0
  32. wandb/automations/_generated/get_automations.py +24 -0
  33. wandb/automations/_generated/get_automations_by_entity.py +26 -0
  34. wandb/automations/_generated/input_types.py +104 -0
  35. wandb/automations/_generated/integrations_by_entity.py +22 -0
  36. wandb/automations/_generated/operations.py +647 -0
  37. wandb/automations/_generated/slack_integrations_by_entity.py +22 -0
  38. wandb/automations/_generated/update_automation.py +17 -0
  39. wandb/automations/_utils.py +237 -0
  40. wandb/automations/_validators.py +165 -0
  41. wandb/automations/actions.py +220 -0
  42. wandb/automations/automations.py +87 -0
  43. wandb/automations/events.py +287 -0
  44. wandb/automations/integrations.py +45 -0
  45. wandb/automations/scopes.py +78 -0
  46. wandb/beta/workflows.py +9 -10
  47. wandb/bin/gpu_stats.exe +0 -0
  48. wandb/bin/wandb-core +0 -0
  49. wandb/cli/cli.py +3 -3
  50. wandb/env.py +11 -0
  51. wandb/integration/keras/keras.py +2 -1
  52. wandb/integration/langchain/wandb_tracer.py +2 -1
  53. wandb/jupyter.py +137 -118
  54. wandb/old/settings.py +4 -1
  55. wandb/old/summary.py +0 -2
  56. wandb/proto/v3/wandb_internal_pb2.py +297 -292
  57. wandb/proto/v3/wandb_settings_pb2.py +2 -2
  58. wandb/proto/v3/wandb_telemetry_pb2.py +10 -10
  59. wandb/proto/v4/wandb_internal_pb2.py +292 -292
  60. wandb/proto/v4/wandb_settings_pb2.py +2 -2
  61. wandb/proto/v4/wandb_telemetry_pb2.py +10 -10
  62. wandb/proto/v5/wandb_internal_pb2.py +292 -292
  63. wandb/proto/v5/wandb_settings_pb2.py +2 -2
  64. wandb/proto/v5/wandb_telemetry_pb2.py +10 -10
  65. wandb/proto/v6/wandb_base_pb2.py +41 -0
  66. wandb/proto/v6/wandb_internal_pb2.py +393 -0
  67. wandb/proto/v6/wandb_server_pb2.py +78 -0
  68. wandb/proto/v6/wandb_settings_pb2.py +58 -0
  69. wandb/proto/v6/wandb_telemetry_pb2.py +52 -0
  70. wandb/proto/wandb_base_pb2.py +2 -0
  71. wandb/proto/wandb_deprecated.py +8 -0
  72. wandb/proto/wandb_internal_pb2.py +3 -1
  73. wandb/proto/wandb_server_pb2.py +2 -0
  74. wandb/proto/wandb_settings_pb2.py +2 -0
  75. wandb/proto/wandb_telemetry_pb2.py +2 -0
  76. wandb/sdk/artifacts/_generated/__init__.py +289 -0
  77. wandb/sdk/artifacts/_generated/add_aliases.py +21 -0
  78. wandb/sdk/artifacts/_generated/artifact_collection_membership_files.py +43 -0
  79. wandb/sdk/artifacts/_generated/artifact_version_files.py +36 -0
  80. wandb/sdk/artifacts/_generated/create_artifact_collection_tag_assignments.py +36 -0
  81. wandb/sdk/artifacts/_generated/delete_aliases.py +21 -0
  82. wandb/sdk/artifacts/_generated/delete_artifact_collection_tag_assignments.py +25 -0
  83. wandb/sdk/artifacts/_generated/delete_artifact_portfolio.py +35 -0
  84. wandb/sdk/artifacts/_generated/delete_artifact_sequence.py +35 -0
  85. wandb/sdk/artifacts/_generated/enums.py +17 -0
  86. wandb/sdk/artifacts/_generated/fetch_linked_artifacts.py +67 -0
  87. wandb/sdk/artifacts/_generated/fragments.py +221 -0
  88. wandb/sdk/artifacts/_generated/input_types.py +28 -0
  89. wandb/sdk/artifacts/_generated/move_artifact_collection.py +35 -0
  90. wandb/sdk/artifacts/_generated/operations.py +611 -0
  91. wandb/sdk/artifacts/_generated/project_artifact_collection.py +101 -0
  92. wandb/sdk/artifacts/_generated/project_artifact_collections.py +33 -0
  93. wandb/sdk/artifacts/_generated/project_artifact_type.py +24 -0
  94. wandb/sdk/artifacts/_generated/project_artifact_types.py +24 -0
  95. wandb/sdk/artifacts/_generated/project_artifacts.py +42 -0
  96. wandb/sdk/artifacts/_generated/run_input_artifacts.py +51 -0
  97. wandb/sdk/artifacts/_generated/run_output_artifacts.py +51 -0
  98. wandb/sdk/artifacts/_generated/update_artifact.py +26 -0
  99. wandb/sdk/artifacts/_generated/update_artifact_portfolio.py +35 -0
  100. wandb/sdk/artifacts/_generated/update_artifact_sequence.py +35 -0
  101. wandb/sdk/artifacts/_graphql_fragments.py +57 -79
  102. wandb/sdk/artifacts/_validators.py +120 -1
  103. wandb/sdk/artifacts/artifact.py +419 -215
  104. wandb/sdk/artifacts/artifact_file_cache.py +4 -6
  105. wandb/sdk/artifacts/artifact_manifest_entry.py +13 -3
  106. wandb/sdk/artifacts/storage_handlers/azure_handler.py +1 -0
  107. wandb/sdk/artifacts/storage_policies/wandb_storage_policy.py +182 -1
  108. wandb/sdk/artifacts/storage_policy.py +3 -0
  109. wandb/sdk/data_types/base_types/media.py +2 -3
  110. wandb/sdk/data_types/base_types/wb_value.py +34 -11
  111. wandb/sdk/data_types/html.py +36 -9
  112. wandb/sdk/data_types/image.py +12 -12
  113. wandb/sdk/data_types/table.py +5 -0
  114. wandb/sdk/data_types/trace_tree.py +2 -0
  115. wandb/sdk/data_types/utils.py +1 -1
  116. wandb/sdk/data_types/video.py +59 -57
  117. wandb/sdk/interface/interface.py +4 -3
  118. wandb/sdk/internal/internal_api.py +21 -31
  119. wandb/sdk/internal/profiler.py +6 -5
  120. wandb/sdk/internal/run.py +13 -6
  121. wandb/sdk/internal/sender.py +5 -2
  122. wandb/sdk/launch/sweeps/utils.py +8 -0
  123. wandb/sdk/lib/apikey.py +25 -4
  124. wandb/sdk/lib/asyncio_compat.py +1 -1
  125. wandb/sdk/lib/deprecate.py +13 -22
  126. wandb/sdk/lib/disabled.py +2 -1
  127. wandb/sdk/lib/printer.py +37 -8
  128. wandb/sdk/lib/printer_asyncio.py +46 -0
  129. wandb/sdk/lib/redirect.py +10 -5
  130. wandb/sdk/projects/_generated/__init__.py +47 -0
  131. wandb/sdk/projects/_generated/delete_project.py +22 -0
  132. wandb/sdk/projects/_generated/enums.py +4 -0
  133. wandb/sdk/projects/_generated/fetch_registry.py +22 -0
  134. wandb/sdk/projects/_generated/fragments.py +41 -0
  135. wandb/sdk/projects/_generated/input_types.py +13 -0
  136. wandb/sdk/projects/_generated/operations.py +88 -0
  137. wandb/sdk/projects/_generated/rename_project.py +27 -0
  138. wandb/sdk/projects/_generated/upsert_registry_project.py +27 -0
  139. wandb/sdk/service/server_sock.py +19 -14
  140. wandb/sdk/service/service.py +18 -8
  141. wandb/sdk/service/streams.py +5 -0
  142. wandb/sdk/verify/verify.py +6 -3
  143. wandb/sdk/wandb_init.py +217 -70
  144. wandb/sdk/wandb_login.py +13 -4
  145. wandb/sdk/wandb_run.py +419 -295
  146. wandb/sdk/wandb_settings.py +27 -10
  147. wandb/sdk/wandb_setup.py +61 -0
  148. wandb/util.py +33 -29
  149. {wandb-0.19.9.dist-info → wandb-0.19.11.dist-info}/METADATA +5 -5
  150. {wandb-0.19.9.dist-info → wandb-0.19.11.dist-info}/RECORD +153 -83
  151. wandb/_globals.py +0 -19
  152. wandb/sdk/internal/_generated/base.py +0 -226
  153. wandb/sdk/internal/_generated/typing_compat.py +0 -14
  154. {wandb-0.19.9.dist-info → wandb-0.19.11.dist-info}/WHEEL +0 -0
  155. {wandb-0.19.9.dist-info → wandb-0.19.11.dist-info}/entry_points.txt +0 -0
  156. {wandb-0.19.9.dist-info → wandb-0.19.11.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,87 @@
1
+ # ruff: noqa: UP007 # Avoid using `X | Y` for union fields, as this can cause issues with pydantic < 2.6
2
+
3
+ from __future__ import annotations
4
+
5
+ from datetime import datetime
6
+ from typing import Optional
7
+
8
+ from pydantic import Field
9
+ from typing_extensions import Annotated
10
+
11
+ from wandb._pydantic import GQLBase, GQLId
12
+
13
+ from ._generated import TriggerFields
14
+ from .actions import InputAction, SavedAction
15
+ from .events import InputEvent, SavedEvent
16
+ from .scopes import AutomationScope
17
+
18
+
19
+ # ------------------------------------------------------------------------------
20
+ # Saved types: for parsing response data from saved automations
21
+ class Automation(TriggerFields):
22
+ """A local instance of a saved W&B automation."""
23
+
24
+ id: GQLId
25
+
26
+ created_at: Annotated[datetime, Field(repr=False, frozen=True, alias="createdAt")]
27
+ """The date and time when this automation was created."""
28
+
29
+ updated_at: Annotated[
30
+ Optional[datetime], Field(repr=False, frozen=True, alias="updatedAt")
31
+ ] = None
32
+ """The date and time when this automation was last updated, if applicable."""
33
+
34
+ name: str
35
+ """The name of this automation."""
36
+
37
+ description: Optional[str]
38
+ """An optional description of this automation."""
39
+
40
+ enabled: bool
41
+ """Whether this automation is enabled. Only enabled automations will trigger."""
42
+
43
+ event: SavedEvent
44
+ """The event that will trigger this automation."""
45
+
46
+ scope: AutomationScope
47
+ """The scope in which the triggering event must occur."""
48
+
49
+ action: SavedAction
50
+ """The action that will execute when this automation is triggered."""
51
+
52
+
53
+ class NewAutomation(GQLBase, extra="forbid", validate_default=False):
54
+ """A new automation to be created."""
55
+
56
+ name: Optional[str] = None
57
+ """The name of this automation."""
58
+
59
+ description: Optional[str] = None
60
+ """An optional description of this automation."""
61
+
62
+ enabled: Optional[bool] = None
63
+ """Whether this automation is enabled. Only enabled automations will trigger."""
64
+
65
+ event: Optional[InputEvent] = None
66
+ """The event that will trigger this automation."""
67
+
68
+ # Ensure that the event and its scope are always consistent, if the event is set.
69
+ @property
70
+ def scope(self) -> Optional[AutomationScope]:
71
+ """The scope in which the triggering event must occur."""
72
+ return self.event.scope if self.event else None
73
+
74
+ @scope.setter
75
+ def scope(self, value: AutomationScope) -> None:
76
+ if self.event is None:
77
+ raise ValueError("Cannot set `scope` for an automation with no `event`")
78
+ self.event.scope = value
79
+
80
+ action: Optional[InputAction] = None
81
+ """The action that will execute when this automation is triggered."""
82
+
83
+
84
+ __all__ = [
85
+ "Automation",
86
+ "NewAutomation",
87
+ ]
@@ -0,0 +1,287 @@
1
+ """Events that trigger W&B Automations."""
2
+
3
+ # ruff: noqa: UP007 # Avoid using `X | Y` for union fields, as this can cause issues with pydantic < 2.6
4
+
5
+ from __future__ import annotations
6
+
7
+ from typing import TYPE_CHECKING, Any, Literal, Optional, Union
8
+
9
+ from pydantic import Field
10
+ from typing_extensions import Annotated, Self, get_args
11
+
12
+ from wandb._pydantic import (
13
+ GQLBase,
14
+ SerializedToJson,
15
+ ensure_json,
16
+ field_validator,
17
+ model_validator,
18
+ pydantic_isinstance,
19
+ )
20
+
21
+ from ._filters import And, MongoLikeFilter, Or
22
+ from ._filters.expressions import FilterableField
23
+ from ._filters.run_metrics import MetricChangeFilter, MetricThresholdFilter, MetricVal
24
+ from ._generated import FilterEventFields
25
+ from ._validators import LenientStrEnum, simplify_op
26
+ from .actions import InputAction, InputActionTypes, SavedActionTypes
27
+ from .scopes import ArtifactCollectionScope, AutomationScope, ProjectScope
28
+
29
+ if TYPE_CHECKING:
30
+ from .automations import NewAutomation
31
+
32
+
33
+ # NOTE: Re-defined publicly with a more readable name for easier access
34
+ class EventType(LenientStrEnum):
35
+ """The type of event that triggers an automation."""
36
+
37
+ # ---------------------------------------------------------------------------
38
+ # Events triggered by GraphQL mutations
39
+ UPDATE_ARTIFACT_ALIAS = "UPDATE_ARTIFACT_ALIAS" # NOTE: Avoid in new automations
40
+
41
+ CREATE_ARTIFACT = "CREATE_ARTIFACT"
42
+ ADD_ARTIFACT_ALIAS = "ADD_ARTIFACT_ALIAS"
43
+ LINK_ARTIFACT = "LINK_MODEL"
44
+ # Note: "LINK_MODEL" is the (legacy) value expected by the backend, but we
45
+ # name it "LINK_ARTIFACT" here in the public API for clarity and consistency.
46
+
47
+ # ---------------------------------------------------------------------------
48
+ # Events triggered by Run conditions
49
+ RUN_METRIC_THRESHOLD = "RUN_METRIC"
50
+ RUN_METRIC_CHANGE = "RUN_METRIC_CHANGE"
51
+
52
+
53
+ # ------------------------------------------------------------------------------
54
+ # Saved types: for parsing response data from saved automations
55
+
56
+
57
+ # Note: In GQL responses containing saved automation data, the filter is wrapped in an extra `filter` key.
58
+ class _WrappedSavedEventFilter(GQLBase): # from: TriggeringFilterEvent
59
+ filter: SerializedToJson[MongoLikeFilter] = And()
60
+
61
+
62
+ class _WrappedMetricFilter(GQLBase): # from: RunMetricFilter
63
+ threshold_filter: Optional[MetricThresholdFilter] = None
64
+ change_filter: Optional[MetricChangeFilter] = None
65
+
66
+ @model_validator(mode="before")
67
+ @classmethod
68
+ def _wrap_metric_filter(cls, v: Any) -> Any:
69
+ if pydantic_isinstance(v, MetricThresholdFilter):
70
+ return cls(threshold_filter=v)
71
+ if pydantic_isinstance(v, MetricChangeFilter):
72
+ return cls(change_filter=v)
73
+ return v
74
+
75
+ @model_validator(mode="after")
76
+ def _ensure_exactly_one_set(self) -> Self:
77
+ set_fields = [name for name, val in self if (val is not None)]
78
+
79
+ if not set_fields:
80
+ all_names = ", ".join(map(repr, type(self).model_fields))
81
+ raise ValueError(f"Expected one of: {all_names}")
82
+
83
+ if len(set_fields) > 1:
84
+ set_names = ", ".join(map(repr, set_fields))
85
+ raise ValueError(f"Expected exactly one metric filter, got: {set_names}")
86
+
87
+ return self
88
+
89
+ @property
90
+ def event_type(self) -> EventType:
91
+ if self.threshold_filter is not None:
92
+ return EventType.RUN_METRIC_THRESHOLD
93
+ if self.change_filter is not None:
94
+ return EventType.RUN_METRIC_CHANGE
95
+ raise RuntimeError("Expected one of: `threshold_filter` or `change_filter`")
96
+
97
+
98
+ class RunMetricFilter(GQLBase): # from: TriggeringRunMetricEvent
99
+ run: Annotated[SerializedToJson[MongoLikeFilter], Field(alias="run_filter")] = And()
100
+ metric: Annotated[_WrappedMetricFilter, Field(alias="run_metric_filter")]
101
+
102
+ # ------------------------------------------------------------------------------
103
+ legacy_metric_filter: Annotated[
104
+ Optional[SerializedToJson[MetricThresholdFilter]],
105
+ Field(alias="metric_filter", deprecated=True),
106
+ ] = None
107
+ """Deprecated legacy field that was previously used to define run metric threshold events.
108
+
109
+ For new automations, use the `metric` field (`run_metric_filter` JSON alias) instead.
110
+ """
111
+
112
+ @model_validator(mode="before")
113
+ @classmethod
114
+ def _wrap_metric_filter(cls, v: Any) -> Any:
115
+ if pydantic_isinstance(v, (MetricThresholdFilter, MetricChangeFilter)):
116
+ # If only an (unnested) metric filter is given, nest it under the
117
+ # `metric` field, delegating to inner validator(s) for further
118
+ # wrapping/nesting, if needed.
119
+ # This is necessary to conform to the expected backend schema.
120
+ return cls(metric=v)
121
+ return v
122
+
123
+ @field_validator("run", mode="after")
124
+ def _wrap_run_filter(cls, v: MongoLikeFilter) -> Any:
125
+ v_new = simplify_op(v)
126
+ return v_new if pydantic_isinstance(v_new, And) else And(and_=[v_new])
127
+
128
+
129
+ class SavedEvent(FilterEventFields): # from: FilterEventTriggeringCondition
130
+ """A triggering event from a saved automation."""
131
+
132
+ event_type: Annotated[EventType, Field(frozen=True)] # type: ignore[assignment]
133
+
134
+ # We override the type of the `filter` field in order to enforce the expected
135
+ # structure for the JSON data when validating and serializing.
136
+ filter: SerializedToJson[Union[_WrappedSavedEventFilter, RunMetricFilter]]
137
+ """The condition(s) under which this event triggers an automation."""
138
+
139
+
140
+ # ------------------------------------------------------------------------------
141
+ # Input types: for creating or updating automations
142
+
143
+
144
+ # Note: The GQL input for "eventFilter" does NOT wrap the filter in an extra `filter` key, unlike the
145
+ # eventFilter returned in responses for saved automations.
146
+ class _BaseEventInput(GQLBase):
147
+ event_type: EventType
148
+
149
+ scope: AutomationScope
150
+ """The scope of the event."""
151
+
152
+ filter: SerializedToJson[Any]
153
+
154
+ def then(self, action: InputAction) -> NewAutomation:
155
+ """Define a new Automation in which this event triggers the given action."""
156
+ from .automations import NewAutomation
157
+
158
+ if isinstance(action, (InputActionTypes, SavedActionTypes)):
159
+ return NewAutomation(event=self, action=action)
160
+
161
+ raise TypeError(f"Expected a valid action, got: {type(action).__qualname__!r}")
162
+
163
+ def __rshift__(self, other: InputAction) -> NewAutomation:
164
+ """Implements `event >> action` to define an Automation with this event and action."""
165
+ return self.then(other)
166
+
167
+
168
+ # ------------------------------------------------------------------------------
169
+ # Events that trigger on specific mutations in the backend
170
+ class _BaseMutationEventInput(_BaseEventInput):
171
+ filter: SerializedToJson[MongoLikeFilter] = And()
172
+ """Additional condition(s), if any, that must be met for this event to trigger an automation."""
173
+
174
+ @field_validator("filter", mode="after")
175
+ def _wrap_filter(cls, v: Any) -> Any:
176
+ """Ensure the given filter is wrapped like: `{"$or": [{"$and": [<original_filter>]}]}`.
177
+
178
+ This is awkward but necessary, because the frontend expects this format.
179
+ """
180
+ v_new = simplify_op(v)
181
+ v_new = v_new if pydantic_isinstance(v_new, And) else And(and_=[v_new])
182
+ return Or(or_=[v_new])
183
+
184
+
185
+ class OnLinkArtifact(_BaseMutationEventInput):
186
+ """A new artifact is linked to a collection."""
187
+
188
+ event_type: Literal[EventType.LINK_ARTIFACT] = EventType.LINK_ARTIFACT
189
+
190
+
191
+ class OnAddArtifactAlias(_BaseMutationEventInput):
192
+ """A new alias is assigned to an artifact."""
193
+
194
+ event_type: Literal[EventType.ADD_ARTIFACT_ALIAS] = EventType.ADD_ARTIFACT_ALIAS
195
+
196
+
197
+ class OnCreateArtifact(_BaseMutationEventInput):
198
+ """A new artifact is created."""
199
+
200
+ event_type: Literal[EventType.CREATE_ARTIFACT] = EventType.CREATE_ARTIFACT
201
+
202
+ scope: ArtifactCollectionScope
203
+ """The scope of the event: only artifact collections are valid scopes for this event."""
204
+
205
+
206
+ # ------------------------------------------------------------------------------
207
+ # Events that trigger on run conditions
208
+ class _BaseRunEventInput(_BaseEventInput):
209
+ scope: ProjectScope
210
+ """The scope of the event: only projects are valid scopes for this event."""
211
+
212
+
213
+ class OnRunMetric(_BaseRunEventInput):
214
+ """A run metric satisfies a user-defined condition."""
215
+
216
+ event_type: Literal[EventType.RUN_METRIC_THRESHOLD, EventType.RUN_METRIC_CHANGE]
217
+
218
+ filter: SerializedToJson[RunMetricFilter]
219
+ """Run and/or metric condition(s) that must be satisfied for this event to trigger an automation."""
220
+
221
+ @model_validator(mode="before")
222
+ @classmethod
223
+ def _infer_event_type(cls, data: Any) -> Any:
224
+ """Infer the event type at validation time from the inner filter.
225
+
226
+ This allows this class to accommodate both "threshold" and "change" metric
227
+ filter types, which are can only be determined after parsing and validating
228
+ the inner JSON data.
229
+ """
230
+ if isinstance(data, dict) and (raw_filter := data.get("filter")):
231
+ # At this point, `raw_filter` may or may not be JSON-serialized
232
+ parsed_filter = RunMetricFilter.model_validate_json(ensure_json(raw_filter))
233
+ return {**data, "event_type": parsed_filter.metric.event_type}
234
+
235
+ return data
236
+
237
+
238
+ # for type annotations
239
+ InputEvent = Annotated[
240
+ Union[
241
+ OnLinkArtifact,
242
+ OnAddArtifactAlias,
243
+ OnCreateArtifact,
244
+ OnRunMetric,
245
+ ],
246
+ Field(discriminator="event_type"),
247
+ ]
248
+ # for runtime type checks
249
+ InputEventTypes: tuple[type, ...] = get_args(InputEvent.__origin__) # type: ignore[attr-defined]
250
+
251
+
252
+ # ----------------------------------------------------------------------------
253
+
254
+
255
+ class RunEvent:
256
+ name = FilterableField(server_name="display_name")
257
+ # `Run.name` is actually filtered on `Run.display_name` in the backend.
258
+ # We can't reasonably expect users to know this a priori, so
259
+ # automatically fix it here.
260
+
261
+ @staticmethod
262
+ def metric(name: str) -> MetricVal:
263
+ """Define a metric filter condition."""
264
+ return MetricVal(name=name)
265
+
266
+
267
+ class ArtifactEvent:
268
+ alias = FilterableField()
269
+
270
+
271
+ MetricThresholdFilter.model_rebuild()
272
+ RunMetricFilter.model_rebuild()
273
+ _WrappedSavedEventFilter.model_rebuild()
274
+
275
+ OnLinkArtifact.model_rebuild()
276
+ OnAddArtifactAlias.model_rebuild()
277
+ OnCreateArtifact.model_rebuild()
278
+ OnRunMetric.model_rebuild()
279
+
280
+ __all__ = [
281
+ "EventType",
282
+ *(cls.__name__ for cls in InputEventTypes),
283
+ "RunEvent",
284
+ "ArtifactEvent",
285
+ "MetricThresholdFilter",
286
+ "MetricChangeFilter",
287
+ ]
@@ -0,0 +1,45 @@
1
+ from typing import Union
2
+
3
+ from pydantic import Field
4
+ from typing_extensions import Annotated
5
+
6
+ from wandb._pydantic import GQLBase
7
+ from wandb.automations._generated import (
8
+ GenericWebhookIntegrationFields,
9
+ SlackIntegrationFields,
10
+ )
11
+
12
+
13
+ class SlackIntegration(SlackIntegrationFields):
14
+ team_name: str
15
+ """The name of the Slack workspace (not the W&B team) that this integration is associated with."""
16
+
17
+ channel_name: str
18
+ """The name of the Slack channel that this integration will post messages to."""
19
+
20
+
21
+ class WebhookIntegration(GenericWebhookIntegrationFields):
22
+ name: str
23
+ """The name of this webhook integration."""
24
+
25
+ url_endpoint: str
26
+ """The URL that this webhook will POST events to."""
27
+
28
+
29
+ Integration = Annotated[
30
+ Union[SlackIntegration, WebhookIntegration],
31
+ Field(discriminator="typename__"),
32
+ ]
33
+
34
+
35
+ # For parsing integration instances from paginated responses
36
+ class _IntegrationEdge(GQLBase):
37
+ cursor: str
38
+ node: Integration
39
+
40
+
41
+ __all__ = [
42
+ "Integration",
43
+ "SlackIntegration",
44
+ "WebhookIntegration",
45
+ ]
@@ -0,0 +1,78 @@
1
+ """Scopes in which a W&B Automation can be triggered."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Literal, Union
6
+
7
+ from pydantic import BeforeValidator, Field
8
+ from typing_extensions import Annotated, TypeAlias, get_args
9
+
10
+ from wandb._pydantic import GQLBase
11
+ from wandb.automations._generated import (
12
+ ArtifactPortfolioScopeFields,
13
+ ArtifactSequenceScopeFields,
14
+ ProjectScopeFields,
15
+ )
16
+
17
+ from ._validators import LenientStrEnum, to_scope
18
+
19
+
20
+ # NOTE: Re-defined publicly with a more readable name for easier access
21
+ class ScopeType(LenientStrEnum):
22
+ """The kind of scope that triggers an automation."""
23
+
24
+ PROJECT = "PROJECT"
25
+ ARTIFACT_COLLECTION = "ARTIFACT_COLLECTION"
26
+
27
+
28
+ class _BaseScope(GQLBase):
29
+ scope_type: Annotated[ScopeType, Field(frozen=True)]
30
+
31
+
32
+ class _ArtifactSequenceScope(_BaseScope, ArtifactSequenceScopeFields):
33
+ """An automation scope defined by a specific `ArtifactSequence`."""
34
+
35
+ scope_type: Literal[ScopeType.ARTIFACT_COLLECTION] = ScopeType.ARTIFACT_COLLECTION
36
+
37
+
38
+ class _ArtifactPortfolioScope(_BaseScope, ArtifactPortfolioScopeFields):
39
+ """An automation scope defined by a specific `ArtifactPortfolio` (e.g. a registry collection)."""
40
+
41
+ scope_type: Literal[ScopeType.ARTIFACT_COLLECTION] = ScopeType.ARTIFACT_COLLECTION
42
+
43
+
44
+ # for type annotations
45
+ ArtifactCollectionScope = Annotated[
46
+ Union[_ArtifactSequenceScope, _ArtifactPortfolioScope],
47
+ BeforeValidator(to_scope),
48
+ Field(discriminator="typename__"),
49
+ ]
50
+ """An automation scope defined by a specific `ArtifactCollection`."""
51
+
52
+ # for runtime type checks
53
+ ArtifactCollectionScopeTypes: tuple[type, ...] = get_args(
54
+ ArtifactCollectionScope.__origin__ # type: ignore[attr-defined]
55
+ )
56
+
57
+
58
+ class ProjectScope(_BaseScope, ProjectScopeFields):
59
+ """An automation scope defined by a specific `Project`."""
60
+
61
+ scope_type: Literal[ScopeType.PROJECT] = ScopeType.PROJECT
62
+
63
+
64
+ # for type annotations
65
+ AutomationScope: TypeAlias = Annotated[
66
+ Union[_ArtifactSequenceScope, _ArtifactPortfolioScope, ProjectScope],
67
+ BeforeValidator(to_scope),
68
+ Field(discriminator="typename__"),
69
+ ]
70
+ # for runtime type checks
71
+ AutomationScopeTypes: tuple[type, ...] = get_args(AutomationScope.__origin__) # type: ignore[attr-defined]
72
+
73
+
74
+ __all__ = [
75
+ "ScopeType",
76
+ "ArtifactCollectionScope",
77
+ "ProjectScope",
78
+ ]
wandb/beta/workflows.py CHANGED
@@ -5,6 +5,7 @@ from typing import Any, Dict, List, Optional, Union
5
5
  import wandb
6
6
  import wandb.data_types as data_types
7
7
  from wandb.data_types import _SavedModel
8
+ from wandb.sdk import wandb_setup
8
9
  from wandb.sdk.artifacts.artifact import Artifact
9
10
  from wandb.sdk.artifacts.artifact_manifest_entry import ArtifactManifestEntry
10
11
 
@@ -85,12 +86,13 @@ def _log_artifact_version(
85
86
  Artifact
86
87
 
87
88
  """
88
- if wandb.run is None:
89
+ run = wandb_setup._setup(start_service=False).most_recent_active_run
90
+ if not run:
89
91
  run = wandb.init(
90
- project=project, job_type=job_type, settings=wandb.Settings(silent="true")
92
+ project=project,
93
+ job_type=job_type,
94
+ settings=wandb.Settings(silent=True),
91
95
  )
92
- else:
93
- run = wandb.run
94
96
 
95
97
  if not scope_project:
96
98
  name = f"{name}-{run.id}"
@@ -124,7 +126,7 @@ def log_model(
124
126
 
125
127
  Supported frameworks include PyTorch, Keras, Tensorflow, Scikit-learn, etc. Under
126
128
  the hood, we create a model artifact, bind it to the run that produced this model,
127
- associate it with the latest metrics logged with `wandb.log(...)` and more.
129
+ associate it with the latest metrics logged with `run.log(...)` and more.
128
130
 
129
131
  Args:
130
132
  model_obj: any model object created with the following ML frameworks: PyTorch,
@@ -215,8 +217,7 @@ def use_model(aliased_path: str, unsafe: bool = False) -> "_SavedModel":
215
217
  )
216
218
 
217
219
  # Returns a _SavedModel instance
218
- if wandb.run:
219
- run = wandb.run
220
+ if run := wandb_setup._setup(start_service=False).most_recent_active_run:
220
221
  artifact = run.use_artifact(aliased_path)
221
222
  sm = artifact.get("index")
222
223
 
@@ -261,9 +262,7 @@ def link_model(
261
262
  """
262
263
  aliases = wandb.util._resolve_aliases(aliases)
263
264
 
264
- if wandb.run:
265
- run = wandb.run
266
-
265
+ if run := wandb_setup._setup(start_service=False).most_recent_active_run:
267
266
  # _artifact_source, if it exists, points to a Public Artifact.
268
267
  # Its existence means that _SavedModel was deserialized from a logged artifact, most likely from `use_model`.
269
268
  if model._artifact_source:
wandb/bin/gpu_stats.exe CHANGED
Binary file
wandb/bin/wandb-core CHANGED
Binary file
wandb/cli/cli.py CHANGED
@@ -83,14 +83,13 @@ def cli_unsupported(argument):
83
83
 
84
84
  class ClickWandbException(ClickException):
85
85
  def format_message(self):
86
- # log_file = util.get_log_file_path()
87
- log_file = ""
88
86
  orig_type = f"{self.orig_type.__module__}.{self.orig_type.__name__}"
89
87
  if issubclass(self.orig_type, Error):
90
88
  return click.style(str(self.message), fg="red")
91
89
  else:
92
90
  return (
93
- f"An Exception was raised, see {log_file} for full traceback.\n"
91
+ f"An Exception was raised, see {_wandb_log_path} for full"
92
+ " traceback.\n"
94
93
  f"{orig_type}: {self.message}"
95
94
  )
96
95
 
@@ -257,6 +256,7 @@ def login(key, host, cloud, relogin, anonymously, verify, no_offline=False):
257
256
  key=key,
258
257
  relogin=relogin,
259
258
  verify=verify,
259
+ referrer="models",
260
260
  )
261
261
 
262
262
 
wandb/env.py CHANGED
@@ -88,6 +88,7 @@ LAUNCH_QUEUE_NAME = "WANDB_LAUNCH_QUEUE_NAME"
88
88
  LAUNCH_QUEUE_ENTITY = "WANDB_LAUNCH_QUEUE_ENTITY"
89
89
  LAUNCH_TRACE_ID = "WANDB_LAUNCH_TRACE_ID"
90
90
  _REQUIRE_LEGACY_SERVICE = "WANDB_X_REQUIRE_LEGACY_SERVICE"
91
+ ENABLE_DCGM_PROFILING = "WANDB_ENABLE_DCGM_PROFILING"
91
92
 
92
93
  # For testing, to be removed in future version
93
94
  USE_V1_ARTIFACTS = "_WANDB_USE_V1_ARTIFACTS"
@@ -177,6 +178,16 @@ def ssl_disabled() -> bool:
177
178
  return _env_as_bool(DISABLE_SSL, default="False")
178
179
 
179
180
 
181
+ def dcgm_profiling_enabled() -> bool:
182
+ """Checks whether collecting profiling metrics for Nvidia GPUs using DCGM is requested.
183
+
184
+ Note: Enabling this feature can lead to increased resource usage
185
+ compared to standard monitoring.
186
+ Requires the `nvidia-dcgm` service to be running on the machine.
187
+ """
188
+ return _env_as_bool(ENABLE_DCGM_PROFILING, default="False")
189
+
190
+
180
191
  def get_error_reporting(
181
192
  default: bool | str = True,
182
193
  env: MutableMapping | None = None,
@@ -12,8 +12,9 @@ import tensorflow as tf
12
12
  import tensorflow.keras.backend as K # noqa: N812
13
13
 
14
14
  import wandb
15
+ from wandb.proto.wandb_deprecated import Deprecated
15
16
  from wandb.sdk.integration_utils.data_logging import ValidationDataLogger
16
- from wandb.sdk.lib.deprecate import Deprecated, deprecate
17
+ from wandb.sdk.lib.deprecate import deprecate
17
18
  from wandb.util import add_import_hook
18
19
 
19
20
 
@@ -18,6 +18,7 @@ will be raised when importing this module.
18
18
  from packaging import version
19
19
 
20
20
  import wandb.util
21
+ from wandb.proto.wandb_deprecated import Deprecated
21
22
  from wandb.sdk.lib import deprecate
22
23
 
23
24
  langchain = wandb.util.get_module(
@@ -40,7 +41,7 @@ class WandbTracer(WandbTracer):
40
41
  def __init__(self, *args, **kwargs):
41
42
  super().__init__(*args, **kwargs)
42
43
  deprecate.deprecate(
43
- field_name=deprecate.Deprecated.langchain_tracer,
44
+ field_name=Deprecated.langchain_tracer,
44
45
  warning_message="This feature is deprecated and has been moved to `langchain`. Enable tracing by setting "
45
46
  "LANGCHAIN_WANDB_TRACING=true in your environment. See the documentation at "
46
47
  "https://python.langchain.com/docs/ecosystem/integrations/agent_with_wandb_tracing for guidance. "