Copilot扩展跨文件编辑建议范围
GitHub Copilot编辑建议现可跨整个文件运作,减少频繁切换摩擦,显著改善编码流畅度。
GitHub Copilot编辑建议现可跨整个文件运作,减少频繁切换摩擦,显著改善编码流畅度。
2026 年 2 月 26 日,Vikram Duvvur、Gaurav Mittal、Benjamin Simmonds
去年 2 月,我们在 GitHub Copilot 中发布了下一编辑建议(next edit suggestions,NES)。NES 扩展了 ghost text 的能力:它不仅能在光标处插入代码,还会预测你接下来可能要修改的内容,并建议对附近代码进行编辑。这是一次意义重大的进步,但它只能在光标周围的一小块窗口内发挥作用。在真实的编辑工作流中,你下一步需要修改的位置往往在几个屏幕之外。
这正是我们着手通过远距离下一编辑建议解决的问题:扩展 NES,使其能够预测并建议文件中任意位置的编辑,而不再局限于当前光标附近。
想象一次典型的重构过程。你重命名了一个函数,文件中其他地方对该函数的所有调用也需要随之更新。或者,你修改了某个参数的类型,导致 200 行之后的验证逻辑不再正确。这些正是你期望 NES 提供帮助的时刻,但遗憾的是,下一处有意义的编辑位置远远超出了它的有效窗口。
这带来了一个棘手的建模问题。搜索空间从附近寥寥几行骤然扩展到文件中的每一行。而预测错误所造成的代价并不对等:一次正确的跳转能切实节省你的精力,但一次不必要的跳转会打断你的工作流,让你更难信任下一条建议。系统不仅必须学会应该移动到哪里,还必须学会什么时候不该移动。
我们没有修改现有的编辑生成模型,而是决定采用多模型方案。我们训练了一个专用的位置模型,它唯一的职责就是预测下一次编辑应该发生在哪里。选出有效位置后,再由原来的 NES 模型生成编辑建议。
这种职责分离带来了两个好处。首先,每个模型都可以专注于一项任务:一个模型学习空间意图,也就是应该跳转到哪里;另一个模型则负责在局部窗口内生成高质量的编辑。此外,我们还可以独立迭代位置预测能力,而不会干扰核心 NES 模型正在进行的改进。
在训练位置模型之前,我们需要一种方法来衡量它在真实编辑场景中是否确实有效。
我们设计了一套结构化的三步评估流程:
我们首先分析开发者在真实场景中如何将多次编辑串联起来,例如重命名、更改函数签名和更新文档,而不是把每次编辑都视为孤立事件。这些场景有一个共同点:编辑产生的影响会扩散到文件中多个互不相邻的位置。
基于这些工作流,我们构建了一套评估数据集,其中每个样例都包含下一次跳转目标行的 ground truth、最近的编辑历史以及光标上下文。
至关重要的是,我们同时衡量了跳转和不跳转的准确率。虽然许多样例要求模型预测一个新位置,但其中也有相当一部分要求光标留在当前行。一个过于频繁跳转的模型,造成的干扰可能不亚于一个错过重要位置切换的模型。试想一下,当你每次才输入到变量名的一半时,系统就弹出一条跳转建议。
通过让评估扎根于真实工作流,并同时衡量跳转与不跳转两类场景,我们确保离线指标反映的是开发者实际编辑代码的方式,而不是人为构造的场景。
评估体系准备就绪后,我们把注意力转向了训练数据。评估数据集规模较小,可以手工构建,但模型训练需要规模大得多的数据。我们从用于训练核心 NES 模型的同一套数据集入手,其中包含开发者如何在文件中移动和编辑的轨迹。
通过重放这些轨迹,我们把每一次光标移动都转换成一个训练样本。随后,我们应用了一系列过滤条件,例如确保跳转位置出现在 prompt 中,由此得到最终的训练数据集。
为了训练位置模型,我们采用了监督微调(Supervised Finetuning,SFT),并进行了有针对性的超参数搜索。效果最好的方案,是围绕现有 NES 模型的超参数进行结构化网格搜索。我们把搜索空间限制在已知能在相关场景中取得良好效果的取值范围内,从而高效探索不同组合,并找到性能出色的配置。
在最终确定这一方案之前,我们还尝试过贝叶斯优化(Bayesian Optimization),这是一种为优化计算成本高昂的黑盒函数而设计的技术。在我们的场景中,每次评估都需要从头训练一个模型,因此实验的计算成本非常高。尽管这种方法在理论上颇具吸引力,但与更聚焦的网格搜索相比,它并没有带来更好的结果。
最终,结构化网格搜索产出了表现最好的监督模型,也为后续迭代提供了稳定的基础。
如果用户从未注意到模型生成的建议,或者不信任这些建议,那么再好的模型也无济于事。在标准 NES 中,建议会出现在光标附近,并处于用户当前可见的区域内,因此很容易被自然发现。但对于远距离 NES,最相关的编辑可能并不在用户眼前。因此,UX 必须解决一个更棘手的问题:既要呈现远处的编辑,又不能打断用户的工作流。
这归结为需要平衡三个方面:保持建议紧凑、确保建议易于阅读,以及尽量减少它对代码的遮挡。
这不仅仅是一个可发现性问题,更是一个信任问题。当系统建议把光标移动到其他位置时,你需要迅速判断这次跳转是否相关、是否值得关注。UI 必须提供足够的上下文,让你能够评估这条建议,同时又不要求你彻底切换上下文。
我们没有直接在行内渲染大段 diff,也没有强迫用户转移注意力,而是设计了一个紧凑的 widget。它会出现在光标附近,并在条件允许时优先使用空白区域。这个 widget 会根据周围的编辑器布局自动调整,缩小或扩展自身,以自然适配行尾或代码块之间的空白空间。
由于完整编辑可能位于很远的位置,而且内容可能很大,widget 不会尝试渲染整条建议。相反,它会提供一个轻量级预览:从受影响的某一行中截取一小段内容,并使用 diff 风格的高亮进行展示。它提供的上下文刚好足够你判断建议是否相关,并决定要不要采取行动。
如果预览看起来有用,你可以选择跳转到建议的位置,在那里查看或应用完整编辑。如果没有用,你可以继续编辑,不受打扰。
在发布新能力之前,我们始终会先进行内部试用,远距离 NES 也不例外。早期反馈揭示出一个非常明显的问题:模型太急于跳转了。即使预测方向基本正确,频繁出现的建议仍然会让人分心。根本原因在于数据集不平衡:“不跳转”样例远少于跳转样例。模型学会了自信地跳转,却没有学会什么时候应该留在原地。
我们重新平衡了数据集,增加了正确操作应为停留在当前行的样本,例如只输入了一部分的标识符,因为在这种情况下进行跳转并不合理。重新训练后,跳转和不跳转的准确率都得到了提升,建议也明显变得更有针对性。
为了进行大规模验证,我们开展了 A/B 测试,将远距离 NES 与标准 NES 进行比较。结果令人振奋:通过 NES 编写的代码量增加了 23%,其他参与度指标也有所改善。不过,实验也暴露出一项权衡:与标准 NES 相比,距离较远的建议更容易被拒绝。考虑到这是一种新的交互模式,其中一部分拒绝符合预期,但这也表明模型仍需更加谨慎地判断何时应该建议跳转。
这并非单纯的建模问题,也不只是 UX 问题,而是两者共同作用的结果。改进远距离 NES,既需要收紧模型的跳转预测,也要确保界面能让用户轻松评估和接受相关建议。
验证结果指向了一个明确的结论:监督模型需要更加克制。
为了解决这个问题,我们引入了一个强化学习阶段,采用可验证奖励强化学习(Reinforcement Learning with Verified Rewards,RLVR)。我们不再仅仅依赖监督标签,而是添加了一个评分信号,根据模型预测的跳转位置与光标最终移动位置的接近程度进行评分。与实际编辑行为高度一致的预测会获得更高奖励,而不必要或时机不当的跳转则会受到惩罚。
这样一来,模型便可以直接针对真实编辑条件进行优化,无须增加新的人工标注或 UX 埋点。
最终,模型在主动性与克制之间取得了更好的平衡。更新后的模型不仅提升了离线指标,也把这些收益转化成了线上表现:通过 NES 编写的代码量有所增加,同时拒绝率有所降低。这些信号就位后,我们于次月开始发布改进后的版本。
展望未来,我们计划把这项工作扩展到跨文件建议,让模型能够在当前文件之外进行推理。我们还在探索一种统一模型,由它同时预测下一次编辑的位置与内容,这可能进一步提高建议的整体相关性。
远距离下一编辑建议现已在 VS Code 中面向 GitHub Copilot 订阅用户开放——只需确保你已在 VS Code 中启用下一编辑建议和扩展 NES 范围 github.copilot.nextEditSuggestions.extendedRange Open in VS Code Open in VS Code Insiders。下次进行重构时,不妨试一试——无论是重命名变量、更新函数签名,还是进行会在整个文件中产生连锁影响的修改。我们非常期待听到你的反馈!
特别感谢开发者社区持续不断地提供反馈,推动我们在 VS Code 和 GitHub Copilot 中打造尽可能出色的体验。同时,也衷心感谢 GitHub 和 Microsoft 的研究人员、工程师、产品经理与设计师:他们整理训练数据,构建训练 pipeline、评估套件和 serving stack;也感谢 VS Code 与 GitHub Copilot 团队保障模型顺利发布。