课程大纲 › 领域 4:提示工程与结构化输出

4.1 设计带明确标准的提示词,提高准确率、减少误报

タスクステートメント4.1:精度を高め誤検知を減らすために、明示的な基準を備えたプロンプトを設計する

官方大纲原文(日文):知识 3 条 · 技能 3 条

需要掌握的知识

  • 曖昧な指示よりも明示的な基準が重要であること(例:「コメントの正確性を確認する」ではなく「主張されている動作が実際のコードの動作と矛盾する場合にのみコメントを指摘する」)
  • 「保守的に判断する」や「確信度の高い指摘事項のみを報告する」といった一般的な指示が、具体的なカテゴリ別の基準と比べて精度の向上につながらない理由
  • 誤検知率が開発者の信頼に与える影響:誤検知の多いカテゴリが、正確なカテゴリへの信頼まで損なうこと

需要能做到的事

  • 確信度に基づくフィルタリングに頼るのではなく、報告すべき問題(バグ、セキュリティ)とスキップすべき問題(軽微なスタイル、局所的なパターン)を定義する具体的なレビュー基準を記述する
  • 誤検知の多いカテゴリを一時的に無効化し、それらのカテゴリのプロンプトを改善する間に開発者の信頼を回復する
  • 一貫した分類を実現するために、重大度レベルごとに具体的なコード例を伴う明示的な重大度基準を定義する

课程讲解 · AI 草稿,未经人工审核 以官方文档为准

这一条考什么

考你能否用明确、具体的判定标准写提示词来提升准确率、降低误报,而不是依赖“保守一点”“只报高置信度问题”这类笼统指令。还要理解误报对开发者信任的放大效应:一个高误报类别会拖累整个系统的可信度,因此可以先临时关闭该类别、改进其提示后再恢复;并能为每个严重级别给出带代码示例的明确标准,让分类稳定一致。

核心概念

明确标准胜过模糊指令

对比两种写法:

  • 模糊:“检查注释是否准确。”
  • 明确:“只有当注释声称的行为与代码的实际行为矛盾时才报告。例如注释说‘返回 null 表示未找到’,而代码在未找到时抛出异常。注释不完整、措辞可改进、缺少注释都不报告。”

模糊指令让模型自己定义“准确”,于是每次的边界都不同,往往连措辞问题都报出来。明确标准给出了可判定的条件:何时报告、何时不报告,再配上一个例子锚定含义。

为什么“保守一点”“只报高置信度”不起作用

“请保守判断”“只报告你非常确定的问题”听起来能减少误报,但它们:

  • 没有提供判断依据:模型并不知道你的项目里哪些模式是可接受的,“确定”与否仍按它的通用直觉。
  • 模型自评的置信度校准不佳:让模型给每条发现打 1–10 分再过滤 8 分以上,会同时砍掉真问题、保留自信的误报。
  • 作用是整体压低召回,而不是精确排除误报类别:真正的 bug 也可能因此不报。

有效的做法是按类别写出报告与跳过的标准:

## 报告(必须指出)
- 逻辑错误:条件写反、差一错误、未处理的错误返回值
- 安全问题:SQL/命令拼接、未校验的用户输入进入文件路径、密钥硬编码
- 数据风险:事务外的多步写入、静默吞掉异常

## 跳过(不要报告)
- 纯格式与命名风格(由 linter 负责)
- 本仓库约定的模式:Result 类型的早返回、generated/ 目录下的代码
- 只在局部作用域、无副作用的小型重复

误报率与开发者信任

开发者面对的是整个工具的输出。如果“命名建议”类别 70% 是误报,开发者很快会养成“看都不看就关掉”的习惯,连旁边那条准确的 SQL 注入警告也一起忽略。也就是说,一个高误报类别会侵蚀所有类别的信任。

应对策略:

  1. 按类别统计被驳回率,找出误报集中的类别。
  2. 临时关闭这些类别的报告,让剩余输出保持高准确率,恢复开发者信任。
  3. 在后台改进这些类别的标准和示例,用历史数据验证后再重新启用。

带代码示例的严重级别标准

“严重/一般/轻微”如果只写名字,同一问题今天被标 critical、明天被标 minor。为每个级别写出定义和具体代码示例:

## 严重级别
- critical:可被利用的安全漏洞或必然导致数据丢失/错误。
  例:cursor.execute(f"SELECT * FROM users WHERE id = {user_id}")
- major:特定输入下产生错误结果或崩溃,但不涉及安全。
  例:items[len(items)]  # 必然越界
  例:total / count  # count 可能为 0 且未检查
- minor:可维护性问题,当前行为正确。
  例:同一段 10 行校验逻辑在两个函数中重复

示例让模型能“对照”分类,而不是凭感觉。

正确做法与反模式

  • 正确:写清哪些类别必须报告(bug、安全),哪些跳过(轻微风格、局部模式)。反模式:依赖“只报高置信度问题”、置信度打分阈值过滤。
  • 正确:找出高误报类别,暂时停用,改进提示后再恢复。反模式:继续输出所有类别,任由开发者养成忽略习惯;或者整体加一句“更保守”。
  • 正确:为每个严重级别给出定义和代码示例。反模式:只列出级别名,让模型自由理解。
  • 正确:先在提示设计层面解决问题,再考虑基础设施。反模式:一上来就加一个二级分类模型过滤输出。

常见陷阱

  • “让 Claude 给每条发现打 1–10 分,只保留 8 分以上”:自评置信度校准差,既漏真问题又留误报。
  • “追加‘只报告你高度确信的问题’”:典型的笼统指令,不能告诉模型你的项目认为什么可接受。
  • “再训练/再部署一个分类模型过滤结果”:题干若说“在增加基础设施复杂度之前”,答案一定在提示设计层面。
  • “删除严重级别相关指令,交给模型默认判断”:会让分类更不一致。
  • 只扩写描述字段:把每条发现解释得更详细并不能减少误报;若要分析误报原因,更有用的是记录触发该发现的具体代码模式,便于按模式统计和改进标准。

实操练习

目标:对比“模糊指令”与“明确标准”两种系统提示在同一段代码上的审查结果。

  1. 准备一段包含 1 个真实 SQL 注入、1 个除零风险,以及若干团队可接受模式(早返回、简短变量名)的代码。
  2. 用模糊提示运行一次,记录报告数量与误报。
  3. 换成带“报告/跳过”类别和严重级别示例的提示,再运行。
  4. 比较两次输出的误报数与真问题召回情况。
import anthropic

client = anthropic.Anthropic()

CODE = '''
def get_user(db, uid):
    if not uid:
        return None
    q = f"SELECT * FROM users WHERE id = {uid}"
    return db.execute(q).fetchone()

def avg(xs):
    s = sum(xs)
    return s / len(xs)
'''

VAGUE = "你是代码审查者。请保守一些,只报告你高度确信的问题。"

EXPLICIT = """你是代码审查者。
报告:逻辑错误、可能的崩溃、安全漏洞(注入、未校验输入)。
跳过:命名风格、早返回写法、短变量名(本团队允许)。
严重级别:
- critical:可利用的安全漏洞,例:f-string 拼接 SQL
- major:特定输入下崩溃或结果错误,例:未检查除数为 0
- minor:可维护性问题,行为正确
每条输出一行:行号 | 级别 | 问题 | 修复建议。没有问题就输出 NONE。"""

for name, system in [("vague", VAGUE), ("explicit", EXPLICIT)]:
    msg = client.messages.create(
        model="claude-sonnet-4-5",
        max_tokens=800,
        system=system,
        messages=[{"role": "user", "content": f"审查以下代码:\n{CODE}"}],
    )
    print(f"===== {name} =====")
    print(msg.content[0].text)

检查结果:明确标准版本应只报告 SQL 注入(critical)和除零(major),不报早返回或变量名;模糊版本的输出在格式和范围上更随意。可多跑几次观察一致性差异。

自测清单

  • 把“检查注释是否准确”改写成一条明确的报告标准。
  • 为什么“请保守判断”“只报高置信度问题”无法有效降低误报?
  • 一个高误报类别会如何影响开发者对其他类别的信任?你会采取什么步骤?
  • 为严重级别定义标准时,为什么要附带具体代码示例?
  • 题目问“在增加基础设施之前”的改进方案时,应排除哪些选项?

对应题目(7)

题目归类由 AI 判断,仅供参考。

练习这 7 道题