artificial_core/provider/
prompt_execute.rs

1use std::{future::Future, pin::Pin};
2
3use crate::{
4    error::Result,
5    generic::GenericChatCompletionResponse,
6    template::{IntoPrompt, PromptTemplate},
7};
8
9/// A **backend** turns a prompt into a network call to a concrete provider
10/// (OpenAI, Ollama, Anthropic, …) and parses the structured response.
11///
12/// The trait is intentionally minimal:
13///
14/// * **One associated type** – the in-memory `Message` representation this
15///   provider accepts.
16/// * **One async-ish method** – `complete`, which performs a *single*
17///   non-streaming round-trip and returns a value whose type is dictated by
18///   the `PromptTemplate`.
19///
20/// The method returns a [`Pin<Box<dyn Future>>`] so we stay object-safe
21/// without pulling in `async_trait`.
22pub trait PromptExecutionProvider: Send + Sync {
23    /// Chat message type consumed by this backend.
24    ///
25    /// A simple setup can re-use `crate::generic::GenericMessage`.
26    /// Providers with richer wire formats (function calls, images …) can
27    /// supply their own struct.
28    type Message: Send + Sync + 'static;
29
30    /// Execute the prompt and deserialize the provider’s reply into
31    /// `P::Output`.
32    ///
33    /// The blanket constraint `P: PromptTemplate<Message = Self::Message>`
34    /// guarantees at **compile time** that callers only feed the backend
35    /// messages it understands.
36    fn prompt_execute<'a, 'p, P>(&'a self, prompt: P) -> BoxedResponseFut<'p, P::Output>
37    where
38        'a: 'p,
39        P: PromptTemplate + Send + Sync + 'p,
40        <P as IntoPrompt>::Message: Into<Self::Message>;
41}
42
43pub type BoxedResponseFut<'p, Output> =
44    Pin<Box<dyn Future<Output = Result<GenericChatCompletionResponse<Output>>> + Send + 'p>>;