For the remaining of 2024, Boundary Studio is free for new accounts!

Boundary Studio 2 will be released in 2025 with a new pricing model.

To enable observability with BAML, you’ll first need to sign up for a Boundary Studio account.

Once you’ve signed up, you’ll be able to create a new project and get your project token.

Then simply add the following environment variables prior to running your application:

$export BOUNDARY_PROJECT_ID=project_uuid
>export BOUNDARY_SECRET=your_token

There you’ll be able to see all the metrics and logs from your application including:

  • Cost
  • Function calls
  • Execution time
  • Token Usage
  • Prompt Logs
  • and more…

Tracing Custom Events

BAML allows you to trace any function with the @trace decorator. This will make the function’s input and output show up in the Boundary dashboard. This works for any python function you define yourself. BAML LLM functions (or any other function declared in a .baml file) are already traced by default. Logs are only sent to the Dashboard if you setup your environment variables correctly.

Example

In the example below, we trace each of the two functions pre_process_text and full_analysis:

1from baml_client import baml
2from baml_client.types import Book, AuthorInfo
3from baml_client.tracing import trace
4
5# You can also add a custom name with trace(name="my_custom_name")
6# By default, we use the function's name.
7@trace
8def pre_process_text(text):
9 return text.replace("\n", " ")
10
11
12@trace
13async def full_analysis(book: Book):
14 sentiment = await baml.ClassifySentiment(
15 pre_process_text(book.content)
16 )
17 book_analysis = await baml.AnalyzeBook(book)
18 return book_analysis
19
20
21@trace
22async def test_book1():
23 content = """Before I could reply that he [Gatsby] was my neighbor...
24 """
25 processed_content = pre_process_text(content)
26 return await full_analysis(
27 Book(
28 title="The Great Gatsby",
29 author=AuthorInfo(firstName="F. Scott", lastName="Fitzgerald"),
30 content=processed_content,
31 ),
32 )

This allows us to see each function invocation, as well as all its children in the dashboard:

See running tests for more information on how to run this test.

Adding custom tags

The dashboard view allows you to see custom tags for each of the function calls. This is useful for adding metadata to your traces and allow you to query your generated logs more easily.

To add a custom tag, you can import set_tags(..) as below:

1from baml_client.tracing import set_tags, trace
2import typing
3
4@trace
5async def pre_process_text(text):
6 set_tags(userId="1234")
7
8 # You can also create a dictionary and pass it in
9 tags_dict: typing.Dict[str, str] = {"userId": "1234"}
10 set_tags(**tags_dict) # "**" unpacks the dictionary
11 return text.replace("\n", " ")