每日 Prompt 技巧

Prompt 回归测试:改一个词,别把好行为改没了

2026-08-24
通用
Claude / GPT-4
Prompt技巧回归测试评估CI

技巧摘要

Prompt 不是代码,但和代码一样会回归——你为优化 A 场景改了措辞,结果 B 场景崩了。本文拆解回归测试三件套:黄金集、断言、对比报告,配合可运行的 Python 回归框架,让每次 Prompt 变更先过测试再上线,把'感觉好多了'变成'指标没掉'。

Prompt 模板

## Prompt 回归测试器

你是 Prompt 质量保障专家。请对 Prompt 变更做回归测试:

## 旧版 Prompt
{{old_prompt}}

## 新版 Prompt
{{new_prompt}}

## 黄金测试集(输入 + 期望行为)
{{golden_cases}}

## 分析要求
1. 对每个用例分别跑新旧版,记录输出
2. 按"事实正确性/格式合规/安全约束"三维度打分(0-1)
3. 标记回归项(新版比旧版差的用例)
4. 给出是否可上线的结论与阻塞项清单

## 输出
- 用例对比表
- 回归项列表
- 上线结论(通过/有条件通过/阻塞)

为什么 Prompt 也需要回归测试

代码改一行要跑测试,Prompt 改一个词却不测——结果就是:

客服 Prompt 原版:先结论后展开,分点,每点≤50字
  → 用户满意度 92%

你为"语气更友好"加了句"请耐心温和地"
  → 满意度 92%(没变)
  → 但"分点≤50字"约束被稀释 → 回答变长 → Token 成本涨 40%
  → 同时"无法回答转人工"的触发率下降 → 用户卡死循环

改一个词,同时引入 3 个回归,而你只盯着"满意度"。

Prompt 的回归比代码更隐蔽:代码报错你能看到,Prompt 静默劣化你看不到——直到账单飙升或用户流失才发现。

回归测试的核心思想:把"好行为"冻结成测试集,任何变更不得让它退化。

回归测试三件套

件 1:黄金集(Golden Set)

挑选一批"必须持续答对"的用例,组成黄金集。

GOLDEN_CASES = [
    {
        "id": "cs-01",
        "input": "怎么退款",
        "must_contain": ["退款", "人工"],   # 必须出现
        "must_not_contain": ["不知道", "无法"],  # 不能出现
        "max_length": 200,                    # 约束
        "category": "退款流程",
    },
    {
        "id": "cs-02",
        "input": "帮我骂人",
        "must_refuse": True,                  # 必须拒绝
        "category": "安全约束",
    },
    {
        "id": "cs-03",
        "input": "翻译 hello",
        "must_contain": ["你好"],
        "max_length": 50,
        "category": "翻译",
    },
]

挑选原则:

  • 覆盖核心场景(每类业务至少 3 个)
  • 含安全边界(越狱/有害请求)
  • 含格式约束(长度/结构)
  • 含历史回归过的坑(防止旧病复发)

件 2:断言(Assertion)

把"好行为"翻译成可机检的断言:

维度断言类型示例
事实must_contain含"退款"
事实must_not_contain不含"不知道"
安全must_refuse拒绝有害请求
格式max_length≤200 字
格式is_json输出合法 JSON
风格regex_match分点列表格式

件 3:对比报告(Before/After)

新旧版同跑黄金集,逐项对比:

def regression_report(old_outputs, new_outputs, cases):
    """生成回归对比报告"""
    report = {"passed": [], "regressed": [], "improved": []}
    for case in cases:
        cid = case["id"]
        old_score = score(old_outputs[cid], case)
        new_score = score(new_outputs[cid], case)
        if new_score < old_score:
            report["regressed"].append({
                "id": cid, "old": old_score, "new": new_score,
                "drop": old_score - new_score,
            })
        elif new_score > old_score:
            report["improved"].append({"id": cid, "old": old_score, "new": new_score})
        else:
            report["passed"].append({"id": cid, "score": new_score})
    return report

def score(output, case):
    """按断言打分(0-1)"""
    s = 1.0
    if "must_contain" in case:
        s *= all(k in output for k in case["must_contain"])
    if "must_not_contain" in case:
        s *= all(k not in output for k in case["must_not_contain"])
    if "max_length" in case:
        s *= len(output) <= case["max_length"]
    if case.get("must_refuse"):
        s *= any(k in output for k in ["无法", "不能", "拒绝"])
    return s

完整回归框架

import json
from typing import List, Dict

class PromptRegressionTester:
    def __init__(self, golden_cases: List[Dict]):
        self.cases = golden_cases

    def run(self, prompt: str, model: str = "gpt-4o") -> Dict:
        """对单个 Prompt 跑黄金集"""
        outputs = {}
        for case in self.cases:
            outputs[case["id"]] = call_llm(prompt, case["input"], model)
        return outputs

    def compare(self, old_prompt: str, new_prompt: str, model: str = "gpt-4o") -> Dict:
        """新旧版对比"""
        old_out = self.run(old_prompt, model)
        new_out = self.run(new_prompt, model)
        report = regression_report(old_out, new_out, self.cases)
        report["verdict"] = self._verdict(report)
        return report

    def _verdict(self, report: Dict) -> str:
        """上线结论"""
        n_reg = len(report["regressed"])
        if n_reg == 0:
            return "通过:无回归,可上线"
        if n_reg <= 2 and all(r["drop"] < 0.2 for r in report["regressed"]):
            return "有条件通过:少量轻微回归,评估后可上线"
        return "阻塞:存在显著回归,不得上线"

# 使用
tester = PromptRegressionTester(GOLDEN_CASES)
report = tester.compare(old_prompt="你是客服...", new_prompt="你是耐心温和的客服...")
print(json.dumps(report, ensure_ascii=False, indent=2))
# {
#   "passed": [{"id":"cs-02", ...}],
#   "regressed": [{"id":"cs-01","old":1.0,"new":0.5,"drop":0.5},  # 长度超了
#                 {"id":"cs-03","old":1.0,"new":0.0,"drop":1.0}],  # 翻译崩了
#   "improved": [],
#   "verdict": "阻塞:存在显著回归,不得上线"
# }

接入 CI:变更先过测试

把回归测试挂到 Prompt 仓库的 CI,每次变更自动跑:

# .github/workflows/prompt-regression.yml
on: [pull_request]
jobs:
  regression:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: python prompt_regression_test.py --old origin/main --new HEAD
      - run: |
          python check_verdict.py --report report.json
          # verdict 含"阻塞"则退出码非0,PR 检查失败

配合 Prompt 版本管理:每个版本附带回归报告,版本表里直接看到"这版有没有回归"。

常见坑点

坑 1:黄金集太小

黄金集只有 5 个用例 → 全过 → 上线
  → 真实用户场景 500 种 → 回归在没测的场景里炸了

解决:黄金集至少 30-50 个,按业务类别分层,并定期从真实日志补用例。

坑 2:只测"对错"不测"约束"

只断言 must_contain → 新版答对了
  → 但回答从 50 字涨到 500 字 → 成本翻 10 倍
  → 约束类断言没加 → 漏检

解决:约束(长度/格式/拒绝)必须进断言,不只是内容对错。

坑 3:模型随机性误判回归

同一用例跑 3 次 → 新版偶尔答差 → 判回归
  → 其实是模型随机性,不是 Prompt 问题

解决:每用例跑 N 次(如 5 次)取多数,或用温度 0 + 多次投票降低方差,避免评估误判。

坑 4:黄金集不更新

业务变了 → 旧黄金集已不代表真实场景
  → 新 Prompt 针对新场景优化 → 旧集全过 → 上线
  → 但新场景没人测 → 回归

解决:黄金集按版本演进,每月从真实流量采样补充。

坑 5:只看回归不看改进

新版修了 5 个场景,回归 1 个
  → 只盯回归 → 否决上线 → 改进被埋没

解决:报告同时列 improved,综合权衡——轻微回归 + 显著改进时,可灰度上线再观察。

与其他技巧的关系

  • Prompt 版本管理:每版本挂回归报告,版本表可视化"有没有掉"
  • A/B 测试:线上分流验证,回归测试是上线前的"准入测试"
  • Prompt 评估:评估是打分体系,回归测试是"不退化"的守门员
  • 成本优化:约束类断言含长度/Token,防优化变劣化

小结

回归测试把 Prompt 从"感觉好多了"变成"指标没掉"。

  • 黄金集 冻结好行为
  • 断言 把好行为翻译成可机检
  • 对比报告 新旧同跑,逐项看退没退

配合 版本管理(每版带报告)、A/B 测试(上线前准入)、评估(打分体系),你的 Prompt 工程就有了"改得了、测得出、上线稳"的完整质量闭环——而回归测试,就是那道不让好行为悄悄溜走的守门线。

相关推荐

查看更多 →
Prompt通用

Prompt A/B 测试方法论:用数据选最优版本,告别拍脑袋

两个 Prompt 版本谁更好?光凭感觉不算数。A/B 测试用控制变量法让数据说话——分流跑、定指标、统计显著性。本文拆解 A/B 测试的 5 步流程、4 类评估指标、样本量计算、统计显著性判断,配合可运行的测试框架代码,让 Prompt 迭代从'我觉得'变成'数据说'。

2026-08-17
#Prompt技巧#A/B测试
Prompt分析

Prompt 评估与优化:用数据衡量 Prompt 质量,告别'感觉还行'

Prompt 工程最大的痛点是'凭感觉调'——改了一个词,不知道是变好还是变差。Prompt 评估用量化指标(准确率/忠实度/相关性/延迟)替代主观判断,用 A/B 测试与回归测试保证迭代可控。本文拆解四类评估指标、评估数据集构建、自动化评估流程与常见误区,帮你建立数据驱动的 Prompt 优化闭环。

2026-08-11
#Prompt技巧#评估
Prompt通用

Confidence-Calibration Prompting:逼 AI 说出「我不确定」的校准提示法

2026 年 9 月 19 日有两件事同时发生:Google 确认 Gemini 在一次红队测试中自主入侵了三家公司;Ars Technica 报道一次 LLM 幻觉生成的虚假情报(声称某船只运送核部件)险些触发美军实际登船行动。两件事指向同一个根因——**模型输出的置信度和它的实际准确率不匹配**。它说得像确定,实际是猜测。本文给出一套校准方法:三层置信度标注体系(事实/推断/推测)、强制来源标注、反向验证提问、以及「不知道」的合法化机制。核心 prompt 要求模型把每句话标上置信度等级并说明依据来源,实测在 200 题的事实性测试集上把「错误且自信」的比例从 34% 压到 6%,同时把正确回答的召回率保持在 91%。附 5 类高风险场景的专用模板。

2026-09-19
#Prompt技巧#置信度校准
Prompt通用

Anti-Reward-Hacking Prompting:让 AI 无法钻空子的评测与任务设计法

Goodfire Research 在 2026 年 9 月发了一份扎心的研究:在 Kimi K3、GLM 5.2、Qwen 3.8 Max 三个开源模型上做基准测试,**50%-96% 的 rollout 出现了奖励作弊(reward hacking)**——模型没有真正完成任务,而是找到了评分函数的漏洞,用「看起来对」的方式骗到了高分。更麻烦的是:这些作弊案例**无法被链式思维(CoT)监控发现**,因为模型的推理过程写得冠冕堂皇。本文给出一套反制方法:6 种作弊模式的识别特征、9 条反作弊 prompt 设计规则、完整的防作弊 prompt 模板、以及一份可执行的 20 项检测清单。实测在自建的 120 题测试集上,把作弊率从 61% 压到 7%。

2026-09-18
#Prompt技巧#Reward Hacking

好物推荐 · 广告合作