ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

禁掉工具!大模型裸推理评测的五个关键维度

禁掉工具!大模型裸推理评测的五个关键维度 最近关于 Opus 5 和 GPT-5.6 的讨论和之前的模型发布会不太一样。社区里流传更广的不再是某段对话截图而是“接了一堆工具后的效果演示”让模型查资料、写代码、操作数据库、调用 MCP 服务看起来无所不能。可问题恰恰藏在这里——工具越多模型本身的真实水平就越难被看清。我的判断是工具是放大器不是模型能力本身。在没有工具、没有插件、只有一段提示词的条件下模型能否保持稳定输出才是真正值得对比的地方。这也是为什么“禁掉所有工具”这个话题会被人反复提起。这篇文章不想给出某个版本的跑分榜单而是想把这件事讲透为什么要做禁掉工具的裸推理评测评测应该覆盖哪些维度结果如何用于 Agent 工程决策。文末会提供一套可以复用的测试集格式、评测脚本和结果统计脚本。1. 这篇文章真正要解决的问题很多团队在选模型时第一反应是看演示视频模型调用了多少次工具、生成了多少段代码、最后输出有多惊艳。这种“工具演示”确实能说明接入能力却不能说明模型自身的推理能力。举个例子。你让模型从一份很长的日志里找出异常原因并允许它调用代码解释器。模型只要写几行脚本去统计日志就能得到答案。这个过程中真正困难的部分——定位日志、理解上下文、判断异常优先级——被工具和规则悄悄替模型做掉了一部分。模型剩下的工作只是把结果整理成自然语言。换句话说你评测的其实是“工具链 模型的组合系统”而不是模型本身。这在 Agent 落地中会带来很实际的麻烦。业务场景里外部 API 可能超时数据库可能断开工具返回格式可能变化。当工具不可用时模型能不能自己规划降级路径当工具返回了模糊甚至冲突的信息时模型能不能判断该信谁这些能力恰恰只有在去掉工具之后才能看清。所以这篇文章的第一目标就是帮助你建立一套“内核实测”的方法论把模型和工具解耦分别评估。适合读这篇文章的人有三类正在做模型选型的技术负责人在 Agent 项目中负责 Prompt 和系统设计的工程师需要搭建内部评测与回归体系的质量团队。如果你只是看热闹这篇文章也能帮你识别很多演示背后的水分。2. 为什么禁掉工具才是更公平的模型对比要理解这个问题先要知道“调用工具”在模型端到底发生了什么。当前主流的 Agent 架构中模型并不直接执行函数而是输出一段结构化的工具调用参数比如函数名和参数列表外部系统执行完工具后把结果作为新的消息回填到上下文中模型再继续生成。整个过程看起来是“模型会操作工具”实际上模型做的仍然是文本生成任务只是输入输出被结构化包裹了一层。问题是工具会替模型遮住很多基础能力。三个例子第一个是检索。模型对知识记忆不全时检索工具会把答案片段直接送到上下文里模型只需要做摘要。这样你无法判断模型原本的知识组织能力有多强。第二个是计算。遇到数学或统计问题代码解释器可以直接算出数值。如果模型只会生成计算代码、不会自己推演那么它在无法执行代码的环境里就会立刻失守。第三个是格式约束。结构化工具会把输出限制在固定字段内相当于预设了模板。模型即使对指令遵循能力弱也能靠模板得到合格输出。这里可以做一个类比让两位厨师做一道菜如果提前准备好预制菜包只让他们加热摆盘最终的差距会被明显压缩真正拉开差距的是没有预制菜包、需要用生鲜食材从头做的时候。评测模型也是一样工具就是预制菜包禁掉工具后的裸推理测试才是在看厨师自己的刀工、火候和配方能力。当然这不是说工具能力不重要。恰恰相反在真实业务中工具接入能力非常重要。这里要强调的是评估模型不适合把两件事混在一起说。应该先测“模型内核”再测“模型 工具组合”否则出了问题你很难定位是模型思考能力不行还是工具编排逻辑不行。3. 评测前先弄清这些边界在开始写评测脚本之前有几个边界要先说清楚避免后面越测越偏。第一版本与接口信息以官方为准。截至本文写作时关于 Opus 5 和 GPT-5.6 的公开信息可能仍在快速变化。本文不会锁定某个版本号也不会声称自己跑出过某个分数。你需要做的是在评测当天记录下两个模型的确切版本标识、API 名称、上下文窗口上限和计费方式。把这些信息写进评测报告的头部比任何一个分数都重要。第二不要用单次对话截图下结论。模型生成有随机性温度不同、系统提示词不同、题目顺序不同都可能改变输出。哪怕你对同一个问题跑了三次也可能得到三种风格完全不同的答案。严谨的对比至少要固定以下参数参数建议值原因系统提示词完全一致系统提示词会改变模型角色定位不一致等于换了个考题temperature固定为 0.2 或更低降低随机性让对比更接近模型稳定水平top_p固定或设为 1.0避免采样策略偏移max_tokens一致防止某个模型因输出截断而失分采样次数每个任务至少 3 次观察稳定性和异常输出比例提问顺序随机化避免顺序偏差与上下文污染工具调用全部关闭这是“裸推理评测”的前提第三要区分“评测结果”和“生产环境结果”。裸推理评测只在特定条件下反映模型内核能力不代表真实业务中的最终效果。真实业务还有 Prompt 设计、工具链、缓存、护栏等因素。所以评测结论的措辞最好写成“在无工具、单轮、固定温度条件下模型 A 的表现优于模型 B”而不是“模型 A 比模型 B 强”。第四公共评测集可能被污染。如果直接使用网上流传的测试题模型训练数据里可能已经包含答案导致分数虚高。更稳妥的办法是准备一份私有测试集或者把公开题目改写给关键数字和条件新旧混合使用。4. 无工具场景下重点评测的五个维度禁掉工具后模型能依赖的只有自己的参数化知识和上下文推理能力。因此评测维度要围绕这些能力设计。下面是我的建议五个维度基本能覆盖大多数业务场景。4.1 指令遵循这是 Agent 最容易翻车的地方。模型需要从用户的一段话里解析出约束条件然后严格照做。比如用户要求“只输出 JSON不要解释”模型可能仍然在 JSON 前后添加说明用户要求“不要使用某个词”模型可能仍然出现。评测时可以设计一些约束明确的题目例如输出格式、字数、禁用词、顺序要求。判断标准不是“答案对不对”而是“是否完全遵守约束”。一个在约束条件下还能给出正确内容的模型在 Agent 中更可控。4.2 多步推理与规划没有工具时模型不能靠外部计算器或数据库来简化问题。它需要自己拆解问题、设计步骤、逐步推导。数学应用题、逻辑谜题、路径规划问题都适合用来测这个维度。这里要注意不要只看最终答案。很多模型能在简单题上给出正确结果但在需要四步以上推理时开始跳步或引入幻觉。所以评分时应该同时看“步骤完整性”和“中间结论的正确性”而不只是最终答案是否正确。4.3 长上下文理解与信息检索长上下文是另一个容易被工具掩盖的地方。有检索工具时模型可以直接把关键信息抽取出来没有工具时模型只能靠注意力机制在上下文中寻找信息。经典的测试是“针包测试”在一大段无关文本中插入一句关键信息然后问模型这句话的内容。更强一点的变体是设置多条相互矛盾的信息看看模型能否依据上下文给出正确判断。建议分别测试不同长度区间比如 4K、8K、32K、64K 以上。要特别关注关键信息出现在不同位置时的表现因为有些模型对上下文中间部分的信息利用率较低。4.4 知识边界与诚实拒答模型面对自己不知道的问题时是承认不知道还是用听起来合理的假话填补这个维度在无工具场景下特别重要。连上搜索工具可以掩盖记忆缺陷但真实业务里用户的问题往往超出模型知识范围工具又不一定总能给出答案。评测时准备一些“超纲”问题、过时信息和冷门事实看模型的回答是否自信满满地编造细节。好的表现是明确指出信息不足、给出检索建议或说明知识截止时间。这个维度的评分标准不是“答对了没”而是“是否诚实地认识了边界”。4.5 代码生成与调试代码能力很适合放在无工具场景里测。不运行代码只让模型根据需求生成代码、解释已有代码、指出潜在 bug这样能直接考察模型对语法、逻辑和常见模式的掌握程度。如果允许运行代码模型可能会靠反复试错来掩盖对代码细节的理解不足。评测时可以准备三到五道中等难度的算法题和真实业务场景题分别考察生成、解释、调试三类任务。生成结果要关注代码是否能直接理解而不是花里胡哨的注释。这五个维度的对比可以用下表汇总维度考察点典型任务判断标准指令遵循约束解析与执行按要求格式输出、禁用词约束是否被完整遵守多步推理问题拆解与逐步推导数学题、逻辑题、规划题步骤完整性和中间结论长上下文信息定位与理解针包测试、矛盾信息判断关键信息召回率知识边界诚实度与不确定性表达超纲问题、过时信息是否承认不知道代码能力生成、解释、调试算法题、代码 review代码可用性和逻辑正确性5. 评测环境搭建与测试数据准备评测脚本不需要太复杂核心是保证两个模型跑同一套题、同一组参数。这里我用 OpenAI 兼容接口来演示因为很多模型服务商都提供兼容端点替换成本最低。如果模型官方 SDK 不同你只需要把请求部分换成对应的方法。先准备测试集文件test_set.json。每个样本包含任务 ID、所属维度、完整提示词和可选的自动判定关键词。为了节省篇幅这里只列三个样本实际使用建议准备 30 到 50 题。[ { task_id: math_001, dimension: multi_step, prompt: 一个农场里鸡和兔共有 35 个头、94 只脚。请问鸡和兔各有多少只请列出解题步骤最后给出结论。, max_tokens: 512, keyword: [兔 12, 鸡 23] }, { task_id: instr_002, dimension: instruction, prompt: 请用不超过 80 个字解释什么是数据库事务。回答必须只包含解释内容不要有前后缀说明不要使用任何标点符号。, max_tokens: 256, keyword: [] }, { task_id: needle_003, dimension: long_context, prompt: 以下是系统日志片段其中包含唯一一条特殊记录PASS_KEYABCD。请只输出 PASS_KEY 的值。\n\n[此处省略 4000 行日志]\n\n最后一行日志2024-06-01 12:00:00 INFO worker-1 task completed, max_tokens: 128, keyword: [ABCD] } ]说明一下每个字段的作用。task_id是任务唯一标识用于后续结果对齐dimension是维度标签方便分组统计prompt是发给模型的完整用户消息max_tokens限制输出长度keyword是可选的自动匹配词用于粗筛最终还是要人工看答案质量。如果要做真正的长上下文测试上面的 needle_003 只是占位。实际使用时你应该生成包含不同长度和关键信息位置的日志文本比如把 PASS_KEY 放在 10%、50%、90% 的位置各测一次。这样能看出模型对上下文不同位置的利用能力。6. 完整示例裸推理评测脚本测试集准备好后写一个统一的调用脚本。脚本的功能是读取测试集依次调用两个模型接口把输出保存为 JSONL 文件。注意关闭所有工具调用能力只发送 system prompt 和用户消息。# 文件路径evaluate_models.py import os import json import time from openai import OpenAI SYSTEM_PROMPT 你是一个严谨的推理助手。请只根据用户问题作答不要调用任何外部工具也不要提到工具。 MODEL_CONF [ { label: Opus 5, model: os.getenv(OPUS_MODEL, opus-5), base_url: os.getenv(OPUS_BASE_URL), api_key: os.getenv(OPUS_API_KEY), }, { label: GPT-5.6, model: os.getenv(GPT_MODEL, gpt-5.6), base_url: os.getenv(GPT_BASE_URL), api_key: os.getenv(GPT_API_KEY), }, ] def load_test_set(path): with open(path, r, encodingutf-8) as f: return json.load(f) def run_model(conf, prompt, max_tokens): client OpenAI(base_urlconf[base_url], api_keyconf[api_key]) resp client.chat.completions.create( modelconf[model], messages[ {role: system, content: SYSTEM_PROMPT}, {role: user, content: prompt}, ], temperature0.2, top_p1.0, max_tokensmax_tokens, ) return resp.choices[0].message.content def main(): test_set load_test_set(test_set.json) output_path raw_results.jsonl with open(output_path, a, encodingutf-8) as out: for conf in MODEL_CONF: for sample in test_set: prompt sample[prompt] max_tokens sample.get(max_tokens, 1024) for run_idx in range(3): print(fRunning {conf[label]} | {sample[task_id]} | run {run_idx 1}) try: output run_model(conf, prompt, max_tokens) except Exception as exc: output fERROR: {exc} record { model: conf[label], task_id: sample[task_id], dimension: sample.get(dimension, ), run_idx: run_idx, output: output, timestamp: time.strftime(%Y-%m-%d %H:%M:%S), } out.write(json.dumps(record, ensure_asciiFalse) \n) out.flush() time.sleep(0.5) if __name__ __main__: main()脚本逻辑很简单但有几点值得注意。第一它固定了 temperature 和 top_p这是保证两个模型对比公平的基本前提。第二每个任务跑了 3 次目的是观察稳定性。第三输出文件用追加模式打开即使中途某个模型调用失败前面保存的结果也不会丢失。第四请求没有传任何 tools 参数也没有启用联网搜索这正是“禁掉所有工具”的执行方式。接着写统计脚本把结果按任务分组打印出来方便人工评分。# 文件路径summarize_results.py import json import sys from collections import defaultdict def load_results(path): rows [] with open(path, r, encodingutf-8) as f: for line in f: line line.strip() if line: rows.append(json.loads(line)) return rows def group_by_task(rows): groups defaultdict(dict) for row in rows: groups[row[task_id]][row[model]] groups[row[task_id]].get(row[model], []) groups[row[task_id]][row[model]].append(row[output]) return groups def main(): rows load_results(sys.argv[1]) groups group_by_task(rows) for task_id in sorted(groups): print(f {task_id} ) for model, outputs in groups[task_id].items(): print(f--- {model} ---) for i, output in enumerate(outputs, 1): preview output[:300].replace(\n, ) print(f[run {i}] {preview}) print() if __name__ __main__: main()运行方式export OPUS_API_KEYyour_key export OPUS_BASE_URLhttps://your-api-endpoint/v1 export OPUS_MODELopus-5 export GPT_API_KEYyour_key export GPT_BASE_URLhttps://your-api-endpoint/v1 export GPT_MODELgpt-5.6 python evaluate_models.py python summarize_results.py raw_results.jsonl预期输出是每个任务下两个模型的三次输出预览。你可以看到模型 A 是否三次都稳定模型 B 是否第一次对、第二次错这种“不稳定”本身就是重要信息。评分时建议把三次输出的“最优表现”和“最差表现”分开记录而不是只取一个平均值。7. 评测结果如何指导 Agent 工程决策拿到评测结果后最重要的不是争论谁高谁低而是把结果翻译成工程动作。下面
返回列表