改提示词导致的线上故障往往最隐蔽,因为它们根本不会报错
提示词回归(Prompt Regression)是生产环境里最恶心的 Bug。它不像代码逻辑写错了会抛出 Exception,或者 JSON 解析失败会记录 Error Log。当你微调了一个 Prompt,API 依然返回 200,响应速度没变,格式看起来也对,但模型可能悄悄地不再遵守某个约束条件了。比如原本要求输出 ISO 格式,现在可能偶尔夹杂了自然语言。
下一篇
Agent 搜索结果烂到底是因为模型智商不够,还是搜索源本身有问题? →
这种“静默失败”靠人工肉眼检查(Spot-checking)是绝对测不出来的。人类的直觉倾向于测试“快乐路径”(Happy Path),也就是那些模型表现最稳的场景。但真正的风险藏在边缘案例、格式约束、拒绝回答逻辑以及指令冲突里。
我总结了一套极简的评估工具流(Eval Harness),核心逻辑不是追求框架的复杂度,而是建立“黄金案例(Golden Cases)+ 确定性评分器(Deterministic Graders)+ 基准对比(Baseline Comparison)”的闭环。如果新版本的得分比基准线低了,直接让 CI/CD 流水线挂掉。
这套方案只需要一个 Python 文件和一个 JSON 配置文件,实操逻辑如下:
一、构建核心评估脚本
这个脚本通过注册不同的评分器(如正则匹配、关键词检查、字数限制)来对模型输出进行硬性判定。
# eval_harness.py
import json
import re
import sys
from pathlib import Path
GRADERS = {}
def grader(name):
def wrap(fn):
GRADERS[name] = fn
return wrap
return wrap
@grader("regex")
def grade_regex(case, output):
return bool(re.search(case["pattern"], output))
@grader("keyword")
def grade_keyword(case, output):
lowered = output.lower()
return any(k.lower() in lowered for k in case["keywords"])
@grader("word_count_max")
def grade_word_count(case, output):
return len(output.split()) <= case["max_words"]
def make_model_fn(base_url, api_key, model):
from openai import OpenAI
client = OpenAI(base_url=base_url, api_key=api_key)
def fn(prompt):
response = client.chat.completions.create(
model=model,
messages=[{"role": "user", "content": prompt}],
temperature=0.2,
)
return response.choices[0].message.content
return fn
def run_case(case, model_fn):
output = model_fn(case["prompt"])
passed = GRADERS[case["grader"]](case, output)
return {"id": case["id"], "passed": passed, "output": output}
def run_suite(cases, model_fn):
results = [run_case(c, model_fn) for c in cases]
score = sum(r["passed"] for r in results) / len(results)
return score, results
def main():
cases = json.loads(Path("golden_cases.json").read_text())
base_url, api_key, model = sys.argv[1], sys.argv[2], sys.argv[3]
model_fn = make_model_fn(base_url, api_key, model)
score, results = run_suite(cases, model_fn)
if "--save-baseline" in sys.argv:
Path("baseline.json").write_text(json.dumps({"score": score}))
print(f"baseline saved: {score:.2f}")
return
if not Path("baseline.json").exists():
print("Error: baseline.json not found. Run with --save-baseline first.")
sys.exit(1)
baseline = json.loads(Path("baseline.json").read_text())
delta = score - baseline["score"]
print(f"score={score:.2f} baseline={baseline['score']:.2f} delta={delta:+.2f}")
for r in results:
if not r["passed"]:
print(f"FAIL {r['id']}: {r['output'][:160]}")
# 如果得分下降超过 5%,直接判定失败
if delta < -0.05:
sys.exit(1)
if __name__ == "__main__":
main()二、编写黄金案例文件
这里的关键在于,每一个 Case 都应该像一份“合同”。不要写模糊的指令,要明确规定输出必须包含什么、字数上限是多少。
[
{
"id": "date-format-001",
"prompt": "Extract the ISO date from: 'Deploy shipped 2026-08-27 at 14:00 UTC.'",
"grader": "regex",
"pattern": "2026-08-27"
},
{
"id": "summary-length-001",
"prompt": "Summarize in at most 10 words: 'The quick brown fox jumps over the lazy dog.'",
"grader": "word_count_max",
"max_words": 10
},
{
"id": "keyword-check-001",
"prompt": "Explain what a black hole is in one sentence.",
"grader": "keyword",
"keywords": ["gravity", "singularity", "light"]
}
]三、实战部署建议
使用流程非常简单:
1. 先跑一遍初始版本,保存基准分:python eval_harness.py <URL> <KEY> <MODEL> --save-baseline
2. 修改 Prompt 后,直接运行脚本。如果 delta 跌破了设定的阈值(比如 5%),脚本会返回非零退出码,这时你的自动化流水线就会自动拦截这个有风险的改动。
这种做法的核心价值在于把“感觉模型变聪明了/变笨了”这种主观判断,转化成了可度量的工程指标。
免费 AI 工具箱 · 全部完全免费