关于 diagnosing-experiment-health
用于诊断 PostHog 实验结果异常的技能,涵盖偏差、数据为空等情况。它指导 Agent 定位实验、检查配置与数据,并依据症状查阅对应诊断资料。
主要功能
- 01将实验名称解析为 ID
- 02检查实验配置与诊断快照
- 03按症状匹配诊断类别
- 04区分已验证结论与假设
适用场景
- 01调查变体曝光比例不均
- 02排查实验结果缺失或为空
- 03分析显著性变化与指标差异
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ posthog/ ai-plugin --skill diagnosing-experiment-health安装后在 Claude Code 中输入/diagnosing-experiment-health确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/bias-and-skew.mddiagnostic-snapshot.mdempty-experiment.mdinterpretation.mdmid-run-changes.mdnumbers-vs-sql.mdqualitative-feedback.md详细介绍
诊断实验健康状况
此技能解答:我的 PostHog 实验结果看起来不对、有偏差或为空——这是怎么回事? 它用于诊断和检查单个实验的健康状况:包括实验设置、曝光、结果,以及实验运行期间发生的变化。
在分派表中找到与用户问题相符的条目,然后阅读对应的参考文件以进行诊断。
参考文件中的每项诊断都会标记为 [HIGH]、[MEDIUM] 或 [LOW],表示其验证程度:[HIGH] 表示已直接通过 PostHog 代码验证,[MEDIUM] 表示已部分验证或通过团队来源验证,[LOW] 表示描述的是此处未经验证的 SDK/外部行为。将 [LOW] 项视为需要测试的假设,而不是可以直接断言的事实。
步骤 1 — 确认实验
如果用户通过名称或描述提及某个实验,请先加载 finding-experiments 技能,将其解析为具体 ID。
调用 experiment-get 并提取以下字段。它们几乎是所有诊断的输入:
status(draft/running/paused/exposure_frozen/stopped)、start_date、end_date、is_legacyfeature_flag.active和feature_flag.filters.multivariate.variants[]— 变体键和拆分比例(rollout_percentage)。 这是标志当前的状态。发布或编辑后,本次运行的拆分比例会记录在变更历史中(步骤 1.5)。feature_flag.filters.aggregation_group_type_index— 如果已设置,实验单位是群组,而不是个人feature_flag.filters.groups[]— 对每个群组,读取variant、properties和rollout_percentage(该群组的发布比例,即符合条件并进入实验的分桶单位——个人,或当标志或群组按群组类型聚合时的群组——所占的百分比;每个群组都有自己的发布比例,因此除非标志只有一个无条件群组,否则不存在单一的总体发布比例)。非空的variant若属于标志的某个变体键,则表示对符合条件的队列强制覆盖变体(按发布条件分配,而非随机分配)——对应问题 A7。留意严重情形(A7b):绑定了变体的群组具有宽泛或空的properties,且发布比例很高;或者没有任何群组仍进行随机分配(variant: null),也没有通往某一臂的发布路径——这会导致另一变体样本不足(其中一臂的可分析曝光量约为 0)。参见references/bias-and-skew.md。feature_flag.bucketing_identifier和feature_flag.ensure_experience_continuity— 标志用于哈希的内容(A3、A6、A8、A10)holdout和excluded_variants— 有意排除在分析之外的人员和实验臂exposure_criteria.multiple_variant_handling— 若缺失,默认为"exclude"exposure_criteria.exposure_config— 曝光事件及其属性筛选条件。 若未设置,或指定了$feature_flag_called,则使用默认曝光事件:从resolved_exposure_event中读取具体事件。 若其为$feature_flag_called,还要读取$experiment_exposure(event IN ('$feature_flag_called', '$experiment_exposure')),并统计人数,而不是事件行数。 若配置指定$experiment_exposure,则统计该事件,无论resolved_exposure_event的值是什么。 任何其他事件或操作都属于_自定义曝光事件_。 配置中的属性筛选条件适用于上述任一情况(B12)。references/diagnostic-snapshot.md中的表格说明了哪个属性携带变体信息。exposure_criteria.activation_config— 在默认曝光之外的激活事件或操作。 设置后,只有在某人首次标志曝光时或之后发生的首次激活事件,才会将其计为已曝光;该事件的时间即为曝光时间。 它不能与自定义曝光事件同时使用。exposure_criteria.filterTestAccounts— 默认为truemetrics和metrics_secondary,以及共享指标 — 对每项指标,读取其名称、类型和定义。 根据指标定义描述指标,而不是根据其名称(D13)。stats_config—method(Bayesian 或 Frequentist)、置信水平(bayesian.ci_level、frequentist.alpha)、frequentist.sequential_testing_enabled、cuped、baseline_variant_key。 若缺少method,则按 Bayesian 处理;若缺少置信水平,则默认为 95%。序贯检验和 CUPED 使用项目默认值(C13)。running_time_calculation— 目标样本量(所有变体的总量)、达到该目标还需的天数,以及最小可检测效应。 如果估算值来自用户输入的数字,或是在创建时写入且页面从未刷新过,那么天数就是估算的总时长(C12)。 复制的实验在页面刷新数据之前,会沿用来源实验的数值。only_count_matured_users— E11
步骤 1.5 — 获取诊断快照(先验证,再提问)
在向用户提出澄清问题之前,先获取 references/diagnostic-snapshot.md 中的诊断快照。本技能中的大多数诊断 都可以通过这些数据确认或排除,无需访谈。
每次诊断时,都先读取成本低的数据源:先查看已存储的结果,再查看变更历史。 当用户报告了意料之外的变化时,先查看变更历史,再查看已存储的结果。 然后,在诊断需要获取只有曝光数据才能提供的信息时,再查看曝光数据。 仅当这些数据无法说明情况时,才查询原始事件。
步骤 2 — 将症状与诊断相匹配
| 用户说…… | 诊断类别 |
|---|---|
| “较小的变体看起来有偏差”/横幅提示有偏差 | A — 偏差与倾斜 |
| “变体比例与我的分流不符”/不匹配警告/“58/42 正常吗?” | A — 偏差与倾斜 |
| “为什么不是 50/50?”/“每天都有一个变体分到更少的用户” | A — 偏差与倾斜 |
“用户同时出现在对照组和测试组中”/$multiple 占比高 | A — 偏差与倾斜 |
| “我们的自有分析显示分流均匀,但 PostHog 却不是” | A — 偏差与倾斜 |
| “标记的响应大多为 false”/“用户看到新界面一秒钟,然后就消失了” | A — 偏差与倾斜 |
| 服务端渲染应用中的多变体曝光 | A — 偏差与倾斜 |
| 关于功能标记/实验状态不匹配的横幅 | A — 偏差与倾斜 |
| “正在迁移 distinct_id”/运行中从匿名 ID 切换到 user_id | A — 偏差与倾斜 |
| 指标计数远小于曝光量(例如相差 10× 或 100×) | A — 偏差与倾斜(先转到这里,再看 D) |
| “实验显示为 0/数据不足”/为空 | B — 空实验 |
| “变体始终为 undefined/false” | B — 空实验 |
“$feature_flag_called 已触发,但没有曝光记录” | B — 空实验 |
| “添加筛选条件后,曝光量降为零”/“复制的实验为空” | B — 空实验 |
| “曝光量充足,但转化量为零” | B — 空实验(然后看 D11) |
| “实验显示正在运行,但曝光量数周/数月都没有变化” | B — 空实验 |
| “实验运行时间越长,显著性结果越反复” | C — 解读误区 |
| “之前判定为显著,后来又变得不显著了” | C — 解读误区 |
| “实验才运行一天,可以看结果吗?” | C — 解读误区 |
| “46 次曝光中分流比例为 30/16,这是出问题了吗?” | C — 解读误区 |
| “显示已完成/已达到目标,但没有任何指标显著” | C — 解读误区 |
| “A/A 测试显示结果显著” | C — 解读误区 |
| “指标很多——有些显著,有些不显著” | C — 解读误区 |
| “测试变体表现更差,设置正确吗?”/“能帮我检查这个实验吗?” | 第 3 步——先做两项检查,然后看 C 和 D12 |
| “贝叶斯分析显示获胜概率为 96%——我们该发布吗?” | C — 解读误区 |
| “置信区间有重叠——这是否意味着不显著?” | C — 解读误区 |
| “p 值恰好为 1”/“对照组显示有提升” | C — 解读误区 |
| “外部工具(显著性计算器或 AI Agent)的结果与 PostHog 不一致” | C — 解读误区 |
| “该发布吗?主要指标上升了,但次要指标下降了” | C — 解读误区 |
| “PostHog 数字 ≠ 我的 SQL 计数” | D — 数字与 SQL 不一致 |
| “漏斗显示 X%,但原始事件计数显示 Y” | D — 数字与 SQL 不一致 |
| “实验结果显示持平,但我们的仪表板显示下降了” | D — 数字与 SQL 不一致 |
| “收入总和不对”/“细分结果显示 ‘none’” | D — 数字与 SQL 不一致 |
| “指标名称表达的意思和数字不一致” | D — 数字与 SQL 不一致 |
| “录屏与统计数据不符”/“没有已曝光用户的录屏” | D — 数字与 SQL 不一致 |
| “我应用了筛选条件,但用户数没有变化” | D — 数字与 SQL 不一致 |
| “我想按当前用户属性(此时的属性,而非曝光时的属性)细分结果” | D — 数字与 SQL 不一致 |
| “结果没有更新”/“刷新后没有变化” | D — 数字与 SQL 不一致 |
| “运行中更改了分流/发布比例/指标/条件,现在结果很奇怪” | E — 运行中更改 |
| “数字一夜之间变了,但没人动过它” | E — 运行中更改,然后看 D 中的 D8 |
| “我们暂停了几天,现在还能相信结果吗?” | E — 运行中更改 |
| “冻结了实验”/“冻结后用户失去了该变体”/“冻结请求被拒绝” | E — 运行中更改 |
| “实验已结束/已发布——标记现在意外地变成了 0/100” | E — 运行中更改 |
| “我们发布了该变体,但有些用户仍然看不到” | E — 运行中更改 |
| “长期指标的变化方向与主要指标相反” | E — 运行中更改 |
| “留存指标统计了我意料之外的用户” | E — 运行中更改 |
| “实验结束后,无法将功能标记恢复为简单的(布尔值)标记” | E — 运行中更改 |
| “如何使用新变体重新启动实验?” | E — 运行中更改 |
| “显示这是一个旧版实验”/无法编辑指标 | E — 运行中更改(E13 旧版实验) |
“结果无法加载”/许多指标行显示 data: null(并非旧版实验) | 第 1.5 步——诊断快照(空值行) |
| “用户如何看待新的流程?”/想了解实验的定性反馈 | F — 定性反馈 |
| “用户为什么更喜欢对照组?”/“他们不喜欢测试变体的什么地方?” | F — 定性反馈 |
| 如果症状不明确,请先提出一个澄清问题,再选择诊断。大多数诊断的修复方式各不相同 | |
| ——不要猜测。 | |
| 如果某个问题符合多个组中的条目,请逐一阅读这些组(步骤 3)。 |
如果报告来自侦察工具或其他自动化检查,它会指出发现的问题:根据该发现确定路径,并在重新获取数据前沿用报告中的数字。
步骤 3 — 列出证据支持的所有诊断
在步骤 2 中匹配症状并阅读相关参考文件后,请先列出所有适用的诊断,再建议采取行动。
分别列出同时出现的机制——即使其中一种更显著,也不要将它们合并成单一的“等待”或“修复”建议。不同机制有不同的修复方式:_系统性_偏差(例如,不均匀分流 + Exclude)不会因等待而消除;_统计性_模式(例如,小样本方差)则会。将它们合并给出建议,会导致用户照做后偏差仍然存在。
只列出在项目状态中有验证途径的机制——配置(来自 experiment-get)、快照数据、活动日志,或仓库源码(当 Agent 拥有该仓库时)。配置衍生的机制也要计入:80/20 分流且默认 multiple_variant_handling="exclude",可在 experiment-get 中查看,因此可以列出。没有来源的机制不要列出(例如,快照显示变体比例正常时却指出 SRM)。
无论问题是什么,每项诊断都必须包含以下两项检查:
- 实验开始多久了? 在解读结果前,说明实验已运行时长(
start_date)以及当前样本占目标样本的比例(已曝光总人数与running_time_calculation.recommended_sample_size的对比)(参见references/interpretation.md中的 C1)。 页面使用的已曝光总人数取自第一个主要指标:存储结果中所有变体的number_of_samples之和,而不是exposures.total_exposures。recommended_sample_size是页面上次计算估算值时保存的目标样本量。 如果没有该值,表示未保存目标样本量:请明确说明。 - 哪些人获得了曝光? 在称设置合理之前,请将已曝光人群(
exposure_criteria和标志的发布条件)与决策所涉及的人群进行比较(参见references/numbers-vs-sql.md中的 D12)。 默认曝光设置并不能证明实验覆盖了正确的人群。 如果没有信息说明决策针对哪些人,请提出询问。
诊断组
A — 偏差与倾斜
变体看起来不均衡、某个变体似乎存在偏差、应用内警告横幅出现,或用户出现在多个变体中。涵盖不均匀分流与 Exclude 的交互、样本比例不匹配及其成因、实验组之间曝光事件丢失或发送不均、标志对部分受众不返回任何变体、身份碎片化、bootstrap 与 /flags 不匹配、实验中途编辑标志、强制指定变体,以及标志/实验状态不一致。
→ 参见 references/bias-and-skew.md
B — 实验为空 / 曝光数为 0 /“数据不足”
这是常见的痛点。涵盖 SDK 调用(评估方法错误、identify() 时机、去重)、曝光捕获(自定义事件缺少变体属性、必需属性、广告拦截器),以及曝光条件匹配(测试账户筛选器、无法匹配的筛选器、资格判定顺序、曝光前触发的事件)。
→ 参见 references/empty-experiment.md
C — 显著性与结果解读陷阱
显著性反复变化、A/A 测试显示显著性、贝叶斯与频率学派混淆、多重比较、低流量方差、窥视数据 / 提前停止。包括运行时长估算(“已达到目标”不代表结果已出炉),以及会改变结果解读方式的统计设置:序贯检验、CUPED、置信水平和基线变体。
→ 参见 references/interpretation.md
D — 数字对不上(PostHog 与用户的 SQL / 原始计数)
实验页面会应用曝光范围、$multiple 排除、测试账户筛选条件和日期范围,而临时编写的 SQL 几乎从不会复现这些条件。还涉及漏斗归因(统计时只计算第一步 → 最后一步)、细分(从曝光事件而非指标事件读取)、“收入总和”的人均值混淆、过时的存储结果、与统计数据不一致的 Recordings 标签页、统计的人群范围比实验更窄的洞察,以及标题与定义不符的指标。
→ 查看 references/numbers-vs-sql.md
E — 运行期间变更后的意外情况(包括生命周期和留存方面的问题)
提高发布比例是安全的;降低时要谨慎;更改变体分配比例属于反模式;运行期间添加指标属于 p-hacking;ship-variant 会重写标志,而仅仅结束实验不会;重置会清除结果,但不会清除标志(移除曝光冻结除外);暂停、冻结和解除冻结都可能使结果产生偏差;更改开始日期会移动整个分析范围。还涵盖留存指标的特殊情况、“成熟用户”筛选,以及长期与短期指标的差异。
→ 查看 references/mid-run-changes.md
F — 定性反馈:变更带来的感受,而非数字变化幅度
A–E 组用于找出作用机制。F 则用于回答它们无法解决的问题:实验中的人如何看待这项变更。在用户完成实验流程时展示一份简短问卷,即可补充定性反馈——用户可以评分并选填评论,还能按变体查看;目前可通过 MCP 使用。
它适用于部分实验,不适用于其他实验。判断标准是:如果不同时展示两个版本,用户能否描述这项变更?重新设计的流程、布局或过程适用;阈值或排名调整则不适用,无论其测得的影响有多大。机械性诊断问题尚未解决时,不要提供问卷——标志门控故障时附加问卷,收集到的只是关于某项功能的意见,而一半受众根本没有体验到该功能——并且在提出新问卷之前,应检查现有或近期的问卷是否已涵盖该时间范围。
创建问卷前要处理好两件事:只向单个变体展示的问卷本身就会造成变体之间的差异;与标志关联的 运行中 问卷可能会生成曝光事件。
→ 查看 references/qualitative-feedback.md
第 4 步 — 根据实验状态校准建议
先呈现诊断结果(第 3 步)。然后再提出建议,但建议的范围应符合实验当前状态所允许的范围。
- 草稿 — 配置更改不受限制;可以提出建议并应用更改。
草稿标记仍可能为用户提供服务:通过重置创建的草稿,或基于现有标记创建的草稿,其
feature_flag.active可以为 true;编辑该标记会立即影响这些用户。 - 运行中(以及已启动但尚未结束的
paused或exposure_frozen)——每项更改都有取舍。提出建议前,先说明对运行中实验的影响(反模式?安全吗? 用户能看到吗?)。关于运行中实验的规则,请参阅configuring-experiment-rollout及其参考文件references/changing-distribution-after-launch.md。 暂停、冻结、解除冻结和重置也都是更改:每项都会中断运行,并可能导致结果偏差(参见references/mid-run-changes.md中的 E8、E9 和 E16)。 - 已停止 / 已归档 — 实验和其实验标记共同代表本次运行的记录结果。建议仅限于:(a) 解读现有数据;(b) 为 下一次 实验采取行动;或 (c) 解释发生了什么。
诊断应以发现和建议收尾。 对运行中的实验或其标记进行更改(新增指标、新增曝光条件、重置、重新启动、编辑标记),由用户决定:说明更改对迄今收集的数据有何影响,并且只有在用户明确指示时才执行。
对于已停止或已归档的实验,不要主动提出撤销状态变更(将 ship-variant 标记改写、手动编辑标记、重置、归档)。如果用户问“为什么发生了 X?”,就解释 X——不要附加“以下是撤销方法”。这种做法会假定用户有未表达的意图。像 “如果这不是你的本意,可以……” 或 “要我帮你撤销吗?” 这样的条件式提议也属于主动提出;只有用户明确提到撤销操作(“如何撤销?”、“可以回滚 ship-variant 吗?”、“怎样才能恢复 50/50 分流?”)时,才应说明撤销方法。
术语保持一致:变体之间的 分流(split)不同于 推出比例(rollout,即进入某个发布条件的受众占比);默认曝光事件(resolved_exposure_event)不同于_自定义曝光事件_;多变体处理(exposure_criteria.multiple_variant_handling)中的 从分析中排除 / 使用首次看到的变体 选项,决定的是如何统计接触过多个变体的人,而不是哪个事件算作曝光。
相关技能
configuring-experiment-analytics— 修正诊断指出的曝光或指标配置configuring-experiment-rollout— 分流更改的反模式和安全的推出调整managing-experiment-lifecycle— 当实验无法在原位挽救时,重置、结束或重启实验analyzing-experiment-session-replays— 当数据看起来正常,但你需要了解数据背后的行为时debugging-experiments— 当问题是关于他人实验的支持请求,且需要以书面回复时