MCPcopy Create free account
hub / github.com/NVIDIA-NeMo/Switchyard / run_stream

Method run_stream

crates/libsy/src/core/algorithm.rs:650–705  ·  view source on GitHub ↗

Process a request to completion, returning a stream of [`Step`]s. The consumer must fulfill every [`Step::CallLlm`] before the algorithm can continue. The bounded step channel applies backpressure when the consumer is not polling. A successful run ends with [`Step::ReturnToAgent`]; a failure is emitted as an `Err` item. Dropping the stream aborts the spawned algorithm task. Every invocation owns

(
        self: Arc<Self>,
        ctx: Context,
        request: Request,
        observer: Option<RunObserver>,
    )

Source from the content-addressed store, hash-verified

648 /// Every invocation owns a separate [`Driver`]. `observer`, when present, receives
649 /// each completed model call and, after a successful routed run, its routing overhead.
650 fn run_stream(
651 self: Arc<Self>,
652 ctx: Context,
653 request: Request,
654 observer: Option<RunObserver>,
655 ) -> StepStream {
656 // Stamp the algorithm's telemetry label into the request context; the
657 // context rides on every driver call, so its telemetry is attributed.
658 let mut ctx = ctx;
659 ctx.values.insert(
660 observability::ALGORITHM_KEY.to_string(),
661 self.name().to_string(),
662 );
663 let driver = Driver::with_observer(observer);
664 let task_driver = driver.clone();
665 let task_ctx = ctx.clone();
666 let stream = task_driver.stream();
667 // One `libsy.run` span covers the whole algorithm task; the driver's
668 // `libsy.llm_call` spans and decision logs nest inside it via `tracing`'s
669 // contextual parenting.
670 let span = observability::run_span(self.name(), &request);
671 let observed_driver = task_driver.clone();
672 let handle = tokio::spawn(
673 async move {
674 observability::observe_run(
675 task_ctx.clone(),
676 observed_driver,
677 self.create_run_task(task_ctx, task_driver, request),
678 )
679 .await
680 }
681 .instrument(span),
682 );
683 // Dropping the stream aborts the algorithm task when its consumer goes away.
684 let abort_guard = AbortOnDrop(handle.abort_handle());
685
686 let finish_driver = driver.clone();
687 let finish_ctx = ctx;
688 let tail: StepStream = Box::pin(
689 futures::stream::once(async move {
690 let result = match handle.await {
691 Ok(response) => response,
692 Err(source) => Err(LibsyError::AlgorithmTask { source }),
693 };
694 finish_driver.finish(finish_ctx, result).await
695 })
696 .filter_map(|finish_result| async move { finish_result.err().map(Err) }),
697 );
698
699 let stream: StepStream = Box::pin(stream);
700 Box::pin(futures::stream::select(stream, tail).map(move |step| {
701 // link abort guard to stream
702 let _keep_alive = &abort_guard;
703 step
704 }))
705 }
706
707 /// Process a request to completion, returning the final [`Response`] and the trace of

Implementers 13

algorithm.rscrates/libsy/src/core/algorithm.rs
dropping_the_stream_cancels_the_algorithm_taskcrates/libsy/src/core/algorithm.rs
create_run_task_panic_surfaces_as_a_stream_errorcrates/libsy/src/core/algorithm.rs
run_returns_an_error_when_the_algorithm_task_panicscrates/libsy/src/core/algorithm.rs
cancelling_run_cancels_the_algorithm_taskcrates/libsy/src/core/algorithm.rs
fall_through.rscrates/libsy/src/algorithms/fall_throu
llm_class.rscrates/libsy/src/algorithms/llm_class.
passthrough.rscrates/libsy/src/algorithms/passthroug
stage.rscrates/libsy/src/algorithms/stage.rs
noop.rscrates/libsy/src/algorithms/noop.rs
rand.rscrates/libsy/src/algorithms/rand.rs

Calls 9

run_spanFunction · 0.85
observe_runFunction · 0.85
AbortOnDropClass · 0.85
insertMethod · 0.80
nameMethod · 0.45
streamMethod · 0.45
create_run_taskMethod · 0.45
finishMethod · 0.45
mapMethod · 0.45