关于 logfire-evals
此技能指导使用 Python 的 `pydantic_evals` 或 Node.js 的 `logfire/evals` 设置并运行 AI 与 Agent 评估,涵盖数据集选择、评估器配置、冒烟测试和结果验证,也说明现有 Braintrust 套件接入 Logfire 的兼容路径。
主要功能
- 01配置 Python 和 Node.js 评估
- 02使用代码内或托管数据集
- 03配置内置及自定义评估器
- 04提供冒烟测试指导
- 05验证运行与遥测数据
- 06支持 Braintrust 兼容路径
适用场景
- 01为 AI Agent 仓库添加评估
- 02根据用例数据集运行检查
- 03使用 Logfire 托管数据集
- 04将现有 Braintrust 评估重定向至 Logfire
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ pydantic/ skills --skill logfire-evals安装后在 Claude Code 中输入/logfire-evals确认已加载。
详细介绍
使用 Logfire 评估 AI 代码
工作原理
Python 的 pydantic_evals 和 Node.js 的 logfire/evals 会针对测试用例运行任务、应用评估器并返回报告。即使此技能未配置导出器,处于活动状态的 Logfire 或 OpenTelemetry 提供程序仍可能导出输入和输出。若要有意上传数据,Python 需要 logfire.configure(),Node.js 则需要配置导出器。
基于 Span 的评估器会检查任务的 OpenTelemetry Span 树。如果 Logfire 仪表化未正常工作,Python 会报告“没有可用的 Span 树”;Node.js 的 HasMatchingSpan 则可能完全不返回评估器结果。出现任一信号都应视为设置失败,而不是 Agent 的表现证据。
步骤 1:先检查是否已有 Braintrust 测试套件
先做一个简单检查:此代码库是否已有 Braintrust 测试套件——源码中实际存在 Eval(...) 调用或 from braintrust import Eval,而不只是列出了 braintrust 依赖、没有任何实际用法?此路径完全不需要 CLI 身份验证——不要为此运行步骤 2。兼容端点仅适用于 Logfire Cloud US 和 EU;若提供的是其他来源,请改用原生评估路径。
保留现有的 Eval() 代码(Python braintrust>=0.30.1 / TypeScript braintrust>=3.24.0 — 已验证版本),仅更改环境变量,将其下次运行重定向到 Logfire,无需涉及 pydantic_evals:
export BRAINTRUST_APP_URL="https://logfire-us.pydantic.dev/v1/braintrust" # EU: logfire-eu.pydantic.dev
export BRAINTRUST_API_KEY="<logfire-project-api-key>" # Settings -> API Keys
unset BRAINTRUST_API_URL BRAINTRUST_PROXY_URL # these override the endpoint above if set — the #1 "it still hit Braintrust" cause
目标项目的 API 密钥需要具备 project:write_otlp 和 project:read_datasets 权限:SDK 会写入运行记录,然后读取实验元数据以生成摘要。仅允许写入数据的令牌会导致 403 错误。
此兼容性预览支持内联/可调用数据、本地任务和评分器、多个分数、每个名称对应一个标签,以及常规的摘要收尾处理。它不支持 Braintrust 托管资源、BTQL、模型代理、服务端评分和收尾后的反馈。Rust、summarize_scores=False,以及不进行比较的手动 flush(),都不会请求投影所需的摘要。请参阅完整的覆盖范围和概念映射。
直接跳到步骤 5(验证)——SDK 自行打印的结果 URL 也会直接在 Logfire 中打开,而且此路径不适用此处的其他内容(身份验证、数据集定义)。
没有现成的 Braintrust 测试套件?现在继续执行步骤 2,然后再进行步骤 3 中更详细的识别——在此之前,无需了解函数/Agent 或数据集的形态。
步骤 2:在运行需要 Logfire 时进行身份验证
对于不使用 Span 评估器的纯本地运行,请使用一个全新的进程,该进程既不预加载也不导入应用遥测;省略 Python 的 logfire.configure() 和任何 Node.js 导出器引导代码。如果任务配置了导出器,且没有文档说明的禁用开关,请停止操作,不要声称这是纯本地运行。上传数据、使用托管数据集和 Span 评估器都需要通过 Logfire 对指定项目进行身份验证。
对于由 Logfire 支持的运行,请使用身份验证并选择确切项目,根据提供的 Logfire URL 确定 CLI 目标,并使用已验证的 CLI 路径运行面向该目标的 whoami 检查——对于没有 uv 的 JS/TS 项目,请使用外部前缀 npm 回退方式,而不要使用普通的 npx,因为它可能会执行仓库本地的二进制文件。如果该检查已报告正确的项目以及解析后的 --region 或 --base-url 目标,则跳到步骤 3;否则,请继续完成其中完整的身份验证和项目选择流程。此 CLI 流程适用于 logfire.configure();步骤 3 中托管数据集的操作使用的是具有不同权限范围的独立 API 密钥。
步骤 3:确定要评估的内容
确定实际任务和数据集。遵循仓库的包、测试和依赖项约定。首次评估时,优先从测试、架构、示例或合成固件中选取 3-5 个用例,并针对已定义的行为进行确定性检查。不要照搬示例(除非它适用),不要替换评估框架,也不要重构无关代码。如果没有可运行的任务或安全的预期行为,请只提出一个有针对性的问题,而不是自行编造。
- 代码内数据集:使用
pydantic_evals的 Python 模块,或使用logfire/evals的 Node.js 模块。这是 Agent 驱动工作流的默认方式。 - 托管/管理型数据集:用例存储在 Logfire 界面中,由非工程师编辑,并通过单独的
LogfireAPIClient拉取/推送(from logfire.experimental.api_client import LogfireAPIClient)。托管数据集的输入和输出必须是 JSON 对象;代码定义的数据集可接受标量根值,但托管数据集不接受。若不带类型参数调用client.get_dataset(name),它会返回原始 dict,不能传给push_dataset或.evaluate_sync();请传入输入/输出类型(如果使用元数据,也包括元数据类型),以获取真正的pydantic_evals.Dataset:client.get_dataset(name, MyInputType, MyOutputType)。如果存储的数据集包含自定义评估器,也请传入其类,使用custom_evaluator_types=[MyEvaluator](自定义报告评估器则使用custom_report_evaluator_types=[...]),以便反序列化。使用client.push_dataset(dataset)推送。这需要单独的 API 密钥,可在 Settings → API Keys 中获取(权限范围为project:read_datasets/project:write_datasets),而不是步骤 2 的 CLI 身份验证流程。只有当用户明确需要在代码外编辑用例时才相关。
步骤 4:定义数据集并运行
使用仓库现有的包管理器和锁文件。仅为对应语言安装缺少的集成。
Python
使用检测到的 Python 包管理器添加 pydantic-evals[logfire]:uv add、poetry add 或 pdm add。对于 pip/requirements 项目,请更新其声明的依赖项并从该文件安装;不要引入第二个包管理器或锁文件。
import logfire
from pydantic_evals import Case, Dataset
from pydantic_evals.evaluators import EqualsExpected, IsInstance
logfire.configure() # omit only in the isolated local-only process described above
def classify_sentiment(text: str) -> str:
return 'positive' if 'love' in text else 'negative'
dataset = Dataset[str, str, None](
name='sentiment-eval',
cases=[
Case(name='positive', inputs='I love this', expected_output='positive'),
Case(name='negative', inputs='This is terrible', expected_output='negative'),
],
evaluators=[EqualsExpected(), IsInstance(type_name='str')],
)
report = dataset.evaluate_sync(classify_sentiment) # or `await dataset.evaluate(...)`
report.print(include_input=True, include_output=True)
仅当任务明确需要步骤 3 中的托管数据集 API 时,才改用 logfire[datasets]。
Node.js 上的 JavaScript 或 TypeScript
不要将本节用于 Deno、Bun、浏览器或 worker;此技能尚未验证这些环境的导出器配置。
根据现有锁文件选择的包管理器添加 logfire 和 @pydantic/logfire-node:pnpm add、yarn add、bun add 或 npm install。不要引入第二个锁文件。
在加载任务前配置 Logfire。复用现有的检测入口,避免重复配置。
import * as logfire from '@pydantic/logfire-node'
import { Case, Dataset, EqualsExpected, renderReport } from 'logfire/evals'
logfire.configure()
const classifySentiment = (text: string) => (text.includes('love') ? 'positive' : 'negative')
const dataset = new Dataset<string, string>({
name: 'sentiment-eval',
cases: [new Case({ name: 'positive', inputs: 'I love this', expectedOutput: 'positive' })],
evaluators: [new EqualsExpected()],
})
await dataset.evaluate(classifySentiment).then((report) => {
console.log(renderReport(report, { includeInput: true, includeOutput: true }))
}).finally(() => logfire.shutdown({ timeoutMillis: 5000 }))
其他内置项包括 Equals、Contains、IsInstance、MaxDuration、HasMatchingSpan 和 LLMJudge。Node.js 自定义评估器需继承 Evaluator,而 LLMJudge 需要一个评审回调。仅在使用托管数据集时才使用 @pydantic/logfire-node/datasets。
付费运行或完整运行前的冒烟测试
运行完整数据集前,如果数据集较大,或使用了 LLMJudge 或任何会产生计费模型调用的评估器,请先对 2-3 个用例进行冒烟测试。这样可以在错误导致整个数据集的成本增加之前发现设置问题。
Python:
smoke = Dataset(
name=dataset.name,
cases=dataset.cases[:3],
evaluators=dataset.evaluators,
report_evaluators=dataset.report_evaluators,
)
smoke_report = smoke.evaluate_sync(classify_sentiment)
smoke_report.print(include_input=True, include_output=True)
Node.js:
const smoke = new Dataset({
name: dataset.name,
cases: dataset.cases.slice(0, 3),
evaluators: dataset.evaluators,
reportEvaluators: dataset.reportEvaluators,
})
await smoke.evaluate(classifySentiment).then((report) => {
console.log(renderReport(report, { includeInput: true, includeOutput: true }))
}).finally(() => logfire.shutdown({ timeoutMillis: 5000 }))
确认冒烟测试没有意外错误,并且应通过的断言均已通过。然后,如果完整数据集较大或会产生付费模型调用,请告知用户用例数量以及哪些评估器会调用模型,并在运行完整数据集前取得明确确认——仅凭冒烟测试结果良好,不要在未告知的情况下直接进行昂贵的完整运行。
本节其余内容仅适用于 Python。自定义评估器继承 Evaluator 并实现 evaluate;使用 @dataclass 定义可配置字段并实现可移植序列化。数据集中的用例名称必须唯一。最常用的评估器:
| 评估器 | 检查内容 |
|---|---|
Equals(value) / EqualsExpected() | 与字面值 / expected_output 精确匹配(如果未设置 expected_output,则不执行任何操作——不要指望它会悄无声息地捕获此情况) |
IsInstance(type_name) | 输出的类型是否与名称匹配 |
LLMJudge(rubric, model=None, score=False) | 主观判断或基于评分标准的判断;会产生计费模型请求,因此在将其用作质量门槛前,请先用人工审核过的示例验证评分标准 |
ToolCorrectness(expected_tools, ...) | Agent 调用了哪些工具——它会读取跨度树,因此必须先完成步骤 2 的 logfire.configure(),否则完全无法工作,而不仅仅是无法上传 |
还可使用:Contains、MaxDuration、TrajectoryMatch、ArgumentCorrectness、MaxToolCalls、MaxModelRequests——其中与工具 / 轨迹相关的评估器和 ToolCorrectness 一样依赖跨度树;完整列表请参见 pydantic_evals.evaluators。这五个 Agent 式(基于跨度)评估器需要 pydantic-evals>=2.4.0——如果锁定的是较旧版本,请检查 pyproject.toml / uv.lock 并升级后再使用,因为失败的是导入本身,而不是静默地不执行任何操作。
出于安全原因,Python 评估器(执行任意代码)已被移除——即使旧示例中提到了它,也不要使用。
如果要编辑托管数据集:client.push_dataset(dataset) 会覆盖服务器端的评估器,包括移除你在本地删除的评估器——不要将过时的本地副本推送到其他人已在 UI 中编辑过的数据集。
步骤 5:验证
终端中打印出报告,并不能证明结果已到达 Logfire;请确认运行确实已记录。在本次会话中实际检查之前,绝不要报告某个案例已通过、某个分数或某次运行已完成——如果运行失败、取消或没有生成分数,请如实报告失败;绝不要编造分数,也不要凭手动猜测结果「应该」如何。
如果来自步骤 1 的 Braintrust 路径(跳过了步骤 2)? 此处没有通过 whoami 确定的项目可供查询——请使用 SDK 自行打印的结果 URL,它会直接打开正确的 Logfire 项目。请从该页面确认以下相同内容(完成情况、通过情况、案例详情),而不是按名称搜索。
- 如果已连接 Logfire MCP 服务或 API,直接查询该运行——运行的根 span 名为
evaluate {name},带有gen_ai.operation.name = 'experiment'、dataset_name和task_name属性;找到最近一次与数据集名称匹配的运行,并确认logfire.experiment.metadata显示的案例数和通过率符合预期。否则,请在步骤 2 中指定的确切项目里打开 Logfire 的 AI Evaluations → Datasets & Experiments → Experiments,并按名称/时间戳查找运行。 - 先阅读 Overview 标签页(或查询到的元数据):完成数量、断言通过情况、任务错误、平均耗时。**如果完成情况显示为「Not reported」,**表示运行发送了案例数据,但从未发出完成信号——应将其视为运行异常,而不是通过。
- 打开 Cases 标签页,先查看 Needs Review / Failed / Errors,而不是完整列表。
- 在 Live view 中深入查看失败案例的跟踪记录,获取实际证据,而不是只相信汇总分数。
- 修复并重新运行,直到应该通过的案例确实通过,并且任何工具调用/轨迹检查都显示真实的 span 数据,而不是「No span tree available」。
最后,根据刚刚确认的信息撰写报告——包括运行名称、查询到的确切案例数和通过率,以及运行了哪些评估器,而不是套用模板。请附上此实验的直接链接(SDK 自行打印的结果 URL,或你打开该实验的 Datasets & Experiments 页面),让用户无需询问即可查看运行结果。