
如果你最近关注 AI 编程和模型评测可能见过一种现象同一个模型在 A 评测框架里的得分很高换到 B 框架里就明显缩水。很多人第一反应是“模型被高估了”但真正的问题往往不在模型本身而在它外面那层评测脚手架——也就是 Harness。Hacker News 上有人问过一个问题“有人对构建一个只测 Harness 的 Benchmark 感兴趣吗”这个提问看起来小众却点中了当下 LLM 评测体系里一个非常真实、也非常容易被忽略的盲区我们一直在给模型打分却很少给“评测工具本身”打分。这篇文章想围绕这个问题展开。我会先讲清楚 Harness 到底是什么为什么它直接影响模型得分再给出一个可落地的“Harness-only Benchmark”设计思路和工程示例。如果你正在做模型评测、Agent 应用开发或者想搞清楚 DeepSeek-Harness 这类评测框架到底解决了什么问题这篇文章值得读完并收藏。1. 为什么“只测 Harness 的 Benchmark”值得认真讨论先做一个思想实验。你有一条 prompt同一个开箱即用的模型分别用下面两种方式跑方式 A直接把 prompt 发给模型返回结果后人工判断对错。方式 B用一套完整的评测框架先让模型调用代码解释器执行测试用例再把执行结果反馈给模型最后用判题器自动打分。这两种方式得到的分数差异可能非常大。方式 B 往往分数更高因为模型有机会“试错”有代码执行结果作为反馈有工具可以辅助推理。但请注意模型还是那个模型变化的是它外面的 Harness。所以Harness 在评测中的作用绝对不是“连接 API 的脚本”。它决定了模型能不能发挥出真实水平决定了评测结果是否可复现也决定了得分差距到底有多少来自模型能力、多少来自评测工程。这就是“Harness-only Benchmark”存在的意义把 Harness 本身变成被测对象衡量一个评测设计到底有没有把环境准备、工具调用、判题器、执行反馈这些环节做对。传统的 Benchmark 回答的是“模型强不强”Harness-only Benchmark 回答的是“评测体系能不能把模型的能力测准”。从材料看DeepSeek-Harness 是目前讨论度很高的评测工程项目之一。它在同一个工程体系里支持代码竞赛、数学推理、Agent 自定义任务等多种任务类型并且有一套相对完整的执行环境控制。这类项目会让更多人意识到评测框架不是“调接口的壳”而是有大量工程细节的专业领域。2. Harness 到底指什么不是模板而是评测工程全链路2.1 先给一个清晰定义在 LLM 评测语境下Harness 指“让模型在特定任务上完成推理、输出结果、并被正确评价的全部工程组件”。它至少包含这些部分任务定义与数据加载从哪里读题、如何预处理数据。Prompt 组装模板、few-shot 示例、系统提示。模型调用层统一不同模型供应商的 API、处理并发、超时、重试。工具与沙箱环境是否允许模型调用代码解释器、命令行、浏览器等外部工具。执行反馈循环模型输出后要不要把执行结果返回给模型让它继续修正。判题器怎么判断对错是字符串匹配、测试用例对比还是人工评分。指标聚合与日志如何计算 passk、准确率如何记录中间过程。近两年经常听到一个词叫“Harness Engineering”它的核心就是这个链路。一个严谨的评测框架必须把上述环节全部工程化而不是临时写脚本拼凑。2.2 常见的认知误区第一个误区是“Harness 就是 Prompt 模板”。实际上 Prompt 只占 Harness 的一小部分。真正决定评测质量的是判题器、沙箱环境、反馈机制。比如代码生成任务模型给出代码后Harness 能否在安全沙箱里执行这段代码能否正确抓取 stdout能否把编译错误返回给模型这些都直接决定评分。第二个误区是“评测框架越复杂越好”。复杂没有原罪但如果没有可复现性没有隔离环境没有清晰的判定逻辑复杂只会带来更多噪音。Harness-only Benchmark 要做的事之一就是量化这种复杂带来的收益和代价。第三个误区是“模型分数不够高就是模型不行”。从评测工程的角度看在没有确认 Harness 是否合理之前分数差异不能简单归因于模型能力。这个判断在 Agent 任务上尤其重要因为 Agent 任务高度依赖工具调用和执行反馈。2.3 传统 Benchmark 与 Harness-only Benchmark 的区别对比维度传统 BenchmarkHarness-only Benchmark被测对象模型能力评测工程能力核心问题模型在任务 X 上得多少分同样的任务Harness 设计是否最优变量控制固定 Harness观察模型固定模型观察 Harness典型输出模型分数榜Harness 工程评估报告、配置基线目标用户模型选型、研究对比RAG/Agent 应用开发、评测平台建设者传统评测是有价值的但它的边界也很清楚它很难告诉你“如果换一套评测流程模型能不能表现得更好”。这正是 Harness-only Benchmark 要补充的。3. 传统 Benchmark 测不准的真正原因3.1 模型、采样策略、Harness 三位一体任何一个公开分数本质上都是“模型权重 采样策略 Harness”三者共同作用的结果。单纯的模型能力不是分数差异的唯一变量。举个例子一个模型在采样温度 0 和 temperature 0.7 下的表现会不同在允许代码执行和不允许代码执行的任务里表现也会不同在判题器严格匹配和语义匹配下的得分也可能完全不同。更隐蔽的是执行反馈循环。代码生成任务里如果 Harness 会把运行报错重新喂给模型让模型基于报错信息修改代码那么很多原本不能一次生成正确代码的模型也能在两三次迭代后通过测试。如果你没有意识到这一点看到“某个模型在代码任务上分数很高”就以为它真的具备极强的代码能力其实是低估了 Harness 的贡献。3.2 为什么我们需要 Harness-only BenchmarkHarness-only Benchmark 不是为了否定传统评测而是为了让评测本身变得更科学。它的价值体现在三个层面第一对评测平台建设者来说需要一套方法来判断自己的评测框架是否合格。比如 DeepSeek-Harness 这类框架它有没有把代码执行环境隔离好是否支持多轮反馈判题器有没有针对性优化这些都需要被衡量。第二对 Agent 应用开发者来说Harness 的很多概念与 Agent 运行时高度重叠。工具调用、执行反馈、沙箱隔离、任务终止条件……这些都直接影响 Agent 产品体验。一个好的 Harness-only Benchmark实际上也在帮助开发者理解 Agent 系统的工程瓶颈。第三对学术研究来说只有把 Harness 变量显式化才能避免“团队 A 用简单脚本团队 B 用深度 Harness结果分数不可比”的尴尬局面。3.3 Harness-only Benchmark 应该控制什么如果要做 Harness-only Benchmark控制变量是第一原则。最核心的是固定模型和固定任务集只改变 Harness 设计。可以变化的具体维度包括是否提供多步执行反馈。是否提供代码执行沙箱。工具调用的接口设计。Prompt 组装策略。判题器的严格程度。并行度和重试策略。Agent 循环的最大步数。通过这种控制就可以回答“在同一个任务上Harness 设计的哪些改动最影响最终得分”。4. 构建 Harness-only Benchmark 的设计原则这一节给出可落地的设计方法。它不需要你先有一个庞大平台从一个任务集、一个模型、两套 Harness 配置开始就可以。4.1 任务集要覆盖“依赖工程”的任务类型如果只是让模型做单选题Harness 的影响会被压缩得很小因为流程简单不需要执行环境也不需要反馈循环。要做 Harness-only Benchmark任务集应该优先选择那些“对工具调用和执行反馈敏感”的类型比如代码竞赛题需要运行代码并比对测试用例。数学题需要符号计算或代码验证。Agent 任务比如网页操作、API 调用、数据库查询需要真实环境反馈。这些任务有一个共同点Harness 的设计能决定模型是“闭卷答题”还是“开卷实验”。这两者面对的环境复杂度完全不同。4.2 评测的是工程有效性而不是模型聪明程度设计 Harness-only Benchmark 时不要用“模型有没有解出题”作为唯一指标。更合理的指标是“在同样的模型和任务下Harness 的工程设计带来了多少额外收益”。推荐一个简单的评估公式Harness 增益 使用完整 Harness 的得分 - 使用最简 Harness 的得分。这个差值可以拆解到具体环节比如执行反馈带来的增益、工具调用带来的增益、判题器优化带来的增益。另外还要关注效率指标。比如得到正确答案的平均执行轮数、平均 token 消耗、单任务耗时。这些指标直接反映 Harness 的工程效率与模型能力关系较小。4.3 结果必须能复现Harness-only Benchmark 的结果如果不可复现就失去了参考价值。要做到可复现至少需要固定这几项固定模型版本。固定采样参数。固定任务数据版本。固定依赖包版本。记录每次运行的完整日志包括 prompt、中间输出、工具调用结果、判题结果。从这个角度看DeepSeek-Harness 在工程结构上做了不少值得借鉴的设计。它把任务执行逻辑、API 服务和 runner 拆分得比较清楚允许对执行环境做较细粒度控制这对复现评测结果是有帮助的。5. 一个最小可用的 Harness 评测工程实践下面用一个简化示例演示 Harness-only Benchmark 的核心流程。示例用 Python 编写重点展示“如何以工程方式比较两套 Harness”。5.1 环境准备建议 Python 3.10 以上并准备好虚拟环境python3 -m venv harness_bench_env source harness_bench_env/bin/activate pip install pyyaml requests如果后续要接官方评测框架可以把 DeepSeek-Harness 的源码拉到本地重点阅读它的 runner 和 task 目录理解它如何组织任务执行流程。5.2 目录结构规划一个可维护的 Harness-only Benchmark 工程至少要有这些目录harness_only_bench/ ├── configs/ │ ├── baseline_harness.yaml │ └── full_harness.yaml ├── tasks/ │ └── sample_problem.jsonl ├── runners/ │ ├── baseline_runner.py │ └── full_runner.py ├── judges/ │ └── code_judge.py ├── utils/ │ └── logger.py └── run_benchmark.pyconfigs存放 Harness 配置runners存放不同的 Harness 实现judges存放判题逻辑run_benchmark.py负责整体调度。5.3 定义一个统一的任务封装推荐把所有任务统一成“输入 输出 验证函数”的结构这样不同的 Harness 可以在同一个任务集上运行。# 文件路径tasks/sample_problem.jsonl {id: problem_001, instruction: 求两个整数的最大公约数, function_signature: def gcd(a: int, b: int) - int:, test_cases: [{args: [12, 18], expected: 6}, {args: [7, 13], expected: 1}]} {id: problem_002, instruction: 判断一个字符串是否是回文, function_signature: def is_palindrome(s: str) - bool:, test_cases: [{args: [racecar], expected: true}, {args: [hello], expected: false}]}这种 JSON Lines 格式便于扩展。每条样本都可以携带自己的判题数据不同任务互不干扰。5.4 实现两套 Harness极简版与完整版极简版 Harness 只做一件事把 instruction 和函数签名拼进 prompt让模型直接输出代码然后判题。可以理解为“闭卷答题”。# 文件路径runners/baseline_runner.py import json import re from typing import Any class BaselineRunner: 最简 Harness无执行反馈无工具调用。 def __init__(self, model_api): self.model_api model_api def run(self, task: dict[str, Any]) - dict[str, Any]: prompt f{task[instruction]}\n请只输出 Python 函数代码不要输出解释。\n函数签名{task[function_signature]} response self.model_api.generate(prompt) code self._extract_code(response) judge_result self._judge(task, code) return { task_id: task[id], code: code, judge_result: judge_result, } def _extract_code(self, response: str) - str: match re.search(rpython\n(.*?)\n, response, re.DOTALL) return match.group(1) if match else response.strip() def _judge(self, task: dict[str, Any], code: str) - dict[str, Any]: # 简化判题如果代码里包含 def就认为输出结构合法 # 真实场景应该执行代码并比对测试用例 passed def gcd in code or def is_palindrome in code return {passed: passed, detail: code[:200]}注意这里的_judge是极简示例真实项目中判题逻辑不会这么粗糙。完整版 Harness 的核心差异在于它会把代码放到一个可执行的沙箱里运行测试用例把测试结果返回给模型让模型根据错误信息修改代码。这是多轮反馈机制的关键。# 文件路径runners/full_runner.py import subprocess import tempfile import textwrap from typing import Any class FullRunner: 完整 Harness包含代码执行、测试反馈、多轮修正。 def __init__(self, model_api, max_rounds: int 3): self.model_api model_api self.max_rounds max_rounds def run(self, task: dict[str, Any]) - dict[str, Any]: prompt f{task[instruction]}\n函数签名{task[function_signature]} code self.model_api.generate(prompt) code self._extract_code(code) history [] for round_index in range(self.max_rounds): test_output self._execute_in_sandbox(code, task[test_cases]) history.append({round: round_index 1, test_output: test_output}) if test_output[all_passed]: return { task_id: task[id], code: code, rounds: round_index 1, passed: True, history: history, } feedback self._build_feedback(task[instruction], code, test_output) revised_code self.model_api.generate(feedback) code self._extract_code(revised_code) # 最后一轮再执行一次记录最终结果 final_output self._execute_in_sandbox(code, task[test_cases]) return { task_id: task[id], code: code, rounds: self.max_rounds, passed: final_output[all_passed], history: history, } def _extract_code(self, response: str) - str: import re match re.search(rpython\n(.*?)\n, response, re.DOTALL) return match.group(1) if match else response.strip() def _execute_in_sandbox(self, code: str, test_cases: list[dict]) - dict: # 真实环境应该用 Docker 或受限用户执行 # 这里用 subprocess tempfile 做最小演示 all_passed True results [] with tempfile.TemporaryDirectory() as tmp_dir: script_path f{tmp_dir}/solution.py with open(script_path, w, encodingutf-8) as f: f.write(code) for case in test_cases: case_code ffrom solution import *; print(judge({case[args]})) # 这里只是演示真实场景需要把参数序列化后调用函数 # results 收集每次测试的 stdout、stderr、退出码 proc subprocess.run( [python3, -c, case_code], cwdtmp_dir, capture_outputTrue, textTrue, timeout10, ) passed proc.returncode 0 all_passed all_passed and passed results.append({args: case[args], passed: passed, stdout: proc.stdout}) return {all_passed: all_passed, results: results} def _build_feedback(self, instruction: str, code: str, test_output: dict) - str: return textwrap.dedent( f 你生成的代码未能通过全部测试。 {instruction} 当前代码 {code} 测试结果 {test_output} 请根据测试反馈修正代码只输出 Python 代码。 )这个示例里的沙箱执行仍然很简陋没有真正执行测试函数、没有处理函数名解析、没有完整序列化参数。生产环境必须用 Docker 或 Firecracker 这类隔离方案。但核心思想已经体现两套 Harness 在同一个模型、同一种测试数据上差异只在于是否有执行反馈和修正循环。5.5 统一调度入口# 文件路径run_benchmark.py import json import random from runners.baseline_runner import BaselineRunner from runners.full_runner import FullRunner class FakeModelAPI: 模拟模型响应。真实场景替换为 OpenAI / Anthropic / DeepSeek API。 def generate(self, prompt: str) - str: # 模拟模型输出这里只返回一个示例 # 实际使用时这个类应该封装真正的模型调用 if 最大公约数 in prompt or 回文 in prompt: return python\ndef placeholder():\n pass\n return python\ndef placeholder():\n pass\n def load_tasks(path: str) - list[dict]: tasks [] with open(path, encodingutf-8) as f: for line in f: if line.strip(): tasks.append(json.loads(line)) return tasks def main() - None: tasks load_tasks(tasks/sample_problem.jsonl) model FakeModelAPI() baseline_runner BaselineRunner(model) full_runner FullRunner(model, max_rounds3) baseline_scores [] full_scores [] for task in tasks: baseline_result baseline_runner.run(task) full_result full_runner.run(task) baseline_scores.append(1 if baseline_result[judge_result][passed] else 0) full_scores.append(1 if full_result[passed] else 0) print(Baseline Harness Score:, sum(baseline_scores) / len(baseline_scores)) print(Full Harness Score:, sum(full_scores) / len(full_scores)) print(Harness Gain:, (sum(full_scores) - sum(baseline_scores)) / len(tasks)) if __name__ __main__: main()运行方式python run_benchmark.py预期输出会显示两套 Harness 的分数差异。当然用上面的模拟模型 API分数可能是 0因为 placeholder 根本不会通过测试。把FakeModelAPI换成真实模型后两套 Harness 的差异会直观暴露出来。这里的重点是通过一个统一入口、两套 runner、一个任务集就能开始积累 Harness-only 的量化数据。6. 运行与验证如何判断 Harness 好坏6.1 运行结果如何解读Harness-only Benchmark 的价值不在于最终分数高低而在于分数差异的“可解释性”。运行之后重点看几个指标Harness Gain完整 Harness 相比最简 Harness 高多少分。增益越大说明任务越依赖执行反馈Harness 的工程价值越明显。平均修正轮数完整 Harness 里模型通过多少轮反馈才得到正确答案。轮数越少说明反馈信息质量越高。单任务耗时和 token 消耗完整 Harness 会在反馈循环里消耗更多 token。如果增益不明显说明反馈设计需要调整。6.2 判断 Harness 设计是否合理如果出现下面这些情况说明 Harness 可能存在工程问题模型输出格式稳定但判题器一直误判。这可能不是模型问题而是判题逻辑没有处理好。测试代码本身报错却被当成模型答案错误。这说明沙箱环境不可靠。多轮反馈之后分数没有提升。可能是因为反馈信息太冗余模型无法定位错误。6.3 一套健康的 Harness 应该有什么表现一套设计良好的 Harness应当让模型稳定发挥而不是偶尔爆发。具体表现在不同采样温度下分数波动在合理范围内。多次重复运行同一任务结果一致。单轮反馈的信息量集中模型能精确修改错误。沙箱执行失败率低超时和崩溃可控。这三个指标可以用一张表汇总指标含义健康区间Harness Gain完整 Harness 带来的分数提升因任务而异但要正向可解释修正轮数从首次输出到正确答案的轮数越少越好3 轮内为宜沙箱失败率执行环境自身出错的概率趋近于 07. 常见坑与排查清单7.1 常见问题汇总问题现象可能原因排查方式解决方案两套 Harness 分数没有差异任务本身不依赖执行反馈检查任务类型是否适合换成代码执行或 Agent 类任务代码能跑但判题失败判题逻辑没有兼容函数名查看判题器日志按函数签名动态注入调用代码多轮反馈后分数不升反降反馈信息过于混乱打印每轮反馈原文结构化反馈直接输出测试名称和错误类型沙箱进程残留未设置超时或未清理进程组查看系统进程列表使用容器设置 timeout执行后强制清理结果无法复现依赖版本或采样参数不固定检查 run 配置和日志锁定版本记录完整实验配置pnpm dsh web 卡住前端构建阶段执行耗时较长或网络拉取依赖受限查看 pnpm 日志和网络状态使用镜像源或先跳过前端构建直接验证后端 runner7.2 排错顺序建议如果 Harness-only Benchmark 的结果出现异常不要急着改模型先按这个顺序排查先看判题器是不是误判了。再看沙箱是不是命令执行失败而不是模型答案失败。再看反馈反馈给模型的 prompt 是否包含足够的错误上下文。最后才看模型同一个 Harness 下换一个模型确认模型差异是否独立于 Harness。这个顺序非常重要。很多团队一看到分数波动就归因于模型往往忽略了 Harness 才是那个“看不见的变量”。8. 最佳实践与工程建议8.1 设计 Harness-only Benchmark 的工程建议如果你打算在真实项目里落地 Harness-only Benchmark下面这些建议值得实践第一把 Harness 配置与代码分离。Harness 的差异不应该通过改代码实现而应该通过配置切换。比如 yaml 里定义是否启用代码执行、是否开启多轮反馈、最大轮数是多少。这样你才能快速跑出多组对照实验而不是每次都要改一遍 runner。# 文件路径configs/full_harness.yaml harness_type: full max_rounds: 3 enable_code_execution: true sandbox: docker feedback_mode: structured judge_mode: test_case# 文件路径configs/baseline_harness.yaml harness_type: baseline max_rounds: 1 enable_code_execution: false sandbox: none feedback_mode: none judge_mode: string_match第二给每次运行生成唯一的实验 ID。把所有 prompt、中间输出、工具调用结果、判题结果都写进日志文件。后续做归因分析时这些日志就是金矿。第三先跑通一个任务再扩展到全量任务。不要一开始就铺几百道题。先找出 5 道能体现 Harness 差异的题把流水线跑稳再逐步扩大。这种做法能大幅降低调试成本。第四固定模型版本和采样参数。Harness-only Benchmark 的对照组是“不同 Harness”不是“不同模型”。如果模型版本都不固定结果很难归因。8.2 安全边界必须严肃对待在执行模型生成的代码时沙箱是绝对必要的。即使只是评测也不能信任模型的输出。建议使用 Docker 容器并去掉网络访问权限。设置执行超时避免死循环占满 CPU。限制内存和文件系统写入范围。不要在沙箱里挂载真实项目的密钥和配置。在所有评审、运行时环境中明确“代码执行可能带来安全风险”操作前要在测试环境验证。8.3 与 Harness 相关的新方向从当前趋势看Harness Engineering 正在变成一个新的工程方向。它与普通后端开发不同更强调“在模型不可控的前提下设计可控的评测与执行环境”。以下方向比较值得持续关注可观测性的评测链路把模型的每一步工具调用都记录下来。动态判题器根据任务类型自动选择判定策略。多轮反馈优化如何用最少的反馈轮数让模型达到最高正确率。统一 Harness 抽象层让同一份 Harness 配置可以跑在多个模型和多个任务集上。DeepSeek-Harness 这类开源项目正在推动 Harness 工程从“论文附属代码”变成“正式的基础设施”。这件事的意义可能比多刷一分模型分数更大。9. 总结与后续实践建议回到最初那个 Hacker News 问题构建一个只测 Harness 的 Benchmark到底值不值得从工程师的角度看很值得。因为 Harness 不是评测过程中的边角料它决定了模型能力能不能被准确理解。传统 Benchmark 把 Harness 当成固定的背景板Harness-only Benchmark 则把它放到聚光灯下专门考察“评测系统本身设计得好不好”。这个命题在 Agent 应用越来越复杂的今天会变得越来越重要。如果你决定开始实践建议不要先急着搭建完整平台。从最小闭环开始找一个需要代码执行的任务集固定一个模型实现一版“极简 Harness”和一版“带执行反馈的完整 Harness”对比两者得分差异。再把差异拆解到反馈轮数、判题器设计、沙箱稳定性这些具体维度上。当你能够解释每个 Harness 环节给结果带来了多少收益时你才算真正理解了评测。如果想深入研究可以直接阅读 DeepSeek-Harness 的源码重点看它的 task 组织方式、runner 执行逻辑和判题器设计。读这些代码的好处是你能看到一个成熟评测框架如何把执行环境、反馈循环、任务定义拆得清清楚楚。这也是理解 Harness Engineering 最直接的路径。