> ## Documentation Index
> Fetch the complete documentation index at: https://docs.befailproof.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Evaluator SDK

> 构建一个对 Failproof AI 会话进行同步或异步评分的服务。

评估器接收已完成的 Agent 会话，并返回您关注的质量信号：数值分数、每项分数的说明以及可选的摘要。Failproof AI 将这些结果与追踪记录一同存储，并在各 Agent 和环境之间进行图表化展示。

## 设置评估器

<Steps>
  <Step title="安装评估器 SDK">
    安装 SDK 及用于运行它的服务器。

    ```bash theme={null}
    pip install failproofai-sdk uvicorn
    ```
  </Step>

  <Step title="定义评分内容">
    创建 `evaluator.py`。此示例检查会话中是否包含任何失败的工具调用。

    ```python theme={null}
    import os
    from failproofai.evaluator import Evaluator, EvalResponse

    app = Evaluator(token=os.environ.get("EVALUATOR_TOKEN"))

    @app.config
    def config():
        return {"inactivity_timeout_secs": 1800}

    @app.evaluator
    def evaluate(req):
        tool_errors = sum(
            1 for item in req.events
            if item.event_type == "tool_result" and item.payload.get("error")
        )
        return EvalResponse(
            scores={"tool_reliability": 1.0 if tool_errors == 0 else 0.0},
            reasoning={"tool_reliability": f"{tool_errors} tool errors"},
        )
    ```
  </Step>

  <Step title="在本地运行并测试">
    设置共享令牌，启动评估器，并确认其健康检查端点能正常响应。

    ```bash theme={null}
    export EVALUATOR_TOKEN=<shared-token>
    uvicorn evaluator:app --host 0.0.0.0 --port 8080
    ```

    在另一个终端中：

    ```bash theme={null}
    curl http://127.0.0.1:8080/health
    ```
  </Step>
</Steps>

## 将评估器连接到 Failproof AI

1. 将评估器部署在 Failproof AI Cloud 可访问的 HTTPS URL 上。
2. 使用该 URL 配置 `EVALUATOR_ENDPOINT`，并将 `EVALUATOR_TOKEN` 设置为与评估器相同的令牌。对于托管 Cloud，请联系 [support@befailproof.ai](mailto:support@befailproof.ai) 配置连接。
3. 运行评估并确认分数出现在 Failproof AI 中。

<Tabs>
  <Tab title="仪表盘">
    在 **Observe → Sessions** 下打开已完成的会话，如果未自动进行评估，请选择 **Run evaluation**。在会话的 **Evaluation** 面板中查看状态、分数、推理过程和摘要。

    使用 **Observe → Evaluations** 跨 Agent 或环境比较分数。使用 **Observe → Metrics** 查看延迟、费用、令牌及其他数值指标。

    从单个会话开始，确认评估器为该特定运行返回了预期的分数键和有用的推理内容。

    <img src="https://mintcdn.com/exosphere/WgPwQzedeDNwJBTy/images/dashboard/session-detail.png?fit=max&auto=format&n=WgPwQzedeDNwJBTy&q=85&s=7b5f022dd5c485565a8cd92b2e936235" alt="显示评估分数和推理过程（位于追踪记录旁边）的会话详情视图。" width="3200" height="2000" data-path="images/dashboard/session-detail.png" />

    当单个结果看起来正确后，使用评估仪表盘随时间推移以及跨 Agent 或环境比较这些分数。

    <img src="https://mintcdn.com/exosphere/WgPwQzedeDNwJBTy/images/dashboard/dashboard-quality.png?fit=max&auto=format&n=WgPwQzedeDNwJBTy&q=85&s=74c925ae831046fc869a3a3d6e81fc25" alt="按时间绘制评估器分数的质量仪表盘。" width="2880" height="1800" data-path="images/dashboard/dashboard-quality.png" />

    健康的图表应使用稳定的分数名称；更改键名会创建独立的数据系列。
  </Tab>

  <Tab title="CLI">
    ```bash theme={null}
    fp evals --since 1h --score tool_reliability:0..1
    fp evals --since 24h --aggregate
    ```
  </Tab>
</Tabs>

对于自托管 Cloud 实例，在服务器进程上设置 `EVALUATOR_ENDPOINT` 之前，自动评估功能处于禁用状态。更改评估器环境变量后，请重启服务器。

该服务暴露 `GET /health`、`GET /config`、`POST /evaluate`，以及可选的 `GET /evaluate/{job_id}`。对于异步工作，返回 `JobPending` 并注册 `@app.job_lookup`，以便 Failproof AI 能够轮询它。

配置令牌后，除健康检查以外的所有路由均需要 Failproof AI 以 `EVALUATOR_TOKEN` 发送的同一 Bearer 令牌。

## SDK 类型

| 类型                | 字段                                                                                            |
| ----------------- | --------------------------------------------------------------------------------------------- |
| `AgentEvent`      | `id`, `ts`, `event_type`, `payload`                                                           |
| `EvalRequest`     | `schema_version`, `session_id`, `agent_id`, `environment`, `started_at`, `ended_at`, `events` |
| `EvalResponse`    | `scores`, `reasoning`, `summary`                                                              |
| `JobPending`      | `job_id`, `next_poll_secs`                                                                    |
| `EvaluatorConfig` | `inactivity_timeout_secs`, `default_poll_interval_secs`                                       |

## 装饰器与路由

| 装饰器               | 路由                       | 是否必需                |
| ----------------- | ------------------------ | ------------------- |
| `@app.evaluator`  | `POST /evaluate`         | 是                   |
| `@app.job_lookup` | `GET /evaluate/{job_id}` | 返回 `JobPending` 时必需 |
| `@app.config`     | `GET /config`            | 否                   |

SDK 将评估请求体大小上限设为 25 MiB。未知请求字段将被忽略，因此随着事件契约的扩展，服务仍能保持兼容性。

## 返回异步工作

当评估无法在单次请求内完成时，请使用 `JobPending`。Job ID 对 Failproof AI 而言是不透明的，在结果被收集或服务器超时到期之前，您的服务必须始终能够解析该 ID。

```python theme={null}
from failproofai.evaluator import EvalRequest, EvalResponse, Evaluator, JobPending

app = Evaluator(token="shared-secret")

@app.evaluator
def start(req: EvalRequest) -> JobPending:
    job_id = enqueue(req)
    return JobPending(job_id=job_id, next_poll_secs=30)

@app.job_lookup
def lookup(job_id: str):
    result = get_result(job_id)
    if result is None:
        return JobPending(job_id=job_id, next_poll_secs=30)
    return EvalResponse(
        scores=result.scores,
        reasoning=result.reasoning,
        summary=result.summary,
    )
```

轮询频率按以下顺序确定：`JobPending.next_poll_secs`、`EvaluatorConfig.default_poll_interval_secs`，然后是服务器的 `EVALUATOR_POLLING_INTERVAL_SECS`。取值范围限制在 1 秒到 1 小时之间。服务器默认的挂钟轮询上限为 1 小时。

## 请求与响应字段

| 字段                                      | 类型                         | 说明                        |
| --------------------------------------- | -------------------------- | ------------------------- |
| `EvalRequest.schema_version`            | `str`                      | 当前为 `"1"`。                |
| `session_id`, `agent_id`, `environment` | `str`                      | 会话标识与环境。                  |
| `started_at`                            | `datetime`                 | 第一个事件的时间戳。                |
| `ended_at`                              | `datetime \| None`         | 当会话发出结束事件时存在。             |
| `events`                                | `list[AgentEvent]`         | 完整的有序事件流。                 |
| `AgentEvent.id`                         | `int`                      | 后端事件行标识符。                 |
| `AgentEvent.ts`                         | `datetime`                 | 事件时间戳。                    |
| `AgentEvent.event_type`                 | `str`                      | 事件类别，例如 `tool_use`。       |
| `AgentEvent.payload`                    | `dict[str, Any]`           | 完整的事件载荷。                  |
| `EvalResponse.scores`                   | `dict[str, float] \| None` | 在评估中以图表展示的数值维度。           |
| `EvalResponse.reasoning`                | `dict[str, str] \| None`   | 各分数的说明；键应与 `scores` 保持一致。 |
| `EvalResponse.summary`                  | `str \| None`              | 总体评估叙述。                   |

## 服务器运维设置

自动评估为全部署范围生效，当 `EVALUATOR_ENDPOINT` 未设置时保持禁用状态。

| 变量                                 | 默认值     | 用途                                      |
| ---------------------------------- | ------- | --------------------------------------- |
| `EVALUATOR_ENDPOINT`               | 未设置     | 评估器服务的基础 URL。                           |
| `EVALUATOR_TOKEN`                  | 未设置     | 与 `Evaluator(token=...)` 共享的 Bearer 令牌。 |
| `EVALUATOR_WORKERS`                | `2`     | 并发调度工作线程数。                              |
| `EVALUATOR_CLAIM_BATCH`            | `4`     | 每次调度轮次声明的会话数。                           |
| `EVALUATOR_POLLING_INTERVAL_SECS`  | `10`    | 异步轮询的兜底频率。                              |
| `EVALUATOR_REQUEST_TIMEOUT_MS`     | `30000` | 单次请求的评估器超时时间。                           |
| `EVALUATOR_MAX_ATTEMPTS`           | `5`     | 终止失败前的投递重试次数。                           |
| `EVALUATOR_CONFIG_REFRESH_SECS`    | `300`   | `/config` 的刷新频率。                        |
| `EVALUATOR_MAX_POLL_DURATION_SECS` | `3600`  | 异步轮询的最大挂钟时间。                            |

服务器还可以限制哪些组织使用部署级全局评估器。请将端点、令牌、重试及组织访问控制的变更视为运维配置，更改后需重启或滚动更新服务器。

## 安全与运维

* 当流量跨越受信网络边界时，请将评估器部署在 HTTPS 之后。
* 配置非空 Bearer 令牌，并确保两个服务使用相同的令牌。
* 不要在日志中记录令牌或请求载荷中的完整敏感提示词。
* 使同步处理器具有幂等性；重试可能会重复发送请求。
* 在生产环境中，将异步 Job 状态持久化到进程内存之外。
* 保持分数键的稳定性。重命名键会创建新的图表系列，而不是修改旧的系列。

SDK 会发出结构化的生命周期日志，例如 `eval received`、`eval responded`、`job lookup`、`config returned`、`auth rejected` 以及处理器异常信息。SDK 不配置日志处理器；请使用宿主应用的日志配置。
