如果只看各家发布会的演示,你会觉得 Opus 5 和 GPT-5.6 已经没多大差别了:都能处理长文档,都能调用搜索和代码执行,都能在对话里完成复杂任务。但当我把评测环境里的所有工具全部禁掉——没有联网、没有代码执行、没有文件检索,只留下一次单纯的文本生成机会——这两款模型之间的差距反而比任何时候都明显。
原因不复杂。工具调用能力是“外挂装备”,而推理和知识组织才是模型的“内功”。外挂可以靠工程能力补齐,内功只能靠模型本身。当所有模型都站在同一条起跑线上裸考时,装备带来的优势会被抹平,剩下的才是这个模型真正的基本功。很多人选模型只看“能不能用工具”,忽略了底座能力,结果一换场景就翻车。
这篇文章不打算复述发布会参数,而是把“禁工具评测”这件事拆透:它为什么比常规评测更能暴露 Opus 5 和 GPT-5.6 的差异、评测框架怎么设计、代码怎么落地、跑完结果怎么判读,以及最常见的坑在哪里。读完你可以直接照着搭一套自己的模型评测环境。
1. 这篇文章真正要解决的问题
先说结论:常规模型对比评测的价值正在快速下降。原因是模型厂商都在用工具增强来“补差”——搜索不准就接检索,计算不行就加代码执行器,长文本记不住就上文件读取。当每个模型都能借助外部工具把短板撑起来时,你很难判断模型本身的水平到底如何。
但实际开发里,工具并不总是可用。
比如你写了一个离线推理服务,模型跑在内网环境,不允许访问外部 API;比如你处理的是敏感数据,不能把 Prompt 发给搜索服务;再比如你基于模型做代码补全,模型每次只有一次短生成机会,没有机会先跑 Python 再修正。这些场景下,模型只能靠自己的推理和知识回答问题。“禁掉所有工具”不是刁难模型,而是把真实场景中被“工具遮挡”的能力重新暴露出来。
所以这篇文章要解决的核心问题有两个:第一,为什么“禁工具”后 Opus 5 和 GPT-5.6 的差距会放大;第二,如何搭建一套可复现、可扩展的“禁工具”评测环境,并用它得到有参考价值的判断。
读完你至少能获得三样东西:一套评测方法论、一份可运行的评测代码、一组判断差异信号的解读框架。这比看别人公布的跑分更有用,因为你可以用自己的业务题目去验证。
2. 为什么“禁掉工具”比“加上工具”更能暴露差距
很多团队做过类似实验:同一个问题,先让模型直接回答,再给模型接上搜索或代码执行,最后对比答案质量。结果是“加上工具”后,模型之间的回答差距明显缩小——模型自身不知道的知识,工具可以补;模型算不准的数学,代码解释器可以算。这给很多人的错觉是“模型底层能力已经趋同了”。
但工具介入会把模型能力拆成“模型本身能力 + 工具增益”两个部分。工具增益取决于工程实现,比如检索器质量、上下文拼接方式、代码执行环境的稳定性。如果两家模型的工具链路都很成熟,最终体验差异就很小。这时候你评估的其实是工程系统,不是模型。
禁掉工具后,链路被简化到只剩“模型 + 提示词”,此时你会看到三个在工具评测里被忽略的差距点:
第一,知识内化程度。允许搜索时,模型可以“现查现答”;禁掉搜索后,模型只能依赖参见过数据中的知识。Opus 5 和 GPT-5.6 在这类问题上的差异,会直接体现为“答得完整但不准确”和“答得简短但关键点齐全”两种风格。
第二,多步推理的稳定性。工具评测中,模型可以写一段代码来辅助推理,或者拆成多轮对话逐步试探。禁掉工具后,模型必须在一个回答里完成从问题分解到逐步推导的全过程。这里最容易拉开差距:有的模型能保持完整推导链,有的模型前两步正确、第三步开始偷换逻辑。
第三,自我一致性。模型在缺少外部校验时,是否会出现前后矛盾。搜索工具可以快速纠正错误,代码执行可以验证结果,但纯文本生成没有任何外部纠错机制。这个维度最能体现模型内部的“一致性约束”做得好不好。
所以“禁工具评测”本质上不是让模型为难,而是把评测目标从“谁能借助更多工具完成任务”转回“谁在孤立状态下更可靠”。对需要做模型选型的团队来说,这个维度更接近模型底座的真实水平。
3. Opus 5 与 GPT-5.6:从模型定位看差异背景
在展开评测方案之前,有必要先搞清楚 Opus 5 和 GPT-5.6 各自的定位。模型版本更新很快,具体参数和价格会随时间变化,这里不堆配置,只讨论定位层面的差异。
Opus 5 延续了该系列的一贯定位:面向复杂推理、长文本分析和深度写作场景。这类模型的设计目标不是“和用户闲聊”,而是在高难度任务中保持逻辑链的完整。它的典型使用场景包括长文档语义分析、复杂业务规则抽取、代码逻辑审查。由于 OpenAI 和 Anthropic 在模型设计上的取舍不同,Opus 系列在“长上下文理解”和“结构化推理”上的投入一直比较大。
GPT-5.6 则更接近“通用底座模型”的定位:覆盖任务广、指令跟随直接、对不同领域问题的泛化能力强。它的优势在于“能用一套能力应对多样场景”,而不是在某个专项上做到极致。这类模型在日常助手、工具调用、代码辅助等场景中表现得非常灵活。
如果把模型比作人,Opus 5 更像一个研究型专家,擅长长时间专注在一件事上做深度推导;GPT-5.6 更像一个高适应性的综合型选手,换了新任务能快速上手。工具加持下,两者都能完成绝大多数的任务;一旦把工具禁掉,研究型专家和综合型选手的差异就会显现:前者可能在深度推导上更完整,后者可能在不同任务切换中更稳定。
这里必须强调一点:这属于基于公开定位的合理判断,不是“某次实测跑出来的绝对结论”。真实差异需要用你自己的业务题目去验证,因为模型在不同领域上的表现排位可能完全不同。
4. “禁工具”评测的六维框架
评测模型不能只看“答得对不对”,尤其是禁掉工具之后,答案的评价维度会更多元。我建议用六个维度来搭建框架,这样跑出来的结果更容易横向对比。
4.1 事实准确性与知识边界
维度定义:模型在无法联网的前提下,给出的客观知识是否准确;对于自己不知道的信息,是否坦诚。
核心观察点:模型是在明确说“不确定”,还是用一个自信的编造来填补知识空白。禁掉工具后,幻觉率会直接上升,这一维度最能拉开差距。
4.2 多步推理完整性
维度定义:模型能否独立完成多步骤逻辑推导,并且在中间步骤不出现跳步或偷换。
典型题目包括数学证明、逻辑谜题、复杂条件判断。观察点不是最终答案,而是过程链条是否连续。工具评测中模型可以用代码步骤校验,禁掉工具后全靠推理本身。
4.3 长文本信息保持
维度定义:给模型一段较长的背景材料,要求它回答基于材料细节的问题。禁掉工具意味着模型不能主动检索材料,必须把材料内容内化到这次生成中。
观察点是细节保持度:小数字、限定词、例外条件是否被忽略。
4.4 指令跟随精度
维度定义:用户给出的格式约束和规则约束,模型有多大概率严格遵守。
例如要求“不要解释过程,只输出答案”,或者“用 JSON 输出且字段名严格为 specified”。禁掉工具后更接近模型指令跟随的原始水平。
4.5 反事实与边界条件处理
维度定义:当题目假设和常识冲突时,模型是否能坚持题目给定的假设,而不是被常识带跑。
这一维度很能反映模型在“非日常分布”下的稳定程度。有些模型在常识范围内表现不错,但一旦遇到反事实设定,立刻回归套路化回答。
4.6 生成稳定性
维度定义:同一条 Prompt 重复运行 N 次,答案的关键要素是否保持一致。工具评测中模型可以借助检索结果“锚定”答案;禁掉工具后,随机性和解码策略的影响会被放大。
这一维度不要求两模型达到 100% 一致,但差异过大会影响生产环境中的可靠性。
5. 评测环境搭建与前置条件
设计好框架后,下一步是搭建可复现的评测环境。环境准备并不复杂,重点是要把“变量控制”做到位,否则评测结果会失真。
本文使用 Python 3.10+ 和两个官方 SDK。模型 ID 以你实际账号可用为准,不同版本命名规则可能不同。下面代码里的模型名称只是示例,运行前请替换成你账号里真实存在的模型 ID。
5.1 安装依赖
# 创建虚拟环境(推荐) python -m venv .venv source .venv/bin/activate # Windows 下使用 .venv\Scripts\activate # 安装两个模型的官方 SDK pip install openai anthropic # 用于读取环境变量和数据处理 pip install python-dotenv环境变量文件建议放在项目根目录,命名为.env:
# 文件路径:.env OPENAI_API_KEY=你的GPT模型Key ANTHROPIC_API_KEY=你的Opus模型Key5.2 固定可变参数
评测脚本要显式固定三个参数:temperature、max_tokens、top_p。否则模型每次返回的内容随机性过大,统计结果没有可比性。
建议稳定参数统一设置为:
TEMPERATURE = 0.2 MAX_TOKENS = 2048 TOP_P = 1.0这里把温度设成 0.2,是为了保留一定多样性,同时又不至于让结果跳变得太夸张。如果需要测试模型的发散能力,可以单独跑一组高温度对比。
6. 评测流程与完整代码示例
下面给出一个最小可用的“禁工具”评测实现。这个示例强调“直接可用”,没有复杂的工程化封装,方便你快速跑通再扩展。
6.1 统一模型调用封装
为了让两个模型在同一个循环里被调用,先把接口封装成统一的函数。这一步的关键是:完全不调用任何工具,不传联网能力,不执行代码,只发起一次文本生成请求。
# 文件路径:model_client.py import os from openai import OpenAI from anthropic import Anthropic client_gpt = OpenAI(api_key=os.getenv("OPENAI_API_KEY")) client_opus = Anthropic(api_key=os.getenv("ANTHROPIC_API_KEY")) TEMPERATURE = 0.2 MAX_TOKENS = 2048 TOP_P = 1.0 def ask_gpt(prompt: str) -> str: # 模型 ID 请替换为你账号下真实可用的模型 ID response = client_gpt.responses.create( model="gpt-5.6", input=prompt, temperature=TEMPERATURE, max_output_tokens=MAX_TOKENS, top_p=TOP_P, ) return response.output_text def ask_opus(prompt: str) -> str: # 模型 ID 请替换为你账号下真实可用的模型 ID response = client_opus.messages.create( model="claude-opus-5", max_tokens=MAX_TOKENS, temperature=TEMPERATURE, top_p=TOP_P, messages=[ {"role": "user", "content": prompt} ], ) return response.content[0].text def ask(model_name: str, prompt: str) -> str: if model_name == "gpt-5.6": return ask_gpt(prompt) if model_name == "opus-5": return ask_opus(prompt) raise ValueError(f"Unknown model: {model_name}")这段代码有几个值得注意的细节:
第一,temperature和top_p都固定了,避免因为解码策略不一致导致结果偏差。第二,两个模型的接口结构不同,但都被包成了同一个ask(model_name, prompt),后续评测脚本不需要关心模型差异。第三,没有给模型任何“你可以先搜索一下”之类的提示词,这是“禁工具”评测的前提条件。
6.2 准备评测题目集
评测题目集的格式使用 JSON,每个元素包含三个字段:id、dimension、prompt。dimension对应上文六维框架中的维度,方便结果按维度分组统计。
// 文件路径:questions.json [ { "id": "fact_001", "dimension": "fact_accuracy", "prompt": "请简述贝叶斯定理,并说明它与朴素贝叶斯分类器的关系。不要搜索,直接回答。" }, { "id": "reasoning_003", "dimension": "multi_step_reasoning", "prompt": "一个容器里有红球、蓝球、绿球共 100 个。红球数量是蓝球的 2 倍,绿球数量比红球多 10 个。请问三种球各有多少个?请给出完整推导过程。" }, { "id": "instruction_002", "dimension": "instruction_following", "prompt": "请你写一句介绍 Python 的话,要求:不超过 20 个字,必须包含“语法”和“库”两个词,不要输出任何其他内容。" }, { "id": "counterfactual_004", "dimension": "counterfactual", "prompt": "假设地球引力突然变为原来的两倍,那么人在正常行走时,会先感觉到哪些变化?请基于这个假设进行分析,不要用常识反驳假设本身。" } ]题目集的设计有几个原则:同一维度至少准备 10 题以上,否则统计意义太弱;题目难度不要集中于“一眼就能答”的常识题;至少要包含一类需要多步推导的题目,因为这是禁工具后差异最明显的场景。
6.3 自动化执行评测
评测脚本读取题目集,逐个模型运行,把结果保存到 JSON 文件。为了保证公平性,建议用随机顺序交替调用两个模型,避免模型受到“上一题”或“系统当前缓存状态”的偶然影响。
# 文件路径:run_eval.py import json import random import time from model_client import ask def load_questions(path: str) -> list[dict]: with open(path, "r", encoding="utf-8") as f: return json.load(f) def run_eval(questions: list[dict], model_name: str) -> list[dict]: results = [] for idx, q in enumerate(questions): print(f"[{model_name}] 运行题目 {idx + 1}/{len(questions)}: {q['id']}") try: answer = ask(model_name, q["prompt"]) except Exception as e: answer = f"__ERROR__: {e}" results.append({ "question_id": q["id"], "dimension": q["dimension"], "model": model_name, "prompt": q["prompt"], "answer": answer, "timestamp": time.time(), }) # 避免触发接口限流 time.sleep(1) return results def main(): questions = load_questions("questions.json") random.shuffle(questions) # 固定随机顺序,保证两个模型面对完全相同的题目顺序 # 实际运行时,建议每次运行使用不同种子并保存种子值 random.seed(42) all_results = [] for model_name in ["opus-5", "gpt-5.6"]: all_results.extend(run_eval(questions, model_name)) with open("eval_results.json", "w", encoding="utf-8") as f: json.dump(all_results, f, ensure_ascii=False, indent=2) print("评测完成,结果已写入 eval_results.json") if __name__ == "__main__": main()脚本输出文件eval_results.json会保留原始答案。这些原始答案非常宝贵——规则评分只能判断“是否包含关键词”,但人工复核必须回看原文才能发现“看起来答对了但推理过程是错的”这类问题。
6.4 简单评分函数
自动评分最稳妥的起步方式是:先为每道题预置一个“关键元素列表”,然后检查答案中是否出现了这些元素。这个方法不完美,但足够作为第一轮筛选。
# 文件路径:scoring.py import json # 关键元素表需要根据题目集手工维护 KEY_ELEMENTS = { "reasoning_003": ["红球", "蓝球", "绿球", "40", "20", "50"], "instruction_002": ["语法", "库"], } def score_answer(question_id: str, answer: str) -> dict: if question_id not in KEY_ELEMENTS: return {"score": None, "matched": [], "missing": []} matched = [kw for kw in KEY_ELEMENTS[question_id] if kw in answer] missing = [kw for kw in KEY_ELEMENTS[question_id] if kw not in answer] score = len(matched) / len(KEY_ELEMENTS[question_id]) return { "score": round(score, 2), "matched": matched, "missing": missing, } def main(): with open("eval_results.json", "r", encoding="utf-8") as f: results = json.load(f) for r in results: s = score_answer(r["question_id"], r["answer"]) r["auto_score"] = s with open("eval_results_scored.json", "w", encoding="utf-8") as f: json.dump(results, f, ensure_ascii=False, indent=2) print("评分完成,结果已写入 eval_results_scored.json") if __name__ == "__main__": main()这个脚本只做“关键元素覆盖度”检查。需要特别提醒:规则评分不能替代人工复核。你只能把它当作过滤器,真正要看的还是原始答案里的推导过程和逻辑链条。等到题目集积累到一定规模,再考虑用 LLM-as-a-judge 做更细粒度的评分,但那是后续工程化方向。
7. 结果如何看:典型的差异信号与判断方法
评测脚本跑完之后,最忌讳的事是只看一个“总分”。不同维度的差异,比总分更能反映模型特性。从公开评测共识和模型定位来看,禁掉工具后的结果通常会出现以下三类典型分信号。
7.1 推理完整度差异
在多步推理题目上,你会经常看到一种对比:一个模型完整写出了“从条件 A 推出 B,再从 B 推出 C”的过程,另一个模型直接给出最终答案,但答案正确。直接给答案的模型并非“更强”,而是跳过了可验证的中间链。
在生产环境中,这个差异会带来两种体验:需要可解释性的场景,前者更可靠;追求响应速度的场景,后者更高效。但如果是数学计算或逻辑判定类任务,中间推导缺失会让错误更难定位。建议在评测结果中单独标注“是否有完整推导链”,而不是只记录答案是否等于预期值。
7.2 知识边界处理方式差异
禁掉工具后,那些“需要最新信息才能回答”的问题会暴露出模型的自我认知能力。有的模型会直接给出一段听起来很合理、但关键信息已经过时的内容;有的模型会明确说“我的知识截止时间较早,无法确认当前最新情况”。
这两种表现都不是“答对”,但对于生产系统来说,后者的风险明显更低。建议在事实类题目中增加一类“过时信息题”:把 2024 年之后才发生的事件作为问题,观察模型是否会主动声明知识边界。
7.3 指令格式遵守度差异
在严格格式要求下,模型的服从性差异明显。有的模型会严格遵守 JSON 输出要求,即使内容是错的,格式也是对的;有的模型偶尔会在 JSON 前后添加解释性文字,导致下游解析报错。
对于依赖结构化输出的工程团队,这个差异可能比“答得对不对”更重要。建议在评测结果中单独统计“格式合规率”,例如:
python - <<'EOF' import json with open("eval_results_scored.json", "r", encoding="utf-8") as f: results = json.load(f) # 统计每个模型的 JSON 格式合规率 for model in ["opus-5", "gpt-5.6"]: subset = [r for r in results if r["model"] == model] total = len(subset) ok = 0 for r in subset: try: json.loads(r["answer"]) ok += 1 except Exception: pass print(f"{model}: 格式合规率 {ok}/{total} = {ok / total:.2%}") EOF这类结论比总分更贴近工程视角——你选模型是为了能在项目里稳定解析输出,而不是为了一个公开榜单上的排名。
8. 常见问题与排查方法
评测环境本身并不复杂,但实际跑起来时,会因为接口、参数、顺序等各种因素导致结果失真。这里整理几个最常见的问题和处理方法。
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| 某个模型频繁超时或返回 429 | 接口限流 | 查看 SDK 返回的具体错误码 | 在请求之间增加 sleep;降低并发;检查账号配额 |
| 所有答案都非常相似 | 温度参数被固定为 0,或题目难度太低 | 检查脚本中 temperature 配置 | 将温度调至 0.2~0.4;提高题目难度 |
| 模型 ID 不存在或报错 | 模型版本名与代码中不一致 | 查看官方 API 模型列表 | 将代码中的模型名替换为真实可用 ID |
| 两个模型生成长度差异巨大 | max_tokens 设置不同,或模型提前结束 | 检查输出长度 | 统一 max_tokens;增加要模型“继续输出”的提示词(但不要虚构工具) |
| 评测结果不稳定,重跑差异大 | 随机顺序或解码随机性未控制 | 检查 seed 和随机策略 | 固定 seed;多次运行取中位数 |
| 规则评分全是 0 分或全是满分 | 关键元素设计不合理 | 人工抽检原始答案 | 重新设计关键词表,或改用 LLM 评测器 |
| 某道题两个模型都答错 | 题目本身存在歧义 | 人工复盘题目表述 | 删除或改写歧义题 |
最容易忽略的一点是:接口返回的缓存和限流策略会影响耗时,但不影响内容。评测耗时只反映当时的网络状态,不要把它当作模型性能指标。如果你要测耗时,需在同一网络条件下、夹带多个样本交替运行多次取中位数。
9. 最佳实践与工程建议
评测模型和写业务代码一样,要有工程约束。以下几个建议来自实际踩坑,能帮你减少无效劳动。
9.1 评测数据必须防污染
模型训练数据可能包含公开评测集。如果你直接把网上的公开题目拿来做评测,很可能测不出真实能力,因为模型早就“背”过答案。更好的做法是:从你自己的业务场景中生成题目,或者对公开题目做改写,改变具体数值和场景设定。
比如“容器里有红球、蓝球、绿球”是经典题,但线上可以通过随机生成数值来创建变体。每次运行前随机化数字,能大幅降低记忆效应。
9.2 固定版本和时间戳
模型接口的 default 版本可能悄悄变化,导致两周前的评测结果无法复现。工程化做法是在结果 JSON 里记录接口调用时的模型完整 ID、日期和代码版本。
import datetime meta = { "evaluated_at": datetime.datetime.now().isoformat(), "opus_model_id": "claude-opus-5", "gpt_model_id": "gpt-5.6", "prompt_version": "v1.0", }这能帮你在模型更新后快速决定“是否需要重跑评测”。
9.3 先人工标注,再上自动评分
自动评分脚本难免有漏判。第一次跑评测时,建议人工逐条标注 50~100 个答案,再把人工标注结果作为自动评分的校准集。有了校准集,后续大规模评测才有可信度。
如果直接跳到 LLM-as-a-judge,评测器本身的偏好也可能成为新偏差来源。这里的规则是:先确认小样本上的人工一致性,再扩大规模。
9.4 评测维度要有业务权重
不同团队对模型能力的优先级完全不同。做客服机器人的团队,更看重指令跟随和知识边界;做代码助手的团队,更看重多步推理和长文本保持。建议在评分统计时给每个维度加权重,而不是简单求和:
weight = { "fact_accuracy": 0.2, "multi_step_reasoning": 0.3, "instruction_following": 0.2, "counterfactual": 0.1, "long_context": 0.2, }这样得出的最终排名才符合你的业务优先级,而不是一个“平均分”。
9.5 每一轮评测都应该有“失败记录”
真正有用的评测不是只记录“谁答对了”,还要记录“谁以什么方式答错了”。把失败案例单独抽出来归类,是理解模型边界最快的方式。常常出现的情况是:A 模型在数学题上输给 B,但 A 的错误是“过程正确、最后一位计算失误”,而 B 的错误是“从一开始就理解错了题意”。两种错误在生产里的代价完全不同。
10. 总结与后续学习方向
这篇文章围绕“禁掉所有工具”这个评测思路,讲清楚了 Opus 5 和 GPT-5.6 对比评测的方法论与落地实现。核心判断是:工具增益会被工程能力抹平,模型底座能力不会;禁掉工具后,两模型在推理完整性、知识边界处理、指令跟随等维度上的真实差异会变得更加清晰。
你可以从三个方向继续深入:一是把题目集扩展到自己的业务场景,形成长期评测集;二是引入更细粒度的评测方式,比如过程评分、格式合规率、错误分类;三是把评测接入 CI/CD,在模型版本更新时自动触发重跑。
最后提醒一句:不要迷信任何一篇文章给出的对比结论,包括这篇。模型版本迭代太快,同样的评测框架跑在不同版本上,结论可能完全不同。把方法论和代码保存下来,你的业务题目集才是长期有效的评测资产。