AI TOOLS

EP02. "Prompt 评估工作流:从拍脑袋到用数据说话"

首页 › AI 工具 › Claude · Developer and Platform · Claude API · EP02
约 18 分钟· #EP02#Claude#Claude API
🔒 登录后可标记已读
  • Prompt 写完只测一次就上线,上生产环境「大概率会出事」——用户会用你完全没想到的方式提问,靠感觉测几次不够
  • Prompt Engineering(怎么写好一个 prompt)跟 Prompt Evaluation(怎么客观量测一个 prompt 好不好)是两件不同的事,这篇笔记讲后者
  • 一套完整评估流程是:草拟 prompt → 准备测试数据集 → 跑一遍 Claude → 打分 → 照分数改进 prompt → 再跑一次比较分数,全程可以用代码自动化
  • 打分(grading)分三种方式:写代码硬检查格式、找另一个模型当裁判、找真人看——这篇笔记后半段示范用 Claude 自己当裁判
  • 前置知识:读过 [EP01](./EP01_claude-api基础入门.md),会用 client.messages.create()、assistant prefill + stop sequence 这套基本功

重点内容


为什么不能只测一次就上线

写完一个 prompt,一般有三条路:

做法问题
测一次就觉得行了上生产环境后「翻车风险很高」
针对几个想到的边界情况多测几次「用户实际会用的方式,往往比想象中更出人意料」——照样有漏网之鱼
搭一套评估流程(eval pipeline),跑分、再照客观指标迭代前期要多花时间搭基础设施,但能在上线前抓出弱点、客观比较不同版本、靠数据而不是直觉去迭代

📌 一句话总结这篇笔记的立场:"当你把 prompt 部署到生产环境,用户跟它互动的方式,一定会超出你的预料。"


一套典型评估流程的五步

第一步:草拟 prompt

prompt = f"""
Please answer the user's question:

{question}
"""

第二步:准备评估数据集

收集能代表真实使用场景的样本问题。示范用的极简数据集只有三条:「2+2 等于多少」「怎么煮燕麦粥」「月球有多远」。真实项目的数据集可能有几十、几百甚至几千条。

第三步:整批跑过 Claude

把数据集里每一条问题套进 prompt 模板,发给 Claude,收集回答。

第四步:交给评分员打分

用 1-10 分制评估回答质量。示范三条分别拿到 10 分、4 分、9 分,平均 7.66 分。

第五步:照分数改 prompt,重新跑一次

针对拿低分的地方调整 prompt。示范只是加了一句「Answer the question with ample detail」,平均分从 7.66 涨到 8.7。

💡 这套流程的价值在于「拿到客观的数字」——不同版本的 prompt 可以直接拿分数比较,不用靠感觉猜哪个写得更好。


搭一套真正能跑的评估管线

以「帮用户写 AWS 相关代码(Python / JSON / Regex 三选一格式)」这个 prompt 为例,拆成三个函数:

run_prompt:把测试用例套进 prompt 模板、发给 Claude

def run_prompt(test_case):
    """Merges the prompt and test case input, then returns the result"""
    prompt = f"""
Please solve the following task:

{test_case["task"]}
"""

    messages = []
    add_user_message(messages, prompt)
    output = chat(messages)
    return output

📌 这个示范版本的 prompt 刻意写得很简单(没加任何格式要求),所以输出会偏啰嗦——这是为了后面几节示范怎么一步步改进格式约束。

run_test_case:跑一条用例 + 打分(先用占位分数)

def run_test_case(test_case):
    """Calls run_prompt, then grades the result"""
    output = run_prompt(test_case)

    # TODO - Grading
    score = 10

    return {
        "output": output,
        "test_case": test_case,
        "score": score
    }

run_eval:把整个数据集都跑一遍

def run_eval(dataset):
    """Loads the dataset and calls run_test_case with each case"""
    results = []

    for test_case in dataset:
        result = run_test_case(test_case)
        results.append(result)

    return results

执行:

with open("dataset.json", "r") as f:
    dataset = json.load(f)

results = run_eval(dataset)

每条结果包含三样:Claude 的输出、原始测试用例、评分。这就是大多数 AI 评估系统的骨架——接下来只需要把占位的 score = 10 换成真正的打分逻辑。


用 Claude 自己生成测试数据集

数据集不一定要手写,可以让 Claude(建议用 Haiku 这类速度快的模型,不用动用旗舰模型)批量生成。

  • 测试用例统一存成 JSON 对象,带 "task" 字段
  • generate_dataset() 函数的做法:叫 Claude"Generate an evaluation dataset for a prompt evaluation",针对 Python / JSON / Regex 三种 AWS 相关任务各生成几条
  • 拿到结果照样用 assistant prefill( `json )+ stop_sequences=["`"] 这招解析出干净 JSON(跟 [EP01](./EP01_claude-api基础入门.md) 的 Structured Data 技巧完全一样)
  • 生成完存成 dataset.json,供后面步骤反复复用:
json.dump(dataset, f)

打分的三种方式

方式怎么做适合检查什么
Code Grader写代码硬性检查输出长度、有没有出现关键词、语法能不能 parse 成功(JSON/Python/Regex)、可读性
Model Grader另外呼叫一次 Claude 当裁判回答品质、有没有照指令做、完整度、有没有用、安不安全
Human Grader真人看整体品质、全面性、深度、简洁度、相关性

Model Grader 实作

def grade_by_model(test_case, output):
    eval_prompt = """
    You are an expert code reviewer. Evaluate this AI-generated solution.

    Task: {task}
    Solution: {solution}

    Provide your evaluation as a structured JSON object with:
    - "strengths": An array of 1-3 key strengths
    - "weaknesses": An array of 1-3 key areas for improvement
    - "reasoning": A concise explanation of your assessment
    - "score": A number between 1-10
    """

    messages = []
    add_user_message(messages, eval_prompt)
    add_assistant_message(messages, "```json")

    eval_text = chat(messages, stop_sequences=["```"])
    return json.loads(eval_text)

接进 run_test_case:

def run_test_case(test_case):
    output = run_prompt(test_case)
    model_grade = grade_by_model(test_case, output)
    score = model_grade["score"]
    reasoning = model_grade["reasoning"]
    return {
        "output": output,
        "test_case": test_case,
        "score": score,
        "reasoning": reasoning
    }

算整体平均分:

from statistics import mean

def run_eval(dataset):
    results = []
    for test_case in dataset:
        result = run_test_case(test_case)
        results.append(result)
    average_score = mean([result["score"] for result in results])
    print(f"Average score: {average_score}")
    return results

💡 让裁判模型同时给 strengths(优点)、weaknesses(缺点)、reasoning(评分理由),不是只要一个数字——这样能避免模型偷懒,什么都打个不功不过的 6 分,逼它给出有区分度的评分。


Code Grader:检查格式跟语法

Code Grader 检查的是「格式对不对」跟「语法能不能 parse」,这两样纯属客观对错,不需要另一个模型判断:

  • 格式:回答应该只有要求的代码本身(Python / JSON / Regex),不该夹带解释文字
  • 语法:生成的内容要真的能被对应语言 parse 出来
def validate_json(text):
    try:
        json.loads(text.strip())
        return 10
    except json.JSONDecodeError:
        return 0

def validate_python(text):
    try:
        ast.parse(text.strip())
        return 10
    except SyntaxError:
        return 0

def validate_regex(text):
    try:
        re.compile(text.strip())
        return 10
    except re.error:
        return 0

每个函数:能 parse 成功给 10 分,失败给 0 分。

测试用例要多带一个 "format" 字段,告诉评分函数该用哪个 validator:

{
    "task": "Create a Python function to validate an AWS IAM username",
    "format": "python"
}

让 prompt 配合评分标准

要拿到干净的代码输出,prompt 本身也要改得更明确:直接要求「Respond only with Python, JSON, or a plain Regex」,不要解释文字;再搭配 assistant prefill(比如 `code )引导 Claude 直接开始写代码,不写废话。


综合 Model Score 跟 Syntax Score

最终分数可以把两种评分取平均:

(model_score + syntax_score) / 2

📌 两者的权重不是固定的——比如格式正确性对你的应用更重要,就把 syntax score 权重调高,反之亦然。

常见错误

  • ❌ Prompt 只手动测一两次就直接上线——用户实际输入的多样性,几乎一定会超出手测能覆盖的范围
  • ❌ 只给裁判模型一个「打几分」的空格——不要求给 strengths/weaknesses/reasoning,裁判很容易懒得区分、全部打差不多的中间分数
  • ❌ 生成测试数据集用了跟正式评估一样贵的旗舰模型——生成数据这种量大但不需要顶尖品质的任务,用 Haiku 这类快模型更划算
  • ❌ 只做 Model Grader、不做 Code Grader(或反过来)——像「格式对不对」「语法能不能 parse」这种有绝对对错的项目,交给代码检查比交给模型判断更准、更省成本

Sources

官方文档:

  1. Building with the Claude API(Claude Academy 课程)— https://academy.claude.com/courses/building-with-the-claude-api