
AI代码助手,比如GitHub Copilot,是一种能实时给程序员提供代码建议的智能工具。
有个常见的问题是它如何处理那些庞大的代码库——是会一次性扫描整个项目吗?其实并不是,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如何保护你的隐私
说到隐私,Copilot可真是个贴心的小助手。它通过不传输你整个代码库,极大地减少了你专有代码的泄露风险。只有那些完成任务所需的小片段会被发送到AI服务上。这种设计大大缓解了许多安全隐患,因为你的知识产权不会被大规模上传。GitHub也明确表示,Copilot不会保留或利用你的提示来训练其他人的模型,所以你的代码不会被加入公共数据集中——它只是暂时用来计算你的结果而已。
Copilot的专注方法是个优点
总的来说,Copilot的这种聚焦方式其实是它的一项特性,而不是缺点。它在技术和实际的限制范围内,提供相关的帮助。如果你想要一个能分析整个代码库的工具,比如查找安全漏洞或者进行全面的代码审查,那就得寻找其他专门的工具。Copilot的强项是通过分析你正在编写的代码,帮助你更快捷地完成代码的编写。
大型项目的局限性及实用技巧
要知道,Copilot的建议质量高度依赖于你提供的上下文信息。如果关键信息缺失,Copilot可不会凭空猜测。这里有一些在大型项目中使用Copilot的小技巧和注意事项:
- 保持相关文件打开:如之前提到的,确保关键文件是打开的。如果你在处理特定库或组件,最好打开它的实现文件或相关文档(即便只是分屏查看),这样Copilot能更好地获取细节。这一步骤可以显著提升它对跨文件引用的建议精确度。
- 使用清晰的名称和注释:Copilot经过大量公开代码的学习,可以识别模式。清晰的函数名和变量名,以及简短明了的注释,可以大大引导它。例如,给变量起名为 userEmail,而不是 ue,并附上类似“// 验证电子邮件格式”的注释,这样Copilot更容易理解你的意图,并提取相关的验证代码。
- 专注于一件事:编辑文件时,尽量不要打开太多不相关的文件,以为这能让Copilot“学习”所有内容。上下文过多且无关可能会导致效果适得其反,因为Copilot不知道该优先处理哪些部分,结果可能会聚焦在错误的代码上。最好把打开的文件限制在与你当前任务密切相关的范围内。
- 记住它的记忆是短期的:一旦你关闭了文件或继续其他工作,Copilot就不会记得你之前做的事情。如果你在当天晚些时候(或第二天)回到某段代码,可能需要重新加载相同的上下文,才能让Copilot发挥同样的效果。把它当作是始终在处理你工作区当前快照的工具。
- 设计上的安全性:别担心Copilot会泄露你的敏感代码。因为它只获取你提供的内容,而看不到其他部分,所以它输出来自未见过代码的可能性几乎为零。当然,唯一的例外是如果你的代码与训练数据中的内容非常相似,但GitHub已设立过滤器来防止重复已知代码片段。如果你处理的是极其敏感的代码,无法发送出去,完全可以在会话中禁用Copilot——但对于大多数情况,它通过发送最少的数据实现了良好的平衡。
- 没有完美的解决方案:如果你的代码仓库文档不全或代码构架复杂,Copilot不会奇迹般地理解高级设计。它可能在样板和语法上提供帮助,但架构上的改进或深层错误仍需你和团队来解决。把Copilot当作处理小事的助手,这样你能更专注于整体。
展望未来
GitHub团队也提到,他们正在探索如何利用整个代码库生成定制化建议。这并不是一次性传入所有内容(我们都知道这不可能),而是利用先进的算法,比如向量数据库和嵌入技术,按需从整个仓库中检索相关代码。
简单说,他们在研究Copilot如何在你的项目中搜索有用的信息(即使文件没有打开),并提取需要的代码片段。例如,如果你有一个包含帮助函数的utils文件,Copilot可能会自动找到它,即便你忘了它的存在。这些技术已经在早期阶段有所应用(比如,Copilot X的聊天功能可能在你向云端提问时自动从仓库中获取文件)。这样的增强将进一步减少手动打开文件的需求,同时避免让AI被不相关的数据淹没。这个领域正处于活跃发展中,展示了一个光明的未来。
总结
GitHub Copilot通过专注于与当前任务相关的代码,来处理大型项目,而不是一次性扫描整个仓库。它利用打开的文件和你光标周围的代码,构建一个聚焦的提示,发送给AI,并返回针对该上下文的建议。这种方法使Copilot在庞大的代码库中使用时既迅速又高效,因为它充分考虑了AI的限制和开发者的即时需求。
原文链接:Github Copilot的上下文工程 – 汇智网
