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
# 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 按任务类型分析
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 预算分配建议
# 推荐的模型预算分配
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 编码?