☰
五万次运行的启示:5 行 eval 如何度量 VS Code 智能体模型的努力校准与 Token 成本
2026/10/10 2:34:51 网站建设 项目流程
  • 文档
  • 教程

【免费下载链接】vscode-docs

Public documentation for Visual Studio Code

项目地址:https://gitcode.com/gh_mirrors/vs/vscode-docs
点击查看免费下载

2026-06-19 · VS Code Eval Team(作者:Julia Kasper)

2025 年底到 2026 年年中,VS Code 团队在六个月里把同一个只有 5 行定义的say_helloeval 重复运行了50,974 次,覆盖30 个模型,把一次"向文件写入字符串"的冒烟测试变成了一份观测模型努力校准(effort calibration)、工具使用纪律(tool discipline)与输出 Token 成本的数据集。读完本文,你将理解为什么最简单的 eval 反而是最灵敏的仪表,学会用"工具调用序列 + 输出 Token"两个维度评估编码模型的真实效率,并了解 VS Code 与 GitHub Copilot 如何把这些信号接入自动模型选择。

从编码 harness 到最小的冒烟测试

要理解这次实验,需要先回到它的上游:VSC-Bench。在仓库的前一篇博客《GitHub Copilot in VS Code 背后的编码 harness》中,团队介绍了 VSC-Bench——用于度量 VS Code 智能体行为的离线评测套件。它强调一个核心观点:开发者真正交互的不是模型本身,而是编码 harness——负责组装上下文、暴露工具、运行智能体循环、解释工具调用并把模型输出变成编辑器内实际动作的那一层。

正是这套 harness 让"工具调用序列"成为一个可观测、可记录的信号:

  • 上下文组装(context assembly):请求到达模型之前,harness 会把系统消息、用户查询、工作区结构、对话历史、工具结果等拼装成 prompt;
  • 工具暴露(tool exposure):harness 声明模型允许调用的工具(读文件、编辑、终端、搜索等),每个工具都有 JSON Schema 与描述;
  • 工具执行(tool execution):模型请求调用工具后,由 harness 负责校验参数、执行、处理错误并把结果回传给下一轮迭代。

say_hello就是这套 harness 上的"体温计":一个任务足够简单,简单到任何变化都只能来自模型或 harness 本身,而不是任务复杂度带来的噪声。因此它能灵敏地反映 harness 回归、基础设施事故和模型行为差异——一个简单任务是有价值的,恰恰因为它剔除了变量。

say_hello 的定义:5 行 eval 的完整配置

say_hello围绕一个想法构建:每一次运行都从同一个空工作区开始,使用相同的工具、相同的固定 prompt 和相同的 VS Code 智能体 harness。任务本身只要求智能体"向 HELLO.txt 写入 HELLO",并检查两条断言:文件存在、内容正确。完整的 eval 定义如下:

promptSteps: - text: Add HELLO to HELLO.txt. assertions: - check: file_exists("HELLO.txt") - check: file_contains("HELLO.txt", "HELLO")

这份 YAML 值得拆开来看:

  • promptSteps:定义一次运行要发给智能体的用户指令序列。say_hello只有一个步骤、一条指令,因此任何跨运行的行为差异都不可能是"任务理解偏差"造成的;
  • text:发送给智能体的 prompt 原文,固定不变;
  • assertions:判定通过与否的检查器。file_exists("HELLO.txt")验证文件是否被创建,file_contains("HELLO.txt", "HELLO")验证内容是否精确匹配——两条断言共同构成"正确结果唯一且无歧义"的通过标准。

因为say_hello在每个基准测试套件运行前都会先作为冒烟测试执行一次,它悄无声息地在六个月里积累了 50,974 次运行、跨越 30 个模型。这个规模把一次基本的健全性检查,变成了一份关于"不同模型如何处理最简单任务"的数据集。

[!NOTE] VS Code eval harness 会把工作区状态包含在初始 prompt 上下文中。我们假定模型不应该执行冗余的存在性检查——这正是 harness "上下文组装"职责在 eval 中的体现:模型拿到 prompt 时应当"知道"工作区是空的。

理想路径:一次 create_file 调用

一个开发者做这件事时会先意识到工作区是空的,然后创建HELLO.txt并写入要求的内容。在 VS Code 智能体最直接的路径里,这对应一次create_file工具调用,内容就是HELLO:

tool : create_file args : { "filePath": "/path/to/workspace/HELLO.txt", "content": "HELLO" }

这条"直达路径"(direct path)是本次分析的核心基准:一次工具调用、无规划、无探索、无搜索,直接产出正确结果。为了建立基线,团队筛选出走这条路径的通过运行,并观察其中最低的输出 Token 数——这些运行平均约50 个输出 Token(含工具调用结构本身),这就是本任务"现实可行的下限"。

模型如何解决 say_hello:直接路径的四层分布

如预期的那样,say_hello足够简单,所有模型大多数时候都能通过。有意思的不是"能不能做",而是"怎么做":模型能否识别出这是一个只需简单方案的基础请求,还是会像处理复杂问题一样先规划、再探索、再搜索?

下图展示各模型在通过运行中达成"单次工具调用直达路径"的占比:

数据的分布可以清晰地分为四层:

  • 榜首(100%):Model-A 独占。它在 100% 的通过运行中都直接创建文件,每次都只用一次工具调用,从不先做规划或探索;
  • 跟随组(71%–73%):Model-B 与 Model-C 分别以 73% 和 71% 紧随其后;
  • 中部集群(19%–52%):Model-D 至 Model-P 直接路径的达成率在 19% 到 52% 之间。它们能识别简单任务,但不够稳定——更多时候会先加一个小步骤(读取内部状态或做轻量工作区探索)再创建文件;
  • 底部集群(0.2%–6%):Model-Q 至 Model-X 很少走直接路径,其中五个模型低于 1%。对它们而言,"额外工作"是默认行为——几乎总是先规划、探索或搜索,才产出同一个只有 5 个字符的文件;
  • 零达成(0%):Model-Y 至 Model-AC 这五个模型在数千次通过运行中从未走过直接路径。它们总是先做点别的:规划、改用 patch 工具而不是简单的文件创建、先搜索再规划、或者长篇叙述后才创建文件。对它们来说,哪怕最简单的请求也会触发完整的那套复杂任务机制。

所有模型最终都创建了内容正确的文件,但达成同一结果所付出的工作量天差地别。在一个几乎没有任何歧义的任务上,部分模型仍然要规划、搜索或选择更复杂的编辑工具——全部通过了 eval,但通过的"努力量"并不相同。

顺带一提,仓库中与本文同目录附带了一份图表生成脚本 generate_chart.py。从脚本结构看,它是一份可复现的 SVG 图表管线:每个模型一行绘制横向条形图,按厂商(Vendor A/B/C/D)用不同颜色区分,并对达成率为 0% 的模型追加红色注解,最终把 SVG 写入临时 HTML 供预览核对。这说明这类评测数据图表是"数据驱动、可再生成"的资产,而不是手绘的示意图。

多余的开销花在哪里:五种典型模式

因为离线 eval harness 会记录完整的工具调用序列,团队可以把这些 trace 转成模型行为模式。跨运行统计后,模型的额外努力主要落在五种熟悉的形式上:

开销模式频率代表模型具体表现
先规划再行动52–99%Model-AC、Model-Z、Model-S 及其他 13 个模型在创建 5 字符文件之前先起草清单或读取内部状态。可测量的 16 个模型里,每个都至少在一半的运行中如此;Model-AC 达到 99%,Model-Z 达到 96%。有一次甚至在单步任务里出现了 4 个规划步骤。
探索空工作区56–96%Model-T、Model-Q、Model-AA在空工作区里列目录或搜索文件。Model-T 在 96% 的运行中都会列目录;Model-AA 在 56% 的运行中既列目录又搜索——在空房间里寻找线索。
叙述推理过程1,441–3,676 TokenModel-AB、Model-M、Model-U输出远多于任何工具调用需要的文本,一边推理一边反复确认任务。这三个模型在输出 Token 榜上登顶,是现实下限的 29–74 倍,而文件本身只有 5 个字符。
用错工具约 95%Model-AA使用面向"修改既有文件"的复杂 patch/编辑工具,而不是简单的文件创建——好比用数控机床去裁一张纸。
运行终端命令3–14%Model-W、Model-Z、Model-V在存在更简单的文件创建 API 时,选择运行终端命令(如echo HELLO > HELLO.txt)。

这些都不是正确性失败。它们是**模型未能一致地识别"最短路径何时已经足够"**的信号。在长任务上,规划与探索可能非常宝贵;但在单步任务上,它们只增加延迟和成本,不改善结果。

过度思考的代价:输出 Token 的四档分布

为什么要关心模型写一个 5 字符文件多走了几步?因为这些额外步骤并不免费——它们会直接转化为输出 Token 消耗,而输出 Token 意味着真金白银的成本。

对这个简单任务而言,约 50 个输出 Token 是现实可行的下限。下图展示不同模型每次运行的平均输出 Token 数,跨度从贴近下限一直到数千 Token,而产出的都是同一个HELLO.txt:

图表清晰地分成四个波段:

  • 极端组(1,441–3,676 Token):Model-AB、Model-M、Model-U 平均分别消耗 3,676、2,120、1,441 个输出 Token——对同一个 5 字符结果而言,是现实下限的29 到 74 倍;
  • 高开销组(400–1,000 Token):Model-AA、Model-B、Model-N、Model-H、Model-V、Model-E、Model-S、Model-K。没有到数千级别,但仍约为现实下限的8 到 12 倍;
  • 中等组(150–400 Token):Model-P、Model-D、Model-X、Model-T、Model-G、Model-Z、Model-I、Model-AC、Model-F、Model-J、Model-Q。它们有额外开销,但更贴近任务的天然规模;
  • 高效组(低于 150 Token):Model-R、Model-A、Model-Y、Model-W、Model-O、Model-C、Model-L。其中 Model-L 以平均 55 Token 最接近现实下限——即使不总走直接工具路径,也能在几乎不叙述的情况下完成任务。

从产品视角看,这与 VS Code 文档中关于语言模型的说明相互印证:docs/agents/concepts/language-models.md 指出,思考 Token(thinking tokens)同样计入上下文窗口、即使不可见也会影响延迟,而更高思考强度会带来更多思考 Token。选一个"想得更少"的模型能同时节省时间与金钱,但要知道哪个模型在具体任务上最高效,通常意味着要跑自己的基准。为了替开发者承担这个负担,VS Code 与 GitHub Copilot 团队持续投入优化与模型路由。

模型大小并不预测开销

团队最初的假设是"更大的模型想得更多",但数据否定了这一点:

  • Model-F(同族中较大的模型)平均只用 160 个输出 Token、2.1 次工具调用——是它所属模型家族中最自律的一个;
  • Model-H(同族中较小的模型)平均消耗 485 个输出 Token、3.7 次工具调用——开销反而高于它的大兄弟;
  • Model-AB(一款 "mini" 模型)是全部样本中开销最高的,平均 3,676 个输出 Token——样本里最小的模型干了最多的活。

团队的解读是:在每个模型家族内部,新一代的模型趋势上更自律,与参数量无关。这指向训练成熟度(training maturity)——模型能否把自己的努力按眼前任务的规模缩放。而这种校准能力并非学术好奇:它直接体现在账单上。

走向何方:从洞察到工程决策

团队从这些运行中提炼了几条关键洞察,其中一些也可以直接应用到你自己的日常流程里。

[!NOTE]say_hello给了我们很好的洞察,但它只代表一个任务。对于 harness 优化,我们避免只围绕单一任务做过度优化。我们仍然会定期在多样化的任务集上运行完整基准,以验证改动是否在大面上改善了 harness。

让模型与任务匹配

GitHub Copilot 采用基于用量的计费后,输出 Token 同时代表金钱和时间。在这个任务上,最精简与最沉重的模型之间,同样的输出相差约70 倍。最直白的教训似乎是"别拿最大的模型去写 HELLO",但这个教训太粗糙——看清为什么,才是say_hello教给团队最有用的东西。

这里有一个重要的前提:say_hello是单步、单正确答案的短视界任务。在长视界工作上,规划、探索和推理可以避免昂贵的错误、提高完成几率。目标不是消灭规划,而是理解模型能否区分"一步任务"和"三十步任务"。

这也是为什么团队认为模型选择不应该成为开发者的负担。努力校准、Token 效率、工具纪律这类信号,可以帮助自动模型路由为手头任务挑选合适的模型,而不必要求开发者权衡每一个取舍。仓库文档对这套机制有明确描述:docs/agents/concepts/language-models.md#auto-model-selection 说明,VS Code 的自动模型选择由两套系统协同:一套实时跟踪模型健康度与可用性,另一套评估任务复杂度,两者共同把请求路由到能以最高效率解决问题的模型——把高成本推理模型留给真正需要它的难题,把简单任务路由给更快的模型,同时尊重组织级的模型访问策略。团队表示会继续投资和研究自动模型选择,让产品替开发者逐步做出更多此类决策。

从小处着手,好好测量

大多数团队一开始并没有一套每天可跑的私有离线基准套件。但哪怕是一个简单任务,只要稳定运行、完整记录,也能揭示模型或系统行为的有用变化。

实践建议如下:

  1. 从拥有无歧义正确答案的最小任务开始;
  2. 然后持续运行它:把它当作夜间评测之前、新模型接入之前、基础设施变更之前的预检(preflight)检查;
  3. 任务不需要"巧妙",它需要的是足够稳定——稳定到通过率、延迟、工具使用或失败模式的变化都有意义。

最关键的一点是:记录足够的结构来解释"发生了什么"。要记录工具调用序列,而不只是调用次数。知道"有 4 次工具调用"是有用的,但不够;知道"模型先规划、再探索、再搜索、最后创建文件",才能告诉你开销来自哪里、为什么这次运行更贵:

// 大多数 harness 只记录: { "tool_calls": 4, "pass": true } // 你真正需要的是: { "tool_sequence": ["plan", "list_directory", "search_files", "create_file"], "output_tokens": 617, "pass": true }

这套"结构化日志"的思路,与仓库中智能体调试文档的设计一致:文档提供了多个互补的诊断视图——Chat Debug 视图展示发送给模型的 prompt、上下文与工具,Summary 视图汇总耗时、Token 用量与错误,Logs 视图按顺序还原事件。这些能力同样服务于"看清工具调用序列,而不是只看计数"这一目标。

从冒烟测试到信号

say_hello最出乎意料的地方,不是模型能写出HELLO.txt,而是一次 5 字符的编辑让"努力"变得可见:哪些模型会按任务规模收缩,哪些始终在规划或搜索,又有哪些系统级故障只有在数千次运行之后才会显形。

你也可以在自己的 VS Code 里复现这个实验:用你偏好的模型发出同样的请求,打开 Chat Debug 视图 检查它的工具调用序列与 Token 消耗,然后想一想——属于你自己的"最小有用任务"是什么。用上文的两条标准(稳定 + 无歧义答案)把它固定下来、持续运行、完整记录工具序列,你就能把一次冒烟测试变成长期观察模型行为与成本的长效信号。

  • 文档
  • 教程

【免费下载链接】vscode-docs

Public documentation for Visual Studio Code

项目地址:https://gitcode.com/gh_mirrors/vs/vscode-docs
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询