← 文章 / AI技术
GitHub Blog 59分钟前 · 2026-09-03 05:21:14 · 0 阅读

如何在保证任务质量的同时降低AI编程成本

与 AI 编程 Agent 协作时,输出质量固然重要,但真正的效率来自于快速、高效地完成工作,并提供恰当的背景信息。 因此,仅凭单次交互的 Token 数量并不能有效衡量效率。目标不应是减少 Token 用量,而是调用恰当的背景信息来推进任务。有时,过于简洁的工具响应可能因遗漏了 Agent 所需的信息,反而需要额外的调用或工作,最终导致任务更慢、成本更高。 这正是我们注重优化结果而非工具调用的原因。本文介绍 GitHub Copilot 中四项贯彻这一原则的改动:
  • 保留有用信息的同时减少重复输出。
  • 移除对任务无益的格式。
  • 精简指令但不改变有用行为。
  • 无需额外检索步骤即可交付已完成的工作。
我们使用编程基准测试对各项可能的改动进行了离线评估,最有前景的改动在正式上线前还经过了受控在线实验的验证。本文中的示例来自 GitHub Copilot CLI。GitHub Copilot 应用和 Copilot 代码审查等其他多个 Copilot 产品均采用相同的底层框架,同样从这些改进中提升了效率。
Chart showing 3.1% 'Remove view previxes', 5.5% 'Selective output compaction', 2.9% 'Compact task-tool prompt', and 2.3% 'Reduce notification roundtrips'.
图 1:四项独立的 A/B 实验,使用相同的 AI 积分指标。各数据段并列展示以便对比;它们的效果未必严格可加。

本地指标的陷阱

缩短每次工具调用的输出以降低 Agent 成本是很常见的做法。RTK(Rust Token Killer)就是一个在 Agent 读取之前缩短 shell 输出的工具。我们用编程基准测试评估了它对 GitHub Copilot 的影响。 在我们的基准框架和配置下,RTK 虽然缩短了部分响应,但当被省略的内容很关键时,模型有时会重新打开原始输出或重跑命令来恢复所需信息。

这些恢复步骤增加了交互轮次和上下文负载。虽然单次工具响应变短了,但平均来看,任务消耗的 token 更多、耗时也更长。我们省下了局部的 token,却付出了更高的整体成本。

流程图示意:RTK 压缩 shell 输出 → 工具响应变短(局部收益) → 关键细节缺失 → 触发恢复(重读或重跑) → 增加轮次与上下文负载。随后可走向终局(端到端结果:token 与成本上升、任务时长增加、完成率持平),或陷入“恢复循环”重新回到细节缺失状态。
图 2:当细节缺失迫使智能体重新读取输出、重跑命令并携带更多上下文时,更短的工具响应反而会让任务的总成本更高。

该结论仅针对我们测试的集成场景与工作负载,并不适用于所有 RTK 配置或通用输出压缩。这说明将“单次工具调用的 token 消耗”作为优化目标是错误的。任何效率改进都必须放在完整任务链路中评估,从用户发起到最终交付。

真正有意义的探索方向是:找出可以剔除的内容,同时避免让模型做重复劳动。

压缩噪声,保留有用信息

我们的目标是在压缩重复输出的同时,保留智能体完成任务所需的上下文,避免其走弯路。

基准测试分析表明,install、build、test 和 lint 等命令的输出往往充斥着重复噪声,而类源码输出及普通命令结果则更可能包含智能体真正需要的信息。基于这一洞察,我们开发了一种选择性输出压缩器,其设计参考了 RTK 及其他类似方案。

我们在 Agent 编程基准测试及多种开源仓库上对该原型进行了验证,全面测试了它们的 build、test 和 lint 流程。

早期版本过于激进,反而导致模型重复劳动或回查完整历史输出,推高了端到端成本并拉低了任务成功率。例如,我们曾尝试压缩 git diff 的输出,但基准测试显示智能体会被迫重新打开原始输出以补全缺失信息,因此我们最终移除了该过滤规则。

这些早期试错最终凝练为三项核心策略:

  1. 保留源码和任意格式的输出。 catgit diffgit show 以及任意脚本的输出均原样返回。
  2. 重组搜索结果而不丢失内容。 grep 等工具返回的匹配项和文件列表可以更紧凑地分组,同时保留全部结果。
  3. 选择性压缩重复噪音。 安装、构建、测试和进度输出仅在压缩收益显著时才进行压缩。

最终上线版本经过多次评估和迭代优化而来。它偏保守并非因为目标是做一个保守的压缩器,而是因为评估结果支持这样的设计。

当输出被压缩时,agent 仍可通过专用恢复路径获取完整的原始内容。

流程图展示了 GitHub Copilot 如何处理 shell 命令输出。Copilot 调用 shell 命令、对输出分类,然后选择三条路径之一:保留源码/任意输出不变、重组搜索结果不丢失匹配项、或有选择地压缩重复噪音(如安装/构建/测试日志)同时保留完整输出并提供恢复路径。处理后结果返回给 Copilot。
图 3:上线版压缩器保留源码类输出、无损重组搜索结果,仅压缩可预测的重复噪音,同时保留完整原始内容。

这条恢复路径既是安全机制,也是评估信号。我们追踪 agent 是否打开了保存的原始输出、重新执行了命令、重复探索、缩小了搜索范围,或消耗了额外的交互轮次。频繁的恢复操作意味着压缩器可能删掉了有价值的信息。

在触发输出压缩的离线任务中,未发现统计显著的 task-success 下降,且 agent 极少打开保存的原始输出。在线实验中,平均成本略有下降,所追踪的质量指标也未出现明显回落。

先移除格式,再考虑移除信息

来自 view 工具的一个简洁 token 优化。该工具供 agent 将文件内容读入上下文。

以前,`view` 会在将文件内容展示给模型之前,给每行加上行号前缀。早期的文件编辑工具依赖这些行号来定位修改,但当前工具改用匹配周围代码,已不再使用行号。即便正常的工作流已无需行号,这些前缀却依然被保留了下来。 每个前缀本身很短,但跨文件、跨行的反复累积,让会话中充斥着大量无用的格式文本。于是我们将其去掉了。
Before-and-after image of code snippets. The line-number prefixes re removed from the 'After' image.
图 4:移除行号前缀后,源文件内容保持不变,同时消除了每次读取文件时重复叠加的冗余格式。
行号在 diff 和短代码片段中仍有价值,但此处的问题在于:它们被附加到每一次文件读取中,却并未服务于当前的编辑工作流,造成了浪费。 在离线智能体编码基准测试中,移除行号使模型推理成本下降了约 5%。成功率保持在预期的逐次波动范围内,编辑失败率也未上升。 随后我们在 Copilot CLI 用户中进行了在线实验。结果显示,每位用户的日均模型推理成本降低了约 3%,所追踪的质量与满意度指标也未出现显著下滑。 对开发者而言,这意味着更多的上下文窗口可以留给实际工作,而非被 AI 根本不需要的格式占用。 这是一次"理想型"改动:无需向模型新增指令,无需恢复任何信息源,也无需做出额外的决策。文件内容原封不动地送达模型。

压缩提示,但不压缩意图

提示词承载着指导智能体行为的工作指令,且每一轮交互都会发送给模型。只有当智能体仍然保留开发者依赖的行为模式时,缩短提示词才能真正提升效率。 在 GitHub Copilot 中,task 工具负责为并行任务启动专用智能体。它的指导来源分散积累在工具描述、架构定义、智能体规范、系统指令和配套工具之中。

通过元提示循环,让 Copilot 迭代生成并精简自身的提示词,最终将提示长度缩短了近一半。Copilot 会生成并打磨出更精简的候选版本,再通过定向的行为测试来检验是否保留了我们期望的关键能力。

首轮线上实验发现了一处离线评估未能察觉的回归问题:元提示循环将原本谨慎的并行性指导改写成了硬性调度策略,导致各个独立自定义代理变成了串行执行。

我们立即叫停了实验。在再次修改提示之前,我们针对用户实际暴露出的行为编写了回归评估。最终的修复方案用一句话替代了原先的显式白名单和黑名单:

独立代理可以并行运行,但请留意副作用。

这句话更简短、限制更少,将是否并行运行子代理的决策权交还给模型,而非沿用此前的显式指令。有了这条规则,我们的新行为测试得以通过,且未导致任何现有行为测试失败。

提示词的行为需要测试。如果某项行为没有经过测试,更精简的提示词就可能悄悄将其移除而无人察觉。

Three-stage diagram labeled Compression → Regression + fix → Completed. Left panel shows an original prompt compressed by about 50%. Middle panel highlights a regression where agents became serialized, then a fix by editing one sentence to restore parallelism. Right panel shows final shipped prompt with restored behavior and cumulative savings of about 1,300 fewer tokens per turn across steps.
图 5 直到回归测试暴露出代理串行化的问题、并通过一句话修复恢复了并行能力后,提示词压缩才变得安全可靠;由此带来的 token 节省会在每一轮模型调用中持续累积。

上线后的提示词每轮可节省约 1,300 个 task 工具提示 token,相当于每次会话的总提示 token 减少约 1.8%,按活跃时长折算的归一化成本降低约 2.9%,且在各项评估中均未检测到质量回退。

无需额外检索轮次即可交付完成的后台任务

Agent 经常在后台运行独立任务,例如长时间运行的 shell 命令与子 agent 调查并行执行。通知机制让 agent 无需消耗工具调用等待,即可继续推进直到后台工作就绪。 如果 agent 没有显式等待某个任务,harness 会在 shell 命令或子 agent 完成时唤醒模型并通知它。 此前,这类通知并不包含已完成的结果,agent 必须额外花费一轮去获取 Copilot 早已收到的输出。当多个任务几乎同时结束时,这种绕路操作可能反复发生。现在,Copilot 会将符合条件的完成通知批量处理,并在现有的工具结果格式中直接交付已完成的结果。agent 可以直接基于所需信息继续推进,无需额外一轮重新请求。对于仍在运行的工作,显式读取行为保持不变。
Before-and-after sequence diagram comparing orchestration behavior.

Before: model waits on separate shell and sub-agent completions, causing retrieval detours and four LLM calls to process two results.
After: a harness batches related completions and emits synthetic tool events so background work continues while waiting; both results are processed together in a single LLM call.
The visual emphasizes reduced latency and fewer model round trips.
图 6 此前,每次背景任务的完成都可能触发仅用于检索的模型调用轮次;现在,harness 将符合条件的完成通知批量处理,并以现有的工具结果格式直接交付结果。
在此次改动之前,每个已完成的任务都需要一次模型调用请求结果,再加一次处理结果,共两次调用。以上面示例中的 shell 命令和子 agent 为例,这就是四轮模型调用后才能继续工作。 现在,harness 将两个完成项批量处理并统一提供结果,一次模型调用即可同时处理两者。去除这些检索绕路,还能避免在多余的调用中反复携带完整的会话上下文。 通过直接交付已完成的结果——不做压缩、不摘要、不省略——harness 降低了平均 token 相关用量,以 AI Credits 衡量,降幅约为 2.3%。

测量上下文的变更

某项在某一 Copilot 工作流中节省 token 的改动,可能在另一个工作流中增加成本。

例如,受 Copilot 代码审查积极成果的启发,我们精简了一套文件工具指令。但在 Copilot CLI 的在线测试中,该方案反而增加了成本,因此未予发布。

相比之下,在使用生产模型的大规模 Copilot 代码审查任务独立评估中,移除行号前缀和选择性压缩输出均使每次审查的平均 prompt tokens 数降低了约 5%,且追踪的审查质量指标未出现实质性变化。

这些发现独立于此前将 Copilot 代码审查迁移至共享文件工具的举措(详见此处),后者结合审查指令调优,已将代码审查成本降低了约 20%。

每项变更都需在其运行的工作流中进行衡量。

构建高效 AI 编码代理的五大经验教训

  1. 优化最终完成的任务,而非工具调用本身。若代理需花费更多轮次来补救被精简的内容,输出虽短却未必更省钱。
  2. 优化编排逻辑,而非仅优化模型输出。消除那些由编排框架可确定性完成的模型轮次。
  3. 根据输出语义进行压缩。保留原始内容精度,优先采用无损变换,并监控代理触发恢复路径的频率。
  4. 提示词改写有时会产生意外后果。需验证预期行为是否得以保留。
  5. 证据具有工作负载的本地性。需在离线基准测试、在线实验以及产品上线的所有场景中重新评估这些变更。

上述变更并未让模型变得更聪明,它们只是消除了模型本无需执行的冗余工作。

本文所述的变更正在通过底层框架相同的 GitHub Copilot 各项体验陆续上线。

原始来源: GitHub Blog

评论 (0)