关于 baml
BAML 是用于构建结构化、类型安全 LLM 应用的 DSL 与速查资料。它可为 Python、TypeScript、Go 和 Ruby 生成客户端代码,并介绍语法、测试及命令行用法。
主要功能
- 01类型化结构化输出模式
- 02生成四种语言的客户端
- 03基于 Jinja 的提示词模板
- 04宽容的模式对齐解析
- 05内置测试与命令行指令
适用场景
- 01使用 LLM 提取结构化数据
- 02将输入分类为枚举值
- 03构建多轮对话或多模态流程
- 04测试 BAML 函数
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ ouachitalabs/ skills --skill baml安装后在 Claude Code 中输入/baml确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
examples/chat.bamlclassification.bamlextraction.bamlmultimodal.bamlusage.py详细介绍
BAML 快速参考
BAML(Boundary AI Markup Language)是一种用于构建大模型应用的 DSL,可生成结构化、类型安全的输出。它可以为 Python、TypeScript、Go 和 Ruby 生成客户端代码。
BAML 的工作方式
baml_src/中的所有.baml文件都可以彼此全局访问- 使用
baml-cli generate生成客户端 - 生成的
baml_client/提供类型安全的函数,可供导入和调用 - BAML 类型会转换为 Pydantic 模型(Python)、TypeScript 类型、Go 结构体或 Sorbet 类型(Ruby)
基本语法
类型
// Primitives
string, int, float, bool, null
// Composite
Type? // optional (nullable)
Type[] // array
Type1 | Type2 // union
map<K, V> // dictionary
// Literals
"spam" | "ham" // literal string union
// Multimodal
image, audio, video, pdf
类
定义结构化数据形状。字段名和类型之间不加冒号。
class Resume {
name string
email string? // optional
skills string[] // array
experience Experience[] // nested type
seniority SeniorityLevel // enum
}
class Experience {
company string
role string @description("Job title") // hint for the LLM
years int @alias("duration_years") // JSON key mapping
}
枚举
固定的值集合,适用于分类任务。
enum SeniorityLevel {
JUNIOR @description("0-2 years experience")
MID @description("2-5 years experience")
SENIOR @description("5+ years experience")
}
enum Category {
SPAM
HAM
UNKNOWN @skip // excluded from prompts
}
函数
定义与大模型的交互。函数名必须以大写字母开头。
function ExtractResume(resume_text: string) -> Resume {
client "openai/gpt-4o"
prompt #"
Extract structured information from this resume.
{{ ctx.output_format }}
Resume:
---
{{ resume_text }}
---
"#
}
客户端
配置大模型提供方。有两种风格:
// Shorthand (uses env vars automatically)
client "openai/gpt-4o"
client "anthropic/claude-sonnet-4-20250514"
// Named client (full control)
client<llm> GPT4 {
provider openai
options {
model "gpt-4o"
api_key env.OPENAI_API_KEY
temperature 0.0
}
}
// Fallback chain
client<llm> Resilient {
provider fallback
options {
clients [GPT4, Claude, GPT4Mini]
}
}
生成器
配置代码生成:
generator target {
output_type "python/pydantic" // or "typescript", "go", "ruby/sorbet"
output_dir "../"
default_client_mode "sync" // or "async"
version "0.203.1"
}
你可以为多种语言配置多个位置的代码生成。
例如,你可能希望让后端和前端的类型保持一致,以供各自的 BAML 客户端使用。
你可以通过初始化两个 generator 块来实现。
两个关键概念
1. {{ ctx.output_format }}
这个 Jinja 宏必须包含在每个提示词中。它会渲染返回类型的架构,让大模型知道应生成什么结构。
function ClassifyEmail(email: string) -> Category {
client GPT4
prompt #"
Classify this email.
{{ ctx.output_format }}
Email: {{ email }}
"#
}
对于 Category 枚举,它会渲染出类似这样的内容:
Answer with any of the categories:
SPAM
HAM
对于类,它会渲染出包含字段描述的 JSON 架构。
2. 架构对齐解析(SAP)
BAML 的解析器有意采用宽松策略。它会自动修正常见的大模型输出问题:
- 字符串缺少引号
- 末尾多余的逗号
- JSON 中的注释
- 不完整的序列
- 未转义的字符
这意味着,与严格的 JSON 解析或函数调用相比,你可以获得高出 87-93% 的准确率。
提示词语法(Jinja)
BAML 提示词使用 Jinja 模板:
prompt #"
{# Comments don't appear in output #}
{{ _.role("system") }}
You are a helpful assistant.
{{ _.role("user") }}
{% for msg in messages %}
{{ msg.content }}
{% endfor %}
{% if verbose %}
Be detailed in your response.
{% endif %}
{{ ctx.output_format }}
"#
主要结构:
{{ variable }}- 插入变量值{% for item in list %}...{% endfor %}- 循环{% if cond %}...{% endif %}- 条件判断{{ _.role("system"|"user"|"assistant") }}- 设置消息角色{{ value|filter }}- 应用过滤器(例如|upper、|length、|join(","))
调用 BAML 函数
Python
from baml_client import b
from baml_client.types import Resume
# Sync
resume = b.ExtractResume(resume_text)
print(resume.name, resume.skills)
# Async
from baml_client.async_client import b
resume = await b.ExtractResume(resume_text)
# Streaming
stream = b.stream.ExtractResume(resume_text)
for partial in stream:
print(partial) # partial Resume object
final = stream.get_final_response()
TypeScript
import { b } from './baml_client'
// Async (default)
const resume = await b.ExtractResume(resumeText)
console.log(resume.name, resume.skills)
// Streaming
const stream = b.stream.ExtractResume(resumeText)
for await (const partial of stream) {
console.log(partial)
}
const final = await stream.getFinalResponse()
Go
import b "example.com/myproject/baml_client"
resume, err := b.ExtractResume(ctx, resumeText, nil)
if err != nil {
log.Fatal(err)
}
fmt.Println(resume.Name, resume.Skills)
测试
直接在 BAML 文件中定义测试:
test SimpleExtraction {
functions [ExtractResume]
args {
resume_text "John Doe, Software Engineer at Acme Corp for 5 years"
}
@@assert({{ this.name == "John Doe" }})
}
运行测试:
baml-cli test # run all
baml-cli test -i "ExtractResume" # filter by function
baml-cli test --parallel 5 # parallel execution
属性参考
字段级:
@alias("name")- 重命名 JSON 输出中的字段@description("...")- 为大模型提供上下文@skip- 从提示词中排除(仅适用于枚举)
块级:
@@dynamic- 允许在运行时修改类或枚举
验证:
@check(expr, name)- 软验证(返回结果,不会失败)@assert(expr, name)- 硬验证(失败时抛出异常)
流式处理:
@@stream.done- 对象仅在完成后出现@stream.not_null- 父级开始流式传输前,字段必须有值@stream.with_state- 包含完成状态元数据
CLI 命令
baml-cli init # initialize new project
baml-cli generate # generate client code
baml-cli dev # dev server with hot reload
baml-cli test # run tests
baml-cli serve # start REST API server (port 2024)
baml-cli fmt # format BAML files
常见模式
完整的可运行示例请参阅 examples/ 目录:
extraction.baml- 结构化数据提取classification.baml- 基于枚举的分类chat.baml- 携带消息历史的多轮聊天multimodal.baml- 图像、音频和 PDF 输入usage.py- Python 调用模式
Further Resources
Getting Started
- Installation: https://docs.boundaryml.com/guide/installation-language/python.md
- TypeScript setup: https://docs.boundaryml.com/guide/installation-language/typescript.md
- Go setup: https://docs.boundaryml.com/guide/installation-language/go.md
Language Reference
- Complete syntax: https://docs.boundaryml.com/ref/overview.md
- Type system: https://docs.boundaryml.com/ref/baml/types.md
- Classes: https://docs.boundaryml.com/ref/baml/class.md
- Enums: https://docs.boundaryml.com/ref/baml/enum.md
- Functions: https://docs.boundaryml.com/ref/baml/function.md
- Generator: https://docs.boundaryml.com/ref/baml/generator.md
LLM Providers
- OpenAI: https://docs.boundaryml.com/ref/llm-client-providers/open-ai.md
- OpenAI-compatible (Ollama, vLLM, etc.): https://docs.boundaryml.com/ref/llm-client-providers/openai-generic.md
- Fallback strategy: https://docs.boundaryml.com/ref/llm-client-strategies/fallback.md
- Round-robin strategy: https://docs.boundaryml.com/ref/llm-client-strategies/round-robin.md
Prompt Engineering
- Reducing hallucinations: https://docs.boundaryml.com/examples/prompt-engineering/reducing-hallucinations.md
- Classification patterns: https://docs.boundaryml.com/examples/prompt-engineering/classification.md
Advanced
- Streaming: https://docs.boundaryml.com/guide/baml-basics/streaming.md
- Dynamic types: https://docs.boundaryml.com/guide/baml-advanced/dynamic-types.md
Testing
- Writing tests: https://docs.boundaryml.com/ref/baml/test.md