A/B 实验是产品策略迭代里常见的决策工具:一部分用户进入实验组,另一部分用户进入对照组,通过指标差异判断策略是否应该继续运行。
当实验数量只有几十个时,人工看数还能撑住;一旦实验数量变成几百、几千,人工巡检会暴露出几个明显问题:
| 问题 | 表现 | 影响 |
|---|---|---|
| 人工巡检成本高 | 专业同学每天花 4 到 6 小时逐个看实验 | 人力被大量占用,策略迭代速度变慢 |
| 判断一致性差 | 不同人对波动、反弹、衰减的理解不同 | 同一类实验可能得到不同处置 |
| 规则引擎太僵硬 | 只能写阈值、正则、简单 AND/OR | 很难理解“先跌后反弹”“正向衰减”“累计仍为正”等复杂情况 |
| 单一统计指标不够 | 只看 p-value 或单日收益 | 容易忽略 1 到 7 天小样本数据里的波动特征 |
大语言模型(Large Language Model,LLM)适合介入这种场景,但前提是:不能只把实验数据丢给模型,让它自由判断。生产环境需要的是稳定、可解释、可回归测试的输出,而不是一段看起来合理的自然语言分析。
更可靠的做法是把业务判断规则显式编码进 Prompt,让模型按固定的决策树执行,并输出机器可解析的 JSON。
1. 业务场景:为什么 A/B 实验需要自动巡检
这里讨论的是一种高频策略调优场景:
flowchart LR
A[大模型生产人群策略] --> B[策略快速上线]
B --> C[T+2 产出实验数据]
C --> D[巡检策略效果]
D -->|负向或风险高| E[下线策略]
D -->|暂不满足下线条件| F[继续观察]
F --> C
这种模式的特点是实验增长速度很快:每天新增策略可能远多于下线策略,在线策略数量持续膨胀。策略越积越多后,会影响“打包留白实验”的整体评估。
所谓打包留白实验,可以理解为把多个相同类型的策略放进一个大包里,用统一的留白组评估整体效果。
flowchart LR
S1[策略 A] --> P[策略包]
S2[策略 B] --> P
S3[策略 C] --> P
S4[策略 D] --> P
P --> E[整体实验组]
C[统一留白组] --> R[整体效果评估]
E --> R
R -->|整体指标负向| D[定位并下线负向策略]
单个策略的 DAU(日活跃用户数)变化可能只有 0.1% 到 0.5%,单看不一定明显;多个策略叠加后,累积影响就会反映在整体指标上。
问题在于:一个策略包里可能混入大量“灰色地带”策略。
常见类型包括:
- 前 1 到 2 天看起来正向,第 3 天开始持续衰减;
- 早期靠随机波动出现正向,但累计收益为负;
- 中间出现反弹,但反弹幅度不足以抵消前期损失;
- 单日波动很大,方向来回切换,难以判断真实趋势。
这些策略最难人工判断,也最适合用一套稳定的自动化规则辅助巡检。
试运行一周后,一个自动推理系统可以做到:
| 指标 | 变化 |
|---|---|
| 在线策略下线数量 | 从 300+ 降至 100+ |
| 下线准确率 | 约 68% |
| 人工巡检耗时 | 从 6 小时/天降至 30 分钟/天 |
| 打包留白关键指标 | 从每日负向波动,逐步转为稳定正向趋势 |
68% 不是终点,但已经足够说明方向可行:LLM 不直接替代业务判断,而是把大量低价值重复巡检压缩掉,让人只处理边界案例。
2. 为什么不用纯规则或纯统计方法
自动评估实验结果有几种常见做法。
| 方案 | 做法 | 优点 | 局限 |
|---|---|---|---|
| 人工巡检 | 分析师逐个看趋势、收益和置信情况 | 能结合业务上下文 | 成本高,容易疲劳,难扩展 |
| 规则引擎 | 写固定阈值,如连续负向 3 天下线 | 稳定、可控 | 规则之间容易冲突,难处理复杂趋势 |
| 统计判断 | 看 p-value、置信区间、显著性 | 理论清晰 | 小样本早期数据容易误判 |
| LLM + Prompt 决策树 | 把业务规则写进 Prompt,让模型按步骤推理 | 能兼顾规则、趋势、解释文本 | Prompt 设计不严谨会产生误判 |
LLM 的价值不在于“替代统计学”,而在于处理多因素决策:
- 同时看相对变化、绝对变化、流量比例、趋势形态;
- 理解“虽然有一天负向,但最近反弹了”这种非线性判断;
- 生成可解释的推荐理由,方便产研二次确认;
- 通过 Prompt 快速迭代规则,而不一定要重新训练模型。
不过,生产环境里的 Prompt 必须像代码一样设计。它要有输入格式、输出格式、规则优先级、异常处理和回归测试。
3. 系统整体流程
一个可落地的自动实验评估系统,可以拆成四个环节:
flowchart LR
A[实验平台] --> B[同步 1-7 天实验数据]
B --> C[数据预处理与校验]
C --> D[LLM Prompt 推理]
D --> E[JSON 结果]
E --> F[实验卡片状态更新]
F --> G[人工复核边界案例]
G --> H[Bad Case 库]
H --> I[Prompt 版本迭代]
I --> D
模型输入是一组实验日粒度数据,输出只有两个字段:
{
"isRecommendOffline": true,
"recommendation": "最近两天用户持续减少,分别损失20人和35人,损失扩大,建议停止实验"
}
这两个字段分别服务于不同对象:
| 字段 | 类型 | 用途 |
|---|---|---|
isRecommendOffline | boolean | 给系统做自动状态流转 |
recommendation | string | 给业务和研发解释判断依据 |
生产系统里,输出格式比自然语言分析更重要。只要 JSON 格式不稳定,下游 Java 服务就可能解析失败,所以 Prompt 必须强约束输出:
输出必须是有效 JSON 对象;
只允许包含 isRecommendOffline 和 recommendation 两个字段;
isRecommendOffline 必须是 boolean,不允许用 "true" 或 "false" 字符串;
recommendation 不超过 200 字;
不得输出额外解释、Markdown、换行说明。
4. 输入数据设计
一次实验评估输入 1 到 7 条日粒度记录。每条记录包含 6 个字段:
[
{
"dt": "2025-12-08",
"dauRelativeChangePct": "-0.54%",
"dauAbsoluteChange": -54,
"experimentTrafficRatio": 100000,
"controlTrafficRatio": 100000,
"isSignificant": "N"
}
]
字段含义如下:
| 字段 | 含义 | 示例 |
|---|---|---|
dt | 日期 | "2025-12-08" |
dauRelativeChangePct | 实验组相对留白组的 DAU 百分比变化 | "-0.54%" |
dauAbsoluteChange | DAU 绝对变化人数 | -54 |
experimentTrafficRatio | 实验组流量人数 | 100000 |
controlTrafficRatio | 留白组流量人数 | 100000 |
isSignificant | 统计显著性标记 | "Y" / "N" |
这里有几个关键处理点。
4.1 必须先按日期排序
模型不能默认输入数组就是有序的。生产系统里,上游数据同步、补数、重跑都可能导致日期乱序。
处理前必须按 dt 升序排序;
后续所有“最近两天”“连续三天”都基于排序后的数据。
4.2 必须校验正负号一致性
dauRelativeChangePct 和 dauAbsoluteChange 的符号应当一致:
| 相对变化 | 绝对变化 | 是否合理 |
|---|---|---|
-0.54% | -54 | 合理 |
+0.20% | 20 | 合理 |
-0.30% | 18 | 异常 |
+0.10% | -5 | 异常 |
如果不做这个检查,模型可能把正向数据理解成损失,或者把负向数据当成收益。
4.3 流量差异超过 5% 时要归一化
实验组和留白组流量可能不完全一致。如果差异过大,直接比较绝对人数会失真。
流量差异率计算方式:
flow_diff_rate = |experimentTrafficRatio - controlTrafficRatio| / controlTrafficRatio
当 flow_diff_rate > 5% 时,用千人 DAU 变化量做归一化:
normalized_dau_change = dauAbsoluteChange / (experimentTrafficRatio / 1000)
这样可以避免一个策略因为实验流量更大而看起来收益更高,也能避免流量变小导致百分比被放大。
5. 生产级 Prompt 的骨架
生产级 Prompt 不应该只写一句“请判断实验是否应该下线”。更稳的写法是把角色、目标、输入、输出、约束、流程全部写清楚。
可以按这个结构组织:
## Profile
你是资深用户增长数据分析师,负责 A/B 实验效果评估。
你需要基于 1-7 天实验数据,判断策略是否建议下线。
## Goals
1. 输出 isRecommendOffline,类型为 boolean。
2. 输出 recommendation,说明判断原因,包含具体数据。
3. 只输出 JSON,不输出额外内容。
## Input
输入是 JSON 数组,每个元素包含:
dt、dauRelativeChangePct、dauAbsoluteChange、
experimentTrafficRatio、controlTrafficRatio、isSignificant。
## Preprocess
1. 按 dt 升序排序。
2. 解析百分比为浮点数。
3. 校验相对变化和绝对变化的正负号。
4. 判断是否需要流量归一化。
5. 计算累计收益、连续负向天数、连续正向天数、最近两天趋势、波动程度。
## Decision Rules
严格按照优先级 P0 到 P6 判断。
命中某一级后立即返回,不再继续判断。
## Output
{
"isRecommendOffline": boolean,
"recommendation": string
}
这类 Prompt 的核心不是“写得像人”,而是让模型没有自由发挥空间。越接近伪代码,越容易稳定执行。
6. 六层优先级决策树
如果把所有规则平铺给模型,很容易发生冲突。比如一个实验同时满足“高波动”和“最后一天反弹”,模型可能一会儿建议下线,一会儿建议继续观察。
更稳的做法是分层,并采用短路评估:命中高优先级规则就直接返回。
flowchart TD
A[输入 1-7 天实验数据] --> B{P0 数据不足<br/>天数 < 3?}
B -->|是| H0[继续观察<br/>数据量不足]
B -->|否| C{P1 连续负向<br/>连续≥3天≤0%<br/>最后一天≤0%<br/>最近2天无正向?}
C -->|是| D1[建议下线]
C -->|否| D{P2 趋势恶化<br/>最近2天都≤0%<br/>最后一天损失更大?}
D -->|是| D2[建议下线]
D -->|否| E{P3 负向转正失败<br/>历史有负向<br/>最近2天仍有负向<br/>无连续强反弹?}
E -->|是| D3[建议下线]
E -->|否| F{全局收益检查<br/>累计收益 > 0?}
F -->|是| H1[继续观察<br/>整体仍为正]
F -->|否| G{P4 正向衰减<br/>连续正向后末日不足峰值50%?}
G -->|是| D4[建议下线]
G -->|否| I{P5 高波动无趋势<br/>波动大且累计≤0?}
I -->|是| D5[建议下线]
I -->|否| H6[P6 继续观察]
优先级的设计原则:
| 层级 | 类型 | 处理方式 |
|---|---|---|
| P0 | 数据不足 | 保守,继续观察 |
| P1-P3 | 高危信号 | 命中后直接建议下线 |
| P4-P5 | 中等风险 | 必须加排除条件,避免误杀 |
| P6 | 兜底 | 默认继续观察 |
7. P0:数据不足时不要急着下线
规则:
IF 实验天数 < 3:
RETURN false, "数据量不足,建议延长实验"
少于 3 天的数据很容易被单日噪声污染。例如某天推送触达延迟、服务异常、节假日流量变化,都可能让实验短期出现异常。
早期数据负向不一定说明策略失败,尤其是 Push、推荐、增长策略这类存在触达延迟的场景。过早下线的代价可能比多观察一天更高。
所以 P0 是最高优先级:数据不够时,不进入复杂判断。
8. P1:连续负向是最强下线信号
规则:
IF 最长连续负向天数 >= 3
AND 最后一天 <= 0%
AND 最近2天无正向:
RETURN true
它捕捉的是最明确的风险:实验组相对留白组连续下滑,并且最近没有恢复迹象。
例子:
| 日期 | DAU 变化 |
|---|---|
| 12-01 | -5 |
| 12-02 | -8 |
| 12-03 | -4 |
| 12-04 | -2 |
输出可以是:
{
"isRecommendOffline": true,
"recommendation": "连续4天用户减少,最后仍未好转,共损失19人,建议停止实验"
}
这里有一个关键细节:不能只看“曾经连续 3 天负向”,还要看最近是否已经反弹。如果前 3 天负向,但第 4 天明显转正,就不能直接下线。
9. P2:趋势恶化比稳定小亏更危险
规则:
IF 最近2天都 <= 0%
AND |最后一天损失| > |倒数第二天损失|
AND 不存在负向转正反弹:
RETURN true
这条规则识别的是“越亏越快”。
| 日期 | DAU 变化 |
|---|---|
| 12-06 | -20 |
| 12-07 | -35 |
虽然只有两天,但最后一天损失扩大,说明风险在加速。输出可以写成:
{
"isRecommendOffline": true,
"recommendation": "最近两天用户持续减少,分别损失20人和35人,损失扩大,建议停止实验"
}
这里优先使用绝对变化人数,而不是只看百分比。低频、高波动场景下,流量变化会放大百分比,真实损失人数更贴近业务代价。
10. P3:负向转正失败要和短期反弹区分开
规则:
IF 历史上出现过 <= 0%
AND 最近2天中至少1天 <= 0%
AND 不存在连续2天增长 > 0.3%
AND 全局累计收益不为正
AND 末日不是正向反弹:
RETURN true
它处理的是一种常见陷阱:策略早期负向,中间有一点反弹,但没站稳,后面又回到负向。
| 类型 | 示例 | 判断 |
|---|---|---|
| 真反弹 | -0.5% -> +0.4% -> +0.5% | 连续两天较强正向,可以继续观察 |
| 假反弹 | -0.5% -> +0.1% -> -0.2% | 反弹太弱,风险仍在 |
| 末日修复 | +0.2% -> -0.45% -> +0.28% | 需要结合累计收益和最后一天趋势,不能机械下线 |
P3 容易误判,所以必须引入全局收益和末日趋势作为排除条件。只要累计收益仍为正,或者最后一天已经明确反弹,就不应只因为中间有一天负向而下线。
11. P4:正向衰减不能误伤累计收益为正的策略
规则:
IF 连续正向天数 >= 3
AND 末日归一化收益 < 历史峰值的 50%
AND 累计绝对收益 <= 0:
RETURN true
正向衰减指策略早期收益明显,但后续增益快速下降。
例子:
| 日期 | DAU 变化 |
|---|---|
| 12-01 | +102 |
| 12-02 | +35 |
| 12-03 | +12 |
| 12-04 | +5 |
| 12-05 | -3 |
这组数据看起来在衰减,但累计仍是 +151。如果直接因为“末日收益低于峰值 50%”就下线,会误杀一个总体赚钱的策略。
所以 P4 必须加排除条件:
| 排除条件 | 含义 |
|---|---|
| 累计收益 > 0 | 整体仍然赚钱,不因短期衰减下线 |
| 连续正向且累计收益足够大 | 增长幅度下降,但业务价值仍在 |
| 最近两天正向递增 | 衰减趋势可能已经结束 |
P4 是最容易产生误判的层级,因为“衰减”本质上是趋势判断,不是单点判断。它需要比 P1、P2 更谨慎。
12. P5:高波动无趋势要排除正向波动
规则:
IF 3天窗口内波动明显
AND 最近2天方向矛盾
AND 累计收益 <= 0
AND 不存在负向转正反弹
AND 最近2天不是正向递增:
RETURN true
有些策略不是稳定亏损,而是忽正忽负:
| 日期 | 相对变化 | 绝对变化 |
|---|---|---|
| 12-01 | +0.5% | +50 |
| 12-02 | -1.2% | -120 |
| 12-03 | +0.8% | +80 |
| 12-04 | -0.3% | -30 |
这类策略的问题是不可预测。对平台稳定性来说,一个方向反复切换、累计又不赚钱的策略,风险并不低。
但 P5 也不能简单写成“波动大就下线”。需要排除几种情况:
| 场景 | 处理 |
|---|---|
| 负向后单日强反弹 | 继续观察 |
| 最近两天都正向且递增 | 继续观察 |
| 累计绝对收益 > 0 | 继续观察 |
| 最近两天趋势一致 | 交给更明确的趋势规则处理 |
P5 必须放在 P1-P3 后面。清晰负向趋势优先于高波动判断,否则规则会互相抢结果。
13. P6:兜底继续观察,但必须解释原因
规则:
DEFAULT:
RETURN false
兜底不等于只输出“继续观察”。可解释性是系统能不能长期运行的关键。
较差输出:
{
"isRecommendOffline": false,
"recommendation": "建议继续观察"
}
较好输出:
{
"isRecommendOffline": false,
"recommendation": "最近一天已反弹48人,无法确认趋势恶化,建议继续观察"
}
一个合格的 recommendation 应该包含:
| 要求 | 示例 |
|---|---|
| 有具体数据 | “分别损失20人和35人” |
| 有趋势解释 | “损失扩大” |
| 能说明为什么不下线 | “最后一天已反弹” |
| 少用专业术语 | 不在业务提示里写“标准差”“千人 DAU” |
| 可被人工快速验证 | 数字能从输入数据中直接找到 |
14. 关键指标要用伪代码定义
Prompt 里最危险的词是模糊词,比如“连续”“最近”“趋势恶化”“波动较大”。模型会尝试自己理解这些词,而生产系统需要的是固定算法。
连续负向天数应写成伪代码:
max_consecutive_negative = 0
current_consecutive = 0
for day in sorted_days_by_dt:
if day.dauRelativeChangePct <= 0:
current_consecutive += 1
max_consecutive_negative = max(
max_consecutive_negative,
current_consecutive
)
else:
current_consecutive = 0
最近两天趋势也要显式定义:
last_day = sorted_days_by_dt[-1]
second_last_day = sorted_days_by_dt[-2]
last_2_days_both_negative = (
last_day.dauRelativeChangePct <= 0
and second_last_day.dauRelativeChangePct <= 0
)
negative_to_positive_rebound = (
second_last_day.dauRelativeChangePct <= 0
and last_day.dauRelativeChangePct > 0
)
累计收益必须保留正负号:
cumulative_absolute_change = sum(
day.dauAbsoluteChange
for day in sorted_days_by_dt
)
用伪代码的好处是消除模型的“创意空间”。模型不需要猜“连续”是什么意思,只需要按定义执行。
15. 模型选择:复杂规则需要强推理和强格式遵循
这种任务对模型有三个要求:
| 能力 | 为什么重要 |
|---|---|
| 多步推理 | 要按 P0-P6 顺序判断,还要计算中间指标 |
| 指令遵循 | 不能跳过排除条件,也不能擅自改规则 |
| 输出稳定 | JSON 必须能被 Java JSON 库直接解析 |
实际可选模型包括 DeepSeek-R1-0528、Qwen3-Max 这类推理和指令遵循能力较强的模型。
理想推理过程如下:
sequenceDiagram
participant U as 调用方
participant M as 大语言模型
participant S as 下游系统
U->>M: Prompt + 实验 JSON 数据
M->>M: 按日期排序
M->>M: 校验正负号和流量差异
M->>M: 计算连续段、累计收益、最近趋势
M->>M: 按 P0-P6 短路判断
M->>M: 生成 recommendation
M-->>U: 纯 JSON 输出
U->>S: 更新实验状态
中间推理过程不输出给用户,但 Prompt 要明确要求模型在内部完成这些步骤。最终只暴露机器可解析的结果。
16. Bad Case 1:日期未排序导致趋势判断错误
输入数据简化后如下:
12-07: -67人(-0.67%)
12-08: -35人(-0.35%)
12-09: +34人(+0.34%)
12-10: +45人(+0.45%)
正确判断是继续观察,因为最近两天已经反弹,且反弹幅度在扩大。
错误输出可能变成:
{
"isRecommendOffline": true,
"recommendation": "最近两天用户持续减少,趋势恶化,建议停止实验"
}
根因通常是 Prompt 没有强制要求按 dt 排序,模型可能直接按照数组顺序或错误顺序理解“最近两天”。
修复方式是在预处理阶段加入硬约束:
在任何计算前,必须按 dt 字段升序排序;
生成内部数据验证结果;
明确列出排序后的日期序列;
后续所有连续性和最近趋势判断都基于排序后的序列。
17. Bad Case 2:连续性定义不清导致误判
输入数据:
12-07: +19人(+0.19%)
12-08: -26人(-0.26%)
12-09: -19人(-0.19%)
12-10: +19人(+0.19%)
序列是:
+ - - +
它没有连续 3 天负向,最后一天也已经反弹,所以不应该下线。
如果 Prompt 只写“连续负向则下线”,模型可能错误地把中间的两个负向和其他数值拼成连续三天。修复方法是用伪代码定义连续段,并明确遇到正向时计数清零。
如果某天 dauRelativeChangePct > 0%,current_consecutive 必须重置为 0。
连续 3 天表示排序后相邻的 3 条记录都 <= 0%。
这类定义越明确,模型越不容易自由解释。
18. Bad Case 3:只看局部负向,忽略累计收益
输入数据:
12-07: +4人(+0.04%)
12-08: +20人(+0.20%)
12-09: -45人(-0.45%)
12-10: +28人(+0.28%)
累计收益:
4 + 20 - 45 + 28 = +7
虽然第 3 天掉得比较多,但第 4 天反弹,整体仍为正。这个实验不应该因为单日下跌直接下线。
修复方式是在局部规则前加入全局收益检查:
if cumulative_absolute_change > 0:
GLOBAL_POSITIVE = True
elif cumulative_absolute_change < 0 and abs(cumulative_absolute_change) > max_single_positive * 2:
GLOBAL_NEGATIVE_SEVERE = True
else:
GLOBAL_NEUTRAL = True
然后在 P3-P5 中把 GLOBAL_POSITIVE 作为排除条件:
如果累计收益为正,不因短期波动或弱反弹失败直接下线。
如果末日为正向且相对前一天改善,也不直接下线。
这一步能修复大量“局部看起来危险、整体仍然赚钱”的误判。
19. Prompt 迭代闭环
Prompt 不能靠一次编写就稳定运行。更可靠的方式是像维护代码一样维护它。
flowchart LR
A[采集 Bad Case] --> B[RCA 根因分析]
B --> C[修改 Prompt]
C --> D[Bad Case 集回归]
D --> E[历史全量集验证]
E --> F[新数据 Hold-out 验证]
F --> G[合并新版本]
G --> A
RCA(Root Cause Analysis,根本原因分析)可以分三层:
| 层级 | 要回答的问题 | 示例 |
|---|---|---|
| Level 1 表面原因 | 系统错在哪里 | 把正向反弹判断成持续负向 |
| Level 2 直接原因 | 哪条规则或指标出错 | 连续负向天数计算不清 |
| Level 3 根本原因 | Prompt 设计缺了什么 | 没有按日期排序和伪代码定义 |
不要看到一个 Bad Case 就直接加一句补丁。补丁越多,Prompt 越容易变成互相冲突的规则堆。
20. 回归测试要分三层
Prompt 修改后至少要过三类测试:
| 测试层级 | 数据集 | 目标 |
|---|---|---|
| Bad Case 集 | 已知误判案例 | 确认目标问题被修复 |
| 历史全量集 | 已标注历史样本 | 确认整体准确率不下降 |
| Hold-out 新样本 | 未参与调 Prompt 的新数据 | 防止过拟合到旧案例 |
一次 Prompt 修改可能修好 3 个 Bad Case,同时弄错 10 个原本正确的样本。没有回归测试,就无法判断这次修改到底是优化还是退化。
可以用版本表记录演进:
| 版本 | 修改内容 | 影响范围 | Bad Case 修复数 | 准确率 | 备注 |
|---|---|---|---|---|---|
| v1.0 | 初版规则 | 全局 | 0/30 | 68% | baseline |
| v1.1 | 强化数据预处理 | 全局 | 8/30 | 72% | 修复日期和符号问题 |
| v1.2 | 增加全局收益检查 | P3-P5 | 9/30 | 77% | 修复局部误判 |
| v1.2-b | 细化衰减判断 | P4 | 5/30 | 78% | 降低误杀 |
| v1.2-c | 补充业务场景 | 全局 | 3/30 | 79% | 接近 80% 目标 |
21. Prompt 修改也要分风险等级
不是所有 Prompt 修改风险都一样。
| 修改类型 | 风险 | 影响范围 | 建议做法 |
|---|---|---|---|
| 增加排除条件 | 低 | 局部 | 快速测试后合入 |
| 调整阈值 | 中 | 中等 | 同时跑 Bad Case 集和全量集 |
| 新增优先级 | 高 | 全局 | 必须跑完整三级测试 |
| 重定义指标 | 高 | 全局 | 需要充分验证,避免大面积回归 |
例如“全局收益检查”属于指标级修改,会影响 P3-P5 多条规则。它不能只在单个案例上验证,必须确认不会让真实负向策略被错误保留。
22. 生产级 Prompt 的五个原则
22.1 显式优于隐式
不要写:
如果连续负向,建议下线。
要写:
连续负向定义:
按 dt 升序排序后,相邻记录中 dauRelativeChangePct <= 0% 的最长长度。
遇到 dauRelativeChangePct > 0% 时,计数清零。
模型越少猜测,结果越稳定。
22.2 分层优于平铺
不要把十几条规则放在一个列表里让模型自己选择。应当建立优先级和短路逻辑:
IF P0 命中,返回;
ELIF P1 命中,返回;
ELIF P2 命中,返回;
...
ELSE P6。
这样可以避免规则互相打架。
22.3 排除条件保障精准率
主规则负责召回风险,排除条件负责减少误杀。
例如 P5 的主规则是“高波动且累计不赚钱”,排除条件是“最近已经反弹、累计为正、最近两天正向递增”。
每条规则的排除条件不宜无限增加。如果某条规则需要超过 3 到 4 个排除条件,通常说明规则本身需要重构。
22.4 全局检查比局部判断更重要
局部规则只能回答“某个模式是否出现”,全局检查回答“这个策略整体是否真的该下线”。
累计收益、末日趋势、最大单日损失、最大单日收益,都是全局视角里的关键变量。
22.5 可解释性决定系统能否持续迭代
自动推理系统不是只给机器看的。业务、研发、数据分析同学都需要知道它为什么这么判断。
好的解释要包含:
触发原因 + 具体数据 + 趋势判断 + 建议动作
例如:
{
"isRecommendOffline": true,
"recommendation": "最近两天用户持续减少,分别损失20人和35人,损失扩大,建议停止实验"
}
这类输出可以直接被人工复核,也方便后续归因 Bad Case。
23. 哪些任务适合用这种方式
LLM + Prompt 决策树适合“规则明确但组合复杂”的场景。
| 适合 | 不适合 |
|---|---|
| 输入输出结构化 | 输入高度非结构化且无稳定字段 |
| 有明确业务规则 | 规则本身还没形成共识 |
| 需要可解释建议 | 只追求极致实时性能 |
| 规则经常迭代 | 规则多年不变,用代码更简单 |
| 人工判断成本高 | 样本量很小,不值得工程化 |
A/B 实验评估之所以适合,是因为它满足几个条件:
- 输入是标准 JSON;
- 输出是固定 JSON;
- 规则复杂但可以显式定义;
- Bad Case 能被收集和标注;
- 自动结果只作为建议,边界案例仍可人工复核。
类似思路也可以迁移到内容审核、风控初筛、推荐候选过滤、工单分流等场景。
24. 落地时的注意事项
不要让显著性字段主导决策
isSignificant 可以作为参考,但不能作为主要判断依据。1 到 7 天的小样本实验里,统计显著性经常不稳定。业务上更需要结合趋势、绝对人数、累计收益和流量差异一起判断。
recommendation 不要写太专业
技术系统内部可以计算千人 DAU、标准差、归一化收益,但给业务侧的解释最好写成:
最近两天分别减少20人和35人,损失扩大。
不要写成:
3日滑窗标准差超过15%,千人DAU末日低于峰值50%。
前者能直接辅助决策,后者会增加理解成本。
JSON 格式要强约束
Prompt 中必须反复强调:
只输出 JSON;
不要输出 Markdown;
不要输出解释段落;
boolean 不允许写成字符串;
字段名固定;
不能多字段。
下游解析失败会让自动化流程中断,这是工程问题,不是模型问题。
Bad Case 要沉淀成库
Bad Case 不只是失败样本,它是后续准确率提升的主要来源。每个案例至少记录:
{
"badcase_id": "BC-001",
"input": [],
"system_output": {},
"human_judgment": false,
"category": "date_sorting_error",
"root_cause": "日期排序缺失",
"fix_applied": "v1.1",
"resolved": true
}
长期看,这个库会变成领域知识资产。
25. 一个可复用的最终 Prompt 模板
可以把完整 Prompt 压缩成一个工程模板:
## Role
你是用户增长数据分析师,负责 A/B 实验结果评估。
## Task
根据 1-7 天实验数据判断是否建议下线实验。
输出字段:
- isRecommendOffline: boolean
- recommendation: string
## Input Schema
[
{
"dt": "YYYY-MM-DD",
"dauRelativeChangePct": "-0.54%",
"dauAbsoluteChange": -54,
"experimentTrafficRatio": 100000,
"controlTrafficRatio": 100000,
"isSignificant": "Y|N"
}
]
## Preprocess
1. 按 dt 升序排序。
2. 解析 dauRelativeChangePct 为数字。
3. 校验 dauRelativeChangePct 与 dauAbsoluteChange 正负号一致。
4. 计算 flow_diff_rate。
5. 若 flow_diff_rate > 5%,计算 normalized_dau_change。
6. 计算:
- 累计绝对收益
- 最长连续负向天数
- 最长连续正向天数
- 最近2天趋势
- 是否负向转正
- 是否正向衰减
- 是否高波动
## Decision
按顺序执行:
P0: 天数 < 3 -> false
P1: 连续≥3天负向,且最后一天仍负向,且最近2天无正向 -> true
P2: 最近2天都负向,且最后一天损失更大 -> true
P3: 历史有负向,最近2天仍有负向,无连续强反弹,且累计收益不为正 -> true
Global: 累计收益 > 0 -> false
P4: 连续正向后明显衰减,且累计收益不为正 -> true
P5: 高波动、方向矛盾、累计不赚钱,且无正向排除条件 -> true
P6: 其他情况 -> false
## Recommendation Rules
- 下线:写清触发原因和具体人数。
- 不下线:写清为什么不满足下线条件。
- 不使用专业术语。
- 不超过 200 字。
## Output
只输出 JSON:
{"isRecommendOffline": boolean, "recommendation": string}
A/B 实验自动评估的关键,不是让模型“更聪明”,而是把人的判断逻辑拆成明确、可执行、可测试的规则。Prompt 在这里更像一份可读的决策程序:它把数据分析经验、业务约束和工程输出格式放进同一个结构里。
当规则有优先级,指标有伪代码,输出可解析,Bad Case 可回归,LLM 才能从一次性问答工具变成生产系统里的稳定推理组件。