Here's a list of all the types that can be represented in BAML: ## Primitive Types * `bool` * `int` * `float` * `string` * `null` ## Literal Types This feature was added in: v0.61.0. The primitive types `string`, `int` and `bool` can be constrained to a specific value. For example, you can use literal values as return types: ```rust function ClassifyIssue(issue_description: string) -> "bug" | "enhancement" { client GPT4Turbo prompt #" Classify the issue based on the following description: {{ ctx.output_format }} {{ _.role("user")}} {{ issue_description }} "# } ``` See [Union(|)](#union-) for more details. ## Multimodal Types See [calling a function with multimodal types](/guide/baml-basics/multi-modal) and [testing image inputs](/guide/baml-basics/testing-functions#test-image-inputs-in-the-playground) BAML's multimodal types are designed for ease of use: we have deliberately made it easy for you to construct an `image`, `audio`, `pdf`, or `video` instance from a URL. Under the hood, depending on the model you're using, BAML may need to download the file and transcode it (usually as base64) for the model to consume. This ease-of-use does come with some tradeoffs; namely, if you construct a multimodal instance using untrusted user input, you may be exposing yourself to [server-side request forgery (SSRF) attacks][ssrf]. Attackers may be able to fetch files on your internal network, on external networks using your application's identity, or simply excessively drive up your cloud network bandwidth bill. To prevent this, we recommend only using URLs from trusted sources/users or validating them using allowlists or denylists. [ssrf]: https://portswigger.net/web-security/ssrf ### `image` You can use an image like this for models that support them: ```rust function DescribeImage(myImg: image) -> string { client GPT4Turbo prompt #" {{ _.role("user")}} Describe the image in four words: {{ myImg }} "# } ``` You cannot name a variable `image` at the moment as it is a reserved keyword. Calling a function with an image type: ```python Python from baml_py import Image from baml_client import b async def test_image_input(): # from URL res = await b.TestImageInput( img=Image.from_url("https://upload.wikimedia.org/wikipedia/en/4/4d/Shrek_%28character%29.png") ) # Base64 image image_b64 = "iVBORw0K...." res = await b.TestImageInput( img=Image.from_base64("image/png", image_b64) ) ``` ```typescript TypeScript import { b } from '../baml_client' import { Image } from "@boundaryml/baml" ... // URL let res = await b.TestImageInput( Image.fromUrl('https://upload.wikimedia.org/wikipedia/en/4/4d/Shrek_%28character%29.png'), ) // Base64 let res = await b.TestImageInput( Image.fromBase64('image/png', image_b64), ) ``` ```ruby Ruby require_relative "baml_client/client" b = Baml.Client Image = Baml::Image def test_image_input # from URL res = b.TestImageInput( img: Image.from_url("https://upload.wikimedia.org/wikipedia/en/4/4d/Shrek_%28character%29.png") ) # Base64 image image_b64 = "iVBORw0K...." res = b.TestImageInput( img: Image.from_base64("image/png", image_b64) ) end ``` ```go Go package main import ( "context" "log" b "example.com/myproject/baml_client" ) func main() { ctx := context.Background() // From URL img, err := b.NewImageFromUrl("https://upload.wikimedia.org/wikipedia/en/4/4d/Shrek_%28character%29.png", nil) if err != nil { log.Fatal(err) } res, err := b.TestImageInput(ctx, img) if err != nil { log.Fatal(err) } // Base64 image imageB64 := "iVBORw0K...." img2, err := b.NewImageFromBase64(imageB64, stringPtr("image/png")) if err != nil { log.Fatal(err) } res2, err := b.TestImageInput(ctx, img2) if err != nil { log.Fatal(err) } } // Helper function for creating string pointers func stringPtr(s string) *string { return &s } ``` If using Pydantic, the following are valid ways to construct the `Image` type. ```json { "url": "https://upload.wikimedia.org/wikipedia/en/4/4d/Shrek_%28character%29.png" } ``` ```json { "url": "https://upload.wikimedia.org/wikipedia/en/4/4d/Shrek_%28character%29.png", "media_type": "image/png" } ``` ```json { "base64": "iVBORw0K....", } ``` ```json { "base64": "iVBORw0K....", "media_type": "image/png" } ``` ### `audio` Example ```rust function DescribeSound(myAudio: audio) -> string { client GPT4Turbo prompt #" {{ _.role("user")}} Describe the audio in four words: {{ myAudio }} "# } ``` Calling functions that have `audio` types. ```python Python from baml_py import Audio from baml_client import b async def run(): # from URL res = await b.TestAudioInput( audio=Audio.from_url( "https://actions.google.com/sounds/v1/emergency/beeper_emergency_call.ogg" ) ) # Base64 b64 = "iVBORw0K...." res = await b.TestAudioInput( audio=Audio.from_base64("audio/ogg", b64) ) ``` ```typescript TypeScript import { b } from '../baml_client' import { Audio } from "@boundaryml/baml" ... // URL let res = await b.TestAudioInput( Audio.fromUrl('https://actions.google.com/sounds/v1/emergency/beeper_emergency_call.ogg'), ) // Base64 const audio_base64 = ".." let res = await b.TestAudioInput( Audio.fromBase64('audio/ogg', audio_base64), ) ``` ```ruby Ruby require_relative "baml_client/client" b = Baml.Client Audio = Baml::Audio def test_audio_input # from URL res = b.TestAudioInput( audio: Audio.from_url( "https://actions.google.com/sounds/v1/emergency/beeper_emergency_call.ogg" ) ) # Base64 image audio_b64 = "iVBORw0K...." res = b.TestAudioInput( audio: Audio.from_base64("audio/mp3", audio_b64) ) end ``` ```go Go package main import ( "context" "log" b "example.com/myproject/baml_client" ) func main() { ctx := context.Background() // From URL aud, err := b.NewAudioFromUrl("https://actions.google.com/sounds/v1/emergency/beeper_emergency_call.ogg", nil) if err != nil { log.Fatal(err) } res, err := b.TestAudioInput(ctx, aud) if err != nil { log.Fatal(err) } // Base64 audio audioB64 := "iVBORw0K...." aud2, err := b.NewAudioFromBase64(audioB64, stringPtr("audio/mp3")) if err != nil { log.Fatal(err) } res2, err := b.TestAudioInput(ctx, aud2) if err != nil { log.Fatal(err) } } // Helper function for creating string pointers func stringPtr(s string) *string { return &s } ``` ### `pdf` Example ```rust function AnalyzePdf(myPdf: pdf) -> string { client GPT4Turbo prompt #" {{ _.role("user")}} Summarize the main points of this Pdf: {{ myPdf }} "# } ``` > **Note** Pdf inputs must be provided as Base64 data using `Pdf.from_base64`. URL-based inputs are not currently supported. ```python Python from baml_py import Pdf from baml_client import b async def run(): # Base64 data b64 = "JVBERi0K...." res = await b.TestPdfInput( pdf=Pdf.from_base64("application/pdf", b64) ) ``` ```typescript TypeScript import { b } from '../baml_client' import { Pdf } from "@boundaryml/baml" ... // Base64 const pdf_base64 = ".." let res = await b.TestPdfInput( Pdf.fromBase64('application/pdf', pdf_base64), ) ``` ```ruby Ruby # Pdf inputs must be provided as Base64. URL support is currently unavailable. require_relative "baml_client/client" b = Baml.Client Pdf = Baml::Pdf def test_pdf_input # Base64 Pdf pdf_b64 = "JVBERi0K...." res = b.TestPdfInput( pdf: Pdf.from_base64("application/pdf", pdf_b64) ) end ``` ```go Go package main import ( "context" "log" b "example.com/myproject/baml_client" ) func main() { ctx := context.Background() // Base64 PDF (URL support is not currently available) pdfB64 := "JVBERi0K...." pdf, err := b.NewPDFFromBase64(pdfB64, stringPtr("application/pdf")) if err != nil { log.Fatal(err) } res, err := b.TestPdfInput(ctx, pdf) if err != nil { log.Fatal(err) } } // Helper function for creating string pointers func stringPtr(s string) *string { return &s } ``` ### `video` Example ```rust function DescribeVideo(myVideo: video) -> string { client GPT4Turbo prompt #" {{ _.role("user")}} Describe what happens in this video: {{ myVideo }} "# } ``` Calling functions that have `video` types. > **Note** When you provide a `Video` via URL the URL is passed directly to the model. Some models cannot download external media; in that case convert the video to Base64 first. ```python Python from baml_py import Video from baml_client import b async def run(): # from URL res = await b.TestVideoInput( video=Video.from_url( "https://example.com/sample.mp4" ) ) # Base64 b64 = "AAAAGGZ0eXBpc29t...." res = await b.TestVideoInput( video=Video.from_base64("video/mp4", b64) ) ``` ```typescript TypeScript import { b } from '../baml_client' import { Video } from "@boundaryml/baml" ... // URL let res = await b.TestVideoInput( Video.fromUrl('https://example.com/sample.mp4'), ) // Base64 const video_base64 = ".." let res = await b.TestVideoInput( Video.fromBase64('video/mp4', video_base64), ) ``` ```ruby Ruby require_relative "baml_client/client" b = Baml.Client Video = Baml::Video def test_video_input # from URL res = b.TestVideoInput( video: Video.from_url( "https://example.com/sample.mp4" ) ) # Base64 video video_b64 = "AAAAGGZ0eXBpc29t...." res = b.TestVideoInput( video: Video.from_base64("video/mp4", video_b64) ) end ``` ```go Go package main import ( "context" "log" b "example.com/myproject/baml_client" ) func main() { ctx := context.Background() // From URL vid, err := b.NewVideoFromUrl("https://example.com/sample.mp4", nil) if err != nil { log.Fatal(err) } res, err := b.TestVideoInput(ctx, vid) if err != nil { log.Fatal(err) } // Base64 video videoB64 := "AAAAGGZ0eXBpc29t...." vid2, err := b.NewVideoFromBase64(videoB64, stringPtr("video/mp4")) if err != nil { log.Fatal(err) } res2, err := b.TestVideoInput(ctx, vid2) if err != nil { log.Fatal(err) } } // Helper function for creating string pointers func stringPtr(s string) *string { return &s } ``` ## Composite/Structured Types ### enum **See also:** [Enum](/docs/snippets/enum) A user-defined type consisting of a set of named constants. Use it when you need a model to choose from a known set of values, like in classification problems ```baml enum Name { Value1 Value2 @description("My optional description annotation") } ``` If you need to add new variants, because they need to be loaded from a file or fetched dynamically from a database, you can do this with [Dynamic Types](/guide/baml-advanced/dynamic-runtime-types). ### class **See also:** [Class](/docs/snippets/class) Classes are for user-defined complex data structures. Use when you need an LLM to call another function (e.g. OpenAI's function calling), you can model the function's parameters as a class. You can also get models to return complex structured data by using a class. **Example:** Note that properties have no `:` ```baml class Car { model string year int @description("Year of manufacture") } ``` If you need to add fields to a class because some properties of your class are only known at runtime, you can do this with [Dynamic Types](/docs/calling-baml/dynamic-types). ### Optional (?) A type that represents a value that might or might not be present. Useful when a variable might not have a value and you want to explicitly handle its absence. **Syntax:** `Type?` **Example:** `int?` or `(MyClass | int)?` ### Union (|) A type that can hold one of several specified types. This can be helpful with **function calling**, where you want to return different types of data depending on which function should be called. **Syntax:** `Type1 | Type2` **Example:** `int | string` or `(int | string) | MyClass` or `string | MyClass | int[]` Order is important. `int | string` is not the same as `string | int`. For example, if you have a `"1"` string, it will be parsed as an `int` if you use `int | string`, but as a `string` if you use `string | int`. ### List/Array (\[]) A collection of elements of the same type. **Syntax:** `Type[]` **Example:** `string[]` or `(int | string)[]` or `int[][]` * Array types can be nested to create multi-dimensional arrays * An array type cannot be optional ### Map A mapping of strings or enums to elements of another type. **Syntax**: `map` **Example**: `map` Enums and literal strings can also be used as keys. ```baml enum Category { A B C } // Enum key syntax map // Literal strings syntax map<"A" | "B" | "C", string> ``` {/* For TS users: `map` will generate a `Record` type annotation, but using any other type for the key will generate a `Map`, e.g. `map` in BAML will generate a `Map` type annotation in TypeScript. */} ### ❌ Set * Not yet supported. Use a `List` instead. ### ❌ Tuple * Not yet supported. Use a `class` instead. ## Type Aliases This feature was added in: v0.71.0. A *type alias* is an alternative name for an existing type. It can be used to simplify complex types or to give a more descriptive name to a type. Type aliases are defined using the `type` keyword: ```baml type Graph = map ``` Type aliases can point to other aliases: ```baml type DataStructure = string[] | Graph ``` Recursive type aliases are supported only through map or list containers, just like in TypeScript: ```baml type JsonValue = int | string | bool | float | JsonObject | JsonArray type JsonObject = map type JsonArray = JsonValue[] ``` Aliases can also refer to themselves: ```baml type JsonValue = int | float | bool | string | null | JsonValue[] | map ``` However, this is invalid since no value can satisfy this type: ```baml type A = B type B = A ``` ## Examples and Equivalents Here are some examples and what their equivalents are in different languages. ### Example 1 ```baml BAML int? | string[] | MyClass ``` ```python Python Equivalent Union[Optional[int], List[str], MyClass] ``` ```typescript TypeScript Equivalent (number | null) | string[] | MyClass ``` ```go Go Equivalent Union3IntOrStringArrayOrMyClass // Generated union type ``` ### Example 2 ```baml BAML string[] ``` ```python Python Equivalent List[str] ``` ```typescript TypeScript Equivalent string[] ``` ```go Go Equivalent []string ``` ### Example 3 ```baml BAML (int | float)[] ``` ```python Python Equivalent List[Union[int, float]] ``` ```typescript TypeScript Equivalent number[] ``` ```go Go Equivalent []Union2IntOrFloat // Generated union type slice ``` ### Example 4 ```baml BAML (int? | string[] | MyClass)[] ``` ```python Python Equivalent Optional[List[Union[Optional[int], List[str], MyClass]]] ``` ```typescript TypeScript Equivalent ((number | null) | string[] | MyClass)[] ``` ```go Go Equivalent []Union3IntOrStringArrayOrMyClass // Generated union type slice ``` ### Example 5 ```baml BAML "str" | 1 | false ``` ```python Python Equivalent Union[Literal["str"], Literal[1], Literal[False]] ``` ```typescript TypeScript Equivalent "str" | 1 | false ``` ```go Go Equivalent Union3StringOrIntOrBool // Generated union type with literal validation ``` ## ⚠️ Unsupported * `any/json` - Not supported. We don't want to encourage its use as it defeats the purpose of having a type system. if you really need it, for now use `string` and call `json.parse` yourself or use [dynamic types](/guide/baml-advanced/dynamic-runtime-types) * `datetime` - Not yet supported. Use a `string` instead. * `duration` - Not yet supported. We recommend using `string` and specifying that it must be an "ISO8601 duration" in the description, which you can parse yourself into a duration. * `units (currency, temperature)` - Not yet supported. Use a number (`int` or `float`) and have the unit be part of the variable name. For example, `temperature_fahrenheit` and `cost_usd` (see [@alias](/ref/baml/class))