- 文档
- 教程
【免费下载链接】vscode-docs
Public documentation for Visual Studio Code
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 Token | Model-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 的自动模型选择由两套系统协同:一套实时跟踪模型健康度与可用性,另一套评估任务复杂度,两者共同把请求路由到能以最高效率解决问题的模型——把高成本推理模型留给真正需要它的难题,把简单任务路由给更快的模型,同时尊重组织级的模型访问策略。团队表示会继续投资和研究自动模型选择,让产品替开发者逐步做出更多此类决策。
从小处着手,好好测量
大多数团队一开始并没有一套每天可跑的私有离线基准套件。但哪怕是一个简单任务,只要稳定运行、完整记录,也能揭示模型或系统行为的有用变化。
实践建议如下:
- 从拥有无歧义正确答案的最小任务开始;
- 然后持续运行它:把它当作夜间评测之前、新模型接入之前、基础设施变更之前的预检(preflight)检查;
- 任务不需要"巧妙",它需要的是足够稳定——稳定到通过率、延迟、工具使用或失败模式的变化都有意义。
最关键的一点是:记录足够的结构来解释"发生了什么"。要记录工具调用序列,而不只是调用次数。知道"有 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
相关推荐
Claude Code /code-review 低努力模式(Low Effort)解析:一次 Diff 扫描完成运行时正确性审查
Claude Code /code review 低努力模式(Low Effort)解析:一次 Diff 扫描完成运行时正确性审查 本文基于开源仓库 claud
文档提示工程人工智能Go并发编程实战第2版示例项目:5种并发模式的最佳实践与应用场景
Go并发编程实战第2版示例项目:5种并发模式的最佳实践与应用场景 Go语言以其出色的并发编程能力而闻名,而《Go并发编程实战》第2版示例项目正是学习和掌握Go并
从源码到部署:Argon Design System React项目完整流程指南
从源码到部署:Argon Design System React项目完整流程指南 Argon Design System React是基于Bootstrap 4
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考