关于 llm-obs-eval-pipeline
用于引导已接入 Datadog 的 LLM 应用完成链路分类、根因分析、评估器配置、数据集与实验创建及分析的编排 Skill。它通过检查点协调专用子 Skill,并支持从指定阶段开始或结束。
主要功能
- 01六阶段评估工作流
- 02链路分类与根因分析
- 03评估器、数据集和实验配置
- 04阶段检查点与状态保存
- 05自定义起止阶段
适用场景
- 01分类已接入应用的近期链路
- 02构建评估数据集和实验
- 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/.gitignoreload_env.pypublish_dataset.py详细介绍
后端
检测 — 每次调用开始时,在采取任何操作之前,确定要使用的后端:
- 如果用户在调用参数中的任何位置传入了
--backend pup→ 立即使用 pup 模式,无论是否存在 MCP 工具。跳过步骤 2–4。 - 检查当前工具列表中是否存在 MCP 工具。标准判断依据是可用工具中是否出现
mcp__datadog-llmo-mcp__search_llmobs_spans。 - 如果存在 MCP 工具 → 全程使用 MCP 模式。严格按照子技能工作流部分中列出的名称调用 MCP 工具。
- 如果不存在 MCP 工具 → 检查
pup是否可执行:通过 Bash 运行pup --version。包含"version"的 JSON 响应表示 pup 可用。 - 如果 pup 有响应 → 全程使用 pup 模式。每项子技能都附有自己的工具参考附录,其中包含完整的 MCP→pup 映射。
- 如果两者都不可用 → 停止并告知用户:
“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-7d | Phase 1 分类和 Phase 4 数据集采样的回溯时间窗口。 |
--trace-limit | 否 | 20 | Phase 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。
-
后端——已在此技能的开头检测到。在预检查输出中注明所选后端,供用户确认。
-
ml_app有近期追踪——调用search_llmobs_spans(query="@ml_app:\"<ml_app>\"", root_spans_only=true, limit=1, from="<timeframe>")(MCP)或对应的 pup 命令。如果结果为空,则停止并告知用户预检查失败——没有可供评估的数据——并建议扩大--timeframe范围或确认ml_app名称。 -
解析
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 之前进行修改(如果该名称不符合预期)。 -
确保
--output-dir和<output-dir>/state/存在——通过 Bash 执行mkdir -p <output-dir>/state。开销很小。state/子目录用于持久化各阶段的输出(见下文“状态持久化和阶段进入/退出”)。 -
**解析凭据。**按照下方的发现顺序查找 Datadog 凭据,确保在 Phase 4 需要时已找到——到发布步骤才发现凭据缺失会带来糟糕的用户体验。此阶段只读:不要写入任何新文件。不要向用户打印机密值;只报告加载了哪个文件以及解析出了哪些键。
发现顺序(每个变量以首次命中为准;shell 环境变量始终优先于文件):
- 如果提供了
--env-file <path>,优先使用该文件——始终首先尝试。 - 当前 shell 环境(
os.environ)——已导出的DD_API_KEY/DD_APPLICATION_KEY/DD_APP_KEY/DD_SITE优先于文件中的值。如果所有必需的键都已存在,则跳过文件加载。 <output-dir>/.env——如果用户之前运行过此技能,并在之前生成的文件旁放置了.env,则优先使用该文件。<app-root>/.env——已解析的pyproject.toml/setup.cfg/setup.py/package.json所在目录(如果都没有,则为 cwd)。<app-root>/.env.local——通常被 Git 忽略的本地覆盖文件。<cwd>/.env——如果 cwd 与 app-root 不同,则作为回退选项。- 向上遍历父目录:从 cwd 开始,逐级向上查找
.env,直到到达/或用户的 home 目录。找到第一个匹配项后停止。 ~/.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 构建规则:
- 主机:在
DD_SITE前加上app.。如果未设置DD_SITE,则默认为app.datadoghq.com。datadoghq.com→app.datadoghq.comdatadoghq.eu→app.datadoghq.euus3.datadoghq.com→app.us3.datadoghq.comus5.datadoghq.com→app.us5.datadoghq.comap1.datadoghq.com→app.ap1.datadoghq.comap2.datadoghq.com→app.ap2.datadoghq.comdatad0g.com→app.datad0g.com(暂存环境)
- 路径:
/llm/traces(LLM Observability Traces 探索器)。 - 查询字符串:对
@ml_app:"<ml_app>" @status:ok @parent_id:undefined进行 URL 编码,并绑定到query=。 - 时间窗口:将
--timeframe转换为绝对纪元毫秒数(开始时间为now - <duration in ms>,结束时间为now),并绑定到start=/end=。 - 可选:追加
&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_apptimeframe= 提供的 timeframesample_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”路径。
运行模式解析
调用子技能之前,先解析运行模式:
-
--offline-evaluators(默认)→ 不带模式标志调用llm-obs-eval-bootstrap(其sdk_code为默认值)。 -
--online-evaluators→ 调用llm-obs-eval-bootstrap --publish。 -
--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 classify | state/01-classification.md | 完整的 # Session Classification Summary 块及所有按单元划分的精简块,原样取自 llm-obs-session-classify。Markdown。 |
| 2 rca | state/02-rca-report.md | 来自 llm-obs-trace-rca 的完整 Phase 6 RCA 报告,原样保留。Markdown。 |
| 3 eval-bootstrap | state/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 dataset | state/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 experiment | state/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 analyze | state/06-analysis.md | 来自 llm-obs-experiment-analyzer 的完整分析器报告。Markdown。 |
应在 Precheck 开始处(与现有的 <output-dir> 创建操作一起),通过 mkdir -p 创建 <output-dir>/state/。绝不要在此目录之外写入状态文件。
--start-at 解析
运行开始时,在 Precheck 之后,根据 --start-at 分支处理:
-
如果未设置
--start-at,或其值为classify,则按正常流程进入 Phase 1。 -
否则,对开始阶段之前的每个阶段,加载对应的状态文件。如果传入了覆盖标志(
--classification-summary、--rca-report、--dataset-file、--dataset-name、--experiment-file、--experiment-id、--experiment-url),则优先使用覆盖标志,而不是状态文件。 -
如果缺少必需的状态文件,且未提供覆盖标志,则立即失败,并显示清晰的提示:
"无法执行
--start-at <phase>— Phase 的状态文件<output-dir>/state/0(N-1)-<name>.{md,json}不存在,且未提供--<prior-phase>-override <path>标志。请从更早的阶段重新运行,或显式传入覆盖标志。" -
对于每个已加载的状态文件或覆盖项,在 Precheck 输出中打印一行“已加载先前状态:,来源:”,以便用户了解正在复用的内容。
-
直接跳到开始阶段。第一个实际运行的阶段会显示完整横幅;较早阶段则在 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 本身几乎不会直接调用工具——直接调用仅限于:
- 预检查
search_llmobs_spans(用于确认 ml_app 有跟踪数据)。 - 第 4 阶段(运行发布脚本)和第 5 阶段(运行生成的实验)使用
Bash。 - 第 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 结果是原始字典或列表。