From 4f4109cbc4ca667805dbcac730cebd305501ee35 Mon Sep 17 00:00:00 2001 From: monoxgas Date: Mon, 7 Jul 2025 11:26:30 -0600 Subject: [PATCH 1/3] Exclude @ symbol from label filters --- docs/sdk/api.mdx | 4 ++-- docs/sdk/data_types.mdx | 16 +++++++++++++++- dreadnode/util.py | 4 ++-- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/docs/sdk/api.mdx b/docs/sdk/api.mdx index fa742891..b5017b0f 100644 --- a/docs/sdk/api.mdx +++ b/docs/sdk/api.mdx @@ -981,7 +981,7 @@ Timestamp when the metric was recorded. ### value ```python -value: float +value: float | None ``` Value of the metric. @@ -1259,7 +1259,7 @@ Exception details if the run failed. ### id ```python -id: ULID +id: ULID | str ``` Unique identifier for the run. diff --git a/docs/sdk/data_types.mdx b/docs/sdk/data_types.mdx index 21cc612e..c8d1aaae 100644 --- a/docs/sdk/data_types.mdx +++ b/docs/sdk/data_types.mdx @@ -72,6 +72,11 @@ def __init__( caption: Optional caption for the audio format: Optional format to use (default is wav for numpy arrays) """ + if sf is None: + raise ImportError( + "Audio processing requires optional dependencies. " + "Install with: pip install dreadnode[multimodal]" + ) self._data = data self._sample_rate = sample_rate self._caption = caption @@ -178,6 +183,10 @@ def __init__( caption: Optional caption for the image format: Optional format to use when saving (png, jpg, etc.) """ + if PILImage is None: + raise ImportError( + "Image processing requires PIL (Pillow). Install with: pip install dreadnode[multimodal]" + ) self._data = data self._mode = mode self._caption = caption @@ -555,8 +564,13 @@ def to_serializable(self) -> tuple[bytes, dict[str, t.Any]]: return self._process_bytes() if isinstance(self._data, (np.ndarray, list)): return self._process_numpy_array() - if isinstance(self._data, VideoClip): + if VideoClip is not None and isinstance(self._data, VideoClip): return self._process_moviepy_clip() + if VideoClip is None and hasattr(self._data, "write_videofile"): + raise ImportError( + "MoviePy VideoClip detected but moviepy not installed. " + "Install with: pip install dreadnode[multimodal]" + ) raise TypeError(f"Unsupported video data type: {type(self._data)}") ``` diff --git a/dreadnode/util.py b/dreadnode/util.py index 706ea4cb..9380c391 100644 --- a/dreadnode/util.py +++ b/dreadnode/util.py @@ -30,9 +30,9 @@ def clean_str(s: str) -> str: """ - Clean a string by replacing all non-alphanumeric characters with underscores. + Clean a string by replacing all non-alphanumeric characters (except `/` and `@`) with underscores. """ - return re.sub(r"[^\w/]+", "_", s.lower()) + return re.sub(r"[^\w/@]+", "_", s.lower()) def safe_repr(obj: t.Any) -> str: From 2a454d716c50452e09f820aea64aecbeec9a5f07 Mon Sep 17 00:00:00 2001 From: monoxgas Date: Mon, 7 Jul 2025 11:27:41 -0600 Subject: [PATCH 2/3] Allow tasks to be called outside runs --- dreadnode/task.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/dreadnode/task.py b/dreadnode/task.py index af1ab0c4..8e23c908 100644 --- a/dreadnode/task.py +++ b/dreadnode/task.py @@ -8,7 +8,7 @@ from opentelemetry.trace import Tracer from dreadnode.metric import Scorer, ScorerCallable -from dreadnode.tracing.span import TaskSpan, current_run_span +from dreadnode.tracing.span import Span, TaskSpan, current_run_span from dreadnode.types import INHERITED, Inherited P = t.ParamSpec("P") @@ -326,6 +326,19 @@ async def run(self, *args: P.args, **kwargs: P.kwargs) -> TaskSpan[R]: return span async def __call__(self, *args: P.args, **kwargs: P.kwargs) -> R: + if not current_run_span.get(): + with Span( + self.name, + self.attributes, + self.tracer, + label=self.label, + tags=self.tags, + ): + result = self.func(*args, **kwargs) + if inspect.isawaitable(result): + result = await result + return result + span = await self.run(*args, **kwargs) return span.output From bf777487a7ff240f00daead50ad38644cb6e329b Mon Sep 17 00:00:00 2001 From: monoxgas Date: Mon, 7 Jul 2025 11:52:41 -0600 Subject: [PATCH 3/3] Fixing some docstring examples --- docs/sdk/main.mdx | 68 +++++++++++++++++++++++------------------------ dreadnode/main.py | 42 ++++++++++++++--------------- 2 files changed, 55 insertions(+), 55 deletions(-) diff --git a/docs/sdk/main.mdx b/docs/sdk/main.mdx index 7538c79b..d382da95 100644 --- a/docs/sdk/main.mdx +++ b/docs/sdk/main.mdx @@ -505,11 +505,11 @@ prompt and the resulting output. Example ```python -with dreadnode.run("my_run") as run: +with dreadnode.run("my_run"): model = SomeModel() data = SomeData() - run.link_objects(model, data) + dreadnode.link_objects(model, data) ``` **Parameters:** @@ -539,11 +539,11 @@ def link_objects(self, origin: t.Any, link: t.Any, **attributes: JsonValue) -> N Example: ~~~ - with dreadnode.run("my_run") as run: + with dreadnode.run("my_run"): model = SomeModel() data = SomeData() - run.link_objects(model, data) + dreadnode.link_objects(model, data) ~~~ Args: @@ -577,26 +577,26 @@ This method uploads a local file or directory to the artifact storage associated Log a single file: ```python -with dreadnode.run("my_run") as run: +with dreadnode.run("my_run"): # Save a file with open("results.json", "w") as f: json.dump(results, f) # Log it as an artifact - run.log_artifact("results.json") + dreadnode.log_artifact("results.json") ``` Log a directory: ```python -with dreadnode.run("my_run") as run: +with dreadnode.run("my_run"): # Create a directory with model files os.makedirs("model_output", exist_ok=True) save_model("model_output/model.pkl") save_config("model_output/config.yaml") # Log the entire directory as an artifact - run.log_artifact("model_output") + dreadnode.log_artifact("model_output") ``` **Parameters:** @@ -620,25 +620,25 @@ def log_artifact( Examples: Log a single file: ~~~ - with dreadnode.run("my_run") as run: + with dreadnode.run("my_run"): # Save a file with open("results.json", "w") as f: json.dump(results, f) # Log it as an artifact - run.log_artifact("results.json") + dreadnode.log_artifact("results.json") ~~~ Log a directory: ~~~ - with dreadnode.run("my_run") as run: + with dreadnode.run("my_run"): # Create a directory with model files os.makedirs("model_output", exist_ok=True) save_model("model_output/model.pkl") save_config("model_output/config.yaml") # Log the entire directory as an artifact - run.log_artifact("model_output") + dreadnode.log_artifact("model_output") ~~~ Args: @@ -813,17 +813,17 @@ They can be used to track performance, resource usage, or other quantitative dat With a raw value: ```python -with dreadnode.run("my_run") as run: - run.log_metric("accuracy", 0.95, step=10) - run.log_metric("loss", 0.05, step=10, mode="min") +with dreadnode.run("my_run"): + dreadnode.log_metric("accuracy", 0.95, step=10) + dreadnode.log_metric("loss", 0.05, step=10, mode="min") ``` With a Metric object: ```python -with dreadnode.run("my_run") as run: +with dreadnode.run("my_run"): metric = Metric(0.95, step=10, timestamp=datetime.now(timezone.utc)) - run.log_metric("accuracy", metric) + dreadnode.log_metric("accuracy", metric) ``` **Parameters:** @@ -904,16 +904,16 @@ def log_metric( Examples: With a raw value: ~~~ - with dreadnode.run("my_run") as run: - run.log_metric("accuracy", 0.95, step=10) - run.log_metric("loss", 0.05, step=10, mode="min") + with dreadnode.run("my_run"): + dreadnode.log_metric("accuracy", 0.95, step=10) + dreadnode.log_metric("loss", 0.05, step=10, mode="min") ~~~ With a Metric object: ~~~ - with dreadnode.run("my_run") as run: + with dreadnode.run("my_run"): metric = Metric(0.95, step=10, timestamp=datetime.now(timezone.utc)) - run.log_metric("accuracy", metric) + dreadnode.log_metric("accuracy", metric) ~~~ Args: @@ -1297,8 +1297,8 @@ metadata. Example ```python -with dreadnode.run("my_run") as run: - run.log_param("param_name", "param_value") +with dreadnode.run("my_run"): + dreadnode.log_param("param_name", "param_value") ``` **Parameters:** @@ -1336,8 +1336,8 @@ def log_param( Example: ~~~ - with dreadnode.run("my_run") as run: - run.log_param("param_name", "param_value") + with dreadnode.run("my_run"): + dreadnode.log_param("param_name", "param_value") ~~~ Args: @@ -1370,8 +1370,8 @@ metadata. Example ```python -with dreadnode.run("my_run") as run: - run.log_params( +with dreadnode.run("my_run"): + dreadnode.log_params( param1="value1", param2="value2" ) @@ -1405,8 +1405,8 @@ def log_params(self, to: ToObject = "run", **params: JsonValue) -> None: Example: ~~~ - with dreadnode.run("my_run") as run: - run.log_params( + with dreadnode.run("my_run"): + dreadnode.log_params( param1="value1", param2="value2" ) @@ -1861,8 +1861,8 @@ Add one or many tags to the current task or run. Example ```python -with dreadnode.run("my_run") as run: - run.tag("my_tag") +with dreadnode.run("my_run"): + dreadnode.tag("my_tag") ``` **Parameters:** @@ -1888,8 +1888,8 @@ def tag(self, *tag: str, to: ToObject = "task-or-run") -> None: Example: ~~~ - with dreadnode.run("my_run") as run: - run.tag("my_tag") + with dreadnode.run("my_run"): + dreadnode.tag("my_tag") ~~~ Args: diff --git a/dreadnode/main.py b/dreadnode/main.py index 9b578877..8575f508 100644 --- a/dreadnode/main.py +++ b/dreadnode/main.py @@ -838,8 +838,8 @@ def tag(self, *tag: str, to: ToObject = "task-or-run") -> None: Example: ``` - with dreadnode.run("my_run") as run: - run.tag("my_tag") + with dreadnode.run("my_run"): + dreadnode.tag("my_tag") ``` Args: @@ -897,8 +897,8 @@ def log_param( Example: ``` - with dreadnode.run("my_run") as run: - run.log_param("param_name", "param_value") + with dreadnode.run("my_run"): + dreadnode.log_param("param_name", "param_value") ``` Args: @@ -921,8 +921,8 @@ def log_params(self, to: ToObject = "run", **params: JsonValue) -> None: Example: ``` - with dreadnode.run("my_run") as run: - run.log_params( + with dreadnode.run("my_run"): + dreadnode.log_params( param1="value1", param2="value2" ) @@ -964,8 +964,8 @@ def log_metric( Example: ``` - with dreadnode.run("my_run") as run: - run.log_metric("metric_name", 42.0) + with dreadnode.run("my_run"): + dreadnode.log_metric("metric_name", 42.0) ``` Args: @@ -1010,8 +1010,8 @@ def log_metric( Example: ``` - with dreadnode.run("my_run") as run: - run.log_metric("metric_name", 42.0) + with dreadnode.run("my_run"): + dreadnode.log_metric("metric_name", 42.0) ``` Args: @@ -1056,16 +1056,16 @@ def log_metric( Examples: With a raw value: ``` - with dreadnode.run("my_run") as run: - run.log_metric("accuracy", 0.95, step=10) - run.log_metric("loss", 0.05, step=10, mode="min") + with dreadnode.run("my_run"): + dreadnode.log_metric("accuracy", 0.95, step=10) + dreadnode.log_metric("loss", 0.05, step=10, mode="min") ``` With a Metric object: ``` - with dreadnode.run("my_run") as run: + with dreadnode.run("my_run"): metric = Metric(0.95, step=10, timestamp=datetime.now(timezone.utc)) - run.log_metric("accuracy", metric) + dreadnode.log_metric("accuracy", metric) ``` Args: @@ -1293,25 +1293,25 @@ def log_artifact( Examples: Log a single file: ``` - with dreadnode.run("my_run") as run: + with dreadnode.run("my_run"): # Save a file with open("results.json", "w") as f: json.dump(results, f) # Log it as an artifact - run.log_artifact("results.json") + dreadnode.log_artifact("results.json") ``` Log a directory: ``` - with dreadnode.run("my_run") as run: + with dreadnode.run("my_run"): # Create a directory with model files os.makedirs("model_output", exist_ok=True) save_model("model_output/model.pkl") save_config("model_output/config.yaml") # Log the entire directory as an artifact - run.log_artifact("model_output") + dreadnode.log_artifact("model_output") ``` Args: @@ -1440,11 +1440,11 @@ def link_objects(self, origin: t.Any, link: t.Any, **attributes: JsonValue) -> N Example: ``` - with dreadnode.run("my_run") as run: + with dreadnode.run("my_run"): model = SomeModel() data = SomeData() - run.link_objects(model, data) + dreadnode.link_objects(model, data) ``` Args: