返回

Everything Claude Code 教程 10:Verification Loops 与持续学习

本文详解 Everything Claude Code 的 Verification Loops 系统和持续学习机制,包含 pass@k 评估和 checkpoint evals。

教程概述

Verification Loops 确保 AI 的输出是可靠的,而不是"看起来对"。本教程将教你如何建立有效的验证循环和持续学习机制。

你将学到

  • ✅ Verification Loop 的两种模式
  • ✅ pass@k vs pass^k 评估指标
  • ✅ Benchmarking 工作流
  • ✅ continuous-learning skill 配置
  • ✅ Stop Hook vs UserPromptSubmit 设计决策

为什么需要 Verification Loops?

问题:AI “声称完成”

flowchart LR
    A[AI: "功能已完成"] --> B{实际验证}
    B --> C[✅ 真的完成]
    B --> D[❌ 有 bug]
    B --> E[❌ 测试失败]
    B --> F[❌ 需求理解错误]

    style D fill:#ffcccc
    style E fill:#ffcccc
    style F fill:#ffcccc

解决方案:验证循环

flowchart TD
    A[实现] --> B[验证]
    B --> C{通过?}
    C -->|是| D[完成]
    C -->|否| E[修复]
    E --> A

    style B fill:#e8f5e9

Verification Loop 模式

模式 1:Checkpoint-Based Evals

在关键检查点设置验证:

sequenceDiagram
    participant AI as Claude
    participant C as Checkpoint
    participant V as Verifier

    AI->>C: 检查点 1: 功能实现
    C->>V: 验证
    V-->>C: ✅ 通过

    AI->>C: 检查点 2: 测试通过
    C->>V: 验证
    V-->>C: ❌ 失败

    C->>AI: 返回修复
    AI->>C: 检查点 2: 重新验证
    C->>V: 验证
    V-->>C: ✅ 通过

    AI->>C: 检查点 3: 代码审查
    C->>V: 验证
    V-->>C: ✅ 通过

配置示例

checkpoints:
  - name: 功能实现
    criteria:
      - 代码编译通过
      - 无 TypeScript 错误
    on_failure: 继续实现

  - name: 测试通过
    criteria:
      - pytest 通过
      - 覆盖率 ≥80%
    on_failure: 修复测试

  - name: 代码审查
    criteria:
      - 无安全漏洞
      - 代码风格一致
    on_failure: 修复问题

模式 2:Continuous Evals

定期运行完整验证:

flowchart TD
    A[开发中] --> B{每 N 分钟}
    B --> C[运行完整测试套件]
    C --> D{全部通过?}
    D -->|是| E[继续开发]
    D -->|否| F[暂停并修复]

    style C fill:#e3f2fd

配置示例

continuous_evals:
  interval: 10  # 分钟
  commands:
    - npm run test
    - npm run lint
    - npm run typecheck

  on_failure:
    - 通知用户
    - 记录失败点

两种模式对比

特性 Checkpoint-Based Continuous
验证时机 关键节点 定期
成本 较低 较高
反馈延迟
适用场景 需要确认的里程碑 长时间开发会话
推荐 ✅ 主要使用 补充使用

pass@k vs pass^k 指标

定义

pass@k:k 次尝试中至少有一次成功

P(at least 1 success in k attempts)

示例:
k=1: 70% 成功率
k=3: 91% 成功率
k=5: 97% 成功率

pass^k:k 次尝试全部成功

P(all k attempts succeed)

示例:
k=1: 70% 成功率
k=3: 34% 成功率
k=5: 17% 成功率

计算公式

pass@k = 1 - (n - c choose k) / (n choose k)

其中:
n = 总测试数
c = 通过测试数
k = 尝试次数

简化版(当 n 很大时):
pass@k ≈ 1 - (1 - c/n)^k

选择建议

flowchart TD
    A[选择评估指标] --> B{需求是什么?}
    B -->|只要能成功一次| C[pass@k]
    B -->|必须每次都成功| D[pass^k]

    C --> E[适用场景:<br/>探索性任务<br/>创意性任务]
    D --> F[适用场景:<br/>生产部署<br/>安全关键]

示例计算

场景:单个任务成功率 70%

# pass@k 计算
def pass_at_k(single_success_rate, k):
    return 1 - (1 - single_success_rate) ** k

pass_at_k(0.70, 1)  # 0.70 (70%)
pass_at_k(0.70, 3)  # 0.973 (97.3%)
pass_at_k(0.70, 5)  # 0.99757 (99.76%)

# pass^k 计算
def pass_k(single_success_rate, k):
    return single_success_rate ** k

pass_k(0.70, 1)  # 0.70 (70%)
pass_k(0.70, 3)  # 0.343 (34.3%)
pass_k(0.70, 5)  # 0.16807 (16.8%)

Benchmarking 工作流

流程图

flowchart TD
    A[定义基准任务] --> B[创建测试集]
    B --> C[运行基准]
    C --> D[记录结果]

    D --> E[应用优化]
    E --> F[重新测试]
    F --> G{改进?}
    G -->|是| H[记录改进]
    G -->|否| I[回滚/调整]

    H --> J[更新基线]
    I --> E

    style A fill:#e3f2fd
    style D fill:#e8f5e9
    style H fill:#fff3e0

示例:比较有无 Skill 的效果

# 步骤 1:创建测试集
mkdir -p benchmarks/tasks
echo "实现一个链表" > benchmarks/tasks/01-linked-list.txt
echo "实现一个栈" > benchmarks/tasks/02-stack.txt
echo "实现一个二叉树" > benchmarks/tasks/03-binary-tree.txt

# 步骤 2:运行基准测试(无 Skill)
for task in benchmarks/tasks/*.txt; do
    claude --no-skill "$(cat $task)" > benchmarks/results/no-skill-$(basename $task).txt
done

# 步骤 3:运行基准测试(有 Skill)
for task in benchmarks/tasks/*.txt; do
    claude --skill tdd-workflow "$(cat $task)" > benchmarks/results/with-skill-$(basename $task).txt
done

# 步骤 4:比较结果
python scripts/compare_benchmarks.py

关键指标

指标 说明 目标
首次成功率 一次尝试就正确 ≥85%
Token 效率 输出/输入比 优化
时间效率 任务完成时间 最小化
错误率 生成错误代码频率 最小化

continuous-learning Skill

工作原理

sequenceDiagram
    participant S as Session
    participant H as Stop Hook
    participant L as Learner
    participant K as Skills

    S->>H: 会话结束
    H->>L: 分析会话

    alt 发现新模式
        L->>K: 创建新 Skill
        K-->>L: 保存成功
    else 无新模式
        L->>L: 记录日志
    end

    L-->>H: 学习完成

配置

~/.claude/skills/continuous-learning/README.md

# 持续学习 Skill

## 触发条件
通过 Stop Hook 在会话结束时触发

## 学习规则

### 保存条件
1. 同一问题出现 ≥2 次
2. 解决方案非显而易见
3. 可复用于其他项目

### 忽略条件
1. 一次性问题
2. 项目特定配置
3. 已有文档覆盖

## 输出位置
~/.claude/skills/learned/YYYY-MM-DD-topic.md

配套 Stop Hook

{
  "Stop": [
    {
      "matcher": "true",
      "hooks": [
        {
          "type": "command",
          "command": "python ~/.claude/scripts/continuous_learner.py --session-log $SESSION_LOG"
        }
      ]
    }
  ]
}

Stop Hook vs UserPromptSubmit

设计决策

特性 Stop Hook UserPromptSubmit
触发频率 每会话一次 每条消息
延迟影响 无(会话结束时) 有(每条消息)
上下文 完整会话 单条消息
推荐用途 持久化、学习 预处理、注入

推荐选择

✅ 使用 Stop Hook 用于:
- 会话摘要
- 持续学习
- 状态持久化
- 清理工作

❌ 避免 UserPromptSubmit 用于:
- 学习相关任务(增加每条消息延迟)

✅ 使用 UserPromptSubmit 用于:
- 上下文注入
- 预处理用户输入

验收标准验证

完整验证流程

flowchart TD
    A[声称完成] --> B[检查文件存在]
    B --> C[运行编译检查]
    C --> D[运行测试套件]
    D --> E[运行 Lint]
    E --> F[检查覆盖率]
    F --> G{全部通过?}
    G -->|是| H[✅ 验证通过]
    G -->|否| I[❌ 返回修复]

    style H fill:#e8f5e9
    style I fill:#ffcccc

验证脚本示例

#!/bin/bash
# verify_completion.sh

echo "=== 验证开始 ==="

# 1. 编译检查
npm run build || { echo "❌ 编译失败"; exit 1; }
echo "✅ 编译通过"

# 2. 类型检查
npm run typecheck || { echo "❌ 类型错误"; exit 1; }
echo "✅ 类型检查通过"

# 3. 测试
npm test || { echo "❌ 测试失败"; exit 1; }
echo "✅ 测试通过"

# 4. 覆盖率
COVERAGE=$(npm run test:coverage -- --silent | grep "All files" | awk '{print $4}' | tr -d '%')
if [ "$COVERAGE" -lt 80 ]; then
    echo "❌ 覆盖率不足: $COVERAGE% < 80%"
    exit 1
fi
echo "✅ 覆盖率: $COVERAGE%"

# 5. Lint
npm run lint || { echo "❌ Lint 失败"; exit 1; }
echo "✅ Lint 通过"

echo "=== ✅ 全部验证通过 ==="

小结

关键要点

  • ✅ Checkpoint-Based Evals 在关键节点验证
  • ✅ pass@k 用于"至少成功一次"场景
  • ✅ pass^k 用于"必须每次成功"场景
  • ✅ continuous-learning 通过 Stop Hook 实现
  • ✅ Stop Hook 比 UserPromptSubmit 更适合学习任务

系列导航