BamlSchemaRegistry

Struct BamlSchemaRegistry 

Source
pub struct BamlSchemaRegistry { /* private fields */ }
Expand description

Registry for collecting schema definitions and building IR

§Example

use simplify_baml::*;

#[derive(BamlSchema)]
struct Person {
    name: String,
    age: i64,
}

let ir = BamlSchemaRegistry::new()
    .register::<Person>()
    .build();

Implementations§

Source§

impl BamlSchemaRegistry

Source

pub fn new() -> Self

Create a new empty registry

Examples found in repository?
examples/nested_macro.rs (line 61)
57fn main() {
58    println!("=== Nested Structures with Macros ===\n");
59
60    // Build IR with automatic nesting resolution
61    let ir = BamlSchemaRegistry::new()
62        .register::<Role>()
63        .register::<Address>()
64        .register::<Employee>()
65        .register::<Company>()
66        .build();
67
68    println!("✅ Generated IR with {} classes and {} enums:",
69        ir.classes.len(),
70        ir.enums.len()
71    );
72    println!();
73
74    // Show what was generated
75    for enum_def in &ir.enums {
76        println!("📋 Enum: {}", enum_def.name);
77        println!("   Variants: {}", enum_def.values.join(", "));
78        println!();
79    }
80
81    for class in &ir.classes {
82        println!("📦 Class: {}", class.name);
83        for field in &class.fields {
84            let optional = if field.optional { " (optional)" } else { "" };
85            println!("   - {}: {}{}",
86                field.name,
87                field.field_type.to_string(),
88                optional
89            );
90        }
91        println!();
92    }
93
94    // Test parsing with the generated IR
95    let parser = simplify_baml::parser::Parser::new(&ir);
96
97    let test_json = r#"
98    {
99        "name": "TechCorp",
100        "employees": [
101            {
102                "name": "Alice",
103                "age": 30,
104                "role": "engineer"
105            },
106            {
107                "name": "Bob",
108                "age": 35,
109                "role": "manager"
110            }
111        ],
112        "address": {
113            "street": "123 Main St",
114            "city": "San Francisco",
115            "zipCode": "94102"
116        }
117    }
118    "#;
119
120    match parser.parse(test_json, &FieldType::Class("Company".to_string())) {
121        Ok(result) => {
122            println!("✅ Successfully parsed nested JSON!");
123            println!("{:#?}", result);
124        }
125        Err(e) => {
126            println!("❌ Parse error: {}", e);
127        }
128    }
129
130    println!("\n=== Code Comparison ===");
131    println!("Manual IR building (nested_parsing.rs): ~90 lines");
132    println!("With macros (this file): ~40 lines of definitions");
133    println!("Reduction: ~55% less code!");
134    println!("\n✨ The macro handles:");
135    println!("  • Nested structs (Company contains Address)");
136    println!("  • Lists of structs (Vec<Employee>)");
137    println!("  • Enum fields (Role in Employee)");
138    println!("  • Field renaming (zip_code → zipCode)");
139}
More examples
Hide additional examples
examples/with_macros.rs (line 80)
75async fn main() -> anyhow::Result<()> {
76    println!("=== BAML Complete Macro Example ===\n");
77    println!("✨ Using all three macros for maximum productivity!\n");
78
79    // Build IR automatically from types
80    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    // Print what was generated
92    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    // Configure the LLM client using macro-generated struct
108    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    // Build the runtime
116    let runtime = RuntimeBuilder::new()
117        .ir(ir)
118        .client("openai", client)
119        .build();
120
121    // Prepare input parameters
122    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    // Execute the function
135    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}
examples/extract_person_macro.rs (line 60)
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    // Step 1: Build IR using the registry - automatically collects all schema definitions
60    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    // Print what was generated
87    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    // Step 2: Configure the LLM client
96    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    // Step 3: Build the runtime
109    let runtime = RuntimeBuilder::new()
110        .ir(ir)
111        .client("openai", client)
112        .build();
113
114    // Step 4: Prepare input parameters
115    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    // Step 5: Execute the function
131    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}
Source

pub fn register<T: BamlSchema>(self) -> Self

Register a type that implements BamlSchema

This will automatically register the type and all its dependencies into the registry.

Examples found in repository?
examples/nested_macro.rs (line 62)
57fn main() {
58    println!("=== Nested Structures with Macros ===\n");
59
60    // Build IR with automatic nesting resolution
61    let ir = BamlSchemaRegistry::new()
62        .register::<Role>()
63        .register::<Address>()
64        .register::<Employee>()
65        .register::<Company>()
66        .build();
67
68    println!("✅ Generated IR with {} classes and {} enums:",
69        ir.classes.len(),
70        ir.enums.len()
71    );
72    println!();
73
74    // Show what was generated
75    for enum_def in &ir.enums {
76        println!("📋 Enum: {}", enum_def.name);
77        println!("   Variants: {}", enum_def.values.join(", "));
78        println!();
79    }
80
81    for class in &ir.classes {
82        println!("📦 Class: {}", class.name);
83        for field in &class.fields {
84            let optional = if field.optional { " (optional)" } else { "" };
85            println!("   - {}: {}{}",
86                field.name,
87                field.field_type.to_string(),
88                optional
89            );
90        }
91        println!();
92    }
93
94    // Test parsing with the generated IR
95    let parser = simplify_baml::parser::Parser::new(&ir);
96
97    let test_json = r#"
98    {
99        "name": "TechCorp",
100        "employees": [
101            {
102                "name": "Alice",
103                "age": 30,
104                "role": "engineer"
105            },
106            {
107                "name": "Bob",
108                "age": 35,
109                "role": "manager"
110            }
111        ],
112        "address": {
113            "street": "123 Main St",
114            "city": "San Francisco",
115            "zipCode": "94102"
116        }
117    }
118    "#;
119
120    match parser.parse(test_json, &FieldType::Class("Company".to_string())) {
121        Ok(result) => {
122            println!("✅ Successfully parsed nested JSON!");
123            println!("{:#?}", result);
124        }
125        Err(e) => {
126            println!("❌ Parse error: {}", e);
127        }
128    }
129
130    println!("\n=== Code Comparison ===");
131    println!("Manual IR building (nested_parsing.rs): ~90 lines");
132    println!("With macros (this file): ~40 lines of definitions");
133    println!("Reduction: ~55% less code!");
134    println!("\n✨ The macro handles:");
135    println!("  • Nested structs (Company contains Address)");
136    println!("  • Lists of structs (Vec<Employee>)");
137    println!("  • Enum fields (Role in Employee)");
138    println!("  • Field renaming (zip_code → zipCode)");
139}
More examples
Hide additional examples
examples/with_macros.rs (line 81)
75async fn main() -> anyhow::Result<()> {
76    println!("=== BAML Complete Macro Example ===\n");
77    println!("✨ Using all three macros for maximum productivity!\n");
78
79    // Build IR automatically from types
80    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    // Print what was generated
92    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    // Configure the LLM client using macro-generated struct
108    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    // Build the runtime
116    let runtime = RuntimeBuilder::new()
117        .ir(ir)
118        .client("openai", client)
119        .build();
120
121    // Prepare input parameters
122    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    // Execute the function
135    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}
examples/extract_person_macro.rs (line 61)
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    // Step 1: Build IR using the registry - automatically collects all schema definitions
60    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    // Print what was generated
87    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    // Step 2: Configure the LLM client
96    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    // Step 3: Build the runtime
109    let runtime = RuntimeBuilder::new()
110        .ir(ir)
111        .client("openai", client)
112        .build();
113
114    // Step 4: Prepare input parameters
115    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    // Step 5: Execute the function
131    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}
Source

pub fn add_class(&mut self, class: Class)

Add a class to the registry (called by the derive macro)

Source

pub fn add_enum(&mut self, enum_def: Enum)

Add an enum to the registry (called by the derive macro)

Source

pub fn build(self) -> IR

Build the final IR from all registered types

Examples found in repository?
examples/nested_macro.rs (line 66)
57fn main() {
58    println!("=== Nested Structures with Macros ===\n");
59
60    // Build IR with automatic nesting resolution
61    let ir = BamlSchemaRegistry::new()
62        .register::<Role>()
63        .register::<Address>()
64        .register::<Employee>()
65        .register::<Company>()
66        .build();
67
68    println!("✅ Generated IR with {} classes and {} enums:",
69        ir.classes.len(),
70        ir.enums.len()
71    );
72    println!();
73
74    // Show what was generated
75    for enum_def in &ir.enums {
76        println!("📋 Enum: {}", enum_def.name);
77        println!("   Variants: {}", enum_def.values.join(", "));
78        println!();
79    }
80
81    for class in &ir.classes {
82        println!("📦 Class: {}", class.name);
83        for field in &class.fields {
84            let optional = if field.optional { " (optional)" } else { "" };
85            println!("   - {}: {}{}",
86                field.name,
87                field.field_type.to_string(),
88                optional
89            );
90        }
91        println!();
92    }
93
94    // Test parsing with the generated IR
95    let parser = simplify_baml::parser::Parser::new(&ir);
96
97    let test_json = r#"
98    {
99        "name": "TechCorp",
100        "employees": [
101            {
102                "name": "Alice",
103                "age": 30,
104                "role": "engineer"
105            },
106            {
107                "name": "Bob",
108                "age": 35,
109                "role": "manager"
110            }
111        ],
112        "address": {
113            "street": "123 Main St",
114            "city": "San Francisco",
115            "zipCode": "94102"
116        }
117    }
118    "#;
119
120    match parser.parse(test_json, &FieldType::Class("Company".to_string())) {
121        Ok(result) => {
122            println!("✅ Successfully parsed nested JSON!");
123            println!("{:#?}", result);
124        }
125        Err(e) => {
126            println!("❌ Parse error: {}", e);
127        }
128    }
129
130    println!("\n=== Code Comparison ===");
131    println!("Manual IR building (nested_parsing.rs): ~90 lines");
132    println!("With macros (this file): ~40 lines of definitions");
133    println!("Reduction: ~55% less code!");
134    println!("\n✨ The macro handles:");
135    println!("  • Nested structs (Company contains Address)");
136    println!("  • Lists of structs (Vec<Employee>)");
137    println!("  • Enum fields (Role in Employee)");
138    println!("  • Field renaming (zip_code → zipCode)");
139}
Source

pub fn build_with_functions(self, functions: Vec<Function>) -> IR

Build IR and include additional functions

Examples found in repository?
examples/with_macros.rs (line 83)
75async fn main() -> anyhow::Result<()> {
76    println!("=== BAML Complete Macro Example ===\n");
77    println!("✨ Using all three macros for maximum productivity!\n");
78
79    // Build IR automatically from types
80    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    // Print what was generated
92    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    // Configure the LLM client using macro-generated struct
108    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    // Build the runtime
116    let runtime = RuntimeBuilder::new()
117        .ir(ir)
118        .client("openai", client)
119        .build();
120
121    // Prepare input parameters
122    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    // Execute the function
135    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}
More examples
Hide additional examples
examples/extract_person_macro.rs (lines 63-79)
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    // Step 1: Build IR using the registry - automatically collects all schema definitions
60    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    // Print what was generated
87    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    // Step 2: Configure the LLM client
96    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    // Step 3: Build the runtime
109    let runtime = RuntimeBuilder::new()
110        .ir(ir)
111        .client("openai", client)
112        .build();
113
114    // Step 4: Prepare input parameters
115    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    // Step 5: Execute the function
131    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}

Trait Implementations§

Source§

impl Default for BamlSchemaRegistry

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> ErasedDestructor for T
where T: 'static,