print_type is a utility function in baml that takes all the type information about any type and converts it into a string, useful for telling an LLM what the schema of the output should be.

Syntax

#"
  {#print_type(<type>)}
"#
  • <type> is any type that you want to print. This can be a primitive type like int or str, or a complex type like MyCustomClass or (MyCustomClass | int[])?.

Most of the time, you can use the special keyword: output as a shortcut for the return type of the function for <type> like print_type(output).

print_type can only be used within a block string!

Property Attributes

@alias

The alias decorator allows you to temporarily rename a property.

class BugIntake {
  last_seen string?
  description string @alias(what_happened)
  repro_steps string? @alias(how_to_reproduce)

  severity int
}

print_type(BugIntake) will now print:

{
  "last_seen": string | null
  "what_happened": string
  "how_to_reproduce": string | null
  "severity": int
}

Deserialization with @alias

The deserializer automatically maps @alias to the actual property!

Your application code remains unchanged! Its still BugIntake.description and BugIntake.repro_steps in your code. @alias is only used for serialization and deserialization.

In the above example, the deserializer will now map the value of what_happend to description and how_to_reproduce to repro_steps!

@description

The description decorator allows you to add a description to a property.

class BugIntake {
  last_seen string?
  description string
  repro_steps string?
  severity int @description(#"
    The severity of the bug. This is a number between 1 and 10.
    Lower numbers are less severe.
  "#)
}

print_type(BugIntake) will now print:

{
  "last_seen": string | null
  "description": string
  "repro_steps": string | null
  // The severity of the bug. This is a number between 1 and 10.
  // Lower numbers are less severe.
  "severity": int
}

Block Attributes

You can add some attributes to the entire class by using a double @@ symbol.

@@reorder

Not currently implemented.

If you want to reorder how properties are rendered, for now you will have to change the order in the class definition itself.

override

By default, any attributes and block attributes you write will apply to every application of that class. If you want to override the attributes for a specific impl, you can use the override keyword.

  • override can only be used within an impl block
  • print_type first looks for attributes in the override block, then in the type definition. So, attributes defined in the class block will be the default value.
  • There is currently no easy way to “reset” an attribute to its default value in an override block
  • You cannot add new properties to a class in an override block. See adapters for this capability.

class BugIntake {
  last_seen string? @description(#"
    The last relative time the bug was seen.
  "#)
  description string
  repro_steps string?
  severity int
}

impl<llm, MyAiFunction> foo {
  override BugIntake {
    repro_steps @alias(how_to_reproduce)
    @description(#"
      Any steps taken to reproduce the bug.
    "#)
    severity @description(#"
      The severity of the bug. This is a number between 1 and 10.
      Lower numbers are less severe.
    "#)
  }

  prompt #"
    Given the following bug report, extract the required data.

    Bug Report
    ---
    {#input}
    ---

    Output JSON:
    {#print_type(BugIntake)}

    JSON:
  "#

  client SomeClient
}

This prompt will now print:

Given the following bug report, extract the required data.

Bug Report
---
{#input}
---

Output JSON:
{
  // The last relative time the bug was seen.
  "last_seen": string | null
  "description": string
  // Any steps taken to reproduce the bug.
  "how_to_reproduce": string | null
  // The severity of the bug. This is a number between 1 and 10.
  // Lower numbers are less severe.
  "severity": int
}

Custom Printers

This capability is currently hidden behind a feature flag. Reach out to us on discord if you want to enable it. We will be adding more documentation on this soon.

At a high level, it allows you to write python code that runs when you call print_type with all properties of the whats passed into print_type.