Skip to main content

ferrin_core/generate_text/
builder.rs

1//! The `generate_text` builder.
2
3use std::fmt;
4use std::future::IntoFuture;
5use std::sync::Arc;
6
7use ferrin_spec::BoxFuture;
8use ferrin_spec::LanguageModelRef;
9
10use super::GenerateTextResult;
11use super::config::CallConfig;
12use super::run;
13use crate::error::Error;
14use crate::output::NoOutput;
15use crate::output::Output;
16use crate::output::OutputHandler;
17
18/// Starts building a non-streaming text generation call.
19///
20/// The builder is a future: `.await` runs the generation loop.
21#[must_use]
22pub fn generate_text(model: impl Into<LanguageModelRef>) -> GenerateText<()> {
23    GenerateText {
24        config: CallConfig::new(model.into()),
25        output: Arc::new(NoOutput),
26    }
27}
28
29/// Builder and future of a `generate_text` call.
30pub struct GenerateText<O> {
31    pub(crate) config: CallConfig,
32    pub(crate) output: Arc<dyn OutputHandler<O>>,
33}
34
35crate::builder::impl_call_builder!(GenerateText);
36
37impl<O> GenerateText<O> {
38    /// Requests structured output parsed by `output`.
39    pub fn output<T>(self, output: Output<T>) -> GenerateText<T> {
40        GenerateText {
41            config: self.config,
42            output: output.handler(),
43        }
44    }
45}
46
47impl<O> fmt::Debug for GenerateText<O> {
48    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49        f.debug_struct("GenerateText")
50            .field("config", &self.config)
51            .finish_non_exhaustive()
52    }
53}
54
55impl<O: Send + 'static> IntoFuture for GenerateText<O> {
56    type Output = Result<GenerateTextResult<O>, Error>;
57    type IntoFuture = BoxFuture<'static, Self::Output>;
58
59    fn into_future(self) -> Self::IntoFuture {
60        Box::pin(run::run(self.config, self.output))
61    }
62}