Run each item through a chain of `stages`, with no barrier between stages. Each stage is a callable `stage(ctx) -> spec_dict | None`, where `ctx = {"previous": , "item": }`. Return a spec dict (snake_case keys) to run that step, or `None` to stop the item's chain. A chain also stops when a step fails. Returns one entry per item (the last outcome dict, or `None`), in inp
(
&self,
py: Python<'_>,
items: Vec<Bound<'_, PyAny>>,
stages: Vec<Bound<'_, PyAny>>,
)
| 1597 | /// chain). Per-stage `output_schema` is not supported here — use `parallel` |
| 1598 | /// for schema-validated steps. |
| 1599 | fn pipeline( |
| 1600 | &self, |
| 1601 | py: Python<'_>, |
| 1602 | items: Vec<Bound<'_, PyAny>>, |
| 1603 | stages: Vec<Bound<'_, PyAny>>, |
| 1604 | ) -> PyResult<Vec<Option<PyObject>>> { |
| 1605 | let rust_items = items |
| 1606 | .iter() |
| 1607 | .map(|i| py_to_json_value(py, i)) |
| 1608 | .collect::<PyResult<Vec<_>>>()?; |
| 1609 | let rust_stages: Vec<RustPipelineStage<serde_json::Value>> = stages |
| 1610 | .into_iter() |
| 1611 | .map(|s| { |
| 1612 | let stage = std::sync::Arc::new(PythonPipelineStage { |
| 1613 | callback: s.unbind(), |
| 1614 | }); |
| 1615 | let ps: RustPipelineStage<serde_json::Value> = |
| 1616 | std::sync::Arc::new(move |prev, item| stage.invoke(prev, item)); |
| 1617 | ps |
| 1618 | }) |
| 1619 | .collect(); |
| 1620 | |
| 1621 | let session = self.inner.clone(); |
| 1622 | let outcomes = py.allow_threads(move || { |
| 1623 | get_runtime().block_on(async move { |
| 1624 | let executor = session.agent_executor(); |
| 1625 | execute_pipeline(executor, rust_items, rust_stages, None).await |
| 1626 | }) |
| 1627 | }); |
| 1628 | |
| 1629 | outcomes |
| 1630 | .iter() |
| 1631 | .map(|o| match o { |
| 1632 | Some(outcome) => step_outcome_to_py(py, outcome).map(Some), |
| 1633 | None => Ok(None), |
| 1634 | }) |
| 1635 | .collect() |
| 1636 | } |
| 1637 | |
| 1638 | /// Send a prompt or request and get a streaming iterator of events. |
| 1639 | /// |
no test coverage detected