eval-driven-dev 技能 Step 5 实战:运行 pixie test 并修复机制性问题
【免费下载链接】awesome-copilotCommunity-contributed instructions, agents, skills, and configurations to help you make the most of GitHub Copilot.项目地址: https://gitcode.com/GitHub_Trending/aw/awesome-copilot
本指南聚焦于 eval-driven-dev 技能工作流中的Step 5(Run pixie test and Fix Mechanical Issues),讲解如何使用 pixie-qa 评测框架端到端执行评估流水线:从命令行启动测试、理解评估 harness 的内部执行顺序,到系统性地分类并修复"机制性问题"(mechanical issues),最终让每个数据集条目都产出真实可用的评估分数。读完本文,你将掌握pixie test的完整运行原理、并发安全陷阱的排查方法,以及如何区分"该在 Step 5 修的问题"与"必须留给 Step 6 分析的问题"。
一、Step 5 在整个工作流中的位置与目标
eval-driven-dev 是一条完整的评估驱动开发流水线,共 6 个步骤:
- Step 1:分析应用、确定入口点、定义评估标准(产出
pixie_qa/00-project-analysis.md、01-entry-point.md、02-eval-criteria.md) - Step 2:用
wrap()对应用打点(2a-instrumentation)、实现 Runnable(2b-implement-runnable)、捕获参考 trace(2c-capture-and-verify-trace) - Step 3:定义评估器(3-define-evaluators)
- Step 4:构建数据集(4-build-dataset)
- Step 5:运行
pixie test并修复机制性问题 ——本文主题 - Step 6:分析评估结果、生成行动方案(6-analyze-outcomes)
Step 5 的目标非常明确:让整个流水线"跑起来",而不是评估结果好坏。它只修复你在前几步构建的东西——数据集(dataset)、Runnable、自定义评估器(custom evaluators)——中的机制性问题,比如数据集格式错误、Runnable 无法运行、评估器报错等。这一步不评估应用输出质量,也不修复应用本身的 bug。
按 SKILL.md 的定义,最终交付物是一个能产生真实分数的pixie test运行——不是方案、不是打点、不是数据集。Step 5 就是这个交付物的"临门一脚"。
注意:Step 5 的检查点(Checkpoint)要求
pixie test完整跑通,每个数据集条目都有评估器分数(真实的EvaluationResult或PendingEvaluation),且没有 setup 错误、导入失败、数据校验错误。一旦产出分数就立即进入 Step 6——不要在 Step 5 停下询问用户,因为 pending 评估只有经过 Step 6 分析才会完成,否则用户只能看到一堆未解释的原始分数。
二、5a:运行测试
2.1 基本命令
在项目根目录(虚拟环境已激活的前提下)执行:
uv run pixie testpixie test会自动加载.env文件后再运行测试,因此你的环境变量(如 LLM API Key)会按预期注入。
如果需要查看每个测试用例的分数和评估器推理过程,使用详细输出模式:
uv run pixie test -v2.2 相关 CLI 命令速览
根据 testing-api.md 的 CLI 命令表,与测试流程相关的命令还包括:
| 命令 | 说明 |
|---|---|
pixie test [path] [-v] [--no-open] | 对数据集文件运行评估测试 |
pixie dataset create <name> | 创建新的空数据集 |
pixie dataset list | 列出所有数据集 |
pixie dataset save <name> [--select MODE] | 将一个 span 保存到数据集 |
pixie dataset validate [path] | 校验数据集 JSON 文件 |
pixie analyze <test_run_id> | 生成分析与建议(对应 Step 6) |
在 Step 5 之前或排查阶段,pixie dataset validate可以提前发现数据集 JSON 的格式问题,减少进入测试环节后的返工。
三、评估 harness 的执行流程(运行原理)
当pixie test运行时,评估 harness 按以下顺序处理(对应 5-run-tests.md 中描述的 8 个环节):
- 解析 Runnable:从数据集的
runnable字段解析出目标类(格式为filepath:ClassName,例如"pixie_qa/run_app.py:AppRunnable")。 - 构建实例并初始化:调用
Runnable.create()构造实例,然后调用一次setup()(用于初始化共享资源,如 HTTP 客户端、数据库连接、测试服务器)。 - 并发运行所有数据集条目(最多 4 个并行): a. 从条目读取
input_data和eval_inputb. 用eval_input数据填充 wrap 输入注册表(wrap input registry) c. 初始化捕获注册表(capture registry) d. 将input_data校验为 Pydantic 模型,并调用Runnable.run(args)e. 应用中wrap(purpose="input")调用返回注册表中的值,而不是调用真实外部服务f.wrap(purpose="output"/"state")调用捕获数据供评估使用 g. 由捕获数据构建Evaluableh. 运行评估器(evaluators) - 收尾:最后调用一次
Runnable.teardown()(释放setup()中获取的资源)。
3.1 Runnable 生命周期与并发模型
根据 wrap-api.md 中的pixie.Runnable协议定义:
class pixie.Runnable(Protocol[T]): @classmethod def create(cls) -> Runnable[Any]: ... async def setup(self) -> None: ... async def run(self, args: T) -> None: ... async def teardown(self) -> None: ...生命周期要点:
create()—— 类方法,构造并返回一个 runnable 实例;setup()——async,在第一次run()之前调用一次,用于初始化共享资源;可选,默认是 no-op;run(args)——async,为每个数据集条目并发调用(最多 4 个并行),args是由input_data构建并校验过的 Pydantic 模型;在此调用应用的真实入口点;teardown()——async,在最后一次run()之后调用一次;可选,默认是 no-op。
因为run()通过asyncio.gather并发调用,你的实现必须并发安全。
3.2 wrap 注册表在测试时的行为
Step 5 的执行之所以能"用测试数据替换外部依赖",依赖的是wrap()在 eval 模式下的行为(详见 wrap-api.md):
purpose="input":在 eval 模式下,返回注册表中的注入值。若data是 callable,返回的包装器会忽略原函数、每次调用都返回注入值——从而阻止真实外部调用执行。purpose="output"/purpose="state":在 eval 模式下捕获输出/状态,供构建Evaluable使用。
这也是为什么在 2a-instrumentation 中强调:对purpose="input"的外部调用必须使用函数形式(wrap(fetch_page, purpose="input", name="fetched_page")(url)),否则真实调用仍会执行,导致测试变慢、不稳定、依赖外部服务可用性。
3.3 并发安全:必读的 Semaphore 模式
由于条目并发运行,Runnable 的run()方法必须并发安全。如果你看到sqlite3.OperationalError、"database is locked"或类似错误,说明你的 Runnable 中共享了 SQLite 连接等可变状态,需要在 Runnable 中加Semaphore(1)(详见 Step 2 参考文档的并发安全章节)。
wrap-api.md 给出的标准做法:
class AppRunnable(pixie.Runnable[AppArgs]): _sem: asyncio.Semaphore @classmethod def create(cls) -> "AppRunnable": inst = cls() inst._sem = asyncio.Semaphore(1) # serialise DB access return inst async def run(self, args: AppArgs) -> None: async with self._sem: await call_app(args.message)常见并发陷阱(来自 wrap-api.md):
- SQLite:并发写入不安全——使用
Semaphore(1)或aiosqlite并开启 WAL 模式; - 全局可变状态:在
run()中修改的模块级 dict/list 需要保护; - 限流 API:加信号量以避免 429 错误。
但注意:只有当应用确实存在共享可变状态时才需要加信号量。如果应用使用按请求隔离的状态(按唯一 ID 隔离)或天然无状态,并发调用自然是隔离的(2b-implement-runnable)。另外,2b-implement-runnable.md 提醒:不要在 runnable 文件中使用from __future__ import annotations——它会破坏 Pydantic 对嵌套模型的解析,应改用带引号的返回类型(-> "AppRunnable")。
四、5b:只修复机制性问题
这一阶段严格限定为修复你在前几步构建的东西——数据集、Runnable、自定义评估器。你修复的是阻止流水线运行的机制问题,不是评估或改进应用的输出质量。
4.1 属于机制性问题(需要修复)
| 错误 | 原因 | 修复方式 |
|---|---|---|
WrapRegistryMissError: name='<key>' | 数据集条目缺少应用wrap(purpose="input", name="<key>")所期望的name对应的eval_input项 | 在每个受影响的条目中,向eval_input添加缺失的{"name": "<key>", "value": ...} |
WrapTypeMismatchError | 反序列化后的类型与应用期望的类型不匹配 | 修正数据集中的 value |
| Runnable 解析失败 | runnable路径或类名错误,或类未实现Runnable协议 | 修正数据集中的filepath:ClassName;确保类有create()和run()方法 |
| 导入错误 | runnable/evaluator 的模块路径或语法错误 | 修正被引用的文件 |
ModuleNotFoundError: pixie_qa | pixie_qa/目录缺少__init__.py | 运行pixie init重建 |
TypeError: ... is not callable | 评估器名称指向不可调用的属性 | 评估器必须是函数、类或可调用实例 |
sqlite3.OperationalError | 并发的run()调用共享 SQLite 连接 | 在 Runnable 中添加asyncio.Semaphore(1)(见上文) |
| 自定义评估器崩溃 | 自定义评估器实现中的 bug | 修复评估器代码 |
4.2 不属于机制性问题(不要在此处修复)
- 应用产出错误/低质量输出→ 这是应用行为,留待 Step 6 分析
- 评估器分数偏低→ 这是质量信号,留待 Step 6 分析
- 应用内部的 LLM 调用失败→ 在 Step 6 中报告,不要 mock 或绕过
- 评估器分数在不同运行间波动→ LLM 非确定性的正常现象,不是 bug
这一"修复边界"的设计意图很关键:Step 5 只保证"管道通了",至于分数高低、应用好坏,必须在完整分析后才有意义。尤其要注意最后一点——LLM 评估天然带有非确定性,分数波动不是你需要修的问题。
4.3 迭代策略
修复是循环过程:修错误 → 重新运行 → 修下一个错误,直到pixie test完整跑通、所有条目都产出真实评估分数。
遇到意外错误(参数名错误、导入失败、API 不匹配)时,不要靠猜——先阅读 wrap-api.md、evaluators.md 或 testing-api.md 获取权威 API 参考,再动手修复。
4.4 从源头减少机制性问题
很多 Step 5 的报错其实可以在前序步骤预防:
eval_input缺失问题:根据 4-build-dataset,如果应用存在任何wrap(purpose="input")调用,每个数据集条目都必须提供对应的eval_input值(否则应用会在 eval 运行时发起真实外部调用)。其 4c″ 节的"数据集真实性审计"硬门槛中就有"eval_input完整性检查"一项,逐条核对每个 input wrap 是否都有对应条目。WrapTypeMismatchError:eval_input的值必须与wrap()调用返回的精确类型和格式匹配(4-build-dataset 4b′ 节"内容格式")。以参考 trace 为模板复制数据形状,而不是凭空构造。- Runnable 解析失败:数据集的
"runnable"字段格式为"pixie_qa/run_app.py:AppRunnable",路径相对项目根目录,且项目根目录会自动加入sys.path,可直接用普通import引用项目模块(wrap-api.md)。
五、输出:结果目录结构
pixie test成功运行后,结果按条目存储到如下目录结构中:
{PIXIE_ROOT}/results/<test_id>/ meta.json # 测试运行元数据 dataset-{idx}/ metadata.json # 数据集名称、路径、runnable entry-{idx}/ config.json # 评估器、描述、期望 eval-input.jsonl # 提供给评估器的输入数据 eval-output.jsonl # 从应用捕获的输出数据 evaluations.jsonl # 评估结果(已评分 + 待处理 pending) trace.jsonl # LLM 调用 trace(如已捕获)各文件含义:
meta.json—— 本次测试运行的元数据(时间、参数等);dataset-{idx}/metadata.json—— 数据集名称、路径、runnable 引用;entry-{idx}/config.json—— 该条目的评估器列表、描述(description)、期望(expectation);entry-{idx}/eval-input.jsonl—— 喂给评估器的输入数据;entry-{idx}/eval-output.jsonl—— 运行应用时捕获的输出数据;entry-{idx}/evaluations.jsonl——核心产物:每条评估结果,包含已评分的(scored)与待处理的(pending,例如 agent evaluator 产生的PendingEvaluation);entry-{idx}/trace.jsonl—— LLM 调用 trace(若已捕获)。
<test_id>会打印在控制台输出中。在 Step 6 你会引用这个目录:按 SKILL.md 的硬性完成门槛,Step 6 必须把evaluations.jsonl中每个"status": "pending"条目替换为含score与reasoning的评分结果,并为每个数据集目录生成analysis.md/analysis-summary.md、为测试运行根目录生成action-plan.md/action-plan-summary.md。
六、与前后步骤的衔接
- 循环规则(来自 SKILL.md):每次成功的
pixie test都会创建具体的pixie_qa/results/<test_id>目录并开启一个新的分析周期。在修改应用代码、提示词、数据集、评估器或重跑pixie test之前,必须先针对该结果目录完成 Step 6。不要跳过早期周期只分析最后一次运行。 pixie test与pixie trace的关系:测试阶段使用 eval 模式(注册表注入输入、捕获输出),而 trace 阶段运行真实依赖以捕获参考数据(wrap-api.md 中wrap()在三种模式——no-op、tracing、eval——下的行为差异,是理解整条流水线的钥匙)。- 应用真实代码路径原则:整个评估过程中应用的 LLM 调用必须走真实 LLM,绝不 mock、stub 或拦截。如果项目自带测试套件中包含 LLM mock 模式,那是项目自身单元测试用的,不要移植到 eval Runnable 中(SKILL.md)。同理,Step 5 遇到"应用内部 LLM 调用失败"也不能用 mock 绕过,而应在 Step 6 报告。
七、小结
Step 5 是评估驱动开发流水线中"从构建到验证"的转换点。记住三条核心原则:
- 目标纯粹:只修"管道问题"(数据集格式、Runnable 可运行性、评估器可调用性),不评质量、不改应用;
- 理解执行模型:Runnable 生命周期(create → setup → 并发 run → teardown)、wrap 注册表注入、并发安全(Semaphore)是排查一切报错的基础;
- 产出明确:
pixie test完整跑通、所有条目有真实分数后,立即进入 Step 6 分析——结果目录{PIXIE_ROOT}/results/<test_id>/是后续所有分析工作的数据基础。
想深入 API 细节的读者,可直接查阅 testing-api.md(数据集 JSON 格式、评估器名称解析、Evaluable/Evaluation/ScoreThreshold类型)、wrap-api.md(Runnable 协议、wrap()三种模式、错误类型)与 evaluators.md(内置评估器选择指南、自定义评估器工厂函数)。
【免费下载链接】awesome-copilotCommunity-contributed instructions, agents, skills, and configurations to help you make the most of GitHub Copilot.项目地址: https://gitcode.com/GitHub_Trending/aw/awesome-copilot
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考