使用结构化事件和 SQL 评估 AI 代理
代理完成一次运行,不代表它完成了任务。将运行、需要分析的模型和工具调用以及评估结果分别记录为事件。SQL 可以按发布版本比较质量、成本、延迟、重试和转人工情况。先用其他证据核对模型生成的评分,再判断评分是否正确。
Telemetry 是该工作流程中的分析层。它不执行记分器、管理提示版本、管理评估数据集或提供提示和完成重播。将这些工作流程保留在您的应用程序或专用评估系统中,然后发送聚合分析所需的批准结果字段。
operation_id 应在不同版本之间保持唯一。
首先定义评估单位
选择回答“什么获得了分数?”的行在选择指标之前。常见单位包括:
- 向用户显示一个最终答案;
- 一次已完成的代理运行;
- 一个已解决的支持案例;
- 一项工具选择决策;
- 针对冻结示例检索到的答案;
- 一项业务操作可以包括多次代理尝试。
为该单元指定一个稳定的标识符,例如 operation_id。对 run_id、response_id 和 evaluation_id 使用单独的标识符。一次重试可以为一项操作创建多次运行,并且一个输出可以接受多次评估。对每个grain重复使用单个标识符会产生错误的连接和重复计算的成本。
单独的运行、请求和评估事件
实用的起始合约使用三个或四个事件表:
| 活动 | 谷物 | 有用的字段 |
|---|---|---|
agent_run_completed |
一台终端代理运行 | operation_id、run_id、workflow、status、duration_ms、tool_call_count、human_handoff、prompt_version、release |
llm_request_completed |
一位提供商请求 | operation_id、run_id、response_id、provider、model、input_tokens、output_tokens、estimated_cost_usd、latency_ms |
agent_tool_completed |
一种工具尝试 | run_id、tool_call_id、tool_name、status、duration_ms、retry_count、error_type |
ai_output_reviewed |
一项评估结果 | operation_id、evaluation_id、evaluator_type、evaluator_version、metric_name、score、passed、review_outcome、is_final、dataset_version、release |
不要将所有四粒谷物强行挤成一排。否则,进行五次工具尝试和两次评估的运行会增加成本或加入时的成功次数。
使用多种证据
没有一个评估者足以满足每个代理工作流程。仅组合与实际决策相对应的信号:
- 确定性检查验证模式、所需引用、允许的工具选择、精确计算、策略规则或已知的最终状态。
- 人工审查捕获有界的标题,例如正确、部分正确、不安全或需要升级。记录标题和审稿人流程,而不是私人审稿人笔记。
- 基于模型的评分可以以更高的量应用可重复的评分标准。对判断模型、指令和阈值进行版本控制,并定期将分数与人工审核进行比较。
- 产品结果记录用户是否接受、保存、更正、重新生成、升级或放弃结果。
LLM评委是一个衡量工具,而不是一个客观标签。跟踪分歧、缺失评估以及法官配置的变化。 Langfuse评价理念 和 Arize Phoenix 评估文档 描述了可以保留在 Telemetry 上游的附加评估工作流程。
发出经过审查的结果事件
此 JavaScript 示例在评分者或人工审核工作流程完成后发送紧凑的评估器结果:
import telemetry from "telemetry-sh";
telemetry.init(process.env.TELEMETRY_API_KEY);
export async function recordAgentEvaluation({
operationId,
evaluationId,
evaluatorType,
evaluatorVersion,
metricName,
score,
threshold,
reviewOutcome,
isFinal,
datasetVersion,
promptVersion,
release,
}) {
await telemetry.log("ai_output_reviewed", {
operation_id: operationId,
evaluation_id: evaluationId,
evaluator_type: evaluatorType,
evaluator_version: evaluatorVersion,
metric_name: metricName,
score,
threshold,
passed: score >= threshold,
review_outcome: reviewOutcome,
is_final: isFinal,
dataset_version: datasetVersion,
prompt_version: promptVersion,
release,
});
}
只有对该操作、指标、评估器版本和产品版本具有最终效力的唯一决定,才将 isFinal 设为 true。代理运行结束并不等于评审已定稿。
默认情况下,将原始提示、完成、检索到的文档、工具参数、秘密和自由格式的审阅者注释保留在事件之外。更喜欢稳定的类别和版本标识符。如果内容保留获得批准,请将其存储在专为该访问和删除策略设计的系统中,并将其与受限标识符相关联。
按版本比较质量
本例要求每个操作、产品版本、指标和评估器版本只有一条 is_final = true 的最终评审。初步评审应标记为 is_final = false。若要修正最终决定,请使用新的评估器版本或独立的定稿事件。查询会排除重复的最终评审,并只统计已完成的操作;解释覆盖率或通过率前应先调查重复记录。
WITH completed AS (
SELECT release, operation_id
FROM agent_run_completed
WHERE timestamp_utc >= now() - INTERVAL '30 days'
AND status = 'success'
GROUP BY release, operation_id
),
final_reviews AS (
SELECT release, operation_id, MAX(score) AS score,
MAX(CASE WHEN passed THEN 1 ELSE 0 END) AS passed
FROM ai_output_reviewed
WHERE timestamp_utc >= now() - INTERVAL '30 days'
AND metric_name = 'task_quality'
AND evaluator_version = 'quality-rubric-v3'
AND is_final = true
GROUP BY release, operation_id
HAVING COUNT(*) = 1
)
SELECT
c.release,
COUNT(*) AS completed_operations,
COUNT(f.operation_id) AS evaluated_operations,
ROUND(
100.0 * COUNT(f.operation_id)
/ NULLIF(COUNT(*), 0),
1
) AS evaluation_coverage_pct,
ROUND(
100.0 * SUM(CASE WHEN f.passed = 1 THEN 1 ELSE 0 END)
/ NULLIF(COUNT(f.operation_id), 0),
1
) AS evaluated_pass_rate_pct,
ROUND(AVG(f.score), 3) AS average_final_score
FROM completed c
LEFT JOIN final_reviews f
ON f.release = c.release AND f.operation_id = c.operation_id
GROUP BY c.release
ORDER BY c.release;
在使用结果做版本决策前,请检查被排除的重复最终评审:
SELECT release, operation_id, COUNT(*) AS conflicting_final_reviews
FROM ai_output_reviewed
WHERE timestamp_utc >= now() - INTERVAL '30 days'
AND metric_name = 'task_quality'
AND evaluator_version = 'quality-rubric-v3'
AND is_final = true
GROUP BY release, operation_id
HAVING COUNT(*) > 1
ORDER BY release, operation_id;
不要在不分离这些维度的情况下比较使用不同标准的版本、判断模型、阈值、数据集版本或采样规则。评估者变更后的分数变化并不是产品回归的证据。
计算每个可接受结果的成本
先按操作汇总成本,再与唯一的最终决定关联。本例中的 operation_id 在不同版本间全局唯一;如果你的系统不是这样,请在两侧关联键中加入 release。重复的最终决定会被排除,并需要调查。
WITH operation_cost AS (
SELECT
operation_id,
SUM(estimated_cost_usd) AS total_cost_usd
FROM llm_request_completed
WHERE timestamp_utc >= now() - INTERVAL '30 days'
GROUP BY operation_id
),
terminal_outcome AS (
SELECT
operation_id,
MAX(CASE WHEN review_outcome = 'accepted' THEN 1 ELSE 0 END) AS accepted
FROM ai_output_reviewed
WHERE timestamp_utc >= now() - INTERVAL '30 days'
AND metric_name = 'task_quality'
AND evaluator_version = 'quality-rubric-v3'
AND is_final = true
GROUP BY operation_id
HAVING COUNT(*) = 1
)
SELECT
COUNT(*) AS evaluated_operations,
SUM(accepted) AS accepted_operations,
ROUND(SUM(total_cost_usd), 4) AS evaluated_cost_usd,
ROUND(
SUM(total_cost_usd) / NULLIF(SUM(accepted), 0),
4
) AS cost_per_accepted_operation_usd
FROM operation_cost c
JOIN terminal_outcome o ON o.operation_id = c.operation_id;
只有当“接受”有稳定的定义时,这个指标才有意义。复制的答案、用户可见的答案、无需重新打开即可解决的案例以及人工评分通行证是不同的结果。
构建回归门
对于每个提议的版本:
- 使用相同的评估器配置运行相同的冻结数据集。
- 记录候选
release、prompt_version、dataset_version和evaluator_version。 - 将通过率、严重失败率、切换率、p95 持续时间以及每个接受操作的成本与批准的基线进行比较。
- 检查源评估系统中的失败示例。
- 使用运行前选择的阈值批准或拒绝发布。
- 单独监控生产结果,因为冻结数据集无法代表每个实时输入。
当决策需要时,包括最小样本量和置信区间。避免对分母很小的百分比发出告警。还跟踪评估覆盖范围:20 次审核运行的及格分数并不代表 10,000 次未经审核的运行。
何时保留专用评估平台
当团队需要提示和完成检查、数据集管理、注释队列、提示管理、实验执行、跟踪重放或内置评估器时,请使用专业平台。 Telemetry 可以收到 SQL 分析的版本化分数和结果;它不是功能对功能的替代。
接下来,使用 AI质量回归秘诀、代理任务成功和移交秘诀 和 每美元配方可接受的产出。对于更广泛的实现边界,请参阅 AI代理监控。