Skip to content

Commit 89ac517

Browse files
strickvlCopilot
andauthored
Add documentation for the StepContext object (#3953)
* Update metadata documentation for accessing context in steps This update enhances the documentation on how to access the `StepContext` within steps. It provides detailed information on the availability of the context, how to retrieve it, and the properties it exposes, including pipeline and step run details, model information, and input metadata. Additionally, it includes examples demonstrating the usage of context in both standard steps and advanced scenarios involving hooks and materializers. This change aims to improve clarity and usability for users working with step contexts in ZenML. * Update docs/book/how-to/metadata/metadata.md Co-authored-by: Copilot <[email protected]> --------- Co-authored-by: Copilot <[email protected]>
1 parent f084a97 commit 89ac517

File tree

1 file changed

+105
-15
lines changed

1 file changed

+105
-15
lines changed

docs/book/how-to/metadata/metadata.md

Lines changed: 105 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -303,29 +303,119 @@ When fetching metadata using a specific key, the returned value will always refl
303303

304304
### Accessing Context Within Steps
305305

306-
Within a step, you can access information about the current execution context using the `StepContext`:
306+
The `StepContext` object is your handle to the *current* pipeline/step run while a step executes. Use it to read run/step information, inspect upstream input metadata, and work with step outputs: URIs, materializers, run metadata, and tags.
307+
308+
It is available:
309+
- Inside functions decorated with `@step` (during execution, not composition time).
310+
- Inside step hooks like `on_failure` / `on_success`.
311+
- Inside materializers triggered by a step’s `save` / `load`.
312+
- Calling `get_step_context()` elsewhere raises `RuntimeError`.
313+
314+
Getting the context is done via `get_step_context()`:
307315

308316
```python
309317
from zenml import step, get_step_context
310318

311319
@step
320+
def trainer(param: int = 1):
321+
ctx = get_step_context()
322+
print("run:", ctx.pipeline_run.name, ctx.pipeline_run.id)
323+
print("step:", ctx.step_run.name, ctx.step_run.id)
324+
print("params:", ctx.step_run.config.parameters)
325+
```
326+
327+
This exposes the following properties:
328+
329+
* `ctx.pipeline` → the `PipelineResponse` for this run (convenience; may raise if the run has no pipeline object).
330+
* `ctx.pipeline_run``PipelineRunResponse` (id, name, status, timestamps, etc.).
331+
* `ctx.step_run``StepRunResponse` (name, parameters via `ctx.step_run.config.parameters`, status).
332+
* `ctx.model` → the configured `Model` (resolved from step or pipeline); raises if none configured.
333+
* `ctx.inputs``{input_name: StepRunInputResponse}`; use `...["x"].run_metadata` to read upstream metadata.
334+
* `ctx.step_name` → convenience name string.
335+
336+
### Working with outputs
337+
338+
For a single-output step you can omit `output_name`. For multi-output steps you **must** pass it (unnamed outputs are called `output_1`, `output_2`, …).
339+
340+
* `get_output_artifact_uri(output_name=None) -> str` – where the output artifact lives (write side files, etc.).
341+
* `get_output_materializer(output_name=None, *, custom_materializer_class=None, data_type=None) -> BaseMaterializer` – get an initialized materializer; pass `data_type` to select from `Union[...]` materializers or `custom_materializer_class` to override.
342+
* `add_output_metadata(metadata, output_name=None)` / `get_output_metadata(output_name=None)` – set/read run metadata for the output. Values provided via `ArtifactConfig(..., run_metadata=...)` on the return annotation are merged with runtime values.
343+
* `add_output_tags(tags, output_name=None)` / `get_output_tags(output_name=None)` / `remove_output_tags(tags, output_name=None)` – manage tags for the produced artifact version. Configured tags via `ArtifactConfig(..., tags=...)` are unioned with runtime tags; duplicates are de‑duplicated in the final artifact.
344+
345+
Minimal example:
346+
347+
```python
348+
from typing import Annotated, Tuple
349+
from zenml import step, get_step_context, log_metadata
350+
from zenml.artifacts.artifact_config import ArtifactConfig
351+
352+
@step
353+
def produce(name: str) -> Tuple[
354+
Annotated[
355+
str,
356+
ArtifactConfig(
357+
name="custom_name",
358+
run_metadata={"config_metadata": "bar"},
359+
tags=["config_tags"],
360+
),
361+
],
362+
str,
363+
]:
364+
ctx = get_step_context()
365+
# Attach metadata and tags to the named (or default) output
366+
ctx.add_output_metadata({"m": 1}, output_name=name)
367+
ctx.add_output_tags(["t1", "t1"], output_name=name) # duplicates ok
368+
return "a", "b"
369+
```
370+
371+
#### Reading upstream metadata via `inputs`
372+
373+
```python
374+
from zenml import step, get_step_context, log_metadata
375+
376+
@step
377+
def upstream() -> int:
378+
log_metadata({"quality": "ok"}, infer_artifact=True)
379+
return 42
380+
381+
@step
382+
def downstream(x: int) -> None:
383+
md = get_step_context().inputs["x"].run_metadata
384+
assert md["quality"] == "ok"
385+
```
386+
387+
#### Hooks and materializers (advanced)
388+
389+
```python
390+
from zenml import step, get_step_context
391+
from zenml.materializers.base_materializer import BaseMaterializer
392+
393+
def on_failure(exc: BaseException):
394+
c = get_step_context()
395+
print("Failed step:", c.step_run.name, "-", type(exc).__name__)
396+
397+
class ExampleMaterializer(BaseMaterializer):
398+
def save(self, data):
399+
# Context is available while the step triggers materialization
400+
data.meta = get_step_context().pipeline.name
401+
super().save(data)
402+
403+
@step(on_failure=on_failure)
312404
def my_step():
313-
# Get the step context
314-
context = get_step_context()
315-
316-
# Access context information
317-
pipeline_name = context.pipeline.name
318-
run_name = context.pipeline_run.name
319-
step_name = context.step_run.name
320-
321-
# Get information about output artifacts
322-
output_uri = context.get_output_artifact_uri()
323-
materializer = context.get_output_materializer()
324-
325-
# Use the context information
326-
print(f"Executing step {step_name} in pipeline {pipeline_name}, run {run_name}")
405+
raise ValueError("boom")
327406
```
328407

408+
**Common errors to expect.**
409+
410+
* `RuntimeError` if `get_step_context()` is called outside a running step.
411+
* `StepContextError` for output helpers when:
412+
413+
* The step has no outputs,
414+
* You omit `output_name` on a multi‑output step,
415+
* You reference an unknown `output_name`.
416+
417+
See the [full SDK docs for `StepContext`](https://sdkdocs.zenml.io/latest/core_code_docs/core-steps.html#zenml.steps.StepContext) for a concise reference to this object.
418+
329419
### Accessing Context During Pipeline Composition
330420

331421
During pipeline composition, you can access the pipeline configuration using the `PipelineContext`:

0 commit comments

Comments
 (0)