extract_person_macro/
extract_person_macro.rs1use simplify_baml::*;
14use simplify_baml_macros::BamlSchema;
15use std::collections::HashMap;
16use std::env;
17
18#[derive(BamlSchema)]
21#[baml(description = "Calendar month of the year")]
22enum Month {
23 January,
24 February,
25 March,
26 April,
27 May,
28 June,
29 July,
30 August,
31 September,
32 October,
33 November,
34 December,
35}
36
37#[derive(BamlSchema)]
38#[baml(description = "Information about a person")]
39struct Person {
40 #[baml(description = "Full name of the person")]
41 name: String,
42
43 #[baml(description = "Age in years")]
44 age: i64,
45
46 #[baml(description = "Month of birth, if mentioned")]
47 #[baml(rename = "birthMonth")]
48 birth_month: Option<Month>,
49
50 #[baml(description = "Job title or profession, if mentioned")]
51 occupation: Option<String>,
52}
53
54#[tokio::main]
55async fn main() -> anyhow::Result<()> {
56 println!("=== BAML Macro Example: Extract Person ===\n");
57 println!("✨ Using #[derive(BamlSchema)] to automatically generate IR!\n");
58
59 let ir = BamlSchemaRegistry::new()
61 .register::<Month>()
62 .register::<Person>()
63 .build_with_functions(vec![Function {
64 name: "ExtractPerson".to_string(),
65 inputs: vec![Field {
66 name: "text".to_string(),
67 field_type: FieldType::String,
68 optional: false,
69 description: Some("Text containing person information to extract".to_string()),
70 }],
71 output: FieldType::Class("Person".to_string()),
72 prompt_template: r#"Extract the person's information from the following text:
73
74{{ text }}
75
76Please extract: name, age, birth month (if mentioned), and occupation (if mentioned)."#
77 .to_string(),
78 client: "openai".to_string(),
79 }]);
80
81 println!("📊 IR built successfully with {} classes and {} enums",
82 ir.classes.len(),
83 ir.enums.len()
84 );
85
86 for class in &ir.classes {
88 println!(" - Class: {} ({} fields)", class.name, class.fields.len());
89 }
90 for enum_def in &ir.enums {
91 println!(" - Enum: {} ({} variants)", enum_def.name, enum_def.values.len());
92 }
93 println!();
94
95 let api_key = env::var("OPENAI_API_KEY").unwrap_or_else(|_| {
97 eprintln!("Warning: OPENAI_API_KEY not set. Using mock response.");
98 "mock".to_string()
99 });
100
101 let client = if api_key == "mock" {
102 println!("Using mock mode (no real API calls)\n");
103 LLMClient::openai(api_key, "gpt-4o-mini".to_string())
104 } else {
105 LLMClient::openai(api_key, "gpt-4o-mini".to_string())
106 };
107
108 let runtime = RuntimeBuilder::new()
110 .ir(ir)
111 .client("openai", client)
112 .build();
113
114 let mut params = HashMap::new();
116 params.insert(
117 "text".to_string(),
118 BamlValue::String(
119 "John Smith is 30 years old and was born in March. He works as a software engineer."
120 .to_string(),
121 ),
122 );
123
124 println!(
125 "Input text: {}",
126 params.get("text").unwrap().as_string().unwrap()
127 );
128 println!("\nExecuting BAML function 'ExtractPerson'...\n");
129
130 match runtime.execute("ExtractPerson", params).await {
132 Ok(result) => {
133 println!("Success! Parsed result:");
134 print_result(&result);
135 }
136 Err(e) => {
137 eprintln!("Error: {}", e);
138 eprintln!("\nNote: If you haven't set OPENAI_API_KEY, this is expected.");
139 eprintln!("Set it with: export OPENAI_API_KEY='your-key-here'");
140 }
141 }
142
143 println!("\n=== Comparison ===");
144 println!("Without macros: ~70 lines of manual IR construction");
145 println!("With macros: ~25 lines of struct/enum definitions");
146 println!("Savings: Less tedious, more readable, and type-safe!");
147
148 Ok(())
149}
150
151fn print_result(value: &BamlValue) {
153 match value {
154 BamlValue::Map(map) => {
155 println!("{{");
156 for (key, val) in map {
157 print!(" {}: ", key);
158 match val {
159 BamlValue::String(s) => println!("\"{}\"", s),
160 BamlValue::Int(i) => println!("{}", i),
161 BamlValue::Float(f) => println!("{}", f),
162 BamlValue::Bool(b) => println!("{}", b),
163 BamlValue::Null => println!("null"),
164 _ => println!("{:?}", val),
165 }
166 }
167 println!("}}");
168 }
169 _ => println!("{:?}", value),
170 }
171}