Harness-Only Benchmark:将工程脚手架与模型能力解耦的评测新方法

📅 2026/8/27 5:05:19
Harness-Only Benchmark:将工程脚手架与模型能力解耦的评测新方法
harness-only benchmark 这个概念最近在评测圈讨论得不少简单说就是只评测 harness不评测模型。Harness 指的是模型外面那一层工程脚手架提示词模板、工具调用协议、记忆管理、重试逻辑、并发调度、输出解析、缓存策略……这些都不属于模型本身的权重参数却实实在在影响评测最终能拿到多少分。只要你搭过 agent 应用或者跑过多模型对比大概率遇到过同一个模型换一套框架后效果明显变化的情况这就是 harness 在起作用。这篇文章适合正在做 agent 评测、RAG 验证、模型选型或者想把自己的工具链固化下来的人。最值得先说清楚的一点harness-only benchmark 不是要证明哪个模型更强而是要证明哪一层工程更稳。1. 先理清什么是 harness以及为什么值得单独评测1.1 模型能力和外围工程要分开看很多人在做评测时默认分数高低就是模型能力高低。这个判断在纯模型评测里成立但在 agent 应用、RAG 流水线、工具调用场景里并不成立。因为真正跑任务的是一整套系统模型只是其中一部分。你可以在本地把模型跑起来给它一段 prompt让它输出一段文本这是模型能力。但一旦接入业务prompt 需要拼装、工具描述需要格式化、模型输出需要解析、失败需要重试、上下文需要截断、并发需要排队、缓存需要管理这一整套东西就是 harness。模型能力可以理解成“一个人本身会不会做这件事”harness 可以理解成“你给这个人配了什么工作台、什么流程、什么检查机制”。同一个人工作台顺手和不顺手产出质量差别很大。同一个模型harness 不同评测分数也可以差出十几个点。这不是玄学而是工程层的真实损耗。我见过不少项目两套框架调用同一个模型 API一个任务集得分 85另一个只有 70。模型没变prompt 模板顺序不同、工具描述写法不同、输出解析丢字段、缓存返回了旧结果分数就拉开了。如果不把 harness 单独拆出来看你会误以为是模型选型出了问题。1.2 为什么结果波动时第一个怀疑对象应该是 harness这里有一个实测中经常会遇到的场景同一套系统上个月跑评测还正常这个月突然掉点。很多人第一反应是模型更新了、数据变了或者 API 服务不稳。但我更建议先查 harness。原因很简单模型版本如果没动能力按道理不会突然变化。而 harness 是代码代码随时可能被改某个工具描述被精简了、超时时间从 60 秒改成了 20 秒、重试次数从 3 次改成 1 次、缓存目录被清理导致每次都真实调用、日志里某个字段被改坏导致解析失败。这些改动往往不大但都会让最终分数产生明显波动。所以做评测的第一原则把 harness 当成一个独立组件来管理。它要有版本号要有日志要有自己的回归测试。否则评测分数波动时你连是模型的问题还是工程的问题都分不清。如果搜索热度能说明问题那么“harness 工程”这个概念正在被越来越多的人关注。大家开始意识到评测结果不好不能全怪模型先把外面的壳子检查一遍再说。2. 一套 harness-only benchmark 需要包含哪些模块2.1 任务集要小、要稳定、不要考模型知识harness-only benchmark 的任务集和普通模型评测任务集有本质区别。普通评测要测出模型能力的上限任务要难harness-only benchmark 要测出工程层是否可靠任务要简单。任务应该简单到“只要 harness 正常工作任何主流模型都能答对”这样分数差异才能归因到 harness 上。如果任务本身很难模型答错你分不清是模型不会还是 harness 没把材料传对。任务类型可以从这几个方向选文本分类给定文本要求输出指定类别。信息抽取从文本中抽出字段按固定格式返回。工具调用根据用户需求决定调用哪个工具、传什么参数。多轮状态连续对话中保持历史状态不丢失前文信息。数量不用多20 到 50 条就够。任务集太大反而难维护而且容易引入模型知识相关的内容破坏“只测 harness”的纯度。如果条件允许最好用脚本自动生成样例避免评测数据泄露和人工标注不一致的问题。2.2 接口契约把输入输出固化成 Schemaharness-only benchmark 的第二块核心是接口契约。输入长什么样、输出必须长什么样要先定死。输入侧至少包含任务 ID、用户请求、可用的工具定义。输出侧则要约定结构化结果不能是自由文本。下面是一个工具调用类任务的最小示例{ task_id: tool_call_001, prompt: 请调用 search 工具查询今天上海的天气, tools: [ { name: search, parameters: { query: {type: string} } } ], expected: { tool: search, arguments: { query: 今天上海的天气 } } }这份 JSON 既是任务描述也是验证标准。harness 跑完这条任务后要把模型输出解析成同样的结构然后和 expected 做比对。接口契约定得越细越能暴露 harness 在输出解析、字段映射、类型转换上的问题。我见过大量评测结果异常最后都追溯到输出解析这一层。模型返回的内容五花八门有的是 JSON 包在 markdown 代码块里有的在 JSON 前后加了大量解释有的把字段名从下划线改成驼峰。如果 harness 的解析器不够健壮这些情况都会变成失败样本。2.3 Mock 模型真正做到“只测 harness”的关键要做到真正的 harness-only最好的办法不是用真实模型而是用 mock 模型。Mock 模型就是一段固定返回脚本化结果的程序它会根据输入返回预设的响应包括各种边界情况空字符串、多余文本、错误的 JSON 格式、乱序的工具调用、中英文混合的标点符号。用 mock 模型有几个实际好处。第一结果完全确定不会因为模型采样随机性干扰判断。第二不消耗真实 API 调用跑成本几乎为零。第三可以刻意制造异常输入检验 harness 的容错能力。我一般会准备三档 mock 响应完美响应、轻微问题响应、严重问题响应。完美响应用来验证主流程轻微问题响应用来验证解析器的容错严重问题响应用来验证失败重试和错误上报。每一档都有明确预期harness 处理得好不好一目了然。这一步是很多人容易偷懒的地方。如果直接用真实模型跑分数波动时你很难判断是 harness 的问题还是模型随机性的问题。先用 mock 模型把工程层跑干净再引入真实模型这时候再出问题才能放心地把锅扣给模型。2.4 评分、基线与噪声控制评测必须要有评分。harness-only benchmark 建议从这些维度打分格式合法率模型输出经过解析后有多少比例能变成合法结构化结果。工具调用准确率解析出的工具名和参数与预期是否一致。任务完成率端到端任务是否达到预期结果。重试率多少任务触发了重试重试是否解决了问题。超时率多少任务因为超时失败。Token 损耗相比理想输出harness 多加了多少无效请求或重复输出。评分的意义不是单一指标越高越好而是要看组合。比如任务完成率高但重试率也高说明 harness 在用重试硬撑真实场景下延迟和成本都会恶化。基线也要设计。最简单的基线可以直接用“裸 prompt 模板 简单解析函数”对比你精心设计的完整 harness。只有知道基线是多少才能判断你的 harness 设计到底提升在哪提升多少。最后是噪声控制。模型评测最怕噪声harness-only benchmark 也一样。采样参数要固定通常把 temperature 设为 0缓存策略要么统一禁用要么统一启用每条任务跑多遍取稳定结果任务执行顺序要做随机交错避免位置效应。这些细节看起来琐碎但都会影响最终结论。3. 从零搭一套可复现的实验流程3.1 先把环境和依赖锁死评测类工作最怕环境不一致。同一套代码不同机器、不同依赖版本、不同包管理器跑出来的结果可能完全不同。所以第一件事不是写代码而是锁环境。建议至少固定这几项Node 或 Python 运行时版本。包管理器版本比如 npm、pnpm、uv、pip。依赖锁文件确保每次安装的依赖完全一致。评测入口命令统一固定参数。如果你是新手可能更容易踩到安装阶段的坑。搜索热度里能看到不少人在问 harness 工具怎么安装、怎么部署甚至有“卡在 pnpm dsh web”这类关键词。这类问题大多不是工具本身不行而是本地 Node 版本和项目要求不一致、依赖锁文件没对齐、registry 源配置有问题。解决方案也很常规先统一 Node 版本再用 lockfile 安装清掉本地缓存后重试。下面给出一个示例流程# 先确认运行时版本 node --version pnpm --version # 使用锁文件安装依赖 pnpm install --frozen-lockfile # 启动评测入口先传入单条样例 pnpm run eval --task sample.json --mock model注意这里的命令是通用示例具体参数要以你用的 harness 项目文档为准但“先锁环境、再装依赖、再跑样例”的顺序是通用的。3.2 单条样例先跑通环境准备完成后不要急着开批量先跑一条样例。这一条样例要用 mock 模型输入输出都要打印出来日志要完整。我会重点看三样东西输入给模型的 prompt 是否和我预期一致模型返回的原始内容是否正常harness 解析后的输出结构是否合法。这三样都对了才说明主流程是通的。如果这条样例就报错优先看日志不要猜。报错信息里通常会直接指出是依赖缺失、路径错误、还是解析失败。很多人在这一步浪费时间是因为不看日志直接改参数改完再跑还是错。单条样例跑通还有一个好处你可以把这条样例当作回归测试。以后改动 harness 不管怎么调先跑这一条能过再继续能省大量排错时间。3.3 再跑批量与多轮场景单条稳定之后再扩到批量。我个人习惯是分三档先跑 5 条再跑 20 条最后跑全量 50 条。每一档都观察任务队列是否正常、失败任务是否有重试、输出文件名是否冲突、日志是否有遗漏。批量场景最容易暴露的问题有三个。第一是并发控制同时发出太多请求可能触发限流导致超时和重试第二是输出命名批量任务的输出文件如果都叫 result.json后面的会覆盖前面的第三是失败隔离某一条任务失败不能让整个批量任务中断。多轮场景也要单独测。多轮对话涉及状态保存harness 需要把前几轮的上下文正确传给模型。常见错误是上下文越积越长超过窗口限制或者中间某轮解析失败导致后续轮次全部异常。3.4 把每次运行都留痕评测必须可复现可复现的前提是留痕。每次运行至少保存以下信息配置快照包括模型名称、采样参数、harness 版本。每条任务的原始 prompt。模型原始返回内容。解析后的结构化结果。耗时、重试次数、token 用量。最终的评分汇总。保存这些内容看起来费空间但实际很有必要。以后某个分数异常你可以回溯到具体某一条任务看是输入拼错了、输出解析错了还是评分逻辑错了。没有留痕的评测分数只是数字无法定位问题。4. 关键指标与判断标准4.1 指标表harness-only benchmark 的指标不需要多但每个指标都要有明确的判断标准。下面是我会重点记录的指标表指标衡量什么判断标准格式合法率输出解析是否可靠稳定运行时应接近 100%低于 95% 优先查解析器工具调用准确率工具选择和参数构造是否正确依赖 mock 模型预期波动说明 harness 拼装有问题任务完成率端到端任务是否成功不低于 90%具体看任务集难度重试率失败后能否自愈高于 20% 说明前置环节不稳定不能靠重试掩盖超时率链路是否够快真实场景下应接近 0否则检查并发和超时参数Token 损耗工程层是否浪费对比理想输出额外 token 占比越高越需要优化确定性多次运行结果是否一致同一配置下波动大说明噪声控制失效注意表格里的百分比是通用经验值不是行业标准。你的任务集、模型、环境不同标准会变。关键是先记录再根据实际情况定基线。4.2 不要只用“胜率”衡量 harness很多人喜欢用“胜率”来总结评测结果特别是 agent 场景下的 A/B 对比。比如 harness A 和 harness B 在同一个任务集上各跑一轮看谁赢的任务多。这个思路直观但也有问题。胜率只告诉你谁赢了不告诉你赢在哪、输在哪。两个 harness 可能得分相同但失败模式完全不同一个超时多一个解析错多一个重试多一个 token 浪费多。只看胜率这些信息全丢了。我更建议同时看失败模式分布。把每条失败任务归类解析失败、超时失败、工具参数错误、上下文截断、缓存命中错误。看到失败模式你就知道下一轮优化要改 parser、改超时策略、改缓存策略还是改 prompt 模板。评测圈里经常有人把一个模型家族的 benchmark 结果和 harness 放在一起搜比如“nemotron-3.5 benchmark”“deepseek harness”这类组合词。这说明大家真正的需求是我手上有一个具体模型我想知道把它放进我的 harness 里能跑出什么效果。这个需求恰好是 harness-only benchmark 要回答的模型是变量harness 是对象评测要做的是把两者解耦。5. 实测中的常见坑和排查顺序5.1 安装启动阶段先看依赖再看文档harness 工具第一次跑不起来是最常见的入门问题。从搜索热度看很多人都在搜“deepseek harness 安装”“deepseek harness 怎么使用”“deepseek harness 部署”之类的问题。这类搜索背后往往不是工具复杂而是环境没有对齐。我遇到过的安装启动问题一半以上出在依赖版本上。Node 版本太老某些依赖装不上Python 版本太高某些扩展编译失败pnpm 锁文件和 package.json 不一致安装报错。还有一部分是网络和依赖源问题依赖拉不下来或拉一半失败。解决办法就是先按文档把运行时版本对齐用锁文件安装清缓存重试再看具体报错。如果启动过程卡在“pnpm dsh web”之类的步骤上不要反复重装。先看日志卡在哪一步是依赖下载、构建、还是端口占用。端口占用很常见换一个端口或者杀掉旧进程就能解决。5.2 输出解析和编码问题评测异常里输出解析问题占比最高。模型返回内容经常不是干净 JSON常见情况包括JSON 被 markdown 代码块包裹。JSON 前后有多余解释文字。字段名大小写不一致。中文标点被当成 JSON 内容。返回了空字符串或者截断的半截 JSON。harness 的解析器要能处理这些情况。我的做法是分三层先提取代码块再尝试严格 JSON 解析失败后用修复式解析比如补齐缺失的引号或括号。解析失败时要记录原始内容不能静默丢弃。用 mock 模型测试时我会专门构造这些异常输入确保每一层都有对应处理逻辑。这样真实模型返回不规整内容时harness 不至于直接崩掉。5.3 缓存、并发与重试会污染指标缓存和重试本是 harness 的正常能力但评测时它们会污染指标需要单独处理。缓存命中会让任务看起来又快又省 token但这不是真实链路的能力。测性能时要明确缓存策略到底测带缓存的完整链路还是测无缓存的冷启动链路。我一般两个都测分别记录这样既能看冷启动真实耗时也能看缓存命中率。并发会引发限流。很多模型服务有每分钟请求数限制并发一高就报 429harness 开始重试重试又加重负载。评测时建议从低并发开始观察限流率再逐步调高。不要一上来就开最大并发否则你测出来的不是 harness 能力而是限流下的抖动。重试机制也有两面性。它能提高任务成功率但会掩盖真实的失败原因。如果任务一直失败重试三次后成功这算成功任务但原始失败原因被吞掉了。正确的做法是重试前后都记录日志区分“一次通过”和“重试后通过”两个都要统计。5.4 统一排查顺序当评测结果异常时我习惯按这个顺序排查而不是直接改 harness看现象是报错、卡住、无输出还是输出异常。先确认问题类型。看输入任务文件路径是否正确、编码是否为 UTF-8、JSON 是否有语法错误、prompt 拼装是否符合预期。看依赖运行时版本、依赖锁、registry 源、本地缓存是否一致。看参数并发数、超时时间、重试次数、采样参数、模型路径、输出目录是否配置正确。看 harness 本身版本是否最新、是否存在已知限制、日志是否完整、缓存是否过期。这个顺序的核心逻辑是先排除最简单、最外围的因素再深入业务逻辑。很多问题看着像 harness bug实际是输入格式不对或者路径权限不对。先查输入和依赖往往比改代码省时间。6. 从 benchmark 走向 harness engineering6.1 harness engineering 是什么为什么要重视Harness 工程不是把 prompt 拼一拼、写个解析函数就算了。它包含版本管理、单元测试、回归测试、日志埋点、指标采集、A/B 实验、配置热更新。当你的系统要接入多个模型、服务多个任务类型时harness 就需要被当作一个正式产品来维护。搜索热度里已经有“harness 工程”“harness engineering”这些词说明这不是我一个人在提的概念。工程化的价值在于你可以安全地修改 harness 而不怕破坏现有功能你可以对比不同 harness 版本的效果你可以知道每次改动是提升还是回退。实现方式不复杂。首先是版本控制每次改动 harness 结构都要记录变更说明其次是回归测试把前面提到的单条样例和 mock 模型测试固化进 CI最后是指标看板把格式合法率、重试率、耗时这些指标持续采集。做到这三点harness 就从一个临时脚本变成了可持续演进的工程组件。6.2 与 agent benchmark、codex harness 等方向的衔接harness-only benchmark 不是孤立概念它和几个热门方向互补。agent benchmark 测的是 agent 完成真实任务的端到端能力包括模型推理、工具选择、计划制定。问题在于当 agent benchmark 得分低时很难判断是模型不行还是 agent 框架不行。用 harness-only benchmark 先隔离框架层再跑 agent benchmark归因就会清晰很多。codex harness 这类方向也类似。给代码生成模型搭的脚手架包括代码仓库上下文、编译运行、测试反馈、多轮修复。如果这个脚手架不稳定模型本身的代码能力再强也发挥不出来。把脚手架单独测一遍就能知道每次迭代到底是模型变强了还是 harness 的上下文处理变好了。还有一个角度是模型接入。很多人搜“deepseek harness 插件”“deepseek harness 桌面版”这类关键词本质是想把某个具体模型快速接入到自己的评测工具链里。harness-only benchmark 的思路正好能帮上忙先测 harness 是否兼容模型接口再测完整效果。接口层跑通了后面换模型只是换一个配置项的事。6.3 什么情况下值得做什么情况下先别做最后说清楚适用边界。harness-only benchmark 是有成本的不是所有场景都值得做。值得做的情况你在开发 agent 框架、RAG 平台或评测工具harness 是核心交付物。你要让多个模型接入同一套工具链需要先保证工具链稳定。你被“分数波动但查不出原因”这类问题坑过希望建立可追溯的评测体系。你要长期维护 prompt 模板、工具描述、解析逻辑需要回归测试保护。先别做的情况你只是临时对比两个模型的答案质量直接跑现成 eval 就够了。你的 harness 只有几行 prompt 拼接还没有形成模块先不需要复杂的 benchmark。你的系统还没接入真实业务评测对象还不明确先别急着建指标体系。还要记住harness-only benchmark 不能替代模型能力评测。它回答的是“我的工程层是否稳定可靠”模型评测回答的是“这个模型本身能力如何”。两者结合才是完整的评测方案。踩过几次坑之后你会发现很多评测问题不是工具能力不够而是前置环境和输入材料没有处理干净。与其不断换模型、调 prompt不如先把 harness 这一层测清楚。先把单条任务跑稳再考虑批量和接口最后才是大范围自动化——这个顺序比什么都重要。