1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
//! Module modeling the outputs from LLMs
//!
//! The `output` module contains the `Output` trait, which represents the output of a Large Language Model (LLM). It provides methods for retrieving and combining textual outputs from different models.
use async_trait::async_trait;
use futures::stream::StreamExt;
/// Separator string used when joining primary textual outputs.
const OUTPUT_JOINER_SEQUENCE: &str = "\n";
/// The `Output` trait represents the output of a Large Language Model (LLM). It provides
/// methods for retrieving and combining textual outputs from different models.
#[async_trait]
pub trait Output: Send + Clone + Sync {
/// Gets the primary textual output of the model. This method returns a vector of strings
/// containing zero to many outputs depending on how many "choices" were generated.
async fn primary_textual_output_choices(&self) -> Vec<String>;
/// Gets the primary textual output of the model, if any. If there are multiple choices,
/// it returns the first one. If no choices are available, it returns `None`.
async fn primary_textual_output(&self) -> Option<String> {
let outputs = self.primary_textual_output_choices().await;
if outputs.is_empty() {
None
} else {
Some(outputs[0].clone())
}
}
/// Combines the primary textual outputs from multiple instances implementing the `Output` trait.
/// The outputs are joined using the `OUTPUT_JOINER_SEQUENCE` separator.
async fn combine_primary_textual_outputs(outputs: &[&Self]) -> String {
let primary_outputs = futures::stream::iter(outputs)
.then(|output| output.primary_textual_output())
.filter_map(|opt_output| async move { opt_output })
.collect::<Vec<String>>()
.await;
primary_outputs.join(OUTPUT_JOINER_SEQUENCE)
}
/// Combines the primary textual outputs of a pair of instances implementing the `Output` trait.
/// The outputs are joined using the `OUTPUT_JOINER_SEQUENCE` separator.
async fn combine_primary_textual_outputs_for_pair(output1: &Self, output2: &Self) -> String {
let (output1, output2) = futures::join!(
output1.primary_textual_output(),
output2.primary_textual_output()
);
match (output1, output2) {
(Some(output1), Some(output2)) => {
format!("{}{}{}", output1, OUTPUT_JOINER_SEQUENCE, output2)
}
(Some(output1), None) => output1,
(None, Some(output2)) => output2,
(None, None) => String::new(),
}
}
}