同一个模型换了Harness,代码质量差了3倍——AI编程的瓶颈不在模型

2 阅读9分钟

社区天天讨论哪个模型 SWE-bench 分高、哪个代码能力强。我做了一个对照实验:固定模型不变,只改变它的运行环境(Harness),代码质量差了 3 倍。决定 AI 编程效果的不是模型,是 Harness。

一个反直觉的现象

上周我让 DeepSeek V3 帮我写一个 Express 中间件。直接在普通聊天窗口里给它需求,它写出来的代码能跑,但风格和项目完全不搭——变量命名用了 camelCase(项目是 snake_case),错误处理用了 try-catch(项目统一用 error middleware),甚至导入路径都是猜的。

然后我在 Claude Code 里给了完全相同的需求,同样用 DeepSeek V3(通过 API 网关切过去的)。这次它写出来的代码风格完全一致——snake_case、error middleware、正确的导入路径、甚至注释风格都对了。

同一个模型,同一个需求,输出质量天差地别

差异在哪?在模型周围的那套系统——业界现在叫它 Harness

Harness Engineering 是什么

Harness 是 AI Agent 的"运行时环境"。它不是模型本身,而是模型周围的一切:系统提示词、可用工具、项目上下文、编码规范、记忆系统、错误恢复策略。

一个类比:模型是发动机,Harness 是整辆车。同一台发动机装在拖拉机和跑车里,性能体验完全不同。

Harness 的组成:
├── 系统提示词(角色定义、行为约束)
├── 项目上下文(CLAUDE.md / .cursorrules / 代码库索引)
├── 工具集(MCP Server、文件操作、Shell 命令)
├── 上下文管理策略(窗口大小、历史压缩、注入时机)
├── 记忆系统(跨 session 的知识持久化)
└── 错误恢复(重试、降级、自我修正循环)

2026 年 AI 编程工具的竞争,已经从模型层转移到了 Harness 层。Claude Code、Cursor、Codex 底层都能接多种模型,真正的差异化在 Harness 的设计上。

实验设计:同一模型,三种 Harness

我固定使用 DeepSeek V3,准备了三种 Harness 配置,让它完成同一组编码任务。

三种配置

配置 A:裸模型(Bare)

  • 只有基础的系统提示:"你是一个编程助手"
  • 没有项目上下文、没有工具、没有记忆
  • 相当于在普通聊天窗口里写代码

配置 B:标准 Harness(Standard)

  • 系统提示包含角色定义和基础规范
  • 接入了文件读写和 Shell 工具
  • 手动给它 2-3 个相关文件作为上下文
  • 没有 CLAUDE.md、没有代码库索引、没有记忆

配置 C:完整 Harness(Full)

  • 详细的 CLAUDE.md(编码风格、架构规范、禁止模式)
  • 完整的 MCP 工具链(文件、Shell、Git、搜索)
  • 代码库索引(Agent 能自主浏览项目结构)
  • 上下文管理(滚动窗口 + 历史压缩)
  • 跨 session 记忆(记得之前的决策和偏好)
# 三种配置的代码差异只在系统提示和工具注册
# 模型完全相同:DeepSeek V3,temperature 0.3

# 配置 A:裸模型
messages_a = [
    {"role": "system", "content": "你是一个编程助手。"},
    {"role": "user", "content": task_prompt}
]

# 配置 B:标准 Harness
messages_b = [
    {"role": "system", "content": STANDARD_SYSTEM_PROMPT},
    {"role": "user", "content": f"项目相关文件:\n{context_files}\n\n任务:{task_prompt}"}
]

# 配置 C:完整 Harness
# 通过 Agent 框架执行,自动注入 CLAUDE.md、工具、记忆
agent.execute(task_prompt, tools=full_mcp_tools, memory=persistent_memory)

任务集

10 个编码任务,覆盖不同复杂度:

编号任务复杂度
T1写一个字符串工具函数
T2实现一个 Express 中间件
T3写一个数据库迁移脚本
T4实现分页查询 API(含参数校验)
T5写一个 WebSocket 消息处理器
T6实现带重试的 HTTP 客户端
T7写一个定时任务调度器中高
T8实现 JWT 认证中间件(含刷新逻辑)中高
T9写一个事件发布/订阅系统
T10实现乐观锁的并发更新逻辑

评分维度(每项 1-5 分)

维度评估标准
正确性代码逻辑对不对,能不能跑
风格一致性命名、缩进、注释风格是否和项目统一
架构适配是否遵循项目的分层、模式和约定
边界处理错误处理、空值检查、参数校验
可维护性代码是否清晰、模块化、易于修改

实验结果

总分对比

配置平均总分(/25)相对裸模型
A 裸模型10.3基线
B 标准 Harness17.8+73%
C 完整 Harness22.1+115%

完整 Harness 的代码质量是裸模型的 2.1 倍。 如果只看风格一致性和架构适配两个维度,差距超过 3 倍。

各维度详细数据

维度裸模型 (A)标准 (B)完整 (C)
正确性3.44.14.5
风格一致性1.23.24.7
架构适配1.12.94.5
边界处理2.43.64.2
可维护性2.24.04.2

三个关键发现:

发现 1:正确性差距最小。 裸模型也能写出基本正确的代码(3.4/5)。模型本身的编码能力已经很强了。差距主要在"正确但不适合这个项目"上。

发现 2:风格一致性差距最大。 裸模型只有 1.2 分(几乎完全不符合项目风格),完整 Harness 达到 4.7 分。这就是为什么裸用模型写的代码"看着就不对"——风格不是错,是不一致。 而 CLAUDE.md 里的编码规范直接解决了这个问题。

发现 3:标准 Harness 已经覆盖了大部分收益。 从 A→B 的提升(+73%)远大于 B→C 的提升(+24%)。这意味着你不需要一个完美的 Harness,一个"够用"的 Harness 就能拿到大部分收益。

按任务复杂度拆分

复杂度裸模型标准完整A→C 提升
低 (T1-T2)13.519.022.0+63%
中 (T3-T6)10.518.022.5+114%
中高 (T7-T8)9.017.522.0+144%
高 (T9-T10)7.015.521.0+200%

任务越复杂,Harness 的价值越大。 简单任务裸模型也能应付(提升 63%),高复杂度任务 Harness 带来 3 倍提升。这很好理解——简单函数不需要太多上下文,复杂系统设计严重依赖对项目架构的理解。

消融实验:哪个 Harness 组件最重要

完整 Harness 有 5 个组件。我逐个关闭,看每个组件对总分的贡献:

关闭的组件总分相比完整 Harness
无(完整 Harness)22.1基线
关闭记忆21.3-3.6%
关闭上下文管理20.5-7.2%
关闭 MCP 工具18.9-14.5%
关闭代码库索引17.2-22.2%
关闭 CLAUDE.md15.1-31.7%

CLAUDE.md(项目规范文件)是最重要的单一组件。 关掉它之后质量暴跌 31.7%。这一个文件告诉模型:项目用什么命名规范、什么架构模式、什么是禁止的——没有它,模型只能靠猜。

第二重要的是代码库索引(-22.2%)——让 Agent 能自主浏览项目结构,而不是靠你手动喂文件。

记忆和上下文管理的影响相对小(-3.6% 和 -7.2%),因为我的测试任务是单次执行的。如果是多轮迭代开发,记忆的价值会大得多。

实战建议:最小可用 Harness

如果你现在还在裸用模型写代码(聊天窗口直接问),做两件事就能拿到 70% 以上的收益:

第一步:写一份 CLAUDE.md(20 分钟)

# Project Rules

## 编码规范
- 变量命名: snake_case
- 函数命名: camelCase  
- 文件命名: kebab-case
- 缩进: 2 空格
- 分号: 不加

## 架构约定
- 分层: router → controller → service → repository
- 错误处理: 不用 try-catch,统一走 error middleware
- 数据校验: 在 controller 层用 zod 校验
- 数据库: 用 drizzle ORM,不写裸 SQL

## 禁止
- 不要用 any 类型
- 不要用 console.log 做日志(用 pino)
- 不要在 service 层直接访问 request 对象

这份文件不需要写得很长。30 行就够了,关键是把"我们项目里绝对不做的事"写清楚。 模型不知道你的约定,你不说它就会用它训练数据里最常见的模式。

第二步:让 Agent 能浏览代码库

给 Agent 配一个文件读取工具,让它在写代码之前先看看项目里现有的同类文件是怎么写的。

# 在 Agent 的系统提示里加一句
"在写任何代码之前,先用工具查看项目中同类文件的实现方式,
确保你的代码风格和现有代码一致。"

这句话让模型从"凭空创作"变成"参考现有代码"——风格一致性会大幅提升。

效果估算

投入预期质量提升
写 CLAUDE.md(20 分钟)+50-60%
加文件浏览工具(10 分钟)再 +15-20%
总计 30 分钟+70-80%

30 分钟的一次性投入,之后每次 AI 编码都受益。这个 ROI 比换模型高得多——升级到 Opus 4.7 的提升大约 10-15%,但花费多了 5 倍以上。

对模型选型的影响

这个实验改变了我对模型选型的看法。

以前我觉得"写代码就要用最好的模型"。现在我的策略是:先把 Harness 搭好,再选模型。 一个好的 Harness + 中端模型,效果好于一个差的 Harness + 旗舰模型。

实测数据验证这个判断:

组合总分(/25)
DeepSeek V3 + 完整 Harness22.1
Opus 4.7 + 裸模型13.8

DeepSeek V3(0.27/MTok)配完整Harness的质量,超过了Opus4.70.27/MTok)配完整 Harness 的质量,超过了 Opus 4.7(5/MTok)裸用的质量。便宜 18 倍的模型,靠 Harness 反超了。

当然,最佳组合是旗舰模型 + 完整 Harness。但如果预算有限,先投入 Harness 的 ROI 远高于升级模型。有需要的时候把关键任务路由到旗舰模型就行——我自己日常编码走 DeepSeek,架构决策切 Opus 4.7,都在 TheRouter 上一个 Key 搞定的,切模型改个字符串的事。

常见问题

Q: CLAUDE.md 和 .cursorrules 有什么区别? A: 格式不同,目的一样——都是给 AI 编程工具看的项目规范文件。CLAUDE.md 是 Claude Code 的约定,.cursorrules 是 Cursor 的约定。内容可以互相复制,核心都是编码规范 + 架构约定 + 禁止列表。不管用什么工具,写一份这样的文件是收益最高的单一优化。

Q: Harness Engineering 和 Prompt Engineering 的区别? A: Prompt Engineering 优化的是"怎么跟模型说话"(单次输入)。Harness Engineering 优化的是"模型运行在什么环境里"(系统级)——包括工具、上下文、记忆、错误恢复整套运行时。Prompt 是 Harness 的一个子集。2026 年的共识是:只优化 prompt 远远不够。

Q: 消融实验里记忆影响最小(-3.6%),那记忆不重要? A: 单次任务里确实不重要。但连续开发多天的场景下,记忆的价值会显著上升——Agent 记得你之前做的技术决策、踩过的坑、偏好的方案。这个实验是单任务的,低估了记忆在真实工作流里的价值。