Spaces:
Sleeping
Sleeping
| # API Reference | |
| Complete reference for all public classes, methods, and enums in the pipeline engine. | |
| --- | |
| ## `pipeline.context` | |
| ### `StepContext` | |
| Frozen dataclass passed from step to step. The pipeline engine only reads `sample` and `metadata` β domain-specific fields are added by subclassing. | |
| ```python | |
| @dataclass(frozen=True) | |
| class StepContext: | |
| sample: Any = None | |
| metadata: MappingProxyType = field( | |
| default_factory=lambda: MappingProxyType({}) | |
| ) | |
| ``` | |
| | Method | Signature | Description | | |
| |--------|-----------|-------------| | |
| | `replace` | `(**changes: Any) -> StepContext` | Return a new context with the given fields replaced. Uses `dataclasses.replace` internally. | | |
| **Behavior:** | |
| - `metadata` is auto-coerced from `dict` to `MappingProxyType` in `__post_init__` | |
| - Subclasses inherit `.replace()` β it works on all fields including subclass-defined ones | |
| --- | |
| ## `pipeline.protocol` | |
| ### `StepProtocol` | |
| Structural protocol that every step (and Pipeline/Branch) must satisfy. | |
| ```python | |
| @runtime_checkable | |
| class StepProtocol(Protocol): | |
| requires: AbstractSet[str] | |
| provides: AbstractSet[str] | |
| def __call__(self, ctx: StepContext) -> StepContext: ... | |
| ``` | |
| | Attribute | Type | Description | | |
| |-----------|------|-------------| | |
| | `requires` | `AbstractSet[str]` | Metadata keys the step reads | | |
| | `provides` | `AbstractSet[str]` | Metadata keys the step writes | | |
| | `__call__` | `(StepContext) -> StepContext` | Execute the step | | |
| **Notes:** | |
| - `AbstractSet[str]` accepts both `set` and `frozenset` | |
| - `@runtime_checkable` enables `isinstance(step, StepProtocol)` checks | |
| --- | |
| ### `SampleResult` | |
| Outcome for one sample after the pipeline has run. | |
| ```python | |
| @dataclass | |
| class SampleResult: | |
| sample: Any | |
| output: StepContext | None | |
| error: Exception | None | |
| failed_at: str | None | |
| cause: Exception | None = None | |
| ``` | |
| | Field | Type | Description | | |
| |-------|------|-------------| | |
| | `sample` | `Any` | The original input sample | | |
| | `output` | `StepContext \| None` | Final context (`None` if any step failed) | | |
| | `error` | `Exception \| None` | The exception (`None` if succeeded) | | |
| | `failed_at` | `str \| None` | Class name of the step that raised (`None` if succeeded) | | |
| | `cause` | `Exception \| None` | Inner exception for `BranchError` failures (default `None`) | | |
| **Notes:** | |
| - Mutable β background threads update it in-place when background steps complete | |
| - For background steps, `output`/`error` may be `None` until `wait_for_background()` completes | |
| --- | |
| ## `pipeline.pipeline` | |
| ### `Pipeline` | |
| Ordered sequence of steps. Satisfies `StepProtocol` β can be nested inside other pipelines. | |
| #### Constructor | |
| ```python | |
| Pipeline(steps: list | None = None, hooks: list[PipelineHook] | None = None) | |
| ``` | |
| | Parameter | Type | Default | Description | | |
| |-----------|------|---------|-------------| | |
| | `steps` | `list \| None` | `None` | Optional initial list of steps | | |
| | `hooks` | `list[PipelineHook] \| None` | `None` | Observation-only hooks fired around each foreground step | | |
| Validates step ordering and infers contracts at construction time. | |
| #### Attributes | |
| | Attribute | Type | Description | | |
| |-----------|------|-------------| | |
| | `requires` | `frozenset[str]` | Fields the pipeline needs from external context (auto-inferred) | | |
| | `provides` | `frozenset[str]` | Fields the pipeline writes (auto-inferred, union of all steps) | | |
| #### Methods | |
| ##### `then` | |
| ```python | |
| def then(self, step: object) -> Pipeline | |
| ``` | |
| Append a step and return `self` for chaining. Validates ordering immediately. | |
| | Parameter | Type | Description | | |
| |-----------|------|-------------| | |
| | `step` | `object` | Any object satisfying `StepProtocol` | | |
| **Returns:** `self` (for method chaining) | |
| **Raises:** `PipelineOrderError` if the step requires a field produced by a later step | |
| --- | |
| ##### `branch` | |
| ```python | |
| def branch( | |
| self, | |
| *pipelines: object, | |
| merge: MergeStrategy | Callable = MergeStrategy.RAISE_ON_CONFLICT, | |
| ) -> Pipeline | |
| ``` | |
| Append a `Branch` step and return `self` for chaining. Shorthand for `.then(Branch(*pipelines, merge=merge))`. | |
| **Returns:** `self` (for method chaining) | |
| --- | |
| ##### `run` | |
| ```python | |
| def run( | |
| self, | |
| contexts: Iterable[StepContext], | |
| workers: int = 1, | |
| on_sample_done: Callable[[SampleResult], None] | None = None, | |
| cancel_token: CancellationToken | None = None, | |
| ) -> list[SampleResult] | |
| ``` | |
| Process contexts through the pipeline (sync entry point). | |
| | Parameter | Type | Default | Description | | |
| |-----------|------|---------|-------------| | |
| | `contexts` | `Iterable[StepContext]` | β | Input contexts to process | | |
| | `workers` | `int` | `1` | Max concurrent samples in foreground steps | | |
| | `on_sample_done` | `Callable \| None` | `None` | Callback after each sample's foreground steps complete (or fail). Must not block. | | |
| | `cancel_token` | `CancellationToken \| None` | `None` | Cancellation signal. Checked before each step and each new sample. Pass a fresh token per invocation. | | |
| **Returns:** `list[SampleResult]` β one result per input context | |
| **Notes:** Calls `asyncio.run(self.run_async(...))` internally. For background steps, call `wait_for_background()` after this returns. When `cancel_token` is provided, also sets `cancel_token_var` so code inside steps (e.g. LLM clients) can read it. | |
| --- | |
| ##### `run_async` | |
| ```python | |
| async def run_async( | |
| self, | |
| contexts: Iterable[StepContext], | |
| workers: int = 1, | |
| on_sample_done: Callable[[SampleResult], None] | None = None, | |
| cancel_token: CancellationToken | None = None, | |
| ) -> list[SampleResult] | |
| ``` | |
| Async entry point. Use `await pipe.run_async(contexts)` from coroutine contexts. | |
| Same parameters and return type as `run()`. | |
| --- | |
| ##### `__call__` | |
| ```python | |
| def __call__(self, ctx: StepContext) -> StepContext | |
| ``` | |
| Run all steps sequentially on a single context. Used when the pipeline is nested as a step inside another pipeline. | |
| **Notes:** `async_boundary` markers are ignored in this mode β all steps run to completion. | |
| --- | |
| ##### `wait_for_background` | |
| ```python | |
| def wait_for_background(self, timeout: float | None = None) -> None | |
| ``` | |
| Block until all background tasks complete. | |
| | Parameter | Type | Default | Description | | |
| |-----------|------|---------|-------------| | |
| | `timeout` | `float \| None` | `None` | Max seconds to wait. `None` = wait indefinitely. | | |
| **Raises:** `TimeoutError` if timeout elapses before completion | |
| --- | |
| ##### `background_stats` | |
| ```python | |
| def background_stats(self) -> dict[str, int] | |
| ``` | |
| Return a snapshot of background task progress. Thread-safe. | |
| **Returns:** `{"active": int, "completed": int}` | |
| --- | |
| ## `pipeline.branch` | |
| ### `MergeStrategy` | |
| Enum of built-in merge strategies for `Branch` outputs. | |
| ```python | |
| class MergeStrategy(Enum): | |
| RAISE_ON_CONFLICT = "raise_on_conflict" | |
| LAST_WRITE_WINS = "last_write_wins" | |
| NAMESPACED = "namespaced" | |
| ``` | |
| | Value | Behavior | | |
| |-------|----------| | |
| | `RAISE_ON_CONFLICT` | Raises `ValueError` if two branches write different values to the same named field. Metadata merges with last-writer-wins. | | |
| | `LAST_WRITE_WINS` | Last branch's value wins for every conflicting field. | | |
| | `NAMESPACED` | Each branch's output stored at `metadata["branch_N"]`. No conflict possible. | | |
| --- | |
| ### `Branch` | |
| Runs multiple pipelines in parallel, then merges their outputs. Satisfies `StepProtocol`. | |
| #### Constructor | |
| ```python | |
| Branch( | |
| *pipelines: object, | |
| merge: MergeStrategy | Callable = MergeStrategy.RAISE_ON_CONFLICT, | |
| ) | |
| ``` | |
| | Parameter | Type | Default | Description | | |
| |-----------|------|---------|-------------| | |
| | `*pipelines` | `object` | β | Child pipelines to run in parallel (at least one required) | | |
| | `merge` | `MergeStrategy \| Callable` | `RAISE_ON_CONFLICT` | Merge strategy or custom `fn(list[StepContext]) -> StepContext` | | |
| **Raises:** `ValueError` if no pipelines are provided | |
| #### Attributes | |
| | Attribute | Type | Description | | |
| |-----------|------|-------------| | |
| | `requires` | `frozenset[str]` | Union of all children's requires | | |
| | `provides` | `frozenset[str]` | Union of all children's provides | | |
| | `pipelines` | `list` | The child pipelines | | |
| #### Methods | |
| ##### `__call__` | |
| ```python | |
| def __call__(self, ctx: StepContext) -> StepContext | |
| ``` | |
| Sync fan-out via `ThreadPoolExecutor`. All branches run to completion before any failure is raised. | |
| **Raises:** `BranchError` if any branch fails | |
| --- | |
| ##### `__call_async__` | |
| ```python | |
| async def __call_async__(self, ctx: StepContext) -> StepContext | |
| ``` | |
| Async fan-out via `asyncio.gather`. Sync children are wrapped with `asyncio.to_thread`. | |
| **Raises:** `BranchError` if any branch fails | |
| --- | |
| ## `pipeline.protocol` β Hooks | |
| ### `PipelineHook` | |
| Observation-only protocol fired around each foreground step. Hooks cannot modify context β both methods return `None`. | |
| ```python | |
| @runtime_checkable | |
| class PipelineHook(Protocol): | |
| def before_step(self, step_name: str, ctx: StepContext) -> None: ... | |
| def after_step(self, step_name: str, ctx: StepContext) -> None: ... | |
| ``` | |
| | Method | Parameters | Description | | |
| |--------|-----------|-------------| | |
| | `before_step` | `step_name: str, ctx: StepContext` | Called before each foreground step executes | | |
| | `after_step` | `step_name: str, ctx: StepContext` | Called after each foreground step completes | | |
| **Notes:** | |
| - `step_name` is `type(step).__name__` β hooks know what ran but cannot inspect or mutate the step instance | |
| - Hooks fire for foreground steps only β background steps (after `async_boundary`) do not trigger hooks | |
| - If a hook raises, the pipeline logs the error and continues β a broken hook never kills the pipeline | |
| - For `Branch` steps, hooks fire once for `"Branch"` as a whole, not for inner steps | |
| --- | |
| ## `pipeline.errors` | |
| ### `CancellationToken` | |
| Thread-safe cancellation signal. Create a fresh token per `run()` invocation. | |
| ```python | |
| class CancellationToken: | |
| def cancel(self) -> None: ... | |
| @property | |
| def is_cancelled(self) -> bool: ... | |
| ``` | |
| | Method / Property | Description | | |
| |-------------------|-------------| | |
| | `cancel()` | Signal cancellation. Thread-safe, idempotent. | | |
| | `is_cancelled` | `True` after `cancel()` has been called. | | |
| --- | |
| ### `cancel_token_var` | |
| `ContextVar` set by `Pipeline.run_async()` so code inside steps (e.g. LLM clients) can read the current cancel token without parameter changes. | |
| ```python | |
| cancel_token_var: ContextVar[CancellationToken | None] # default: None | |
| ``` | |
| **Notes:** | |
| - Set before steps run, reset after `run_async()` completes | |
| - `asyncio.to_thread()` copies contextvars automatically β visible in sync steps too | |
| - Read with `cancel_token_var.get(None)` β returns `None` when no pipeline is running | |
| --- | |
| ### `PipelineCancelled` | |
| ```python | |
| class PipelineCancelled(Exception): ... | |
| ``` | |
| A `cancel_token` was triggered. Surfaces in `SampleResult.error` β never propagated to the caller of `run()`. Callers check `isinstance(result.error, PipelineCancelled)` to distinguish cancellation from step failures. | |
| --- | |
| ### `PipelineOrderError` | |
| ```python | |
| class PipelineOrderError(Exception): ... | |
| ``` | |
| A step requires a field that no earlier step provides (but a later step does). Raised at **construction time**. | |
| --- | |
| ### `PipelineConfigError` | |
| ```python | |
| class PipelineConfigError(Exception): ... | |
| ``` | |
| Invalid pipeline wiring. Raised at **construction time**. Examples: | |
| - More than one `async_boundary = True` step in the same pipeline | |
| - An `async_boundary = True` step inside a `Branch` child | |
| --- | |
| ### `BranchError` | |
| ```python | |
| class BranchError(Exception): | |
| failures: list[BaseException] | |
| ``` | |
| One or more branch pipelines failed. All branches always run to completion before this is raised. Raised at **runtime**. | |
| | Attribute | Type | Description | | |
| |-----------|------|-------------| | |
| | `failures` | `list[BaseException]` | One exception per failed branch | | |
| --- | |
| ## Step class attributes | |
| Optional attributes a step class can declare to control pipeline behavior: | |
| | Attribute | Type | Default | Description | | |
| |-----------|------|---------|-------------| | |
| | `requires` | `set[str] \| frozenset[str]` | *(required)* | Metadata keys the step reads | | |
| | `provides` | `set[str] \| frozenset[str]` | *(required)* | Metadata keys the step writes | | |
| | `async_boundary` | `bool` | `False` | Marks the foreground/background split point | | |
| | `max_workers` | `int` | `1` | Max concurrent background threads for this step class | | |