use serde::{Deserialize, Serialize};
use serde_json::Value;
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct Instructions {
pub system_prompt: String,
pub response_schema: Option<Value>,
pub examples: Vec<(String, String)>,
pub metadata: Value,
}
impl Instructions {
pub fn new(system_prompt: impl Into<String>) -> Self {
Self {
system_prompt: system_prompt.into(),
response_schema: None,
examples: Vec::new(),
metadata: Value::Null,
}
}
pub fn with_response_schema(mut self, schema: Value) -> Self {
self.response_schema = Some(schema);
self
}
pub fn with_example(mut self, user: impl Into<String>, assistant: impl Into<String>) -> Self {
self.examples.push((user.into(), assistant.into()));
self
}
pub fn with_metadata(mut self, metadata: Value) -> Self {
self.metadata = metadata;
self
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn builder_chains() {
let i = Instructions::new("you are a detector")
.with_response_schema(json!({"type": "object"}))
.with_example("hi", "hello")
.with_metadata(json!({"model": "x"}));
assert_eq!(i.system_prompt, "you are a detector");
assert!(i.response_schema.is_some());
assert_eq!(i.examples.len(), 1);
assert_eq!(i.metadata["model"], "x");
}
#[test]
fn round_trips_serde() {
let i = Instructions::new("x").with_example("a", "b");
let s = serde_json::to_string(&i).unwrap();
let back: Instructions = serde_json::from_str(&s).unwrap();
assert_eq!(back.examples.len(), 1);
}
}