with_macros/
with_macros.rs1use simplify_baml::*;
17use simplify_baml_macros::{BamlSchema, BamlClient};
18use std::collections::HashMap;
19use std::env;
20
21#[derive(BamlSchema)]
23#[baml(description = "Calendar month of the year")]
24enum Month {
25 January,
26 February,
27 March,
28 April,
29 May,
30 June,
31 July,
32 August,
33 September,
34 October,
35 November,
36 December,
37}
38
39#[derive(BamlSchema)]
40#[baml(description = "Information about a person")]
41struct Person {
42 #[baml(description = "Full name of the person")]
43 name: String,
44
45 #[baml(description = "Age in years")]
46 age: i64,
47
48 #[baml(description = "Month of birth, if mentioned")]
49 #[baml(rename = "birthMonth")]
50 birth_month: Option<Month>,
51
52 #[baml(description = "Job title or profession, if mentioned")]
53 occupation: Option<String>,
54}
55
56#[baml_function(client = "openai")]
58fn extract_person(
59 #[baml(description = "Text containing person information to extract")]
60 text: String
61) -> Person {
62 r#"Extract the person's information from the following text:
63
64{{ text }}
65
66Please extract: name, age, birth month (if mentioned), and occupation (if mentioned)."#
67}
68
69#[derive(BamlClient)]
71#[baml(provider = "OpenAI", model = "gpt-4o-mini")]
72struct OpenAIClient;
73
74#[tokio::main]
75async fn main() -> anyhow::Result<()> {
76 println!("=== BAML Complete Macro Example ===\n");
77 println!("✨ Using all three macros for maximum productivity!\n");
78
79 let ir = BamlSchemaRegistry::new()
81 .register::<Month>()
82 .register::<Person>()
83 .build_with_functions(vec![extract_person()]);
84
85 println!("📊 IR built with {} classes, {} enums, {} functions",
86 ir.classes.len(),
87 ir.enums.len(),
88 ir.functions.len()
89 );
90
91 for class in &ir.classes {
93 println!(" - Class: {} ({} fields)", class.name, class.fields.len());
94 }
95 for enum_def in &ir.enums {
96 println!(" - Enum: {} ({} variants)", enum_def.name, enum_def.values.len());
97 }
98 for func in &ir.functions {
99 println!(" - Function: {} ({} inputs -> {})",
100 func.name,
101 func.inputs.len(),
102 func.output.to_string()
103 );
104 }
105 println!();
106
107 let api_key = env::var("OPENAI_API_KEY").unwrap_or_else(|_| {
109 eprintln!("Warning: OPENAI_API_KEY not set. Using mock mode.");
110 "mock".to_string()
111 });
112
113 let client = OpenAIClient::new(api_key.clone());
114
115 let runtime = RuntimeBuilder::new()
117 .ir(ir)
118 .client("openai", client)
119 .build();
120
121 let mut params = HashMap::new();
123 params.insert(
124 "text".to_string(),
125 BamlValue::String(
126 "John Smith is 30 years old and was born in March. He works as a software engineer."
127 .to_string(),
128 ),
129 );
130
131 println!("Input text: {}", params.get("text").unwrap().as_string().unwrap());
132 println!("\nExecuting BAML function 'ExtractPerson'...\n");
133
134 match runtime.execute("ExtractPerson", params).await {
136 Ok(result) => {
137 println!("✅ Success! Parsed result:");
138 print_result(&result);
139 }
140 Err(e) => {
141 eprintln!("❌ Error: {}", e);
142 eprintln!("\nNote: If you haven't set OPENAI_API_KEY, this is expected.");
143 eprintln!("Set it with: export OPENAI_API_KEY='your-key-here'");
144 }
145 }
146
147 println!("\n=== Code Comparison ===");
148 println!("Manual approach:");
149 println!(" - Class definition: ~15 lines");
150 println!(" - Enum definition: ~15 lines");
151 println!(" - Function definition: ~20 lines");
152 println!(" - Client setup: ~3 lines");
153 println!(" - Total: ~53 lines");
154 println!();
155 println!("With macros:");
156 println!(" - #[derive(BamlSchema)] on struct: ~12 lines");
157 println!(" - #[derive(BamlSchema)] on enum: ~10 lines");
158 println!(" - #[baml_function]: ~8 lines");
159 println!(" - #[derive(BamlClient)]: ~3 lines");
160 println!(" - Total: ~33 lines");
161 println!();
162 println!("💡 Savings: ~38% less code, more readable, and type-safe!");
163 println!("💡 All macros now use consistent #[derive(...)] syntax!");
164
165 Ok(())
166}
167
168fn print_result(value: &BamlValue) {
170 match value {
171 BamlValue::Map(map) => {
172 println!("{{");
173 for (key, val) in map {
174 print!(" {}: ", key);
175 match val {
176 BamlValue::String(s) => println!("\"{}\"", s),
177 BamlValue::Int(i) => println!("{}", i),
178 BamlValue::Float(f) => println!("{}", f),
179 BamlValue::Bool(b) => println!("{}", b),
180 BamlValue::Null => println!("null"),
181 _ => println!("{:?}", val),
182 }
183 }
184 println!("}}");
185 }
186 _ => println!("{:?}", value),
187 }
188}