最近几天AI 圈子里关于“Opus 5 通关 ARC-AGI-3”的讨论非常多。有人把它解读为推理能力的又一次跃迁也有人把焦点放在了一个更工程化的词上——Harness。从代码助手到推理评测Harness 这个名字出现得越来越频繁甚至已经演变出一类被称为“Harness 工程”的工作内容。但这里有一个值得认真拆解的问题Harness 到底是在帮助模型发挥能力还是在悄悄限制模型如果一份推理评测成绩是特定 Harness 约束下产生的结果那么这份成绩究竟能说明模型的真实水平还是只能说明 Harness 的设计水平这篇文章不打算停留在标题式的热闹上而是想从技术角度把 Harness 的概念、构成、代码实现和争议点完整梳理一遍。我们会先搞清楚 ARC-AGI 是什么再一步步拆解 Harness 的作用机制然后手写一个最简单的评测 Harness最后回到那个核心问题Harness 会不会变成捆住模型的绳子。1. 为什么突然都在聊“Opus 5 通关 ARC-AGI-3”1.1 ARC-AGI 到底在测什么ARC-AGI 全称是 Abstraction and Reasoning Corpus翻译过来是“抽象与推理语料库”。它由 François Chollet 在 2019 年提出核心目标不是测试模型背了多少知识而是测试模型能否解决从未见过的新问题。每个 ARC-AGI 题目都是一个很小的“输入-输出”转换任务。输入是一组彩色方格输出也是对应的一组彩色方格。模型需要从几个输入输出样例中推断出潜在规则然后把规则应用到新的输入上。举个例子一份任务可能展示出“所有蓝色方块向右平移一格”的规律另一份任务可能是“红色方块把四周的黑色区域变成绿色”。这类任务有几个特点形式简单用几行代码就能定义一个任务。背景知识要求极低不需要世界知识也不依赖预训练语料中的特定文本。真正的难点在于抽象归纳模型要从极少量的样例中发现规则并完成泛化。传统大模型在 ARC-AGI 上的表现一直不太理想。大模型擅长的是模仿训练数据中的统计模式而 ARC-AGI 恰恰是反概率的——它希望模型遇到的是“没见过”的规律。这也是为什么 ARC-AGI 一直被当作衡量通用智能的一个重要参考。1.2 ARC-AGI-3 与 Opus 5 事件的大致背景ARC-AGI-3 可以理解为 ARC-AGI 体系中的后续扩展版本社区普遍认为它在任务数量、规则复杂度和防记忆设计上做了进一步加固对模型的推理能力要求更高。“Opus 5 通关 ARC-AGI-3”的消息来自国外社区。按照目前公开的讨论来看评测并不是直接把题目丢给模型让它自由回答而是通过一套精心设计的评测脚本——也就是 Harness——来和模型交互。Harness 负责把任务数据加载进来转换成固定格式的提示词调用模型接口获取输出再对输出做解析、校验、计分。这里的关键在于最终的高分不是“模型裸奔”考出来的而是在 Harness 的辅助下完成的。于是社区里很快出现了两种声音支持者认为借助 Harness 完成推理是合理的工程行为就像人类使用草稿纸、辅助工具来解题一样。质疑者认为Harness 一旦介入过深就相当于给模型开了外挂评测结果不再能反映模型本身的推理能力。无论是哪种声音都指向了一个共同的技术议题Harness 的边界在哪里。2. Harness 到底是什么2.1 从软件测试中的 harness 说起Harness 这个词在软件工程里已经存在很久了。它最早指“测试夹具”也就是为了运行和验证代码而搭建的一套外围环境。一个典型的测试 Harness 包括数据准备把测试用例喂给被测对象。运行控制启动被测对象传递参数控制执行流程。结果比对把实际输出和期望输出做对比。报告生成记录通过、失败、异常等信息。简单来说Harness 就是“被测对象之外的那层脚手架”。被测对象本身只负责核心逻辑而 Harness 负责让这个核心逻辑可以在受控环境中被反复验证。2.2 大模型评测中的 model harness到了大模型时代Harness 的概念被沿用了下来但复杂度明显上升。一个大模型评测 Harness 需要处理的问题包括如何把数据集转换成提示词Prompt。如何调用模型接口包括本地模型、云端 API。如何处理模型输出的自由文本从中提取有效答案。如何施加系统提示词和工具调用的约束让模型按预期格式输出。如何在多轮交互中记录上下文分析模型的中间推理过程。如何计算分数避免格式错误被误判为能力不足。换句话说大模型 Harness 是“模型能力”和“评测分数”之间的中介。它决定了模型看到什么、以什么方式作答、作答结果如何被理解。2.3 最近很热的 codex harness、deepseek harness 是什么最近网络热词里出现了 codex harness、deepseek harness这其实是“Agent Harness”方向的具体落地。OpenAI 在部署 Codex 这类智能体时官方就强调过一套外层控制机制包括沙箱环境、工具白名单、任务分解策略、检查点机制等。这套机制在社区里逐渐被称为“Codex Harness”。deepseek harness 则是社区开发者针对 DeepSeek 模型或类似推理模型搭建的 eval harness用来解决“模型推理能力很强但输出格式不听话”的问题。通过强制输出 JSON、限定思考格式、自动解析结果让模型在程序化任务中能够被稳定调用。换句话说Harness 已经从单纯的“评测脚手架”演化成了“模型对外提供服务时的一层统一控制面”。它可以约束模型的输入、输出、工具使用方式甚至约束模型在每一步可以操作的范围。这里需要强调一个安全和合规的边界Harness 工程本身是中立的。它既可以用于合法评测、产品开发、自动化测试也可以被滥用去绕过平台限制或做违规操作。作为技术文章我们讨论的是前者即如何在合法、合规的前提下设计和使用 Harness。3. Harness 的技术构成与约束逻辑要理解“Harness 为什么会变成捆住模型的绳子”最好的方式是一层层拆开它的技术构成。一个完整的大模型评测 Harness 通常包含 6 个核心模块。3.1 任务加载与预处理评测数据集往往不是模型直接能读的文字。以 ARC-AGI 为例原始数据是 JSON 格式里面包含训练对train和测试输入test。每个样本是一组二维数组数组里的数字代表不同的颜色。Harness 要做的事情是读取 JSON 文件解析任务结构。把二维数组转换成可读的文本形式因为纯文本模型无法直接“看图”。构造 few-shot 示例把训练样例拼接到提示词中。决定是否保留原始坐标信息这会影响模型理解任务的方式。这个步骤决定了模型看到的信息质量。如果 Harness 直接把二维数组原样输出模型可能很难理解空间关系如果 Harness 把每个格子的坐标都列出来模型又可能被海量细节淹没。提示词怎么设计实质上就是一种信息筛选。3.2 输入输出格式约束这是 Harness 最关键的约束点。自由文本模型如果不加约束可能输出任何内容包括分析过程、补充说明、无关翻译。对于程序化评测来说这种回答很难被解析。所以 Harness 会在系统提示词中明确要求模型按指定 JSON 格式输出例如你应该输出一个 JSON 对象格式为 {reasoning: 你的思考过程, answer: 二维数组}同时Harness 还要处理模型输出中的额外内容比如注释、代码块标记甚至模型直接拒绝回答的情况。这些都需要在解析层做兜底处理。3.3 模型调用层模型调用层负责实际请求大模型 API 或本地模型服务。它需要处理API 网络参数配置例如 temperature、top_p、max_tokens。重试机制应对请求超时和服务端错误。并发控制评测成百上千个任务时需要控制并发数。成本控制长时间推理任务的 token 消耗非常大。流式输出处理有些推理模型会流式返回中间思考过程。这里有一个容易被忽略的点temperature 参数本身就是 Harness 的一部分。如果评测允许采样温度和 max_tokens 调得很大模型就有更多空间进行长链条推理如果限制太死模型的能力就无法充分释放。3.4 结果校验与计分结果校验是评测 Harness 的核心逻辑。ARC-AGI 这类任务的校验非常简单直接把模型的输出解析成二维数组和正确答案逐格比较。如果完全一致则视为通过。但真正工程化时校验层远比“暴力比对”复杂模型输出里可能带有额外字符需要先提取 JSON 片段。即使 JSON 解析成功answer 字段也可能不是正确的数组维度。模型可能给出多个候选答案需要设计选择策略。校验失败时是否需要触发重试重试是否算作弊这些细节直接影响最终分数。一个严格计分的 Harness 和宽松计分的 Harness在同一个模型上可能得出完全不同的结论。3.5 控制流与超时机制控制流是 Harness 从“单次问答”走向“智能体执行”的关键。当 Harness 允许模型调用工具、执行代码、查看反馈时它就从静态评测变成了动态评测。动态 Harness 需要实现多轮循环模型输出动作 - 执行动作 - 把结果返回给模型。动作白名单只允许模型使用固定的工具集合。最大轮次限制防止模型无限循环。超时中断某个动作执行时间过长需要强制终止。状态保存即使中断也能从最近的检查点恢复。这种动态 Harness 在现代 Agent 评测中非常多见。比如让模型写一段代码来解决某个问题Harness 负责执行代码、捕获报错、把报错反馈给模型继续修改。这里 Harness 就不仅是约束而是变成了模型的“扩展手脚”。3.6 评测日志与可追溯性好的 Harness 不仅仅是输出一个分数还要记录完整的推理轨迹。每一轮的提示词、模型输出、解析结果、校验结果都应该被保存下来。这样做有几个价值复现评测结果避免“同一个模型两次评测分数不同”的问题。查看模型失败样例分析失败原因区分是理解错误、格式错误还是推理中断。审计 Harness 本身判断是否存在信息泄漏或评分不公。随着评测越来越复杂可追溯性已经从“推荐”变成了“必要”。没有日志的评测分数基本等于没有。4. 动手实现一个简易 model harness接下来我们写一个非常精简但完整的评测 Harness模拟 ARC-AGI 风格任务的评测流程。这个项目被称为 mini_model_harness核心目的是演示 Harness 如何加载任务、构造提示词、解析输出并完成计分。4.1 项目结构mini_model_harness/ ├── tasks/ │ └── simple_task.json ├── harness.py ├── llm_client.py └── output/ └── eval_log.jsonltasks 目录存放任务数据。llm_client.py 负责和大模型 API 通信。harness.py 是评测主流程。output 目录保存评测日志。4.2 准备一份任务数据我们构造一个合成任务规则是“把输入中的红色格子移动到它的下方一格”。这个任务足够简单便于观察 Harness 的完整流程。{ task_id: demo_move_down, train: [ { input: [[0, 1, 0], [0, 0, 0], [0, 0, 0]], output: [[0, 0, 0], [0, 1, 0], [0, 0, 0]] }, { input: [[0, 0, 0], [0, 1, 0], [0, 0, 0]], output: [[0, 0, 0], [0, 0, 0], [0, 1, 0]] } ], test_input: [[0, 0, 0], [0, 0, 0], [0, 1, 0]] }这里 1 代表红色格子0 代表空白。测试输入的最后一行有红色格子按照规则它应该继续下移但底部已经没有空间所以预期输出应该是全 0。4.3 编写 LLM 客户端我们把大模型调用封装成一个简易客户端。为了便于演示这里用占位实现实际使用时可替换成 OpenAI、Anthropic、DeepSeek 等任意兼容接口。# llm_client.py import json from typing import Dict, List class LLMClient: 简化版大模型客户端负责发送提示词并返回响应文本。 def __init__(self, api_key: str, base_url: str, model: str): self.api_key api_key self.base_url base_url self.model model def chat(self, messages: List[Dict[str, str]], temperature: float 0.0) - str: 发送对话请求。 真实项目中这里会调用 requests 或 openai SDK。 这里返回固定文本用于模拟模型输出。 # 模拟一个遵守格式的模型输出 return json.dumps({ reasoning: 发现红色格子执行下移操作。, answer: [[0, 0, 0], [0, 0, 0], [0, 0, 0]] })实际开发时你需要把 chat 方法替换为真实接口调用并加上超时、重试和流式输出支持。4.4 编写 Harness 主流程4.4.1 任务格式化# harness.py 片段把二维数组转成文本 def grid_to_text(grid): 把二维数组转换成带坐标的文本表示。 为什么要带坐标因为纯文本模型不具备视觉能力 坐标信息有助于模型理解空间位置。 lines [] for r, row in enumerate(grid): cells [] for c, val in enumerate(row): cells.append(f({r},{c}){val}) lines.append( .join(cells)) return \n.join(lines)4.4.2 提示词构造def build_prompt(task): 构造评测提示词。 关键点把训练样例和测试输入组合成 few-shot 提示 要求模型严格输出 JSON 格式。 sys_msg { role: system, content: ( 你是一个网格推理助手。你会看到一些输入输出示例 请根据示例推断规则并应用到测试输入上。\n 你必须输出 JSON格式为 {reasoning: 推理过程, answer: [[0, 1]]} ) } user_content 下面是训练示例\n\n for i, sample in enumerate(task[train]): user_content f示例 {i 1}:\n user_content f输入:\n{grid_to_text(sample[input])}\n user_content f输出:\n{grid_to_text(sample[output])}\n\n user_content 请对以下测试输入输出答案\n user_content grid_to_text(task[test_input]) user_msg {role: user, content: user_content} return [sys_msg, user_msg]4.4.3 结果解析import json def parse_model_output(raw_text: str): 解析模型输出提取 answer 字段。 工程中需要处理各种异常输出这里先做基础解析。 text raw_text.strip() # 去掉可能存在的代码块标记 if text.startswith(): text text.strip() if text.startswith(json): text text[4:] try: data json.loads(text) return data.get(answer) except json.JSONDecodeError: return None4.4.4 完整评测循环def evaluate(harness_cfg, task): 评测主循环。 1. 加载任务数据 2. 构造提示词 3. 调用模型 4. 解析答案 5. 校验比对 6. 记录日志 client LLMClient( api_keyharness_cfg[api_key], base_urlharness_cfg[base_url], modelharness_cfg[model] ) messages build_prompt(task) raw_output client.chat(messages, temperatureharness_cfg.get(temperature, 0.0)) answer parse_model_output(raw_output) expected task[test_input] # 模拟正确答案把最下方的红色格子下移后消失结果为全 0 expected_answer [[0, 0, 0], [0, 0, 0], [0, 0, 0]] is_correct answer expected_answer log_entry { task_id: task[task_id], is_correct: is_correct, raw_output: raw_output, parsed_answer: answer, } with open(output/eval_log.jsonl, a, encodingutf-8) as f: f.write(json.dumps(log_entry, ensure_asciiFalse) \n) print(f任务 {task[task_id]} 结果: {通过 if is_correct else 失败}) return is_correct if __name__ __main__: with open(tasks/simple_task.json, r, encodingutf-8) as f: task json.load(f) harness_cfg { api_key: your-api-key, base_url: https://api.example.com, model: demo-model, temperature: 0.0 } evaluate(harness_cfg, task)4.5 运行与验证运行命令python harness.py预期输出任务 demo_move_down 结果: 通过同时 output/eval_log.jsonl 中会生成一条记录包含原始输出、解析答案和判定结果。4.6 结果说明Harness 是如何影响成绩的从这个简化例子可以清楚看到最终成绩并不是模型一个人决定的提示词构造决定了模型能否理解任务。格式约束决定了模型输出能否被解析。解析容错决定了格式错误是否会被宽容处理。结果比对的严格程度决定了是否要求“零误差”。换一种提示词写法或者换一种更宽松的 JSON 解析策略同一个模型在同一份任务上的得分就会发生变化。这就是“Harness 影响成绩”的最直接证据。5. Harness 如何变成“捆住模型的绳子”5.1 正向约束没有 Harness模型无法稳定工作先要承认Harness 不是坏事。没有 Harness大模型在生产环境根本没法用。真实场景中我们需要模型输出固定字段、调用特定工具、在限定范围内操作数据库或代码仓库。如果模型想说什么就说什么想调什么函数就调什么函数整个系统会迅速失去控制。Harness 提供的是可靠性的边界。以金融风控场景为例模型可以根据规则生成风险报告但 Harness 必须限制它不能读取用户隐私字段不能调用未授权的接口。这种约束是安全底线应该越严格越好。5.2 过度约束从“辅助”变成“代答”Harness 的问题在于约束一旦越过某条线就会从“辅助”变成“代答”。举几个典型表现Harness 把正确答案的格式提示写得极其详细等于把答案结构直接暴露给了模型。Harness 在模型连续失败后自动重试并把上一次的错误信息反馈给模型这本身不算作弊但如果重试次数过多相当于给了模型很多次“偷看”样例的机会。Harness 在解析阶段把模型的模糊描述自动修正成标准答案。比如模型输出“我猜是红格往下移”Harness 自动把它转成正确数组这已经超出了解析范围进入了信息补充。Harness 在构造提示词时把测试输入的变换规律用某种格式暗示出来例如把坐标对齐方式设计成和正确答案一一对应。一旦 Harness 参与程度过高评测分数就没法代表模型能力只能代表“Harness 对题目的理解程度”。5.3 从“评测工具”到“能力上限”的异化更值得警惕的是当 Harness 评测分数被反复宣传时公众很容易把分数理解为模型的裸奔能力。这就是标题里“捆住模型的绳子”的隐喻一方面Harness 确实像绳索一样把模型限制在可控范围内避免它乱跑另一方面如果绳索本身参与了解题那真正被捆住的就是我们对模型能力的认知。为了避免这种异化社区的最佳实践是同时公开模型版本和权重信息。Harness 源码和提示词模板。详细的运行日志包括每次重试的原始输出。评测环境的算力和超时参数。只有这些信息全部透明评测分数才具备参考意义。6. 常见误区与讨论点误区表现正确理解高分等于强能力只晒分数不看 Harness 设计分数是“模型 Harness”的共同结果Harness 作弊论认为只要用了 Harness 就是作弊工程化评测普遍依赖 Harness关键是约束是否被公开格式错误等于不会做模型输出无法解析直接判失败应区分“推理错误”和“解析失败”分别记录放宽约束更好认为约束越少越能反映能力约束过少会导致输出不可复现评测失去意义Harness 只用于评测觉得 Harness 只是测试工具Harness 已广泛用于 Agent 部署和产品稳定化这里特别想展开讨论一个话题如果评测中 Harness 的提示词构造与真实场景完全脱节那么评测结果对实际部署的参考价值会很有限。比如评测时允许模型在“思维链”中思考 1 万 token但线上产品受成本和延迟限制只能给模型 2 秒生成时间。那么评测分数再高也不能说明线上体验好。反过来说如果线上产品本身就有复杂的工具调用和重试机制评测复用同一套 Harness 反而更有说服力。所以衡量一个 Harness 好不好不在于它是否“严格”或“宽松”而在于它是否和你的真实使用场景对齐。7. Harness 工程最佳实践7.1 最小权限原则Harness 给模型开放的每项能力都应该是达成任务所必需的最小集合。模型不需要读取某个文件就不要把文件路径告诉它不需要调用某个工具就不要把工具放进动作白名单。这条原则既是安全要求也是评测公平性的要求。模型能访问的信息越多它“解题”的线索就越多评测越不纯粹。7.2 约束项透明化每次评测发布时至少要公开以下内容系统提示词的完整内容。是否为模型提供过多次重试机会。是否允许模型运行代码或调用外部工具。温度、max_tokens、超时等采样参数。解析失败后的补偿策略。记录这些信息的过程本身就是在校准 Harness 对模型的影响程度。7.3 日志覆盖全链路评测日志不能只记录最终判定结果。建议至少记录每一轮的完整消息列表。模型原始输出不要做任何修改。解析后的答案结构。运行耗时和 token 用量。Harness 版本号和配置哈希值。日志的意义在于当分数被质疑时你可以拿出证据链来回应。7.4 失败模式分类评测失败不应该被看成“非黑即白”。建议把失败分成四个类别理解失败模型没有理解任务规则。推理失败模型理解了规则但在多步推理中出错。格式失败模型有答案但没有按固定格式输出。执行力失败模型答案正确但不符合校验维度要求。分类统计可以帮你快速定位 Harness 的哪一环最需要优化。如果格式失败占比很高优先优化提示词的输出格式约束如果推理失败占比高才需要考虑提升模型本身的能力。7.5 评测环境与生产环境隔离评测环境必须与生产环境隔离避免评测脏数据污染训练语料也避免生产请求影响评测结果。如果评测任务本身使用了模型训练集中的数据成绩就没有参考价值。7.6 从评测到生产的迁移不要把评测 Harness 直接搬到生产环境。评测环境允许完整尝试和重试生产环境往往有更严格的延迟和成本限制。建议生产环境中关闭重试或者设置更严格的重试次数。生产提示词避免包含训练样例以降低 token 成本。生产环境的解析逻辑要加入更多的防御性判断。对模型输出做格式校验不合法时返回兜底文案。8. 总结与延伸学习建议这个项目最值得掌握的技术点可以归纳为三句话第一Harness 是连接模型能力与应用效果之间的桥梁。没有 Harness模型只是一个孤立的“脑”缺少与外部世界交互的“手脚”。第二Harness 的设计细节决定了评测分数的含义。修改提示词结构、解析策略、重试次数都会直接影响最终成绩。以后看到任何一份大模型评测报告建议先去查它用的 Harness 是什么。第三Harness 的边界需要被明确讨论。它既不能无限放宽也不能越俎代庖。好的 Harness 应该像一副清醒的缰绳既让马跑起来又不让它跑出赛道。如果接下来你想深入学习建议按这个顺序往下走先去跑一遍 ARC-AGI 官方公开的样例任务手动体验一下任务难度。再学会用通用的 eval harness 框架跑几个开源模型对比分数差异。然后尝试为某个具体业务场景写一个自定义 Harness亲身体会“约束设计”带来的影响。最后深入了解一下 Agentic Harness理解模型如何通过工具调用和代码执行完成多步任务。在实际项目中建议优先关注推理日志的完整性和约束透明化。一个分数可能代表模型的巅峰水平但长期可靠的系统依赖的是可复现、可审计、可回归的 Harness 工程。把 Harness 当成一个严肃的工程构件来对待而不是“评测时随便写写的外层脚本”你的模型应用质量就会有非常明显的提升。如果你正在做自己的 eval harness或者最近在研究 ARC-AGI 相关任务欢迎在评论区分享你的 Harness 设计思路。动手跑一次比看十篇文章都有用。