use super::any::into_runnable_any;
use super::error::LcelError;
use super::fallback::RunnableWithFallbacks;
use super::retry::{RetryConfig, RunnableRetry};
use super::runnable_trait::Runnable;
use super::sequence::RunnableSequence;
pub trait RunnableExt<Input: Send + Sync + 'static, Output: Send + Sync + 'static>:
Runnable<Input, Output>
where
Self::Error: Into<LcelError>,
Self: Sized + 'static,
{
fn pipe<O2, R2>(self, other: R2) -> RunnableSequence<Input, O2>
where
O2: Send + Sync + 'static,
R2: Runnable<Output, O2> + Send + Sync + 'static,
R2::Error: Into<LcelError>,
{
RunnableSequence::from_pair(self, other)
}
fn into_sequence(self) -> RunnableSequence<Input, Output> {
RunnableSequence::from_single(self)
}
fn with_fallbacks<R>(self, fallbacks: Vec<R>) -> RunnableWithFallbacks<Input, Output>
where
Input: Clone,
R: Runnable<Input, Output> + Send + Sync + 'static,
R::Error: Into<LcelError>,
{
let fallback_boxes: Vec<Box<dyn super::any::RunnableAny>> = fallbacks
.into_iter()
.map(|r| into_runnable_any(r))
.collect();
RunnableWithFallbacks::new(self, fallback_boxes)
}
fn with_retry(self, retry_config: RetryConfig) -> RunnableRetry<Input, Output>
where
Input: Clone,
{
let runnable_any = into_runnable_any(self);
RunnableRetry::new(runnable_any, retry_config)
}
}
impl<I, O, R> RunnableExt<I, O> for R
where
I: Send + Sync + 'static,
O: Send + Sync + 'static,
R: Runnable<I, O>,
R::Error: Into<LcelError>,
R: Sized + 'static,
{
}
#[cfg(test)]
mod tests {
use super::*;
use crate::RunnableConfig;
use async_trait::async_trait;
use futures_util::StreamExt;
struct Double;
#[async_trait]
impl Runnable<i32, i32> for Double {
type Error = std::convert::Infallible;
async fn invoke(&self, input: i32, _config: Option<RunnableConfig>) -> Result<i32, Self::Error> {
Ok(input * 2)
}
}
struct AddSuffix;
#[async_trait]
impl Runnable<i32, String> for AddSuffix {
type Error = std::convert::Infallible;
async fn invoke(&self, input: i32, _config: Option<RunnableConfig>) -> Result<String, Self::Error> {
Ok(format!("result: {}", input))
}
}
#[tokio::test]
async fn pipe_creates_sequence() {
let chain = Double.pipe(AddSuffix);
let result = chain.invoke(5, None).await.unwrap();
assert_eq!(result, "result: 10");
}
#[tokio::test]
async fn pipe_chain_multiple() {
let chain = Double.pipe(Double).pipe(AddSuffix);
let result = chain.invoke(3, None).await.unwrap();
assert_eq!(result, "result: 12"); }
#[tokio::test]
async fn pipe_stream_works() {
let chain = Double.pipe(AddSuffix);
let mut stream = chain.stream(5, None).await.unwrap();
let result = stream.next().await.unwrap().unwrap();
assert_eq!(result, "result: 10");
}
}