BAML 集成技能
通用模式,用于在任何项目中与 BAML(边界机器学习)合作。BAML 提供了类型安全的 LLM 提示与自动代码生成,支持 Python 和 TypeScript。
设计原则
这项技能是框架通用的。它提供了在任何代码库中都能工作的通用 BAML 模式:
- 不是针对 CodeGraph-DE、Book-Vetting 或任何特定项目的
- 涵盖所有 BAML 项目中通用的模式
- 特定领域的类型应该放在项目特定的技能中
变量
| 变量 | 默认值 | 描述 |
|---|---|---|
| BAML_SRC | baml_src | 包含 BAML 文件的目录 |
| AUTO_GENERATE | true | 在更改时自动运行 baml-cli generate |
| STRICT_TYPES | true | 强制严格的类型匹配 |
指令
MANDATORY - 按照下面的工作流程顺序操作。
- 理解项目中 BAML 的角色
- 检查现有的 BAML 模式和类型
- 在使用 LLMs 时遵循类型安全模式
- 保持生成的代码同步
红旗 - 停止并重新考虑
如果你即将:
- 在没有 BAML 类型的情况下定义 LLM 提示
- 手动解析 LLM 输出而不是使用 BAML
- 在模式更改后跳过运行
baml-cli generate - 忽略生成客户端中的类型错误
停止 -> 定义 BAML 类型 -> 生成客户端 -> 然后继续
工作流程
1. 理解项目 BAML 设置
检查 BAML 配置:
# 查找 BAML 源目录
find . -name "*.baml" -type f | head -5
# 检查 BAML 客户端
ls -la baml_client/ || ls -la baml_src/baml_client/
# 检查生成器配置
cat baml_src/generators.baml 2>/dev/null
2. 审查现有类型
在添加新类型之前,先审查现有的:
// baml_src/types/ 中的常见模式
// 枚举
enum TaskStatus {
PENDING
IN_PROGRESS
COMPLETED
FAILED
}
// 类(DTOs)
class UserRequest {
query string
context string?
preferences map<string, string>?
}
class UserResponse {
answer string
confidence float
sources string[]
}
3. 定义新类型
添加 LLM 功能时:
// 1. 定义输入类型
class MyInput {
field1 string @description("清晰的描述")
field2 int @description("这个数字代表什么")
}
// 2. 定义输出类型
class MyOutput {
result string
metadata MyMetadata?
}
class MyMetadata {
confidence float
reasoning string
}
// 3. 定义函数
function MyFunction(input: MyInput) -> MyOutput {
client GPT4
prompt #"
给定:{{ input.field1 }}
计数:{{ input.field2 }}
提供你的分析。
{{ ctx.output_format }}
"#
}
4. 生成客户端
模式更改后:
# 生成 Python 和 TypeScript 客户端
baml-cli generate
# 或者使用特定配置
baml-cli generate --config baml_src/generators.baml
5. 使用生成的客户端
# Python 使用
from baml_client import b
async def process_request(input_data: dict):
result = await b.MyFunction(
input=MyInput(
field1=input_data["query"],
field2=input_data["count"]
)
)
return result.result
// TypeScript 使用
import { b } from './baml_client';
async function processRequest(inputData: Record<string, unknown>) {
const result = await b.MyFunction({
field1: inputData.query as string,
field2: inputData.count as number
});
return result.result;
}
菜谱
模式同步
- 如果:添加或修改 BAML 类型
- 那么:阅读并执行
./cookbook/schema-sync.md
DTO 生成
- 如果:创建数据传输对象
- 那么:阅读并执行
./cookbook/dto-generation.md
客户端包装模式
- 如果:为你的服务包装 BAML 客户端
- 那么:阅读并执行
./cookbook/client-wrapper.md
快速参考
BAML 类型语法
| 类型 | 语法 | 示例 |
|---|---|---|
| 字符串 | string |
name string |
| 整数 | int |
count int |
| 浮点数 | float |
score float |
| 布尔值 | bool |
active bool |
| 可选 | type? |
nickname string? |
| 数组 | type[] |
tags string[] |
| 映射 | map<K, V> |
metadata map<string, string> |
| 枚举 | enum Name |
status TaskStatus |
| 类 | class Name |
自定义类型 |
| 联合 | type1 | type2 |
result string | Error |
函数属性
| 属性 | 目的 | 示例 |
|---|---|---|
@description |
字段文档 | @description("用户电子邮件") |
@alias |
JSON 键映射 | @alias("user_id") |
@skip |
从输出中排除 | @skip |
客户端选择
// 在 clients.baml 中定义客户端
client GPT4 {
provider openai
options {
model "gpt-4-turbo"
temperature 0.7
}
}
client Claude {
provider anthropic
options {
model "claude-3-opus"
max_tokens 4096
}
}
// 在函数中使用
function MyFunc(input: Input) -> Output {
client GPT4 // 或 Claude
prompt #"..."#
}
重试和回退
// 配置重试
client GPT4WithRetry {
provider openai
retry_policy {
max_retries 3
strategy exponential_backoff
}
}
// 回退链
client_fallback MainClient {
primary GPT4
fallback [Claude, GPT35Turbo]
}
最佳实践
1. 首先类型安全
始终定义明确的类型:
// 好:明确类型
class BookAnalysis {
title string
author string
summary string @description("2-3 句摘要")
rating float @description("0-5 评分")
tags string[]
}
// 坏:使用通用类型
function AnalyzeBook(text: string) -> string // 失去类型安全
2. 使用描述
为 LLM 指导添加描述:
class SearchQuery {
query string @description("用户的自然语言搜索查询")
filters SearchFilters? @description("可选过滤器以缩小结果")
limit int @description("返回结果的最大数量,默认为 10")
}
3. 处理错误
定义错误类型:
class Error {
code string
message string
}
function SafeAnalysis(input: Input) -> Output | Error {
// LLM 可以返回成功或错误
}
4. 版本控制模式
保持模式版本一致:
// baml_src/version.baml
// 模式版本:1.2.0
// 最后更新:2025-12-24
// 在 CHANGELOG 中记录重大更改
集成点
与模式对齐
BAML 类型应与数据库模型对齐:
// BAML 类型
class User {
id int
email string
name string?
}
// 应与 SQLAlchemy 模型匹配
class User(Base):
id: Mapped[int]
email: Mapped[str]
name: Mapped[str | None]
与 API 模式
BAML 类型可以生成 API 响应类型:
// BAML 响应类型
class APIResponse {
success bool
data ResponseData
error string?
}
// 在 FastAPI 中使用生成的类型
@app.post("/analyze")
async def analyze(request: Request) -> APIResponse:
result = await b.Analyze(request.data)
return APIResponse(success=True, data=result)
与前端类型
生成的 TypeScript 类型适用于前端:
// 由 BAML 生成
import type { BookAnalysis } from './baml_client/types';
// 在 React 组件中使用
function BookCard({ analysis }: { analysis: BookAnalysis }) {
return (
<div>
<h2>{analysis.title}</h2>
<p>{analysis.summary}</p>
<Rating value={analysis.rating} />
</div>
);
}
故障排除
生成错误
# 检查 BAML 语法
baml-cli check
# 详细生成
baml-cli generate --verbose
类型不匹配
如果 LLM 输出与预期类型不匹配:
- 检查提示的清晰度
- 添加更多明确的
@description提示 - 考虑使用带有 Error 的联合类型
- 在客户端启用严格模式
客户端导入问题
# 确保客户端已生成
try:
from baml_client import b
except ImportError:
# 运行:baml-cli generate
raise RuntimeError("BAML 客户端未生成。运行:baml-cli generate")