mcpField
B
baml

baml

github.com/ouachitalabs开发256 次安装39 周前更新
代码仓库

关于 baml

BAML 是用于构建结构化、类型安全 LLM 应用的 DSL 与速查资料。它可为 Python、TypeScript、Go 和 Ruby 生成客户端代码,并介绍语法、测试及命令行用法。

主要功能

  1. 01类型化结构化输出模式
  2. 02生成四种语言的客户端
  3. 03基于 Jinja 的提示词模板
  4. 04宽容的模式对齐解析
  5. 05内置测试与命令行指令

适用场景

  1. 01使用 LLM 提取结构化数据
  2. 02将输入分类为枚举值
  3. 03构建多轮对话或多模态流程
  4. 04测试 BAML 函数

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/ouachitalabs/skills --skill baml

安装后在 Claude Code 中输入/baml确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

examples/
chat.baml
classification.baml
extraction.baml
multimodal.baml
usage.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

Language Reference

LLM Providers

Prompt Engineering

Advanced

Testing

评论

支持 Markdown