Skip to main content

rskit_ai/prompt/
builder.rs

1//! Prompt template builder.
2
3use semver::Version;
4
5use super::template::{PromptError, PromptTemplate, VariableDecl, VariableType};
6
7/// Builder for [`PromptTemplate`].
8#[derive(Debug, Clone)]
9pub struct Builder {
10    name: String,
11    version: Version,
12    body: Option<String>,
13    variables: Vec<VariableDecl>,
14    output_schema: Option<serde_json::Value>,
15    description: String,
16}
17
18impl Builder {
19    /// Create a new builder with a stable prompt name.
20    pub fn new(name: impl Into<String>) -> Self {
21        Self {
22            name: name.into(),
23            version: Version::new(0, 1, 0),
24            body: None,
25            variables: Vec::new(),
26            output_schema: None,
27            description: String::new(),
28        }
29    }
30
31    /// Set the template version.
32    #[must_use]
33    pub fn version(mut self, version: Version) -> Self {
34        self.version = version;
35        self
36    }
37
38    /// Set the template body.
39    #[must_use]
40    pub fn body(mut self, body: impl Into<String>) -> Self {
41        self.body = Some(body.into());
42        self
43    }
44
45    /// Add one required variable.
46    #[must_use]
47    pub fn variable(mut self, variable: impl Into<String>) -> Self {
48        self.variables.push(VariableDecl {
49            name: variable.into(),
50            kind: VariableType::Any,
51            required: true,
52            default: None,
53        });
54        self
55    }
56
57    /// Set an optional output schema.
58    #[must_use]
59    pub fn output_schema(mut self, schema: serde_json::Value) -> Self {
60        self.output_schema = Some(schema);
61        self
62    }
63
64    /// Set a description.
65    #[must_use]
66    pub fn description(mut self, description: impl Into<String>) -> Self {
67        self.description = description.into();
68        self
69    }
70
71    /// Build the template.
72    pub fn build(self) -> Result<PromptTemplate, PromptError> {
73        if self.name.trim().is_empty() {
74            return Err(PromptError::MissingField("name"));
75        }
76        Ok(PromptTemplate {
77            name: self.name,
78            version: self.version,
79            template: self.body.ok_or(PromptError::MissingField("body"))?,
80            variables: self.variables,
81            output_schema: self.output_schema,
82            description: self.description,
83        })
84    }
85}
86
87impl PromptTemplate {
88    /// Start building a template.
89    pub fn builder(name: impl Into<String>) -> Builder {
90        Builder::new(name)
91    }
92}