mcpField
L
llm-obs-eval-pipeline

llm-obs-eval-pipeline

github.com/datadog-labs测试与质量180231 次安装6 天前更新
代码仓库

关于 llm-obs-eval-pipeline

用于引导已接入 Datadog 的 LLM 应用完成链路分类、根因分析、评估器配置、数据集与实验创建及分析的编排 Skill。它通过检查点协调专用子 Skill,并支持从指定阶段开始或结束。

主要功能

  1. 01六阶段评估工作流
  2. 02链路分类与根因分析
  3. 03评估器、数据集和实验配置
  4. 04阶段检查点与状态保存
  5. 05自定义起止阶段

适用场景

  1. 01分类已接入应用的近期链路
  2. 02构建评估数据集和实验
  3. 03从指定阶段恢复工作流

MCP 相关

使用 Datadog LLM Observability MCP 工具(包括 span 搜索),并将选定的 MCP 或 pup 后端传递给各子 Skill。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/datadog-labs/agent-skills --skill llm-obs-eval-pipeline

安装后在 Claude Code 中输入/llm-obs-eval-pipeline确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

scripts/
.gitignore
load_env.py
publish_dataset.py

详细介绍

后端

检测 — 每次调用开始时,在采取任何操作之前,确定要使用的后端:

  1. 如果用户在调用参数中的任何位置传入了 --backend pup → 立即使用 pup 模式,无论是否存在 MCP 工具。跳过步骤 2–4。
  2. 检查当前工具列表中是否存在 MCP 工具。标准判断依据是可用工具中是否出现 mcp__datadog-llmo-mcp__search_llmobs_spans。
  3. 如果存在 MCP 工具 → 全程使用 MCP 模式。严格按照子技能工作流部分中列出的名称调用 MCP 工具。
  4. 如果不存在 MCP 工具 → 检查 pup 是否可执行:通过 Bash 运行 pup --version。包含 "version" 的 JSON 响应表示 pup 可用。
  5. 如果 pup 有响应 → 全程使用 pup 模式。每项子技能都附有自己的工具参考附录,其中包含完整的 MCP→pup 映射。
  6. 如果两者都不可用 → 停止并告知用户:

    “Datadog MCP 服务和 pup CLI 均不可用。请连接 MCP 服务(claude mcp add --scope user --transport http datadog-llmo-mcp 'https://mcp.datadoghq.com/api/unstable/mcp-server/mcp?toolsets=llmobs')或安装 pup。”

无论 --backend pup 出现在调用参数的何处,都接受此参数。将其从参数中移除后再传递给子技能,但要保留 pup 模式的决定——整个流水线运行期间,每项子技能也必须使用 pup 模式。

子技能后端传递:启动时检测到的后端适用于六个阶段中调用的所有子技能。不要在每个阶段重新检测。启动时只公告一次:

  • MCP 模式:“(正在使用 MCP 模式 — 所有功能均可用。)”
  • pup 模式:“(正在使用 pup 模式 — 全程使用 pup 命令。所有功能均可用。)”

调用 ID: 每次调用一开始,在调用任何 MCP 工具之前,生成一个 8 位十六进制调用 ID(例如 3a9f1c2b)。整个调用期间保持不变。

意图标记: 每次 MCP 工具调用时,都在 telemetry.intent 前加上 skill:llm-obs-eval-pipeline[<inv_id>] — ,后接调用工具的原因说明。仅在第一次 MCP 工具调用时,改用 skill:llm-obs-eval-pipeline:start[<inv_id>] — (注意 :start 后缀)。首次调用示例:skill:llm-obs-eval-pipeline:start[3a9f1c2b] — 预检查:确认 ml_app 在过去 7 天内有追踪记录


LLM Obs 评估流水线 — 分类 → 根因分析 → 评估引导设置 → 数据集 → 实验 → 分析

这是一条面向已完成埋点的 ml_app 负责人、确定性的六阶段引导式流水线。每个阶段都采用相同的结构——说明所生成实体的横幅、对其用途的说明、操作(调用子技能或执行一小段步骤),以及检查点。你始终清楚当前进度。

[Precheck] verify ml_app, project, backend, credentials, output dir
   ↓
[Phase 1: Classify ml_app traces]        entity: ml_app, trace, span
   ↓
[Phase 2: Root cause analysis]           entity: failure mode, root cause
   ↓
[Phase 3: Bootstrap evaluators]          entity: evaluator, LLM judge
   ↓                                     (stop here with --stop-after eval-bootstrap
   ↓                                      for the classic eval-pipeline behavior)
[Phase 4: Create + publish dataset]      entity: dataset record, published dataset
   ↓                                     (executes: LLMObs.create_dataset)
[Phase 5: Generate + run experiment]     entity: experiment, task, evaluator, run
   ↓                                     (executes: python <generated_file>)
   ↓                                     (in-phase review beat before run)
[Phase 6: Analyze experiment]            entity: metric, comparison, recommendation

此技能纯粹用于编排和引导——不包含新的分析逻辑。实际工作由子技能完成(llm-obs-session-classify、llm-obs-trace-rca、llm-obs-eval-bootstrap、llm-obs-experiment-py-bootstrap、llm-obs-experiment-analyzer)。此技能提供的是确定性的结构:每个阶段都采用相同的形式、遵循相同的检查点约定,并包含相同的实体说明横幅,因此无论用户最初如何表述请求,都能获得一致且有讲解的体验。

用法

/llm-obs-eval-pipeline <ml_app> [--project-name <name>] [--timeframe <window>] [--trace-limit <N>]
                                [--format py|ipynb] [--evaluator-style function|class|remote]
                                [--offline-evaluators | --online-evaluators | --data-only]
                                [--start-at classify|rca|eval-bootstrap|dataset|experiment|analyze]
                                [--stop-after classify|rca|eval-bootstrap|dataset|experiment|analyze]
                                [--classification-summary <path>] [--rca-report <path>]
                                [--dataset-file <path>] [--dataset-name <name>]
                                [--experiment-file <path>] [--experiment-id <uuid> | --experiment-url <url>]
                                [--app-root <path>] [--env-file <path>] [--output-dir <dir>]
                                [--backend pup]

参数:$ARGUMENTS

输入
输入必需默认值描述
ml_app是—要接入/评估的已插桩 LLM 应用。预检查会验证它是否有近期的追踪记录。
--project-name否根据 pyproject.toml / setup.cfg / setup.py / package.json / 当前工作目录推导(顺序与 llm-obs-experiment-py-bootstrap 相同);若无法推导,则使用 experiment-sdk-default管道要将数据集和实验写入的 Datadog 项目。SDK 会在首次使用时通过 LLMObs.enable(project_name=...) 延迟创建项目。在预检查中显示此信息,以便用户确认后再创建任何内容。
--timeframe否now-7dPhase 1 分类和 Phase 4 数据集采样的回溯时间窗口。
--trace-limit否20Phase 4 的采样上限。Phase 1 内部使用 min(20, --trace-limit) 作为分类样本数。
--format否py在 Phase 5 中传递给 llm-obs-experiment-py-bootstrap:py(脚本)或 ipynb(Jupyter 笔记本)。
--evaluator-style否function传递给 llm-obs-eval-bootstrap(Phase 3)和 llm-obs-experiment-py-bootstrap(Phase 5):function、class 或 remote。
--offline-evaluators否开启(默认)Phase 3:生成一套 Python SDK 评估器(BaseEvaluator / LLMJudge 类),用于在数据集上运行实验。内部映射到 llm-obs-eval-bootstrap 的 sdk_code 模式。
--online-evaluators否关闭Phase 3:直接向 Datadog 发布在线 LLM 评审器(创建为已禁用的草稿;需在 UI 中启用)。在线评估器会在生产跨度产生时对其运行。内部映射到 llm-obs-eval-bootstrap 的 publish 模式(原为 --publish)。
--data-only否关闭Phase 3:仅生成本地数据内容,不包含可执行评估器代码,也不进行在线发布。进入 Phase 3 时,技能会提示用户选择以下其中一项:(a) 适用于实验的 DatasetRecordRaw[] JSON(内部映射到 llm-obs-eval-bootstrap --emit-dataset),或 (b) 用于本地分析、与框架无关的 JSON 评估器规范(内部映射到 llm-obs-eval-bootstrap 的 data_only 模式)。
--stop-after <phase>否analyze(运行全部阶段)在指定阶段完成后停止。classify = 仅运行 Phase 1。rca = 运行至 Phase 2。eval-bootstrap = 运行至 Phase 3(与经典 eval-pipeline 相同)。dataset = 运行至 Phase 4(数据集已创建并发布)。experiment = 运行至 Phase 5(实验已生成并运行)。analyze = 运行全部六个阶段(默认)。
--start-at <phase>否classify(从头开始)跳过前面的阶段,从指定阶段开始。可选值与 --stop-after 相同。技能会从 <output-dir>/state/ 自动加载所需的前序阶段产物(参见“状态持久化和进入/退出”一节)。如果某个阶段所需的产物无法自动加载,请使用下方某个覆盖标志提供。可与 --stop-after 组合,以运行管道中连续的一段阶段。
--classification-summary <path>否如果 --start-at rca 或更后面的阶段,则从 <output-dir>/state/01-classification.md 自动加载覆盖 Phase 2 使用的 Phase 1 输出。适用于前序状态文件缺失,或要指定手动编辑过的版本。
--rca-report <path>否如果 --start-at eval-bootstrap 或更后面的阶段,则从 <output-dir>/state/02-rca-report.md 自动加载覆盖 Phase 3 使用的 Phase 2 输出。
--dataset-file <path>否从 <output-dir>/state/04-published-dataset.json 的 dataset_file 字段自动加载(或使用最新的 <output-dir>/dataset_<ml_app>_*.json)本地 DatasetRecordRaw[] JSON。Phase 4 的发布子步骤会在无需重新采样的情况下重新发布时使用此文件。
--dataset-name <name>否如果 --start-at experiment,则从 <output-dir>/state/04-published-dataset.json 自动加载已发布的 Datadog 数据集名称,Phase 5 会将实验关联到该数据集。
--experiment-file <path>否如果 --start-at experiment 且文件已存在,则从 <output-dir>/state/05-experiment-run.json 的 experiment_file 字段自动加载生成的实验文件。如果提供此文件,Phase 5 会跳过代码生成子步骤(5a),直接进入审核环节(5b)→ 运行(5c)。
--experiment-id <uuid>否如果 --start-at analyze,则从 <output-dir>/state/05-experiment-run.json 自动加载Phase 6 要分析的 Datadog 实验 ID。不能与 --experiment-url 同时使用。
--experiment-url <url>否同上,自动加载--experiment-id 的替代选项。技能会从 URL 末尾解析 UUID。
--app-root否根据当前工作目录 / pyproject.toml 等解析将 llm-obs-experiment-py-bootstrap 的任务函数内省限制在此目录树中。
--env-file否无(自动发现会遍历标准位置)用于加载凭据的显式 .env 路径。会在预检查中显示,并写入生成的实验文件,作为 ENV_FILE_OVERRIDE。
--output-dir否./experiments数据集 JSON、发布脚本和生成的实验文件的写入位置。
--backend否自动检测pup 无论 MCP 是否可用,都会强制使用 pup 模式。
如果未提供 ml_app,请先询问用户再继续。三个评估器输出标志(--offline-evaluators、--online-evaluators、--data-only)互斥——如果设置了多个,则报错退出。如果都未设置,默认使用 --offline-evaluators。旧标志名称 --publish 和 --sdk-code 仍作为别名接受,以保持向后兼容,但所有输出中都会映射为新名称。

预检查

在 Phase 1 之前,执行一次简短的验证——不要为此显示“Phase”横幅;这只是准备工作。输出一段预检查摘要,然后直接进入 Phase 1。

  1. 后端——已在此技能的开头检测到。在预检查输出中注明所选后端,供用户确认。

  2. ml_app 有近期追踪——调用 search_llmobs_spans(query="@ml_app:\"<ml_app>\"", root_spans_only=true, limit=1, from="<timeframe>")(MCP)或对应的 pup 命令。如果结果为空,则停止并告知用户预检查失败——没有可供评估的数据——并建议扩大 --timeframe 范围或确认 ml_app 名称。

  3. 解析 project_name——如果提供了 --project-name <name>,则原样使用。否则,按 llm-obs-experiment-py-bootstrap(工作流步骤 1)中的相同解析顺序推导:pyproject.toml → setup.cfg → setup.py → package.json → cwd 基名(转换为 slug)。最终值为 experiment-<service-name>;如果无法解析,则回退为 experiment-sdk-default,并发出警告,告知用户显式设置 --project-name。

    项目创建语义:首次针对组织调用 LLMObs.enable(project_name=...) 时,Datadog SDK 会延迟创建项目(在 Phase 4 的发布脚本中,以及 Phase 5 生成的实验中再次创建)。用户无需在 UI 中预先创建任何内容。在预检查输出中显示所选项目名称,以便用户在 Phase 4 之前进行修改(如果该名称不符合预期)。

  4. 确保 --output-dir 和 <output-dir>/state/ 存在——通过 Bash 执行 mkdir -p <output-dir>/state。开销很小。state/ 子目录用于持久化各阶段的输出(见下文“状态持久化和阶段进入/退出”)。

  5. **解析凭据。**按照下方的发现顺序查找 Datadog 凭据,确保在 Phase 4 需要时已找到——到发布步骤才发现凭据缺失会带来糟糕的用户体验。此阶段只读:不要写入任何新文件。不要向用户打印机密值;只报告加载了哪个文件以及解析出了哪些键。

    发现顺序(每个变量以首次命中为准;shell 环境变量始终优先于文件):

    1. 如果提供了 --env-file <path>,优先使用该文件——始终首先尝试。
    2. 当前 shell 环境(os.environ)——已导出的 DD_API_KEY / DD_APPLICATION_KEY / DD_APP_KEY / DD_SITE 优先于文件中的值。如果所有必需的键都已存在,则跳过文件加载。
    3. <output-dir>/.env——如果用户之前运行过此技能,并在之前生成的文件旁放置了 .env,则优先使用该文件。
    4. <app-root>/.env——已解析的 pyproject.toml / setup.cfg / setup.py / package.json 所在目录(如果都没有,则为 cwd)。
    5. <app-root>/.env.local——通常被 Git 忽略的本地覆盖文件。
    6. <cwd>/.env——如果 cwd 与 app-root 不同,则作为回退选项。
    7. 向上遍历父目录:从 cwd 开始,逐级向上查找 .env,直到到达 / 或用户的 home 目录。找到第一个匹配项后停止。
    8. ~/.datadog/credentials——如果存在,则使用 Datadog 的标准用户级凭据文件。

    对检查的每个文件,逐行解析:跳过空行、注释行(#)和格式错误的行(不含 =)。如果行首有 export ,则将其去除(以支持 .envrc 风格的文件)。按第一个 = 拆分。去掉值两侧的引号。仅设置 os.environ 中尚不存在的变量——绝不覆盖 shell 中的值。 必需的键:DD_API_KEY 和(DD_APPLICATION_KEY 或 DD_APP_KEY)。DD_SITE 是可选项(默认值为 datadoghq.com)。提供商的键(OPENAI_API_KEY、ANTHROPIC_API_KEY 等)会在第 6/7 阶段根据检查出的任务进行验证,而不是在此处验证。

    如果已找到所有必需的键——记录已加载的文件,并在 Precheck 块中输出一行摘要。继续。

    如果遍历所有位置后仍未找到必需的键——停止并向用户显示清晰、可执行的消息:

    "在 shell 环境变量或任何已发现的 .env 文件中都未找到 Datadog 凭据。继续之前有两个选项:

    • 在 shell 中导出:export DD_API_KEY=… 和 export DD_APPLICATION_KEY=…(如果使用非默认值,也设置 DD_SITE=…),然后重新调用此技能。
    • 创建一个 .env 文件:在 <app-root>/.env 中分别单独一行写入 DD_API_KEY=… 和 DD_APPLICATION_KEY=…,然后重新调用此技能。

    提交前,请确保 .env 已列入 .gitignore。"

    不要提议替用户创建 .env 文件——是否将机密保存到磁盘应由用户决定,而不是由技能决定。

输出预检摘要,然后开始第 1 阶段:

## Precheck

- Backend: <MCP | pup>
- ml_app `<ml_app>` has traces in <timeframe>: yes (<sample_count> root spans found)
- Project name: `<project_name>` (created lazily on first LLMObs.enable() call in Phase 4)
- Output dir: `<output-dir>` (created)
- Credentials: <one of:
    "loaded from shell env (DD_API_KEY, DD_APPLICATION_KEY, DD_SITE)"
  | "loaded from <relative path to .env file> (DD_API_KEY, DD_APPLICATION_KEY[, DD_SITE])"
  | "shell env + <relative path>: keys resolved from both (shell overrode file for <list>)"
  >
- Stop-after: <phase from --stop-after, default `analyze`>

Starting Phase 1 of 6.

凭据括号中列出的键必须准确反映实际发现的内容(以便用户确认没有加载任何意外内容)。绝不要打印键值。


阶段模板

以下每个阶段都使用此确切模板。请勿偏离——确定性的外壳能确保每次调用的流程体验一致。

## Phase N of 6: <Title>

**You are here.** Phase N of 6 — <one-line position summary>.

**What this phase produces**: <Entity name>
**What a <entity> is**: <2-3 sentence definition tailored to this phase>
**Why it matters**: <1 sentence on why the user needs this>

→ Action: <invoke <sub-skill> | execute <script>>

<full sub-skill output OR execution log reproduced here — do NOT summarize or truncate>

<after the action completes successfully, Write the phase output to
`<output-dir>/state/0N-<name>.{md,json}` per the State persistence contract — see
"State persistence and entry/exit" section. This happens BEFORE the checkpoint
so the file is on disk even if the user types `stop` next.>

---

### Checkpoint <N>

<concise summary of what was produced, where it lives (path / Datadog URL), and any caveats>

Before I continue to Phase N+1 (<next title>):
- <2–3 phase-specific review prompts the user can answer>

Type `continue` to proceed, `stop` to exit cleanly (state is saved), `redo` to re-run this phase, or give me adjustments.

绝不自动进入下一阶段。 每次都在检查点暂停并等待用户明确输入。这项技能的核心是确定性——包括由用户决定何时继续。

如果当前阶段与 --stop-after 的值一致,请将检查点提示替换为停止摘要(参见本文件底部的“Stop-after 处理”)。


阶段 1:分类 ml_app 轨迹

实体:ml_app、trace、span。

教学横幅(按原文使用,仅替换为实际的 ml_app 名称):

什么是 ml_app:一个逻辑上的 LLM 应用——在检测时为 span 添加的名称(ml_app=<name>)。它将属于同一产品界面的所有生产轨迹和评估器运行归为一组。你稍后创建的每个数据集、实验和评估器都将以此范围为目标。

什么是轨迹:ml_app 的一次端到端执行——通常是针对单个用户请求的 Agent 循环,由一个或多个 span(LLM 调用、工具调用、检索)组成。

此阶段为何重要:在分析故障根因(阶段 2)、引导评估器(阶段 3)或整理数据集(阶段 4)之前,你需要快速了解应用在生产环境中的实际运行情况,以及当前的故障模式。分类可以一次性提供这些信息。

轨迹池预览(必须执行)。 调用子技能之前,先构建并展示一个 Datadog Traces UI 链接,该链接应打开阶段 4 将从中采样的确切根 span 集合。这样,用户可以快速查看轨迹池、发现异常值,或在任何分类工作开始前调整 --timeframe。链接必须与 llm-obs-eval-bootstrap --emit-dataset 在阶段 4 中使用的筛选条件一致(参见 dd-llmo/llm-obs-eval-bootstrap/SKILL.md → 阶段 3D → 采样):仅根 span。

URL 构建规则:

  1. 主机:在 DD_SITE 前加上 app.。如果未设置 DD_SITE,则默认为 app.datadoghq.com。
    • datadoghq.com → app.datadoghq.com
    • datadoghq.eu → app.datadoghq.eu
    • us3.datadoghq.com → app.us3.datadoghq.com
    • us5.datadoghq.com → app.us5.datadoghq.com
    • ap1.datadoghq.com → app.ap1.datadoghq.com
    • ap2.datadoghq.com → app.ap2.datadoghq.com
    • datad0g.com → app.datad0g.com(暂存环境)
  2. 路径:/llm/traces(LLM Observability Traces 探索器)。
  3. 查询字符串:对 @ml_app:"<ml_app>" @status:ok @parent_id:undefined 进行 URL 编码,并绑定到 query=。
  4. 时间窗口:将 --timeframe 转换为绝对纪元毫秒数(开始时间为 now - <duration in ms>,结束时间为 now),并绑定到 start= / end=。
  5. 可选:追加 &paused=true,以免 UI 打开时实时流式传输结果。

紧接着 Action 区块之前展示链接:

**Trace pool being analyzed** ({timeframe}, filter `@ml_app:"<ml_app>" @status:ok`, root spans only):

  <full URL>

Phase 1 will classify the first {min(20, trace-limit)} of these for orientation. Phase 4 will sample up to {trace-limit} from the same pool for the dataset. Click through if you want to see the pool before either runs, or adjust `--timeframe` and re-invoke if the window looks off.

操作:按照 ml_app 模式执行 llm-obs-session-classify 技能,使用:

  • ml_app = 提供的 ml_app
  • timeframe = 提供的 timeframe
  • sample_limit = min(20, trace-limit) — 保持快速;阶段 4 将进行更大规模的采样

按照该技能中定义的流程,完整执行 ml_app 模式工作流(步骤 M1 至 M3)。输出完整的分类结果(所有紧凑的逐单元区块以及最终的 # Session Classification Summary)——不得总结或截断。下游阶段 2 的 RCA 依赖完整文本处于上下文中。

检查点 1

输出 # Session Classification Summary 后,展示:

## Phase 1 complete — you've seen what `<ml_app>` does in production

[verdict distribution table from session-classify]
[failure mode frequency table from session-classify]

**Trace pool for Phase 4's dataset sample**: <full URL from the Trace pool preview above>
(same filter / same timeframe — open it now if you want to scan for traces you'd rather exclude)

Next up — Phase 2 will diagnose *why* the failing traces are failing.

Before I continue:
- Do these failure patterns look right?
- Any traces you'd like to exclude from the dataset sample in Phase 4? (Paste trace IDs from the link above and I'll drop them.)
- Any quality dimension you already know you want to measure later?

Type `continue` to proceed, `stop` to exit cleanly (state is saved), `redo` to re-run this phase, or give me adjustments.

等待用户明确确认。如果用户排除特定轨迹,将其标记为“用户排除”,并从阶段 2 的故障分类和阶段 4 的采样中移除。不要重新分类。

阶段 2:根因分析

实体:failure mode、root cause。

教学提示:

什么是故障模式:指应用以何种方式失败时反复出现的模式,例如“模型生成了虚构的引用 URL”“Agent 在工具调用之间忘记状态”“检索返回了不相关的片段”。每种故障模式都有一个或多个根因(系统提示词缺陷、工具缺失、检索遗漏等)。

为什么此阶段很重要:如果评估器只对“此响应是否良好?”这类通用问题评分,就会漏掉应用中实际出错的具体方面。RCA 让阶段 3 能提出针对应用实际故障模式的评估器,从而获得更精准的信号,减少误报。

操作:遵循 llm-obs-trace-rca 技能。

阶段 1 的 # Session Classification Summary 已在上下文中。该技能会通过其阶段 0 步骤 0S 检查自动检测到它,并进入“基于分类”路径——提取故障类别、展示分类概览,然后直接进入阶段 2(开放式编码),而不运行自己的阶段 1 区间搜索。

完成整个工作流,直到阶段 6(编译后的 RCA 报告)。输出完整的 RCA 报告——不要总结。阶段 3 的检测需要完整报告位于上下文中。

检查点 2
## Phase 2 complete — root causes identified

[the Phase 6 RCA report is above]

Next up — Phase 3 will bootstrap evaluators that target these failure modes.

Before I continue:
- Do these root causes look accurate?
- Any failure modes to add, remove, or reframe?
- Which root causes should the evaluators target? (Default: all of them.)

Type `continue` to proceed, `stop` to exit cleanly (state is saved), `redo` to re-run this phase, or give me adjustments.

等待用户明确确认。如果用户调整了分类体系,请在继续之前纳入这些更改。


阶段 3:引导创建评估器

实体:evaluator、LLM judge。

教学提示:

什么是评估器:一种为单条记录的输出评分的函数。返回 bool / float / 结构化的 EvaluatorResult。有两种类型:代码评估器(确定性检查——JSON 有效性、正则表达式匹配、长度、自定义 Python)和 LLM 即评审者评估器(根据评分标准对模型评分——例如“此响应是否以检索到的文档为依据?”)。

运行模式(互斥;默认为 --offline-evaluators):

  • --offline-evaluators (默认):生成一套 Python SDK 评估器(BaseEvaluator / LLMJudge 类),在针对数据集运行实验时执行。用于在本地运行实验的情况。
  • --online-evaluators:将 LLM 评审者评估器作为已禁用的草稿发布到 Datadog。启用后,它们会在生产区间发出时对其进行评估。用于希望在生产环境中持续评估的情况。
  • --data-only:仅生成本地数据内容——不生成可执行的评估器代码,也不在线发布。会提示你选择用于实验的数据集,或本地分析数据内容(参见下文“运行模式选择”)。

为什么此阶段很重要:评估器是“这个输出看起来没问题”和“这个输出达到我们的质量标准”之间的契约。引导创建的评估器套件以阶段 2 的故障分类体系为依据,比你原本手写的通用评估器更精准。

操作:遵循 llm-obs-eval-bootstrap 技能。

阶段 2 的 RCA 报告已在上下文中。该技能会自动检测 ## Failure Taxonomy 标题,并在阶段 0 进入“基于 RCA”路径。

运行模式解析

调用子技能之前,先解析运行模式:

  1. --offline-evaluators(默认)→ 不带模式标志调用 llm-obs-eval-bootstrap(其 sdk_code 为默认值)。

  2. --online-evaluators → 调用 llm-obs-eval-bootstrap --publish。

  3. --data-only → 通过 AskUserQuestion 提示用户:

    “你为第 3 阶段选择了 --data-only。你想要哪种本地数据块?

    • 用于实验的数据集 — 适合传给 LLMObs.create_dataset(records=...) 的 DatasetRecordRaw[] JSON。当你想用此技能采样的记录为实验提供初始数据时,此选项很有用。(内部调用 llm-obs-eval-bootstrap --emit-dataset <path>。)
    • 用于分析的本地数据块 — 与框架无关的 JSON 评估器规范,用于描述将会生成哪些评估器,但不生成 Python 代码。适合在不运行任何操作的情况下检查评估器覆盖范围。(内部调用 llm-obs-eval-bootstrap --data-only。)”

    如果用户选择“用于实验的数据集”,且流水线会运行到第 4 阶段(即 --stop-after 不是 eval-bootstrap 或更早的阶段),请告知用户:第 4 阶段的采样步骤将跳过,改用第 3 阶段的输出——此处生成的数据集将是第 4 阶段发布的数据集。

原样传递 --evaluator-style。

llm-obs-eval-bootstrap 技能有自己的强制提案检查点(生成代码之前的评估器套件提案)。请遵守此要求——不得跳过或自动确认。

检查点 3
## Phase 3 complete — evaluator suite ready

- Mode: `<offline-evaluators | online-evaluators | data-only (dataset-for-experiment) | data-only (analysis-blob)>`
- Output: `<path to .py / .json / dataset-record JSON / "published as drafts to Datadog">`
- Evaluators emitted: <list of names>
- Coverage: <one-liner: which failure-mode categories are now covered>

Next up — Phase 4 will sample production traces into a dataset you can run experiments against (using these evaluators or the placeholders the experiment template ships with).

If you only wanted evaluators (the classic eval-pipeline flow), this is the natural stopping point: re-invoke with `--stop-after eval-bootstrap` to formalize that as the exit.

Before I continue:
- Do the generated evaluators look right?
- Any to drop or rename before they're referenced in the experiment?

Type `continue` to proceed, `stop` to exit cleanly (state is saved), `redo` to re-run this phase, or give me adjustments.

等待用户明确确认。如果设置了 --stop-after eval-bootstrap,流水线到此结束——输出停止摘要,而不是检查点,然后退出。


第 4 阶段:创建并发布数据集

实体:dataset、dataset record、已发布的数据集(Datadog 端)、dataset_name、版本。

教学说明横幅:

什么是数据集:由一组命名记录构成,实验会针对这些记录运行。每条记录都有 input_data(任务接收的内容),还可以选择包含 expected_output(你期望的返回内容)。数据集存放在 Datadog 的项目下,并带有版本号——每次推送导致记录发生变化时,都会生成一个新版本。

什么是记录:一个 (input_data, expected_output) 对,可选包含 metadata 和 tags。一条记录 = 实验中的一行。

“发布”是什么意思:将本地记录推送到 Datadog,使数据集可在后续所有实验中通过名称访问。发布后,组织中有权限的任何人都可以通过 LLMObs.pull_dataset(dataset_name="…") 拉取数据集——包括我们在第 5 阶段生成的实验代码。

此阶段为何重要:实验需要稳定且可通过名称访问的输入集。对生产跟踪数据进行采样,可以生成一个贴近实际的初始数据集(即应用实际收到的输入);将其发布到项目下,就能作为数据集整理工作与使用这些数据集的实验之间的约定。

此阶段会在你的机器上执行代码(发布步骤会通过 LLMObs.create_dataset(...) 写入 Datadog)。创建数据集的步骤是只读的;只有发布步骤会更改状态。

操作 — 两个子步骤,中间没有检查点:

4a — 将跟踪数据采样为 DatasetRecordRaw[] JSON。 按照 llm-obs-eval-bootstrap 技能的 --emit-dataset 模式执行:

/eval-bootstrap <ml_app> --timeframe <timeframe> --trace-limit <trace-limit> --emit-dataset <output-dir>/dataset_<ml_app>_<YYYYMMDD>.json

此模式会对根 span 进行采样,提取 (input_data, expected_output) 对,应用 PII 脱敏,然后写入 JSON。它不会提议或生成评估器——数据集是唯一产物。完整规范请参阅 dd-llmo/llm-obs-eval-bootstrap/SKILL.md → 第 3D 阶段。

如果用户在检查点 1 中排除了特定跟踪数据,请一并传递排除列表(子技能会在采样时将其剔除——切勿重新分类)。

逐字复现子技能的 ## Generated Dataset 摘要。 如果 Phase 3 已生成数据集,则跳过 4a。 如果用户在 Phase 3 中选择了 --data-only 和「用于实验的数据集」子模式,Phase 3 状态文件(state/03-evaluators.json)中的 mode: data_only_dataset 会指向数据集 JSON 的 output_path。在这种情况下,完全跳过子步骤 4a,直接将 Phase 3 的输出传递给 4b 的发布辅助脚本。显示一行提示:「正在复用 Phase 3 中的数据集(<path>);跳过重新采样。」

4b — 发布到 Datadog。 立即通过 Bash 调用预先提供的发布辅助脚本 <this-skill-dir>/scripts/publish_dataset.py。不要将脚本内容内联到此 SKILL.md 中,也不要从头重写——该辅助脚本是发布流程(凭据发现、标签规范化、项目创建、错误处理)的唯一依据。它接受 CLI 参数,因此无需替换占位符。

python <skill-dir>/scripts/publish_dataset.py \
  --records <absolute path to JSON from 4a> \
  --dataset-name <chosen dataset_name, default <ml_app>_seed_<YYYYMMDD>> \
  --project-name <resolved project_name from Precheck> \
  [--env-file <path>]   # repeatable; takes precedence over auto-discovery

<skill-dir> 解析为技能的安装位置(例如 ~/.claude/skills/llm-obs-eval-pipeline/)。脚本会输出以下内容之一:

  • Loaded credentials from: <file paths>(如果有 .env 文件提供了值),然后
  • OK dataset_name=<name> record_count=<N> url=<url>(成功时),或者
  • 在 stderr 中输出 ERROR: <message>,并以非零状态码退出(认证失败、缺少密钥、ddtrace 导入失败等)。

编排器须知:

  • 调用发布辅助脚本前,先预检查导入是否可用:通过 Bash 运行 python -c "import ddtrace.llmobs"。如果失败,请停止并告知用户:

    "ddtrace 未安装在当前启用的 Python 环境中。请运行 pip install 'ddtrace>=4.7',然后重新调用此技能(从头重新运行——Phase 1–3 的输出具有幂等性)。"

  • 脚本中的 LLMObs.enable(project_name=...) 会实际应用预检查中的 --project-name——Datadog 项目会在首次调用时延迟创建。
  • 如果脚本输出了有关标签规范化的 WARNING: 行,请在 Checkpoint 4 中展示,以便用户了解其上游数据集包含格式错误的标签。
  • 如果脚本输出 Loaded credentials from: ...,请在 Checkpoint 4 中包含该文件路径。
  • 如果脚本因认证错误(401/403)以非零状态码退出,请展示 stderr 并停止——不要重试。告知用户,最可能的原因是 .env 中的值已过期;在 shell 中运行 export DD_API_KEY=... DD_APPLICATION_KEY=... 可覆盖这些值,且 shell 中导出的值优先级更高。
  • 成功时,捕获输出的 dataset_name 和 url,并将它们带入 Phase 5。将二者写入 Phase 4 状态文件(参见状态持久化一节)。

为何 4a 和 4b 之间没有中间检查点? 在常见情况下,本地 JSON 会从 trace 中自动提取,并直接传入 LLMObs.create_dataset(records=...)——这两个步骤之间几乎没有可编辑的内容。希望在发布前检查或编辑 JSON 的用户,应单独运行 eval-bootstrap --emit-dataset,编辑 JSON,然后在手动发布后,使用 --start-at experiment --dataset-name <name> 重新进入此流水线。

检查点 4
## Phase 4 complete — dataset created and published

- Local file: `<path>` (kept for inspection / re-publish)
- Records emitted: <N> (skipped: <M> with no usable output)
- PII redactions: <P>
- Tag normalizations: <T>
- Published as: `<dataset_name>` in project `<project_name>` <(created if it did not exist)>
- Datadog UI: <url or "open LLM Observability → Datasets to confirm">
- Caveat: `expected_output` is the **current production behavior baseline**, not ground truth. Treat the dataset as a regression-style baseline before promoting it to a labelled gold set.

Next up — Phase 5 will generate a Python experiment script that pulls `<dataset_name>` and runs your task code (auto-discovered) against it.

Before I continue:
- Confirm you can see the dataset in the Datadog UI (LLM Observability → Datasets → search `<dataset_name>`)?
- Any second thoughts on the records (we can re-emit and re-publish before generating the experiment)?

Type `continue` to proceed, `stop` to exit cleanly (state is saved), `redo` to re-run this phase, or give me adjustments.

等待确认。


阶段 5:生成并运行实验

实体:experiment、task 函数、evaluator、实验运行、experiment.url、指标流。

教学提示栏:

什么是实验:一种程序化测试框架。它会针对数据集中的每条记录调用 task 函数(你正在测试的代码,通常是一次 LLM 调用),然后运行一个或多个 evaluators 来评估任务的输出。Datadog 会将所有结果汇总到同一个实验视图中,方便你比较不同运行结果。

什么是 task 函数:一个 Python 可调用对象,接收一条记录的 input_data 和一个 config 字典,并返回你的应用针对该输入本应返回的内容。此子技能会检查你的项目并自动找到这个函数——除非找不到,否则不会留下 # TODO(user) 占位符。

什么是 evaluator:请参见上文阶段 3。生成的实验默认附带占位 evaluator;如果你在阶段 3 使用了 --evaluator-style remote,可以在此处接入那些名称。

什么是 experiment.url:Datadog Experiments UI 中指向此次运行的深层链接。阶段 6 会用它分析结果。

为什么此阶段很重要:你的代码会在此阶段针对数据集实际运行并生成测量结果。生成文件成本低;运行才会消耗提供商的令牌并产生信号。

此阶段会在你的计算机上执行代码(经过本阶段内的审核环节后,将端到端运行 Python 文件)。

操作 — 分为三个子步骤,并在代码生成和运行之间设置本阶段内的审核环节:

5a — 生成实验文件。 按照 llm-obs-experiment-py-bootstrap 技能操作:

/llm-obs-experiment-py-bootstrap \
  --dataset-name <dataset_name> \
  --project-name <project_name> \
  --format <format> \
  --evaluator-style <evaluator-style> \
  --app-root <app-root> \
  --env-file <env-file if set> \
  --output <output-dir>/experiment_<ml_app>_<YYYYMMDD>.<py|ipynb>

逐字重现子技能的完整输出(包括生成的 SDK 调用摘要、“Task function source”代码块、凭据发现部分和 Next steps 代码块)。不要总结。“Task function source”代码块会告知用户自动接入的是哪个 module:function——这对下一子步骤至关重要。

5b — 本阶段内的审核环节(必须执行)。 子技能输出后,暂停并显示简短的内联提示(这不是带有新横幅的完整检查点,而是阶段 5 内的一行审核提示):

## Phase 5 — review the generated experiment before running

- File: `<path>`
- Wired to dataset: `<dataset_name>` (pulled at runtime via LLMObs.pull_dataset)
- Task function source: <line lifted from the sub-skill output — module:function, or "placeholder fallback">
- Evaluators: <2–3 evaluator names>

**Open the file and check three things before I run it:**
1. The wired `task_fn` (section 4) — confirm the sub-skill picked the right entry point. If it picked a helper or deprecated path, edit the import to point at the right function. If it fell back to a placeholder, replace it with a real call.
2. The placeholder evaluators (section 5) — these are starting points. If Phase 3 produced online evaluators via `--publish`, swap one of the placeholders for a `RemoteEvaluator(eval_name="...")`.
3. The `experiment.run(jobs=<N>)` parallelism (section 7) — defaults to 10; lower it if you're worried about rate limits.

Type **`run`** to execute the file as-is, **`edit`** to pause here so you can edit and re-run this skill, or **`stop`** to exit cleanly. State for Phase 4 and earlier is preserved.

等待用户回复。

  • 如果回复为 run:继续执行 5c。
  • 如果回复为 edit:告知用户文件位于 <path>,并且满意后可以使用 --start-at experiment 重新调用此技能。正常结束本次运行。生成的文件路径会写入状态文件,因此 --start-at experiment 可以跳过代码生成直接恢复(只需重新运行子步骤 5c)。
  • 如果回复为 stop:输出停止摘要并结束。已完成阶段的状态(包括生成的实验文件)会保留在磁盘上。
  • 其他任何回复:视为调整要求或问题。进行分析并作答,然后再次显示审核提示。

5c — 执行文件。

  • 对于 --format py:通过 Bash 运行 python <generated_path>。将输出实时传递给用户。
  • 对于 --format ipynb:告知用户生成的文件是笔记本,并询问他们是要(a)通过 jupyter nbconvert --to notebook --execute --inplace <path> 执行(需要安装 jupyter),还是(b)交由用户在 JupyterLab 中打开并手动运行单元格。如果 jupyter 在 PATH 中,默认选择(a);否则选择(b)。
  • 从运行的标准输出中捕获打印出的 experiment.url——生成的文件始终以 print(experiment.url) 结尾。如果找不到,则从标准输出中解析子串 https://app.datadoghq.com/llm/experiments/(需考虑非默认的 DD_SITE 主机)。
  • 如果运行失败:不要自动重试。完整显示回溯信息,用一行诊断指出故障类别(身份验证、缺少依赖、未找到数据集、任务函数引发异常、评估器引发异常),并询问用户是否要修复后重新运行。
检查点 5
## Phase 5 complete — experiment generated and run

- File: `<path>`
- Experiment URL: <experiment.url>
- Records processed: <N>
- Duration: <wall-clock seconds>
- Task function: <module:function>
- Evaluator score summary (from stdout, if printed): <table or "open the UI">

Next up — Phase 6 will pull the experiment results back from Datadog and produce an analysis report (struggling metrics, qualitative examples, root-cause hypotheses).

Before I continue:
- Take a look at the experiment in the UI (link above). Do the per-record scores roughly match your expectations?
- Any specific question you want Phase 6 to focus on? (Optional — leaving it open runs an exploratory analysis.)

Type `continue` to proceed, `stop` to exit cleanly (state is saved), `redo` to re-run this phase, or give me adjustments.

等待确认。如果用户提供了关注问题,将其带入阶段 6,作为分析器的 question 参数。

第 6 阶段:分析实验

实体:实验 metric、分段比较、建议。

教学横幅:

什么是实验指标:由某个评估器生成的逐条记录评分,汇总后形成数据集的通过率/得分分布。Datadog Experiments UI 会将这些指标显示为列,并允许你按附加到每条记录的 metadata 字段进行切分。

建议是什么样的:分析器会根据表现不佳的指标以及失败记录中的模式,提出关于下一步要修改什么的假设(系统提示词、检索、任务代码、数据集本身或评估器)。

为什么这一阶段很重要:这就形成了闭环。你从查看生产环境中的行为开始,现在则可以基于证据了解实验暴露了哪些缺口,以及接下来可以尝试什么。

操作:在 single-exploratory 模式下遵循 llm-obs-experiment-analyzer 技能(如果用户在检查点 7 提供了聚焦问题,则使用 single-Q&A):

/llm-obs-experiment-analyzer <experiment_id_from_url> [<focus question if any>] --output agent

从第 5 阶段记录的 URL 中提取 <experiment_id>(/llm/experiments/ 后面的 UUID)。

逐字复现分析器的完整报告。

最终摘要

分析器报告之后,输出结束摘要——这将替代各阶段的检查点:

# LLM Obs Eval Pipeline complete

**ml_app**: `<ml_app>` | **Project**: `<project_name>` | **Timeframe**: <timeframe>

| Phase | Output |
|---|---|
| 1. Classify ml_app | <N> traces classified (<F> failures) |
| 2. Root cause analysis | <K> failure modes, <M> root causes |
| 3. Bootstrap evaluators | <J> evaluators (`<offline-evaluators | online-evaluators | data-only>`) → `<path>` (or "<N> drafts published to Datadog") |
| 4. Create + publish dataset | <K> records → `<dataset_path>`, published as `<dataset_name>` (v1) in project `<project_name>` |
| 5. Generate + run experiment | `<experiment_file_path>` → <experiment.url> (<N> records, <duration>s) |
| 6. Analyze experiment | <2–3 bullet headline findings from the analyzer> |

## What you learned

- The five core entities you touched: **ml_app**, **failure mode**, **evaluator**, **dataset**, **experiment**. Each has a dedicated docs page — see Datadog Documentation below.
- The loop you can now repeat: **edit dataset → re-run experiment → compare in the UI**. Pull-by-name + auto-versioning makes the loop cheap.
- The reusable artifacts you produced: an evaluator suite (Phase 3), a published dataset (Phase 4), and an experiment script (Phase 5). All three survive beyond this pipeline run.

## Recommended next steps

1. Open the experiment in the Datadog UI: <experiment.url>
2. Replace the placeholder evaluators in `<experiment_file_path>` with the ones bootstrapped in Phase 3 (swap the function refs / `RemoteEvaluator` names).
3. Re-run the experiment after every meaningful change to your task code. Datadog will keep the run history under the same project.
4. If you published draft evaluators via `--online-evaluators`, review and enable them in the UI (LLM Observability → Evaluations).

## Datadog Documentation

- LLM Observability overview: <https://docs.datadoghq.com/llm_observability/>
- Datasets: <https://docs.datadoghq.com/llm_observability/experiments/datasets_and_experiments/>
- Experiments: <https://docs.datadoghq.com/llm_observability/experiments/>
- Evaluations: <https://docs.datadoghq.com/llm_observability/evaluations/>
- Python SDK reference: <https://docs.datadoghq.com/llm_observability/instrumentation/sdk/>

提前停止处理

--stop-after <phase> 允许用户在六阶段流水线全部完成之前正常退出。有效值对应阶段编号:

值停止时机使用场景
classify第 1 阶段“我只想看看我的 ml_app 中发生了什么。”
rca第 2 阶段“我想了解故障模式——评估器我会自己编写。”
eval-bootstrap第 3 阶段与经典的 llm-obs-eval-pipeline 行为一致。 适用于“我想要评估器,而不是实验。”
dataset第 4 阶段“我想创建并发布数据集,但实验会由我自己生成/运行/分析。”
experiment第 5 阶段“生成并运行实验;结果我会自己分析。”
analyze第 6 阶段(默认)完整流水线。

当前阶段与停止值匹配时,将该阶段底部的检查点替换为停止摘要:

## Pipeline stopped — `--stop-after <phase>`

Completed phases: <list 1..stop>
Skipped: <list stop+1..6 with one-line descriptions>

Artifacts produced: <list with paths / URLs>

Re-invoke with a later `--stop-after` (or no flag for the full run) when you're ready to continue. State from completed phases is idempotent — re-running them will just re-derive the same outputs.

这样,--stop-after eval-bootstrap 就能直接替代旧版 llm-obs-eval-pipeline 的行为,同时保留编排器的教学横幅。


状态持久化与进入/退出

流水线会将每个阶段的主要输出持久化到 <output-dir>/state/,以便后续调用可以通过 --start-at <phase> 从中途恢复,而不必每次都从第 1 阶段开始。

状态文件约定

每个阶段成功完成后(即用户在检查点输入 continue 继续,或 --stop-after 匹配时,在停止摘要之前),将阶段输出写入 <output-dir>/state/0N-<name>.{md,json}。每个阶段的架构固定如下:

阶段状态文件架构
1 classifystate/01-classification.md完整的 # Session Classification Summary 块及所有按单元划分的精简块,原样取自 llm-obs-session-classify。Markdown。
2 rcastate/02-rca-report.md来自 llm-obs-trace-rca 的完整 Phase 6 RCA 报告,原样保留。Markdown。
3 eval-bootstrapstate/03-evaluators.json{"mode": "offline_evaluators|online_evaluators|data_only_dataset|data_only_analysis", "output_path": "<path>", "evaluator_names": [...], "ml_app": "<ml_app>", "generated_at": "<ISO 8601>"}。实际的评估器代码/JSON/数据集保留在子技能写入的位置。data_only_dataset 模式会生成 DatasetRecordRaw[] JSON,供 Phase 4 直接使用。
4 datasetstate/04-published-dataset.json{"dataset_file": "<path to local DatasetRecordRaw[] JSON>", "dataset_name": "<published name>", "project_name": "<name>", "version": <int>, "url": "<datadog url>", "record_count": <int>, "skipped_count": <int>, "pii_redactions": <int>, "tag_normalizations": <int>, "published_at": "<ISO 8601>"} — 合并了之前的两个状态文件(04-dataset.json 和 05-published-dataset.json),因为 Phase 4 现在会在一个步骤中创建并发布数据集。
5 experimentstate/05-experiment-run.json{"experiment_file": "<path>", "format": "py|ipynb", "dataset_name": "<name>", "task_source": "<module:function>|placeholder", "purpose": "<text>", "experiment_id": "<uuid>", "experiment_url": "<datadog url>", "records_processed": <int>, "duration_seconds": <float>, "generated_at": "<ISO 8601>", "ran_at": "<ISO 8601>"} — 合并了之前的两个状态文件(06-experiment.json 和 07-experiment-run.json),因为 Phase 5 现在会在一个步骤中生成并运行实验。如果用户在阶段内审查节点(5b)选择 edit 后暂停,则只会填入代码生成字段;使用 --start-at experiment 重新进入时,会从此处读取文件路径并从 5c 继续。
6 analyzestate/06-analysis.md来自 llm-obs-experiment-analyzer 的完整分析器报告。Markdown。

应在 Precheck 开始处(与现有的 <output-dir> 创建操作一起),通过 mkdir -p 创建 <output-dir>/state/。绝不要在此目录之外写入状态文件。

--start-at 解析

运行开始时,在 Precheck 之后,根据 --start-at 分支处理:

  1. 如果未设置 --start-at,或其值为 classify,则按正常流程进入 Phase 1。

  2. 否则,对开始阶段之前的每个阶段,加载对应的状态文件。如果传入了覆盖标志(--classification-summary、--rca-report、--dataset-file、--dataset-name、--experiment-file、--experiment-id、--experiment-url),则优先使用覆盖标志,而不是状态文件。

  3. 如果缺少必需的状态文件,且未提供覆盖标志,则立即失败,并显示清晰的提示:

    "无法执行 --start-at <phase> — Phase 的状态文件 <output-dir>/state/0(N-1)-<name>.{md,json} 不存在,且未提供 --<prior-phase>-override <path> 标志。请从更早的阶段重新运行,或显式传入覆盖标志。"

  4. 对于每个已加载的状态文件或覆盖项,在 Precheck 输出中打印一行“已加载先前状态:,来源:”,以便用户了解正在复用的内容。

  5. 直接跳到开始阶段。第一个实际运行的阶段会显示完整横幅;较早阶段则在 Precheck 中显示一行提示。

启用 --start-at 时,Precheck 输出末尾会多出一行:

- Resumed from: --start-at <phase> (loaded state for phases 1..N-1)
可在任意检查点中途退出

每个检查点都接受以下输入(不区分大小写,允许前后有空格):

用户输入行为
continue、c、go、yes、y、next,或不输入任何文本直接按 <Enter>进入下一阶段。
stop、exit、done、quit、q、cancel在此处输出停止摘要并结束运行。效果等同于从一开始就设置了 --stop-after <current-phase>。已完成阶段的状态会保存在磁盘上,因此用户稍后可以使用 --start-at <next-phase> 继续。
redo(可选地附上调整说明,例如 redo with --trace-limit 50)仅重新运行当前阶段。不要重新运行之前的阶段——它们在磁盘上的状态保持不变。应用用户附加的任何调整说明。
back(可选地附上阶段名称)回退一个阶段(或回退到指定阶段),并从那里重新运行。丢弃磁盘上受影响阶段的状态,以便重新生成。
其他任何输入将其视为调整意见或问题,并结合上下文进行判断;如果用户是在询问澄清问题,则回答并重新显示检查点提示。如果用户要求修改某个阶段,则应用修改并重新运行该阶段。

阶段模板中的“输入 'continue' 以继续”一行应更新为:

输入 continue 以继续,输入 stop 以正常退出(状态已保存——稍后可使用 --start-at <next-phase> 恢复),输入 redo 以重新运行此阶段,或告诉我需要调整的内容。

实际重新进入示例
# First-time, full run end-to-end
/llm-obs-eval-pipeline lux --project-name lux

# (user typed 'stop' at Checkpoint 4)
# Later, pick up where they left off:
/llm-obs-eval-pipeline lux --project-name lux --start-at experiment

# Already have a dataset published; want to scaffold + run an experiment around it
/llm-obs-eval-pipeline lux --project-name lux --start-at experiment --dataset-name lux_seed_v3

# Re-analyze a previous experiment without re-running it
/llm-obs-eval-pipeline lux --start-at analyze --experiment-id 8a3f9c2b-...

# Slice — just classify + RCA, leave the rest for later
/llm-obs-eval-pipeline lux --stop-after rca

# Continue from the slice above without redoing classify
/llm-obs-eval-pipeline lux --start-at eval-bootstrap --stop-after eval-bootstrap

--start-at 和 --stop-after 可以自由组合。在内部,--start-at X --stop-after Y 只运行从阶段 X 到阶段 Y(含)的阶段(如果 Y < X,则运行无效——在参数解析时直接报错)。


编排规则

  • 即使重新调用,也始终运行预检。 预检开销很小,还能在你浪费子技能调用之前发现过时的 ml_app 参数、已过期的身份验证令牌,或 --project-name 中的拼写错误。
  • 始终输出预检区块。 尽管它不是一个“阶段”,用户已经习惯将它作为第一项输出查看。
  • 阶段之间绝不自动推进。 每个检查点都必须等待用户明确输入。认可的检查点指令包括 continue / stop / redo / back,以及自由文本调整——完整表格请参见“状态持久化与进入/退出 → 在任意检查点中途退出”。
  • 显示检查点之前,先持久化阶段输出。 每个阶段都会在呈现检查点提示之前,将主要输出写入 <output-dir>/state/0N-<name>.{md,json}。这样,在任何时候输入 stop,磁盘上都会留下可供重新进入的产物——用户之后可以使用 --start-at <next-phase> 恢复,技能会加载先前状态,而无需重新运行任何内容。
  • 严格遵守 --start-at。 设置 --start-at <phase> 时,加载所有先前阶段的状态文件(或提供的覆盖标志),并在预检中为每个已加载阶段打印一行确认,然后从指定阶段开始。如果缺少必需的状态文件,且未提供覆盖标志,则立即失败——不要悄悄重新运行缺失的阶段。
  • 绝不截断子技能输出。 用户是来了解子技能作用的;如果你总结其输出,就违背了教学目的。原样完整复现。后续阶段也依赖上下文中的完整文本(阶段 2 会检测阶段 1 的分类摘要;阶段 3 会检测阶段 2 的失败分类)。
  • 阶段框架不可变。 横幅(“你现在位于阶段 N,共 6 个阶段……”)、实体区块、操作标签和检查点标题必须在每个阶段中保持完全一致。内部内容可以不同,但框架必须不变。这就是技能所承诺的确定性。
  • 仅在阶段 4 和阶段 5 执行操作。 其他阶段都不会在用户的机器上运行代码。阶段 4 运行发布脚本(将数据集写入 Datadog);阶段 5 运行生成的实验文件(针对数据集调用服务提供方 API)。其他所有阶段均为只读操作,或只会向 --output-dir 写入生成的文件。如果子技能输出建议用户自行运行某项操作,请将其交由用户处理——不要悄悄代为执行。
  • 阶段 5 必须包含阶段内审核环节。 在子步骤 5a(代码生成)和 5c(执行)之间,暂停并提示用户进行阶段内审核。等待用户输入 run、edit 或 stop。代码生成后绝不自动运行。
  • 整次运行只使用一个后端。 在启动时检测后端,并将其传递给所有子技能调用。运行过程中不要重新检测。
  • --project-name 一经选择便保持不变。 用户在预检中选择的名称会原样传递到阶段 4、阶段 5 和最终摘要。如果用户在检查点 4 更改了决定,只用新名称重新运行阶段 4——不要悄悄改写先前的输出。
  • 阶段重新进入:如果用户输入类似“用 --trace-limit 30 重新运行阶段 4”,则只重新运行该阶段(并明确说明——“正在使用新的跟踪限制重新运行阶段 4。阶段 1–3 的输出保持不变。”)。完成后,像全新运行一样继续进入阶段 5。

此 skill 不会做什么

这份列表旨在帮助审阅者发现范围蔓延:

  • 不会为你的应用埋点。 受众假设:用户已将 ml_app 跟踪数据发送到 Datadog。如果预检查发现零条跟踪数据,此 skill 会停止并引导用户查看埋点文档,不会尝试从头搭建埋点。
  • 不会推送代码或提交任何内容。 所有生成的文件都存放在 <output-dir> 中;版本控制由用户负责。
  • 未经明确的检查点或审阅确认,不会运行任何阶段的代码。 第 4 阶段会自动从创建数据集子步骤进入发布子步骤(两者之间没有可供用户编辑的环节),但第 5 阶段会在代码生成和运行之间的阶段内审阅节点暂停——用户输入 run 后才会继续。
  • 不会深入修改你的应用。 第 5 阶段的实验文件会 导入 你的任务函数,不会对它进行重构。如果你想在不编辑应用的情况下使用不同提示词 / 模型,可在生成文件的 task_fn 中内联调用。
  • 不会自动创建 .env 文件。 凭证文件只会被发现,不会被生成——磁盘上的密钥如何处理由用户决定。

工具参考

此 skill 本身几乎不会直接调用工具——直接调用仅限于:

  1. 预检查 search_llmobs_spans(用于确认 ml_app 有跟踪数据)。
  2. 第 4 阶段(运行发布脚本)和第 5 阶段(运行生成的实验)使用 Bash。
  3. 第 4 阶段的发布过程不会使用 Write——发布辅助脚本随 SKILL.md 一同存放在 scripts/publish_dataset.py;协调器通过路径和 CLI 参数调用它。此 skill 不会动态生成该脚本。

其他操作都会交由子 skill 处理,各子 skill 都有自己的 MCP-to-pup 映射:

子 skill调用时机工具参考所在位置
llm-obs-session-classify第 1 阶段dd-llmo/llm-obs-session-classify/SKILL.md(工具参考附录)
llm-obs-trace-rca第 2 阶段dd-llmo/llm-obs-trace-rca/SKILL.md(工具参考附录)
llm-obs-eval-bootstrap(offline-evaluators / online-evaluators / data-only)第 3 阶段dd-llmo/llm-obs-eval-bootstrap/SKILL.md(工具参考附录)
llm-obs-eval-bootstrap(--emit-dataset 模式)第 4 阶段(子步骤 4a)dd-llmo/llm-obs-eval-bootstrap/SKILL.md(第 3D 阶段 + 工具参考附录)
llm-obs-experiment-py-bootstrap第 5 阶段(子步骤 5a)dd-llmo/llm-obs-experiment-py-bootstrap/SKILL.md
llm-obs-experiment-analyzer第 6 阶段dd-llmo/llm-obs-experiment-analyzer/SKILL.md(工具参考附录)
预检查 search_llmobs_spans ↔ pup
MCP 工具pup 命令
search_llmobs_spans(query="@ml_app:\"<ml_app>\"", root_spans_only=true, limit=1, from="<timeframe>")pup llm-obs spans search --query "@ml_app:\"<ml_app>\"" --root-spans-only --limit 1 --from <stripped-timeframe> --summary(根据上面的 pup 调用规则,从 timeframe 中去掉 now- 前缀)。
  • MCP 结果解析安全性:在编写任何会遍历 MCP 工具结果或访问其中字段的脚本(Python、jq 等)之前,先检查原始结构——确认 type(result)、顶层键,以及负载是否嵌套在内容块中(例如 [{'type': 'text', 'text': '<json>'}])。如有需要,提取内部负载并调用 json.loads()。绝不要假设 MCP 结果是原始字典或列表。

评论

支持 Markdown