Skip to main content

TypeBuilder

TypeBuilder creates or modifies output schemas at runtime. Useful for dynamic output structures that can't be determined at compile time, like categories from a database or user-provided schemas.

Basic Example​

BAML Code

enum Category {
RED
BLUE
@@dynamic // Makes this enum modifiable at runtime
}

function Categorize(text: string) -> Category {
prompt #"
Categorize this text:
{{ text }}

{{ ctx.output_format }}
"#
}

Runtime Usage

from baml_client.type_builder import TypeBuilder
from baml_client import b

tb = TypeBuilder()
tb.Category.add_value('GREEN')
tb.Category.add_value('YELLOW')

result = b.Categorize("The sun is bright", {"tb": tb})
# result can now be RED, BLUE, GREEN, or YELLOW

Dynamic Types​

Modifying Existing Types​

Mark types with @@dynamic to modify at runtime:

Classes

class User {
name string
age int
@@dynamic // Allow adding more properties
}
tb = TypeBuilder()
tb.User.add_property('email', tb.string())
tb.User.add_property('address', tb.string())

Enums

enum Category {
VALUE1
VALUE2
@@dynamic // Allow adding more values
}
tb = TypeBuilder()
tb.Category.add_value('VALUE3')
tb.Category.add_value('VALUE4')

Creating New Types​

Create entirely new types at runtime:

tb = TypeBuilder()

# Create a new enum
hobbies = tb.add_enum("Hobbies")
hobbies.add_value("Soccer")
hobbies.add_value("Reading")

# Create a new class
address = tb.add_class("Address")
address.add_property("street", tb.string())
address.add_property("city", tb.string())

# Attach new types to existing BAML type
tb.User.add_property("hobbies", hobbies.type().list())
tb.User.add_property("address", address.type())

TypeBuilder Methods​

MethodReturnsDescription
string()FieldTypeCreates a string type
int()FieldTypeCreates an integer type
float()FieldTypeCreates a float type
bool()FieldTypeCreates a boolean type
literal_string(value)FieldTypeCreates a literal string type
literal_int(value)FieldTypeCreates a literal integer type
literal_bool(value)FieldTypeCreates a literal boolean type
list(type)FieldTypeMakes a type into a list
union(types)FieldTypeCreates a union of types
map(key, value)FieldTypeCreates a map type
add_class(name)ClassBuilderCreates a new class
add_enum(name)EnumBuilderCreates a new enum

FieldType Methods​

MethodReturnsDescription
list()FieldTypeMakes a type into a list
optional()FieldTypeMakes a type optional

ClassBuilder Methods​

MethodReturnsDescription
add_property(name, type)ClassPropertyBuilderAdds a property to the class
description(desc)ClassBuilderAdds a description to the class
type()FieldTypeReturns the type of the class

ClassPropertyBuilder Methods​

MethodReturnsDescription
description(desc)ClassPropertyBuilderAdds a description to the property
alias(alias)ClassPropertyBuilderAdds the alias attribute

EnumBuilder Methods​

MethodReturnsDescription
add_value(value)EnumValueBuilderAdds a value to the enum
description(desc)EnumBuilderAdds a description
type()FieldTypeReturns the type of the enum

EnumValueBuilder Methods​

MethodReturnsDescription
description(desc)EnumValueBuilderAdds a description
alias(alias)EnumValueBuilderAdds the alias attribute
skip()EnumValueBuilderAdds the skip attribute

Adding Descriptions​

tb = TypeBuilder()

# Add description to a property
tb.User.add_property("email", tb.string()) \
.description("User's primary email address")

# Add description to an enum value
tb.Category.add_value("URGENT") \
.description("Needs immediate attention")

Using add_baml​

Higher-level API for creating dynamic types:

tb = TypeBuilder()
tb.add_baml("""
// Creates a new class
class Address {
street string
city string
state string
}

// Modifies existing @@dynamic class
dynamic class User {
address Address
}

// Modifies existing @@dynamic enum
dynamic enum Category {
PURPLE
}
""")

Common Patterns​

Dynamic Categories from Database​

categories = fetch_categories_from_db()
tb = TypeBuilder()
for category in categories:
tb.Category.add_value(category)

Dynamic Form Fields​

fields = get_form_fields()
tb = TypeBuilder()
form = tb.add_class("Form")
for field in fields:
form.add_property(field.name, tb.string())

Optional Properties​

tb = TypeBuilder()
tb.User.add_property("middle_name", tb.string().optional())
warning

All types added through TypeBuilder must be connected to the return type of your BAML function. Standalone types that aren't referenced won't affect the output schema.

See Also​