Dynamic Types - TypeBuilder
Dynamic Types - TypeBuilder
Dynamic Types - TypeBuilder
Sometimes you have output schemas that change at runtime — for example if you have a list of Categories that you need to classify that come from a database, or your schema is user-provided.
TypeBuilder is used to create or modify dynamic types at runtime to achieve this.
Imagine we want to make a categorizer prompt, but the list of categories to output come from a database.
@@dynamic to the class or enum definition to mark it as dynamic in BAML.TypeBuilder from baml_client in your runtime code and modify Category. All dynamic types you
define in BAML will be available as properties of TypeBuilder. Think of the
typebuilder as a registry of modified runtime types that the baml function will
read from when building the output schema in the prompt.Now we’ll add some properties to a User class at runtime using @@dynamic.
We can then modify the User schema at runtime. Since we marked User with @@dynamic, it’ll be available as a property of TypeBuilder.
Imagine you have a ChatResponse type in a function that you want to modify with a set of tools.
You want to add a tool_calls property to the ChatResponse type that can be a list of GetWeather or GetNews types, that are completely defined in BAML.
You can modify the set of tools that can be used in the ChatResponse type at runtime like this:
The previous examples showed how to modify existing types. Here we create a new Hobbies enum, and a new class called Address without having them defined in BAML.
Note that you must attach the new types to the existing Return Type of your BAML function(in this case it’s User).
TypeBuilder provides methods for building different kinds of types:
Ok, what if you just want to write some actual baml code to modify the types at runtime?
The TypeBuilder has a higher level API add_baml to do this:
JSON Schema is a declarative language for validating JSON data structures, often derived from language-native type definitions such as Python classes, TypeScript interfaces, or Java classes.
BAML supports converting JSON schemas into dynamic BAML types, allowing you to automatically use your existing data models with BAML’s LLM functions. This feature enables seamless integration between your application’s type system and BAML’s structured output capabilities.
We have a working implementation of this feature, but are waiting for concrete use cases to merge it into the main codebase. For a detailed explanation of this functionality, see our article on dynamic JSON schemas. You can also explore the source code and examples to understand how to implement this in your projects.
Please chime in on the GitHub issue if this is something you’d like to use.
When testing dynamic types there are two different cases:
The first case requires using the type_builder and dynamic blocks in the
test, whereas the second case only requires specifying the values in the args
block.
Suppose we have a dynamic class Resume and we want to add a property that
stores the user’s work experience when we testing a specific function. We can
do that by specifying the types and properties that we need in the
type_builder block.
The rendered prompt for ExtractResume will now include the experience field
defined in the dynamic block and the LLM will correctly extract the experience
in the input text.
Dynamic enums can be included in the type_builder block just like classes. The
only difference is that we inject new variants in the dynamic block instead of
properties.
The Feedback variant will be rendered in the prompt for ClassifyMessage
during the test execution.
When a dynamic type is used as an input parameter of a function, we can simply
pass any value in the args block of the test and the value will be rendered in
the prompt.
Enums work the same way, any variant defined in the args block will be
rendered normally.
For more information about dynamic types, see Type Builder.