Github Copilot的上下文工程

在本文中,我们将解释Copilot(以及类似的AI代码代理)如何处理大型代码库,并使用Copilot的例子来说明它在实际中的工作方式。

Github Copilot的上下文工程

AI代码助手,如GitHub Copilot,是一个AI配对程序员,它在你输入时提供代码建议。

一个常见问题是它是如何处理大型仓库或项目的——它会扫描整个代码库来提供建议吗?答案是:Copilot专注于你当前的上下文,而不是一次扫描整个仓库。这种设计使建议保持相关性、高效性和隐私意识。

在本文中,我们将解释Copilot(以及类似的AI代码代理)如何处理大型代码库,并使用Copilot的例子来说明它在实际中的工作方式。

1、Copilot的上下文驱动方法

Copilot不会将你的整个代码库上传到云端;它使用代码编辑器中的上下文来生成建议

在AI术语中,Copilot发送给其AI模型的代码片段和注释称为提示(prompt)。这个提示是从你正在积极工作的代码中构建的。由于底层AI模型有一个有限的文本窗口(快速模型大约可以处理6000个字符),Copilot必须对其包含的内容进行选择。它不能简单地将所有项目文件喂给AI——这既有技术限制,也没有必要包括你代码中不相关的部分。

Copilot的行为就像一个查看你打开的文件的开发者,而不是扫描你整个项目的全知扫描仪。这种专注的方法意味着,如果你正在编辑一个文件中的函数,Copilot会查看该函数(以及可能的一些相关部分),而不是浪费时间在你未工作的代码库远端部分。

Copilot使用什么作为上下文?

通常,它从以下内容中获取:

  • 你当前正在编辑的文件中的代码,特别是你光标周围的代码(你所在的函数或代码块)。
  • 你在编辑器中打开的其他文件(更多内容见下文),这些文件可能包含相关代码。
  • 你在代码中编写的任何注释或指令(例如,如果你编写// TODO: 对列表进行排序,Copilot会“看到”这一点并尝试帮助)。

所有这些内容都会被组合在一起,并在Copilot即将提出建议时作为提示发送给AI模型。任何不在此提示中的内容在那一刻对Copilot来说都是未知的。这就是为什么有时你会得到一个通用的建议,如果特定细节存在于你没有打开的文件中,或者在你当前光标位置太远的代码中。

2、利用打开的文件丰富上下文

Copilot的一个优势是利用工作区中的打开文件来收集更多上下文。如果你有多个相关文件打开,Copilot可以使用所有这些文件来为其建议提供信息——GitHub团队称之为“相邻标签页”。

例如,想象一下,你同时打开了两个文件——一个定义了一个类,另一个是该类的单元测试。通过查看这两个文件,Copilot有了更多的上下文……从而产生更高质量的建议。

例如:你同时打开了 Customer.java(定义客户类)和 CustomerTest.java(测试该类)的文件。如果你正在编辑 Customer.java 并编写了一个新方法,Copilot可以快速查看 CustomerTest.java,可能会注意到 Customer 实例是如何使用的,或者测试期望的行为是什么。因此,它可能会建议一个与测试期望一致的方法实现。如果没有打开测试文件,Copilot只会知道类本身,可能会错过这一额外的洞察。

另一方面,Copilot无法看到你没有打开的文件。它不需要访问你的仓库,也就是说,它不会自动读取你项目文件夹中的每一个文件。它专注于编辑器的内容。如果一个文件关闭了且从未在你正在处理的内容中引用过,Copilot就不会知道它。这意味着如果另一个文件中有重要信息(比如配置常量或实用函数),你应该打开这些文件或将相关代码复制到视图中,以给Copilot一个线索。否则,Copilot可能会基于其训练提供更一般的建议,而不是针对你项目特定代码的建议。

2.1 为什么采用这种方法?

通过坚持打开的文件,Copilot既保持了相关性又保持了速度。大型项目通常包含许多彼此无关的模块。Copilot将其范围缩小到你当前正在进行的工作,确保它不会因不相关的代码而混淆。它还避免了为分析发送大量数据到网络上。在测试中,当Copilot开始使用多个打开的文件作为上下文时,用户看到建议质量有所提高(用户接受的Copilot建议增加了约5%)。这是仅仅在正确的时间提供一点正确的代码所带来的实际收益。

2.2 最佳实践

在大型代码库中工作时,尽量保持与当前任务相关的关键文件打开。如果你正在编辑与第二个模块交互的代码,请同时打开这两个文件。如果你认为某个文件(比如配置文件或辅助库)包含有用的信息,请打开它。你甚至不需要从其中复制任何内容;只需让它打开就足以让Copilot将其部分内容包含在提示中。这样,你实际上是在引导Copilot查看你关心的代码库部分。

3、为什么不扫描整个仓库?

听起来像是一种限制,即Copilot不摄入你的整个项目。但这种设计有其充分的理由:

  • 技术限制:如前所述,AI模型有输入大小的限制。能够为GitHub Copilot提供动力的快速Transformer每次只能处理大约6,000个字符……字符数量的限制意味着并非开发人员的所有代码都可以用作上下文。即使我们没有其他担忧,AI目前也无法一次性处理500 KB或5 MB的代码库。未来具有更大窗口的模型将扩展这一点(事实上,研究正在进行以增加上下文大小),但总会存在实际限制。
  • 相关性和信号与噪声:即使我们可以将所有内容输入AI,我们真的想要这样做吗?你的仓库中有很多内容可能与你当时正在处理的具体功能或问题无关。通过将提示限定于相关部分,Copilot避免了混淆和噪音。它“告诉模型哪些信息与你的代码相关”,从而产生更好的建议。较小且聚焦的提示通常比庞大的、无焦点的提示更有效。*
  • 性能:为每个单个代码补全扫描或上传一个大型仓库(数百个文件)会很慢并消耗大量带宽。Copilot的实时感依赖于保持数据传输的小规模。当Copilot最初发布时,它只使用当前文件,仍然提供了有用的补全。通过智能地增强上下文(开放标签页等),它在没有显著增加发送数据的情况下得到了改进。*
  • 隐私:通过不发送你的整个代码库,Copilot最小化了你专有代码的暴露。只有完成任务所需的片段才会发送到AI服务。这种设计缓解了许多安全顾虑,因为没有对你知识产权的大规模上传。(GitHub也表示,Copilot不会保留或使用你的提示来训练他人的Copilot模型——你的代码不会被添加到公共数据集中——它只是临时用于计算你的结果)*

总之,Copilot的专注方法是一种特性,而不是缺陷。它在不超出技术和实际边界的情况下提供相关协助。如果你需要一个分析整个代码库的工具(例如查找安全漏洞或进行全面代码审查),有其他专门的工具。Copilot的领域是通过查看你正在编写的代码,帮助你更快地编写代码。

4、大型项目的局限性及技巧

Copilot的建议仅与你提供的上下文一样好。如果某些重要内容不在该上下文中,Copilot可能无法神奇地猜测它。以下是使用Copilot在大型项目中时的一些技巧和注意事项:

  • 打开相关文件:如前所述,保持关键文件打开。如果你正在处理项目中的特定库或组件,请考虑打开其实现文件或文档(即使只是在分屏视图中),以便Copilot可以访问这些细节。这个小步骤可以显著提高其对于跨文件引用的建议准确性。
  • 使用有意义的名称和注释:Copilot经过大量公开代码的训练,它能识别模式。清晰的函数和变量名,以及简短的注释,可以引导它。例如,将变量命名为 userEmail 而不是 ue,并写一个注释如 // 验证电子邮件格式 将有助于Copilot推断你的意图并提取相关的验证代码模式。
  • 一次只做一件事:如果你正在编辑一个文件,尽量不要同时打开几十个不相关的文件,以为这样可以让Copilot“学习”一切。如果上下文太多且不相关,这可能会适得其反,因为目前Copilot可能不知道优先处理哪些部分,最终可能集中在错误的代码片段上。将你打开的文件限制在与当前任务或功能相关的范围内。
  • 了解它的记忆是短期的:一旦你关闭了这些文件或继续前进,Copilot不会记得你早上做的事情。如果你在当天晚些时候(或第二天)回到一段代码,你可能需要重新加载相同的上下文,以便Copilot同样有效。把它看作始终处理你工作区的当前快照。
  • 设计上的安全性:不必担心Copilot可能会泄露你的敏感代码。因为它只看到你提供给它的内容,而看不到其余部分,所以它输出来自它从未见过的代码部分的可能性基本上为零。(唯一的例外可能是如果你的代码非常类似于其训练数据中的内容,但GitHub已经设置了过滤器以防止原样重复已知的代码片段。)如果你曾经处理过极其敏感的代码,无法发送几行代码出去,你可以选择在该会话中禁用Copilot——但对于大多数情况,Copilot通过发送最少的必要数据实现了良好的平衡。
  • 没有万能解决方案:如果你的仓库文档不全或代码非常复杂,Copilot不会神奇地理解高层次的设计。它可能在样板和语法上有帮助,但架构改进或深层错误仍需你和你的团队解决。将Copilot作为处理小事的助手,这样你可以专注于大局。

5、更多展望

GitHub团队已经暗示并提到这里,他们正在尝试使用你的整个代码库来生成定制化的建议。这并不意味着一次性喂入所有内容(我们知道这是不可行的),而是使用先进的算法,如向量数据库嵌入,按需从整个仓库中检索相关代码。

简单来说,他们正在探索Copilot如何在你的项目中搜索有用的信息(即使文件未打开),并提取它需要的代码片段。例如,如果你有一个包含帮助函数的 utils 文件,Copilot可能会自动找到它并将其纳入其中,即使你忘记了它的存在。其中一些技术已经在早期使用(例如,Copilot X的聊天可能在你向云中提问时从仓库中获取文件)。这些增强将进一步减少手动打开文件的需求,同时不会让AI被无关数据淹没。这是一个活跃的发展领域,但它展示了未来。

6、结束语

GitHub Copilot通过专注于与你当前任务相关的代码,而不是一次性扫描整个仓库来处理大型项目。它使用打开的文件和你光标周围的代码来构建一个聚焦的提示,将其发送给AI,并返回针对该上下文的建议。这种方法使Copilot在巨大的代码库上使用时既快速又有效,因为它尊重AI的限制和开发者的即时需求。


原文链接:How AI Coding Assistants Handles Large Codebases

汇智网翻译整理,转载请标明出处