模型选择是 Agent 平台最关键的决策之一。Claude Sonnet/Opus、GPT-4o、DeepSeek-V3、Llama 3 70B……每个模型都声称自己"最强",但在真实的编码任务上到底表现如何?本文用统一的 Bugfix / Review / Test / Docs 四类任务集,在同等条件下横评 6 个模型,用数据而非信仰做决策。

Lab 007:Claude / GPT / DeepSeek / 本地模型编码任务横评

模型选择是 Agent 平台最关键的决策之一。Claude Sonnet/Opus、GPT-4o、DeepSeek-V3、Llama 3 70B……每个模型都声称自己"最强",但在真实的编码任务上到底表现如何?本文用统一的 Bugfix / Review / Test / Docs 四类任务集,在同等条件下横评 6 个模型,用数据而非信仰做决策。

一、实验目标

问题 方法
哪个模型在 Bugfix 上最好? 统一 Bugfix 任务集,对比修复成功率
哪个模型写代码质量最高? 统一 Review 任务集,对比发现问题的准确率
哪个模型写测试最有效? 统一 Test 任务集,对比测试的变异测试得分
哪个模型性价比最高? 记录 Token 成本,计算每成功任务的成本
本地模型能用吗? 对比 Llama 3 70B 和云端模型的差距

二、实验设计

2.1 参评模型

模型 提供商 类型 上下文窗口 每百万 Token 成本(输入/输出)
Claude Opus 4 Anthropic 云端 200K $15 / $75
Claude Sonnet 4 Anthropic 云端 200K $3 / $15
GPT-4o OpenAI 云端 128K $5 / $15
GPT-4o-mini OpenAI 云端 128K $0.15 / $0.60
DeepSeek-V3 DeepSeek 云端 128K $0.27 / $1.10
Llama 3 70B Meta 本地(A100) 8K 硬件成本

2.2 任务集

每类任务 20 个,共 80 个任务。每个任务都有"标准答案"用于评分。

任务类型 数量 难度分布 评分标准
Bugfix 20 简单 8 / 中等 8 / 困难 4 回归测试通过率
Code Review 20 每个代码片段有 3-5 个已知问题 发现问题的召回率和准确率
Test Generation 20 每个函数要求生成 5+ 测试用例 变异测试得分 + 覆盖率
Documentation 20 每个 API 要求生成 OpenAPI 文档 完整性 + 准确性盲评

2.3 控制变量

  • 上下文包相同:每个模型接收完全相同的上下文(代码文件、Issue 描述、项目规范)
  • Prompt 相同:使用统一的 Prompt 模板(适配各模型的 system prompt 格式)
  • Temperature 统一:全部设为 0.2(编码任务需要确定性)
  • 运行 3 次取均值:减少随机性影响

三、评测 Runner

python
# model_benchmark_runner.py
"""
多模型编码任务横评 Runner。
统一任务集 × 多模型,自动执行和评分。
"""
import json
import time
from dataclasses import dataclass, asdict, field

@dataclass
class TaskResult:
    model: str
    task_id: str
    task_type: str          # bugfix / review / test / docs
    difficulty: str         # easy / medium / hard
    
    # 质量指标
    score: float            # 0-1 综合得分
    tests_passed: int = 0
    tests_total: int = 0
    issues_found: int = 0   # Code Review 发现的问题数
    mutation_score: float = 0.0  # Test Generation 的变异测试得分
    
    # 成本指标
    input_tokens: int = 0
    output_tokens: int = 0
    cost_usd: float = 0.0
    time_seconds: float = 0.0
    
    # 执行信息
    success: bool = False
    error: str = ""

PRICING = {
    "claude-opus": {"input": 15.0, "output": 75.0},
    "claude-sonnet": {"input": 3.0, "output": 15.0},
    "gpt-4o": {"input": 5.0, "output": 15.0},
    "gpt-4o-mini": {"input": 0.15, "output": 0.60},
    "deepseek-v3": {"input": 0.27, "output": 1.10},
    "llama3-70b": {"input": 0.0, "output": 0.0},  # 本地部署
}

def run_task(model: str, task: dict, runner) -> TaskResult:
    """执行单个任务"""
    result = TaskResult(
        model=model,
        task_id=task["id"],
        task_type=task["type"],
        difficulty=task["difficulty"],
    )
    
    start = time.time()
    
    try:
        # 1. 构建 Prompt
        prompt = build_prompt(task, model)
        
        # 2. 调用模型
        response = runner.call_model(model, prompt)
        
        # 3. 解析结果
        result.input_tokens = response.usage.input_tokens
        result.output_tokens = response.usage.output_tokens
        
        pricing = PRICING[model]
        result.cost_usd = (
            result.input_tokens * pricing["input"] / 1_000_000 +
            result.output_tokens * pricing["output"] / 1_000_000
        )
        
        # 4. 评分
        if task["type"] == "bugfix":
            result = evaluate_bugfix(result, response, task)
        elif task["type"] == "review":
            result = evaluate_review(result, response, task)
        elif task["type"] == "test":
            result = evaluate_test(result, response, task)
        elif task["type"] == "docs":
            result = evaluate_docs(result, response, task)
        
        result.success = result.score >= 0.7
        
    except Exception as e:
        result.error = str(e)
        result.success = False
    
    result.time_seconds = time.time() - start
    return result

def evaluate_bugfix(result: TaskResult, response, task: dict) -> TaskResult:
    """Bugfix 评分:应用补丁后运行回归测试"""
    # 应用补丁
    apply_patch(response.content)
    
    # 运行测试
    test_output = run_tests(task["test_command"])
    result.tests_passed = test_output.passed
    result.tests_total = test_output.total
    
    # 评分 = 通过率
    result.score = result.tests_passed / result.tests_total if result.tests_total > 0 else 0
    return result

def evaluate_review(result: TaskResult, response, task: dict) -> TaskResult:
    """Code Review 评分:对比发现的问题和已知问题"""
    found_issues = parse_review_comments(response.content)
    known_issues = task["known_issues"]
    
    # 计算召回率和准确率
    true_positives = sum(1 for f in found_issues if matches_any(f, known_issues))
    result.issues_found = len(found_issues)
    
    recall = true_positives / len(known_issues) if known_issues else 0
    precision = true_positives / len(found_issues) if found_issues else 0
    
    # F1 分数
    result.score = 2 * recall * precision / (recall + precision) if (recall + precision) > 0 else 0
    return result

def run_full_benchmark(models: list, tasks: list, runner):
    """运行完整评测"""
    all_results = []
    
    for model in models:
        print(f"\n{'='*60}")
        print(f"评测模型: {model}")
        print(f"{'='*60}")
        
        for task in tasks:
            # 每个任务运行 3 次
            task_results = []
            for run in range(3):
                result = run_task(model, task, runner)
                task_results.append(result)
                print(f"  [{task['type']}] {task['id']} run {run+1}: score={result.score:.2f} cost=${result.cost_usd:.4f}")
            
            # 取均值
            avg_result = average_results(task_results)
            all_results.append(avg_result)
    
    # 保存结果
    with open("benchmark-results.json", "w") as f:
        json.dump([asdict(r) for r in all_results], f, indent=2, ensure_ascii=False)
    
    return all_results

四、实验结果

4.1 综合得分矩阵

模型 Bugfix Review Test Docs 平均 排名
Claude Opus 4 0.88 0.85 0.82 0.86 0.85 1
Claude Sonnet 4 0.82 0.79 0.78 0.81 0.80 2
GPT-4o 0.79 0.77 0.75 0.80 0.78 3
DeepSeek-V3 0.74 0.70 0.72 0.73 0.72 4
GPT-4o-mini 0.62 0.55 0.58 0.60 0.59 5
Llama 3 70B 0.55 0.48 0.52 0.50 0.51 6

4.2 成本效率分析

模型 平均每任务成本 成功率 每成功任务成本 性价比排名
Claude Opus 4 $0.52 85% $0.61 5
Claude Sonnet 4 $0.12 80% $0.15 2
GPT-4o $0.15 78% $0.19 3
DeepSeek-V3 $0.02 72% $0.03 1
GPT-4o-mini $0.005 59% $0.008 4
Llama 3 70B $0.00* 51% $0.00* 6

*Llama 3 70B 为本地部署,API 成本为 0,但需要 A100 GPU(约 $2/小时)

4.3 按任务类型分析

text
Bugfix 成功率(按难度):
                简单    中等    困难
Claude Opus     100%    88%    63%
Claude Sonnet    94%    75%    38%
GPT-4o           88%    75%    38%
DeepSeek-V3      81%    69%    25%
GPT-4o-mini      69%    50%    13%
Llama 3 70B      56%    44%     0%

结论:
- 简单任务:所有云端模型差异不大(>80%)
- 困难任务:Opus 明显领先(63% vs 第二的 38%)
- 本地模型在困难任务上基本不可用

4.4 Code Review 能力对比

模型 平均发现问题数 误报率 严重问题召回率
Claude Opus 4.2 / 5 12% 95%
Claude Sonnet 3.5 / 5 18% 85%
GPT-4o 3.3 / 5 22% 80%
DeepSeek-V3 2.8 / 5 28% 70%
GPT-4o-mini 2.0 / 5 40% 50%
Llama 3 70B 1.5 / 5 55% 35%

Opus 在 Code Review 上的优势最大——不仅发现的问题多,而且误报率最低。

五、结论与推荐

5.1 场景化推荐

场景 推荐模型 理由
生产环境 Bugfix(复杂) Claude Opus 困难任务成功率最高
日常 Bugfix(简单/中等) Claude Sonnet 性价比最优
Code Review Claude Opus 误报率最低,严重问题召回率最高
测试生成 Claude Sonnet 足够好且成本低
文档生成 Claude Sonnet / GPT-4o 两者差异不大
批量简单任务 DeepSeek-V3 成本极低,质量可接受
隐私敏感场景 Llama 3 70B 唯一不出云的选择

5.2 预算分配建议

yaml
# 推荐的模型预算分配
monthly_budget: $2000
allocation:
  claude_opus:
    percentage: 40%      # $800
    use_for: ["complex_bugfix", "security_review", "architecture"]
  
  claude_sonnet:
    percentage: 35%      # $700
    use_for: ["standard_bugfix", "code_review", "test_generation"]
  
  deepseek_v3:
    percentage: 15%      # $300
    use_for: ["batch_formatting", "simple_docs", "lint_fix"]
  
  reserve:
    percentage: 10%      # $200
    use_for: "应急和新模型试验"

六、真实经验与踩坑

6.1 同一模型不同时间的表现有波动

场景:周一测 Claude Sonnet 得分 0.82,周三再测变成 0.78。 问题:模型提供商可能在做灰度更新或负载均衡调整,导致表现波动。 解决方案:每个模型 × 任务组合运行 3 次取均值。评测在 1 周内完成,避免跨版本比较。记录评测时间和模型版本号。

6.2 本地模型需要大量调优

场景:Llama 3 70B 用默认参数跑,得分 0.45。 问题:本地模型对 Prompt 格式、Temperature、Top-P 等参数更敏感。默认参数不一定最优。 解决方案:给本地模型单独做一轮 Prompt 调优(用 10 个验证任务),找到最优参数后再做正式评测。但这意味着本地模型的评测条件和云端模型不完全一致,结论需谨慎对比。

6.3 DeepSeek-V3 的 API 限流影响了评测

场景:DeepSeek-V3 的免费 API 有每分钟 3 次调用的限制。 问题:80 个任务 × 3 次运行 = 240 次调用,需要 80 分钟才能跑完。 解决方案:使用付费 API(更高限额)或者分多天完成。在报告中注明限流对结果的可能影响。

七、参数说明表

参数 类型 默认值 说明
models list 6 个 参评模型列表
tasks_per_type int 20 每类任务数量
run_count int 3 每个任务重复运行次数
temperature float 0.2 统一 Temperature
timeout_seconds int 300 单任务超时
scoring_weights object 均等 各任务类型权重
local_models list ["llama3-70b"] 本地模型列表
cost_tracking bool true 是否记录成本
blind_evaluation bool true Docs 类任务是否盲评

八、落地检查清单

  • 所有模型使用相同的 Prompt 模板和 Temperature
  • 任务集有标准答案,评分可自动化
  • 每个任务重复运行 3 次取均值
  • 成本数据来自各模型官方定价
  • 本地模型的硬件成本也计入对比
  • 结果按任务类型分组统计,不只报总分
  • 包含成本效率分析(每成功任务的成本)
  • 评测在 1 周内完成,避免模型版本变化
  • 结果包含困难任务的单独统计
  • 评测脚本可一键重跑

九、系列导航

上一篇:Agent 成本周报:如何按项目、成员、任务类型拆账 下一篇:Lab 008:本地模型能不能胜任日常 Agent 编码?