Files
2026-07-13 21:35:56 +08:00

17 KiB
Raw Permalink Blame History

测试 API 参考

自动从 pixie 源代码文档字符串生成。 请勿手动编辑——请运行 uv run python scripts/generate_skill_docs.py

pixie.evals —— LLM 应用程序的评估框架。

公开 API - Evaluation —— 单次评估器运行的结果数据类 - Evaluator —— 评估可调用对象的协议 - evaluate —— 针对一个可评估对象运行一个评估器 - run_and_evaluate —— 评估来自 MemoryTraceHandler 的跨度 - assert_pass —— 带通过/失败条件的批量评估 - assert_dataset_pass —— 加载数据集并运行 assert_pass - EvalAssertionError —— 当 assert_pass 失败时抛出 - capture_traces —— 用于内存中追踪捕获的上下文管理器 - MemoryTraceHandler —— 收集跨度的 InstrumentationHandler - ScoreThreshold —— 可配置的通过标准 - last_llm_call / root —— 追踪到可评估对象的辅助函数 - DatasetEntryResult —— 单个数据集条目的评估结果 - DatasetScorecard —— 带非统一评估器的按数据集评分卡 - generate_dataset_scorecard_html —— 将评分卡渲染为 HTML - save_dataset_scorecard —— 将评分卡 HTML 写入磁盘

预置评估器(autoevals 适配器): - AutoevalsAdapter —— 任意 autoevals Scorer 的通用包装器 - LevenshteinMatch —— 编辑距离字符串相似度 - ExactMatch —— 精确值比较 - NumericDiff —— 归一化数值差异 - JSONDiff —— 结构化 JSON 比较 - ValidJSON —— JSON 语法 / Schema 验证 - ListContains —— 列表重叠 - EmbeddingSimilarity —— 嵌入余弦相似度 - Factuality —— LLM 事实准确性检查 - ClosedQA —— 闭卷问答评估 - Battle —— 两两对比 - Humor —— 幽默检测 - Security —— 安全漏洞检查 - Sql —— SQL 等价性 - Summary —— 摘要质量 - Translation —— 翻译质量 - Possible —— 可行性检查 - Moderation —— 内容审核 - ContextRelevancy —— RAGAS 上下文相关性 - Faithfulness —— RAGAS 忠实度 - AnswerRelevancy —— RAGAS 答案相关性 - AnswerCorrectness —— RAGAS 答案正确性

数据集 JSON 格式

数据集是一个 JSON 对象,包含以下顶层字段:

{
  "name": "customer-faq",
  "runnable": "pixie_qa/run_app.py:AppRunnable",
  "evaluators": ["Factuality"],
  "entries": [
    {
      "input_data": { "question": "Hello" },
      "description": "Basic greeting",
      "eval_input": [{ "name": "input", "value": "Hello" }],
      "expectation": "A friendly greeting that offers to help",
      "evaluators": ["...", "ClosedQA"]
    }
  ]
}

条目结构

所有字段均在每个条目上作为顶层字段(扁平结构——无嵌套):

entry:
  ├── input_data    (必需)—— Runnable.run() 的参数
  ├── eval_input      (可选)—— {"name": ..., "value": ...} 对象的列表(默认:[]
  ├── description     (必需)——测试用例的人类可读标签
  ├── expectation     (可选)——用于基于比较的评估器的参考值
  ├── eval_metadata   (可选)——用于自定义评估器的额外逐条目数据
  └── evaluators      (可选)——此条目的评估器名称

字段参考

  • runnable(必需):驱动评估期间应用的 Runnable 子类的 filepath:ClassName 引用。
  • evaluators(数据集级别,可选):默认评估器名称——应用于每个未声明自己的 evaluators 的条目。
  • entries[].input_data(必需):作为 Pydantic 模型传递给 Runnable.run() 的关键字参数。键必须与 run(args: T) 中使用的 Pydantic 模型的字段匹配。
  • entries[].description(必需):测试用例的人类可读标签。
  • entries[].eval_input(可选,默认 []):{"name": ..., "value": ...} 对象的列表。用于填充包装输入注册表——应用中的 wrap(purpose="input") 调用返回按 name 键控的注册表值。运行器在构建 Evaluable 时会自动前置 input_data
  • entries[].expectation(可选):针对基于比较的评估器的简洁预期描述。应描述正确输出的样子,而不是逐字复制输出。对追踪使用 pixie format 以查看实际输出形状,然后编写更短的描述。
  • entries[].eval_metadata(可选):用于自定义评估器的额外逐条目数据——例如,预期的工具名称、布尔标志、阈值。在评估器中通过 evaluable.eval_metadata 访问。
  • entries[].evaluators(可选):行级别的评估器覆盖。规则:
    • 省略 → 条目继承数据集级别的 evaluators
    • ["...", "ClosedQA"] → 数据集默认值 加上 ClosedQA。
    • ["OnlyThis"](无 "...")→ OnlyThis,不包含默认值。

评估器名称解析

在数据集 JSON 中,评估器名称按如下方式解析:

  • 内置名称(裸名称,如 "Factuality""ExactMatch")会自动解析为 pixie.{Name}
  • 自定义评估器使用 filepath:callable_name 格式(例如 "pixie_qa/evaluators.py:my_evaluator")。
  • 自定义评估器引用指向模块级别的可调用对象——类(自动实例化)、工厂函数(如果零参数则调用)、评估器函数(按原样使用)或预实例化的可调用对象(例如 create_llm_evaluator 的结果——按原样使用)。

CLI 命令

命令 描述
pixie test [path] [-v] [--no-open] 对数据集文件运行评估测试
pixie dataset create <name> 创建一个新的空数据集
pixie dataset list 列出所有数据集
pixie dataset save <name> [--select MODE] 将跨度保存到数据集中
pixie dataset validate [path] 验证数据集 JSON 文件
pixie analyze <test_run_id> 生成分析和建议

类型

Evaluable

class Evaluable(TestCase):
    eval_output: list[NamedData]      # wrap(purpose="output") + wrap(purpose="state") 值
    # 继承自 TestCase
    # eval_input: list[NamedData]     # 来自数据集条目中的 eval_input
    # expectation: JsonValue | _Unset # 来自数据集条目中的 expectation
    # eval_metadata: dict[str, JsonValue] | None  # 来自数据集条目中的 eval_metadata
    # description: str | None

评估器的数据载体。使用实际输出扩展 TestCase

  • eval_input —— 从条目的 eval_input 字段加上 input_data(由运行器前置)填充的 list[NamedData]。始终至少包含一个条目。
  • eval_output —— 包含运行期间捕获的所有 wrap(purpose="output")wrap(purpose="state") 值的 list[NamedData]。每个条目都有 .namestr)和 .valueJsonValue)。使用 _get_output(evaluable, "name") 按名称查找。
  • eval_metadata —— 来自条目 eval_metadata 字段的 dict[str, JsonValue] | None
  • expected_output —— 来自数据集的预期文本(如果未提供则为 UNSET

属性: eval_input:命名输入数据项(来自数据集 + 运行器前置的 input_data)。始终非空。 eval_output:命名输出数据项(来自运行期间的 wrap 调用)。 每个条目都有 .namestr)和 .valueJsonValue)。 包含所有 wrap(purpose="output")wrap(purpose="state") 值。 eval_metadata:补充元数据(不存在时为 None)。 expected_output:用于评估的预期/参考输出。 默认为 UNSET(未提供)。可被显式 设置为 None,表示"没有预期输出"。

测试时 wrap() 如何映射到 Evaluable 字段

pixie test 运行数据集条目时,应用中的 wrap() 调用会填充评估器接收的 Evaluable

应用代码中的 wrap() 调用 Evaluable 字段 类型 在评估器中的访问方式
wrap(data, purpose="input", name="X") eval_input list[NamedData] 从数据集条目的 eval_input 预填充
wrap(data, purpose="output", name="X") eval_output list[NamedData] _get_output(evaluable, "X") —— 参见下面的辅助函数
wrap(data, purpose="state", name="X") eval_output list[NamedData] _get_output(evaluable, "X") —— 与输出相同的列表
(来自数据集条目 expectation expected_output str | None evaluable.expected_output
(来自数据集条目 eval_metadata eval_metadata dict | None evaluable.eval_metadata

关键理解purpose="output"purpose="state" 的 wrap 值最终都作为 NamedData 条目进入 eval_output。没有单独的 captured_outputcaptured_state 字典。使用下面的辅助函数按 wrap 名称查找值:

def _get_output(evaluable: Evaluable, name: str) -> Any:
    """Look up a wrap value by name from eval_output."""
    for item in evaluable.eval_output:
        if item.name == name:
            return item.value
    return None

eval_metadata 用于向评估器传递额外的逐条目数据,这些数据既不是输入数据也不是输出——例如,预期的工具名称、布尔标志、阈值。定义为条目的顶层字段,通过 evaluable.eval_metadata 访问。

完整的自定义评估器示例(工具调用检查 + 数据集条目):

from pixie import Evaluation, Evaluable

def _get_output(evaluable: Evaluable, name: str) -> Any:
    """Look up a wrap value by name from eval_output."""
    for item in evaluable.eval_output:
        if item.name == name:
            return item.value
    return None

def tool_call_check(evaluable: Evaluable, *, trace=None) -> Evaluation:
    expected = evaluable.eval_metadata.get("expected_tool") if evaluable.eval_metadata else None
    actual = _get_output(evaluable, "function_called")
    if expected is None:
        return Evaluation(score=1.0, reasoning="No expected_tool specified")
    match = str(actual) == str(expected)
    return Evaluation(
        score=1.0 if match else 0.0,
        reasoning=f"Expected {expected}, got {actual}",
    )

对应的数据集条目:

{
  "input_data": { "user_message": "I want to end this call" },
  "description": "User requests call end after failed verification",
  "eval_input": [{ "name": "user_input", "value": "I want to end this call" }],
  "expectation": "Agent should call endCall tool",
  "eval_metadata": {
    "expected_tool": "endCall",
    "expected_call_ended": true
  },
  "evaluators": ["...", "pixie_qa/evaluators.py:tool_call_check"]
}

Evaluation

Evaluation(score: 'float', reasoning: 'str', details: 'dict[str, Any]' = <factory>) -> None

单个评估器应用于单个测试用例的结果。

属性: score:介于 0.0 和 1.0 之间的评估分数。 reasoning:人类可读的解释(必需)。 details:任意的 JSON 可序列化元数据。

ScoreThreshold

ScoreThreshold(threshold: 'float' = 0.5, pct: 'float' = 1.0) -> None

通过标准:在所有评估器上,pct 比例的输入必须得分 >= threshold

属性: threshold:单次评估必须达到的最低分数。 pct:必须通过的测试用例输入比例(0.0–1.0)。

评估函数

pixie.run_and_evaluate

pixie.run_and_evaluate(evaluator: 'Callable[..., Any]', runnable: 'Callable[..., Any]', eval_input: 'Any', *, expected_output: 'Any' = <object object at 0x7788c2ad5c80>, from_trace: 'Callable[[list[ObservationNode]], Evaluable] | None' = None) -> 'Evaluation'

在捕获追踪的同时运行 runnable(eval_input),然后进行评估。

结合了 _run_and_captureevaluate 的便捷包装器。 runnable 仅被调用一次。

参数: evaluator:评估器可调用对象(同步或异步)。 runnable:要测试的应用函数。 eval_input:传递给 runnable 的单个输入。 expected_output:合并到 evaluable 中的可选预期值。 from_trace:用于从追踪树中选择特定跨度进行评估的可选可调用对象。

返回: Evaluation 结果。

抛出: ValueError:如果执行期间未捕获到任何跨度。

pixie.assert_pass

pixie.assert_pass(runnable: 'Callable[..., Any]', eval_inputs: 'list[Any]', evaluators: 'list[Callable[..., Any]]', *, evaluables: 'list[Evaluable] | None' = None, pass_criteria: 'Callable[[list[list[Evaluation]]], tuple[bool, str]] | None' = None, from_trace: 'Callable[[list[ObservationNode]], Evaluable] | None' = None) -> 'None'

在多个输入上对 runnable 运行评估器。

对于每个输入,通过 _run_and_capture 运行一次 runnable, 然后通过 asyncio.gather 并发地使用每个评估器进行评估。

结果矩阵的形状为 [eval_inputs][evaluators]。 如果未满足通过标准,则抛出携带该矩阵的 :class:EvalAssertionError

当提供了 evaluables 时,行为取决于每个条目是否已填充了 eval_output

  • eval_output 为 None —— 通过 run_and_evaluate 调用 runnable 以从追踪生成输出,并且来自 evaluable 的 expected_output 会合并到结果中。
  • eval_output 不为 None —— 直接使用该 evaluable(该条目不调用 runnable)。

参数: runnable:要测试的应用函数。 eval_inputs:输入列表,每个都传递给 runnable。 evaluators:评估器可调用对象列表。 evaluables:可选的 Evaluable 项列表,每个输入对应一个。 当提供时,它们的 expected_output 会被转发到 run_and_evaluate。必须与 eval_inputs 具有相同的长度。 pass_criteria:接收结果矩阵,返回 (passed, message)。默认为 ScoreThreshold()。 from_trace:可选的跨度选择器,转发到 run_and_evaluate

抛出: EvalAssertionError:当未满足通过标准时。 ValueError:当 evaluables 长度与 eval_inputs 不匹配时。

pixie.assert_dataset_pass

pixie.assert_dataset_pass(runnable: 'Callable[..., Any]', dataset_name: 'str', evaluators: 'list[Callable[..., Any]]', *, dataset_dir: 'str | None' = None, pass_criteria: 'Callable[[list[list[Evaluation]]], tuple[bool, str]] | None' = None, from_trace: 'Callable[[list[ObservationNode]], Evaluable] | None' = None) -> 'None'

按名称加载数据集,然后对其条目运行 assert_pass

这是一个便捷包装器,它:

  1. DatasetStore 加载数据集。
  2. 从每个条目中提取 eval_input 作为 runnable 输入。
  3. 使用完整的 Evaluable 项(它们携带 expected_output 作为评估对象。
  4. 委托给 assert_pass

参数: runnable:要测试的应用函数。 dataset_name:要加载的数据集的名称。 evaluators:评估器可调用对象列表。 dataset_dir:数据集存储的覆盖目录。 当为 None 时,从 PixieConfig.dataset_dir 读取。 pass_criteria:接收结果矩阵,返回 (passed, message)。 from_trace:可选的跨度选择器,转发到 assert_pass

抛出: FileNotFoundError:如果不存在名为 dataset_name 的数据集。 EvalAssertionError:当未满足通过标准时。

追踪辅助函数

pixie.last_llm_call

pixie.last_llm_call(trace: 'list[ObservationNode]') -> 'Evaluable'

在追踪树中找到具有最新 ended_atLLMSpan

参数: trace:追踪树(根 ObservationNode 实例的列表)。

返回: 包装最近结束的 LLMSpanEvaluable

抛出: ValueError:如果追踪中不存在 LLMSpan

pixie.root

pixie.root(trace: 'list[ObservationNode]') -> 'Evaluable'

将第一个根节点的跨度作为 Evaluable 返回。

参数: trace:追踪树(根 ObservationNode 实例的列表)。

返回: 包装第一个根节点跨度的 Evaluable

抛出: ValueError:如果追踪为空。

pixie.capture_traces

pixie.capture_traces() -> 'Generator[MemoryTraceHandler, None, None]'

安装 MemoryTraceHandler 并返回它的上下文管理器。

调用 init()(如果已初始化则为空操作),然后通过 add_handler() 注册该处理器。退出时,处理器被移除,交付队列被刷新,以便所有跨度在 handler.spans 上可用。