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

211 lines
17 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
```yaml
---
name: eval-driven-dev
description: >
使用评估驱动开发改进 AI 应用。定义评估标准、对应用进行插桩、构建黄金数据集、观察和评估应用运行情况、分析结果,并生成具体的改进行动计划。
当用户要求为任何调用 LLM 模型的 Python 项目搭建 QA、添加测试、添加评估、做评测、做基准测试、修复错误行为、改进质量或做质量保障时,始终使用此技能。
license: MIT
compatibility: Python 3.10+
metadata:
version: 0.8.4
pixie-qa-version: ">=0.8.4,<0.9.0"
pixie-qa-source: https://github.com/yiouli/pixie-qa/
---
# Python LLM 应用的评估驱动开发
你正在构建一个**自动化评估流水线**,用于端到端测试基于 Python 的 AI 应用——就像真实用户那样运行它,使用真实输入——然后通过评估器对输出进行评分,并通过 `pixie test` 产生通过/失败结果。
**你测试的是应用本身**——它的请求处理、上下文组装(如何收集数据、构建提示词、管理对话状态)、路由和响应格式化。应用使用了 LLM,这使得输出具有非确定性——这就是为什么你使用评估器(LLM 作为评判者、相似度评分)而不是 `assertEqual`——但被测对象是应用的代码,而不是 LLM。
在评估过程中,应用自身的代码会真实运行——路由、提示词组装、LLM 调用、响应格式化——没有任何内容被 mock 或 stub。但应用从外部来源(数据库、缓存、第三方 API、语音流)读取的数据,会通过插桩(instrumentations)替换为测试指定的值。这意味着每个测试用例精确控制应用看到的数据,同时仍然执行完整的应用代码路径。
**规则:应用的 LLM 调用必须使用真实的 LLM。** 不得用虚假实现替换、mock、stub 或拦截 LLM。LLM 是核心价值生成组件——替换它会使得评估变成同义反复(你同时控制输入和输出,因此评分毫无意义)。如果项目的测试套件中包含 LLM mock 模式,那是项目自身单元测试使用的——切勿将其用于评估 Runnable。
**交付物是一个能运行的 `pixie test` 并产生真实评分**——不是计划,不光是插桩,不光是数据集。
此技能是关于执行工作,而非描述工作。阅读代码、编辑文件、运行命令,产出可运行的流水线。
---
## 开始之前
**首先,激活虚拟环境**。找到项目正确的虚拟环境并激活它。虚拟环境激活后,运行技能资源中包含的 setup.sh 脚本。
该脚本会将 `eval-driven-dev` 技能和 `pixie-qa` Python 包更新到最新版本,初始化 pixie 工作目录(如果尚未初始化),并在后台启动一个 Web 服务器以向用户展示更新。
**安装错误处理——哪些可以跳过,哪些必须成功:**
- **技能更新失败** → 可以继续。现有技能版本足以使用。
- **pixie-qa 升级失败但已安装** → 可以继续使用现有版本。
- **pixie-qa 未安装且安装失败** → **停止。** 请用户帮助。工作流无法在没有 `pixie` 包的情况下进行。
- **`pixie init` 失败** → **停止。** 请用户帮助。
- **`pixie start`Web 服务器)失败** → **停止。** 请用户帮助。检查 pixie 根目录下的 `server.log` 以获取诊断信息。常见原因:端口冲突、缺少依赖、环境运行缓慢。**没有 Web 服务器就不能继续**——用户需要它来查看评估结果。
---
## 工作流程
按顺序执行步骤 1-6,中间不要停顿。不要在中间步骤询问用户确认——自行验证每个步骤并继续。
**如何工作——在执行任何操作之前先阅读以下内容:**
- **一次只做一个步骤。** 只阅读当前步骤的说明。在处理步骤 1 时,不要阅读步骤 2-6。
- **仅在步骤要求时阅读参考资料。** 每个步骤会指定一个特定的参考文件。到达该步骤时再阅读——不要提前阅读。
- **立即创建产物。** 为某个子步骤阅读代码后,立即写入该子步骤的输出文件,再继续下一步。不要在多个子步骤间积累理解之后再写任何东西。
- **验证,然后继续。** 每个步骤都有一个检查点。验证通过后,再进入下一步。不要在验证当前步骤的同时规划后续步骤。
**何时停止并请求帮助:**
有些阻碍是无法也不应该绕过的。当你遇到以下任何情况时,**立即停止并请用户帮助**——不要尝试变通方案:
- **应用因缺少环境变量或配置而无法运行**:应用需要未设置且无法推断的环境变量或配置。**不要**通过 mock、伪造或替换应用组件来绕过——评估必须执行真实的生产代码。请用户修复环境设置。
- **应用导入失败表明项目已损坏**:如果应用的核心模块因缺少系统依赖或不兼容的 Python 版本而无法导入(而不仅仅是你可以安装的 pip 包),请用户修复项目设置。
- **入口点不明确**:如果应用有多个同样合理的入口点,且项目分析无法明确哪个最重要,请询问用户应该以哪个为目标。
你应该自行解决的阻碍(不要询问):缺少 Python 包(安装它们)、缺少 `pixie` 包(安装它)、端口冲突(选择不同端口)、文件权限问题(修复它们)。
**按顺序执行步骤 1-6。** 如果用户的提示明确表明前面的步骤已经完成(例如"运行现有测试"、"重新运行评估"),则跳到相应步骤。如有疑问,从步骤 1 开始。
---
### 步骤 1:理解应用并定义评估标准
**首先,检查用户提示中的具体要求。** 在阅读应用代码之前,先审视用户的要求:
- **引用的文档或规格说明**:提示中是否提到要遵循的文件(例如"按照 EVAL_SPEC.md 中的规格说明"、"使用 REQUIREMENTS.md 中的方法")?如果是,**先阅读该文件**——它可能指定了数据集、评估维度、通过标准或方法论,这些会覆盖你的默认值。
- **指定的数据集或数据来源**:提示是否引用了特定的数据文件(例如"使用 eval_inputs/research_questions.json 中的问题"、"使用 call_scenarios.json 中的场景")?如果是,**阅读这些文件**——你必须以它们为基础构建评估数据集,而不是编造泛化的替代品。
- **指定的评估维度**:提示是否命名了要评估的具体质量方面(例如"评估事实准确性、完整性和偏见"、"测试身份验证和工具调用正确性")?如果是,**每个命名的维度都必须在你的测试文件中有一个对应的评估器**。
如果提示指定了上述任何内容,则它们具有优先权。在继续之前先阅读并整合它们。
步骤 1 有三个子步骤。每个子步骤阅读自己的参考文件并生成自己的输出文件。**在开始下一个子步骤之前,完整完成当前子步骤。**
#### 子步骤 1a:项目分析
> **参考文件**:立即阅读 `references/1-a-project-analysis.md`。
在查看代码结构或入口点之前,先理解这个软件在真实世界中的功能——它的目的、它的用户、真实输入的复杂性,以及它在哪里失败。这种理解驱动所有下游决策:哪些入口点最重要、定义哪些评估标准、使用哪些追踪输入、以及创建哪些数据集条目。在继续之前,先写详细的上下文文件。**注意**:项目可能包含 `tests/`、`fixtures/`、`examples/`、mock 服务器和文档——这些是项目自身的开发基础设施,**不是**你评估流水线的数据来源。在获取追踪输入和数据集内容时忽略它们。
> **检查点**`pixie_qa/00-project-analysis.md` 已写入——涵盖该软件的功能、目标用户、能力清单(如果项目有,至少 3 个能力)、真实输入特征,以及困难问题/故障模式(至少 2 个)。
#### 子步骤 1b:入口点与执行流程
> **参考文件**:立即阅读 `references/1-b-entry-point.md`。
阅读源代码以了解应用如何启动以及真实用户如何调用它。使用 `pixie_qa/00-project-analysis.md` 中的**能力清单**来确定入口点的优先级——专注于能运行最有价值能力的入口点,而不是只找第一个找到的。在继续之前,先写详细的上下文文件。
> **检查点**`pixie_qa/01-entry-point.md` 已写入——涵盖入口点、执行流程、面向用户的接口和环境要求。
#### 子步骤 1c:评估标准
> **参考文件**:立即阅读 `references/1-c-eval-criteria.md`。
定义应用的用例和评估标准。从 `pixie_qa/00-project-analysis.md` 中的**能力清单**推导出用例。从**困难问题/故障模式**推导出评估标准——而不是泛化的质量维度。用例驱动数据集创建(步骤 4);评估标准驱动评估器选择(步骤 3)。在继续之前,先写详细的上下文文件。
> **检查点**`pixie_qa/02-eval-criteria.md` 已写入——涵盖用例、评估标准及其适用范围。现在还不要阅读步骤 2 的说明。
---
### 步骤 2:插桩、运行应用并捕获参考追踪
步骤 2 有三个子步骤。每个子步骤阅读自己的参考文件。**在开始下一个子步骤之前,完整完成当前子步骤。**
#### 子步骤 2a:使用 `wrap` 进行插桩
> **参考文件**:立即阅读 `references/2a-instrumentation.md`。
在应用的数据边界处添加 `wrap()` 调用,以便评估框架可以注入受控输入并捕获输出。这使得应用无需改变其逻辑即可被测试。
> **检查点**:所有数据边界均已添加 `wrap()` 调用。`pixie_qa/02-eval-criteria.md` 中的每个评估标准都有对应的数据点。
#### 子步骤 2b:实现 Runnable
> **参考文件**:立即阅读 `references/2b-implement-runnable.md`。
编写一个 Runnable 类,让评估框架能够像真实用户一样调用应用。Runnable 应该很简单——它只是将应用的真正入口点连接到评估框架接口。如果它变得复杂,说明有问题。
> **检查点**`pixie_qa/run_app.py` 已写入。Runnable 使用真实的 LLM 配置调用应用的真正入口点——没有 mock,没有伪造,没有组件替换。
#### 子步骤 2c:捕获并验证参考追踪
> **参考文件**:立即阅读 `references/2c-capture-and-verify-trace.md`。
通过 Runnable 运行应用并捕获追踪。该追踪证明插桩和 Runnable 工作正常,并为步骤 4 的数据集创建提供所需的数据结构。
> **检查点**`pixie_qa/reference-trace.jsonl` 存在。所有预期的 `wrap` 条目和 `llm_span` 条目均已出现。`pixie format` 显示所有评估所需的数据点。现在还不要阅读步骤 3 的说明。
---
### 步骤 3:定义评估器
> **参考文件**:立即阅读 `references/3-define-evaluators.md` 以获取详细的子步骤。
**目标**:将步骤 1c 中的定性评估标准转化为具体的、可运行的评分函数。每个标准映射到一个内置评估器、一个**智能体评估器**(任何语义或定性标准的默认选择),或一个手动自定义函数(仅用于机械性/确定性检查,如正则表达式或字段存在性)。评估器映射产物在标准和数据集之间架起桥梁,确保每个质量维度都有一个评分器。选择能够衡量 `pixie_qa/00-project-analysis.md` 中识别的**困难问题**的评估器——而不仅仅是泛化的质量维度。
> **检查点**:所有评估器已实现。`pixie_qa/03-evaluator-mapping.md` 已写入,包含标准到评估器的映射及决策理由。现在还不要阅读步骤 4 的说明。
---
### 步骤 4:构建数据集
> **参考文件**:立即阅读 `references/4-build-dataset.md` 以获取详细的子步骤。
**目标**:创建将所有内容联系在一起的测试场景——Runnable(步骤 2)、评估器(步骤 3)和用例(步骤 1c)。每个数据集条目定义要向应用发送什么、应用应从外部服务看到什么数据,以及如何对结果进行评分。使用步骤 2 中的参考追踪作为数据结构和字段名的真相来源。覆盖 `pixie_qa/00-project-analysis.md` 中**能力清单**的条目,并包括针对其中识别的**故障模式**的条目。**不要使用项目自身的测试夹具、mock 服务器或示例数据作为数据集的 `eval_input` 内容**——应使用真实世界的数据。**应用中每个 `wrap(purpose="input")` 必须在每个条目的 `eval_input` 中有预先捕获的内容**——当应用有输入 wrap 时,不要将 `eval_input` 留空。
> **检查点**:数据集 JSON 已创建于 `pixie_qa/datasets/<name>.json`,包含覆盖所有用例的多样化条目。**数据集真实性审核已通过**——条目使用真实世界的数据且规模具有代表性,没有项目测试夹具污染,至少有一个条目针对故障模式且结果不确定,并且每个 `eval_input` 对所有输入 wrap 都有捕获的内容。现在还不要阅读步骤 5 的说明。
---
### 步骤 5:运行 `pixie test` 并修复机械性问题
> **参考文件**:立即阅读 `references/5-run-tests.md` 以获取详细的子步骤。
**目标**:端到端执行完整流水线,使其在没有机械错误的情况下运行。此步骤严格限于修复 pixie QA 组件(数据集、Runnable、自定义评估器)中的设置和数据问题——**不是**修复应用本身或评估结果质量。一旦 `pixie test` 无错误完成,并为每个条目产生真实的评估器评分,此步骤即完成。
> **检查点**`pixie test` 运行完成。每个数据集条目都有评估器评分(真实的 `EvaluationResult` 或 `PendingEvaluation`)。没有设置错误,没有导入失败,没有数据验证错误。
>
> 如果测试报错,那是你的 QA 组件中的机械性 bug——修复并重新运行。但一旦测试产生了评分,就继续前进。不要在这里评估结果质量——那是步骤 6 的事。
**在测试产生评分后,始终进行到步骤 6。** 分析是必不可少的关键步骤——没有它,待定评估永远无法完成,用户只能得到未经解读的原始评分,没有任何可操作的见解。不要停在这里问用户是否要继续。
**迭代运行的循环规则**:每次成功的 `pixie test` 调用都会创建一个具体的 `pixie_qa/results/<test_id>` 目录并启动一个新的分析周期。在你编辑应用代码、提示词、数据集、评估器或重新运行 `pixie test` 之前,先对该确切的结果目录完成步骤 6。不要跳过早期周期而只分析最后一次运行。
---
### 步骤 6:分析结果
> **参考文件**:立即阅读 `references/6-analyze-outcomes.md`——其中包含完整的三阶段分析流程、编写指南和输出格式要求。
**目标**:通过结构化的数据驱动流程分析 `pixie test` 结果,生成关于测试用例质量、评估器质量和应用质量的可操作见解。此步骤完成待定评估,写入每个条目和每个数据集的分析,并生成一个按优先级排序的行动计划。每项陈述必须有评估运行中的具体数据支持——不得推测,不得含糊。
**持久化的分析产物**:在此简化的工作流中,仅在数据集级别和测试运行级别持久化分析。这些产物仍然包含**详细版本**(供智能体消费:数据点、证据线索、推理链)和**摘要版本**(供人类审查:可在 2 分钟内阅读的简洁 TLDR)。不要创建每个条目的分析文件。
**硬性完成门禁**:步骤 6 **未完成**,直到以下所有条件均满足:
- 每个 `pixie_qa/results/<test_id>/dataset-*/entry-*/evaluations.jsonl` 中 `"status": "pending"` 的条目,都已替换为包含 `score` 和 `reasoning` 的评分结果。
- 每个数据集目录都有 `analysis.md` 和 `analysis-summary.md`。
- 测试运行根目录下有 `action-plan.md` 和 `action-plan-summary.md`。
- 你已经针对 `pixie_qa/results/<test_id>` 运行了此技能 `resources/` 目录中的步骤 6 验证脚本,并且它报告成功。
**明确不足够的:**
- 只写一个顶层文件如 `pixie_qa/06-analysis.md`
- 说待定评估留给用户在 Web UI 中查看
- 说某个条目"可能通过"而没有更新 `evaluations.jsonl`
---
## Web 服务器管理
pixie-qa 在后台运行一个 Web 服务器,用于向用户展示上下文、追踪和评估结果。它由设置脚本自动启动(通过 `pixie start` 命令,该命令启动一个分离的后台进程并立即返回)。
当用户完成 eval-driven-dev 工作流后,告知他们 Web 服务器仍在运行,你可以通过以下命令清理它:
```bash
pixie stop
```
重要提示:Web 服务器停止后,Web UI 将无法访问。因此,只有在用户确认他们已完成所有 Web UI 功能后才停止服务器。如果他们想继续使用 Web UI,**不要**停止服务器。
每当你重新启动工作流时,始终再次运行 resources 中的 setup.sh 脚本,以确保 Web 服务器正在运行: