GitHub Copilot 如何在不牺牲任务质量的前提下降低 AI 编码成本
How we make AI coding more cost efficient without sacrificing task quality
GitHub Copilot 团队介绍四项 harness 改动,在不牺牲任务质量的前提下降低编码智能体成本:选择性压缩安装、构建、测试等重复输出并保留源码类输出,移除 view 工具的行号前缀,用元提示词循环把 task 工具提示词压缩约一半,并把后台任务完成结果直接批量返回。
GitHub Copilot 团队公开四项 harness 优化的离线与在线实验数据,可迁移到其他编码智能体的成本控制。
在使用 AI 编码代理时,输出质量很重要,但真正的效率来自于快速、高效地完成任务,并且拥有正确的上下文。
这就是为什么单次交互的 token 数量本身并不能作为衡量效率的有意义指标。目标不应该是使用更少的 token,而是获取恰到好处的上下文来推动任务向前推进。一个简洁的工具响应有时可能需要额外的调用或工作,如果它遗漏了代理所需的信息,最终会使任务变得更慢、更昂贵。
这就是为什么我们希望针对结果而非工具调用进行优化。本文探讨了 GitHub Copilot 中的四项变更,将这些原则付诸实践:
- 在减少重复输出的同时保留有用的上下文。
- 移除对任务没有价值的格式。
- 在不改变有用行为的情况下缩短指令。
- 交付已完成的后台工作,无需额外的检索步骤。
可能的变更使用代理编码基准进行了离线评估。最有前景的变更随后通过受控的在线实验进行验证,然后才发布。本文中的示例来自 GitHub Copilot CLI。其他多个 Copilot 产品,例如 GitHub Copilot 应用和 Copilot 代码审查,使用相同的底层框架,也通过这些改进变得更加高效。

局部指标陷阱
通过缩短每次工具调用的输出来降低代理成本是一种常见做法。RTK(Rust Token Killer)是一个实用工具,可以在代理读取之前缩短 shell 输出。我们使用代理编码基准评估了它对 GitHub Copilot 的影响。
在我们的框架和基准配置中,RTK 缩短了一些响应,但当被省略的文本很重要时,模型有时会重新打开原始输出或重新运行命令来恢复所需内容。
这些恢复步骤增加了轮次,并向前传递了更多上下文。单个工具响应变短了,但平均而言,任务使用了更多 token 并且耗时更长。我们在局部节省了 token,却在全局花费了更多。

这一结果适用于我们测试的集成和工作负载,并不适用于所有 RTK 配置或一般的输出压缩。这意味着每次工具调用的 token 数是错误的目标。效率变更必须在整个任务范围内进行评估,从用户请求到最终结果。
更有用的是审视我们可以在不让模型重复工作的情况下移除什么。
压缩噪声,保留有用信息
目标是缩短重复输出,同时保留代理完成任务所需的上下文,而无需回溯步骤。
对基准运行的分析表明,安装、构建、测试和 lint 输出通常包含重复的噪声,而类似源代码的输出和任意命令结果更可能包含代理所需的信息。这一分析促成了一个选择性输出压缩器,部分参考了 RTK 和类似方法。
该原型在代理编码基准和一系列开源代码仓库上进行了评估,测试了它们的构建、测试和 lint 系统。
早期版本过于激进。它们让模型重复工作或读取完整的已保存输出,增加了端到端成本并降低了任务成功率。例如,我们最初压缩了git diff,但在基准任务显示智能体会重新打开原始输出以恢复缺失信息后,我们移除了该过滤器。
这些早期的失败促成了一项由三部分组成的策略:
- 保留类源输出和任意输出。诸如
cat、git diff、git show等命令以及任意脚本均原样返回。 - 重组搜索结果而不丢弃内容。来自
grep等工具的匹配项和文件列表可以更高效地分组,同时保留每一个结果。 - 有选择地压缩重复性噪声。仅当节省量可观时,才压缩安装、构建、测试和进度输出。
最终发布的版本是通过反复评估和优化而形成的。它之所以保守,并非因为目标是构建一个保守的压缩器,而是因为评估结果支持这样做。
当输出被压缩时,智能体仍可通过直接恢复路径检索完整的原始内容。

该恢复路径既是一种安全机制,也是一种评估信号。我们追踪了智能体是否打开已保存的原始内容、重新运行命令、重复探索、缩小搜索范围或采取额外的轮次。频繁恢复将表明压缩器移除了有价值的内容。
在触发输出压缩的离线任务中,未检测到统计上显著的任务成功率下降,且智能体极少打开已保存的原始内容。在在线实验中,平均成本略有下降,所追踪的质量指标未检测到实质性下降。
先移除格式,再移除信息
一项简洁的 token 优化来自view工具,智能体使用该工具将文件内容读入上下文。
此前,view在向模型显示内容之前,会在每一行前加上行号。早期的文件编辑工具使用这些行号来定位更改,但当前工具改为匹配周围的代码,不再使用行号。尽管常规工作流已不再使用行号前缀,它们仍然保留着。
每个前缀都很小。然而,在每一行和每次文件读取中重复出现,这种未使用的格式会在整个会话中不断累积。因此,我们将其移除。

行号在差异和短代码片段中仍然有用。但在这里它们是浪费的,因为每次文件读取都会附带行号,而当前的编辑工作流并不需要它们。
移除它们后,在离线智能体编码基准测试中,模型推理成本下降了约 5%。成功率保持在预期的运行间波动范围内,编辑失败并未增加。
随后,我们在 Copilot CLI 用户中测试了这一更改。在线实验将每位用户的平均每日模型推理成本降低了约 3%,我们所追踪的质量或满意度指标未检测到实质性下降。
对开发者而言,这意味着上下文窗口中可用于工作本身的空间更大,而不是被智能体并不使用的格式所占用。
这是理想的改动:模型没有新的指令,没有需要恢复的信息来源,也没有额外的决策要做。文件内容原封不动地到达了模型。
压缩提示词,而不压缩意图
提示词承载着塑造智能体工作方式的指令,并且每一轮都会发送给模型。只有当智能体保留开发者所依赖的行为时,缩短提示词才能提升效率。
在 GitHub Copilot 中,task 工具会启动专门的智能体以并行工作。它的指导内容分散积累在工具描述、schema、智能体定义、系统指令和配套工具中。
一个元提示循环让 Copilot 迭代地编写自己的提示词,将该提示词缩减了大约一半。Copilot 生成并优化了更小的候选版本,并通过有针对性的行为测试来检查我们希望保留的需求。
第一次在线实验发现了一个初始离线评估遗漏的回归问题。元提示循环将谨慎的并行指导改写成了硬性的调度策略,导致独立的自定义智能体被串行执行。
我们停止了该实验。在再次修改提示词之前,我们针对用户暴露出的行为编写了一个回归评估。最终的修复用一个句子取代了显式的允许列表和拒绝列表:
独立的智能体可以并行运行;请考虑副作用。
这句话更短、限制更少;它将是否并行运行子智能体的选择权交给了模型,而不是像之前那样给出明确的指导。有了它,我们的新行为测试通过了,且没有导致任何现有行为测试失败。
提示词行为需要测试。如果某个行为没有被测试,更短的提示词可能会在无人察觉的情况下将其移除。

发布后的提示词每轮减少了约 1,300 个 task 工具提示词 token,相当于每个会话总提示词 token 减少约 1.8%,每个活跃小时的归一化成本降低 2.9%,且在所测量的评估中未检测到质量回归。
无需额外的检索轮次即可交付已完成的后台工作
智能体经常在后台运行独立的工作,例如长时间运行的 shell 命令与子智能体调查并行进行。通知让智能体可以继续工作,直到该工作准备就绪,而无需花费一次工具调用来等待。
如果智能体没有显式等待任一任务,当 shell 命令或子智能体完成时,执行框架会唤醒模型并通知它。
此前,该通知不包含已完成的结果,因此智能体不得不额外花费一轮来检索 Copilot 已经收到的输出。当多个任务几乎同时完成时,这种绕路可能会重复发生。现在,Copilot 会批量处理符合条件的完成通知,并以现有的工具结果格式直接交付已完成的结果。智能体可以带着所需信息继续工作,而无需额外花费一轮再次请求它。对于仍在运行的工作,显式读取的行为与之前相同。

在此更改之前,每个完成的任务都需要一次模型调用来请求其结果,另一次调用来处理它。对于上面展示的 shell 命令和子代理,这意味着在工作可以继续之前需要四次模型调用。
现在,harness 将两个完成结果批量处理并一起提供,因此单次模型调用即可处理两者。移除这些检索绕行也避免了通过不必要的调用携带完整的会话上下文。
通过直接交付已完成的结果,不进行压缩、摘要或保留任何内容,harness 将平均 token 相关使用量(以 AI Credits 衡量)降低了约 2.3%。
衡量上下文中的变化
在一个 Copilot 工作流中节省 token 的更改可能会增加另一个工作流的成本。
例如,一组更精简的文件工具指令是受到 Copilot 代码审查中积极结果的启发。在一次 Copilot CLI 在线实验中,它增加了成本,因此我们没有发布它。
相比之下,在使用生产模型对大量 Copilot 代码审查任务进行的独立评估中,移除行号前缀和选择性压缩输出各自将每次审查的平均提示 token 减少了约 5%。我们在跟踪的审查质量指标中未检测到实质性变化。
这些发现与早先将 Copilot 代码审查迁移到共享文件工具是分开的,后者连同审查指令调优,将代码审查成本降低了约 20%。
每项更改都需要在其运行的工作流中进行衡量。
构建高效 AI 编码代理的五条经验
- 优化已完成的任务,而不是工具调用。 如果代理花费更多轮次来恢复被移除的内容,更短的输出并不更便宜。
- 优化编排,而不仅仅是模型输出。 消除那些执行 harness 可以确定性地完成的工作的模型轮次。
- 根据输出所代表的内容进行压缩。 保留精确内容,优先使用无损转换,并衡量代理使用恢复路径的频率。
- 提示重写有时会产生意想不到的后果。 验证预期行为是否得以保留。
- 证据是工作负载局部的。 在离线基准测试、在线实验以及它们发布的每个产品界面中重新评估更改。
这些更改都没有让模型变得更聪明。它们移除了模型从不需要做的工作。
本文中描述的更改正在使用相同底层 harness 的各个 GitHub Copilot 体验中发布。
将代理工作流带到你的终端
使用 GitHub Copilot CLI >
文章 How we make AI coding more cost efficient without sacrificing task quality 首次出现在 The GitHub Blog。
来源:GitHub Blog · AI & ML · github.blog