针对 Copilot 的实战 prompt 技巧,帮助程序员更高效地使用 AI 编程助手提升开发速度。
开始使用 GitHub Copilot 和其他生成式 AI 工具时,我感到很沮丧,因为得到的结果总是不符合预期。为什么别人用这些工具时感觉如此得心应手,它们却不肯按我的要求工作?例如,我会让 GitHub Copilot 帮我解决一道 LeetCode 题。GitHub Copilot 图标开始旋转,表示它正在思考,随后却给出一个牛头不对马嘴的建议,甚至什么建议都没有。我对此很恼火,但后来才发现——原来是我的使用方法不对!经过更多尝试,我开始通过注释和代码提供上下文、示例和清晰的指令,从而改善了与 GitHub Copilot 的沟通方式。后来我才知道,这种实践叫作 prompt engineering。在这篇文章中,我会分享一些重要技巧,帮助你充分发挥 GitHub Copilot 的作用。
首先,我们从基础知识讲起,照顾一下还不熟悉 GitHub Copilot 或 prompt engineering 的读者。
GitHub Copilot 是由 GitHub 开发的 AI 结对程序员。GitHub Copilot 由 OpenAI Codex 提供支持,后者是 OpenAI 创建的一种生成式预训练语言模型。GitHub Copilot 会根据注释和代码提供的上下文,给出与当前场景相关的代码建议。要使用它,你可以在以下集成开发环境(IDE)中安装 GitHub Copilot 扩展:
JetBrains IDE(IntelliJ、PyCharm、WebStorm 等)
在 GitHub,我们会使用“AI 结对程序员”“AI 助手”和“Copilot”这些称呼,因为这款工具离不开你——开发者!事实上,AI 系统只能执行开发者通过程序要求它执行的任务。它们没有自由意志,也无法独立做出决策。在这个场景中,GitHub Copilot 会利用你编写的代码和注释所提供的上下文,即时给出代码建议!借助 GitHub Copilot,你可以把注释转换成代码、自动补全重复代码,还可以查看其他备选建议。
在底层,GitHub Copilot 会从注释和代码中提取上下文,并即时建议单行代码乃至完整函数。GitHub Copilot 由 OpenAI Codex 驱动,这是一种能够把自然语言转换成代码的机器学习模型。
Prompt engineering 是一种通过向 AI 模型提供具体指令,让它生成你想要的结果的实践。prompt 可以是一段文本或一行代码,用来触发 AI 模型作出响应。你可以把这个概念类比为拿到一道作文题。你可能会收到一条 prompt,要求写一篇关于自己克服某项挑战的文章;也可能要求你围绕《了不起的盖茨比》这样的经典著作进行写作。随后,你会根据自己学过的知识回应这条 prompt。大型语言模型(LLM)的行为与此类似。
再用一个例子来说明 prompt engineering:我学习编程时参加过一项活动,需要指导一个机器人制作三明治。这个活动既有趣又有点滑稽,它让我明白了以下几点:
计算机只能做你明确要求它做的事情
你需要给出非常具体的指令
每次只给出一个步骤,效果会更好
算法其实就是一系列指令
例如,如果我要让这个“机器人”制作三明治,就需要这样告诉它:
打开面包袋
从面包袋中取出最前面的两片面包
把两片面包并排放在料理台上
用黄油刀把花生酱涂到其中一片面包上
诸如此类,诸如此类,诸如此类
如果没有这些清晰的指令,机器人可能会做出一些滑稽的事情,比如把花生酱涂到两片面包上,也可能完全无动于衷。机器人不知道三明治是什么,也不知道该怎样制作三明治。它只知道如何遵循指令。
同样,GitHub Copilot 也需要清晰、逐步的指令,才能生成对你最有帮助的代码。
下面我们来讨论使用 GitHub Copilot 进行 prompt engineering 的最佳实践,学习如何向它给出清晰的指令并得到期望的结果。
对我来说,效果最好的技巧是在文件顶部通过注释提供高层上下文,然后再通过注释和代码给出更具体的指令。
例如,假设我要构建一个待办事项应用。我会先在文件顶部写一条注释:“使用 Next.js 构建一个待办事项应用,允许用户添加、编辑和删除待办事项。”接下来,我会逐行写注释,要求创建:
待办事项列表组件,然后让 GitHub Copilot 在注释下方生成该组件
按钮组件,然后让 GitHub Copilot 在注释下方生成该组件
输入框组件,然后让 GitHub Copilot 在注释下方生成该组件
添加函数,然后让 GitHub Copilot 在注释下方生成该函数
编辑函数,然后让 GitHub Copilot 在注释下方生成该函数
删除函数,然后让 GitHub Copilot 在注释下方生成该函数
诸如此类,诸如此类,诸如此类……
下面是我使用这种技巧,通过 p5.js 绘制一栋房子的示例:
在下面的 GIF 中,我先在文件顶部写下一条注释,从高层描述我希望 p5.js 绘制的内容。我要画一栋白色房子,带有棕色屋顶、红色房门和红色烟囱。随后,我为房子的每个元素分别编写一条注释,再让 GitHub Copilot 为每个元素生成代码。
提供具体细节后,GitHub Copilot 才能生成更准确的代码建议。例如,如果你希望 GitHub Copilot 从某个 API 获取数据,就需要告诉它你想获取哪种数据、应该怎样处理这些数据,以及你希望请求哪个 API endpoint。
下面是一条不够具体的注释(prompt)。在这种情况下,GitHub Copilot 不太可能生成有用的建议:
// Get data from API
function getData() {
//code goes here
}
在上面的示例中,除了函数名和开闭括号之外,GitHub Copilot 没有为我生成任何内容。
下面是一条具体的注释(prompt)。在这种情况下,GitHub Copilot 更有可能生成有用的建议:
// Pass in user ids and retrieve user data from jsonplaceholder.typicode.com API, then return it as a JSON object
async function getUserData(userId) {
const response = await fetch(`https://jsonplaceholder.typicode.com/users/${userId}`);
const data = await response.json();
return data;
}
除了告诉 GitHub Copilot 你希望它做什么,还可以通过示例向它展示应该怎样做,并体现你偏好的编码风格。虽然 GitHub Copilot 使用的 AI 模型已经在大量数据上完成训练,但为 GitHub Copilot 提供示例,仍然有助于它理解特定代码片段的上下文和约束条件。通过示例向 AI 模型展示你希望它完成的任务,是机器学习中的常见实践。
下面是工程师训练 AI 模型时采用的几种方法:
我让 ChatGPT 像给一个五岁孩子讲解那样,向我说明这些方法之间的区别。它给出了下面的回答:
这就像你看到一个以前从未见过的新玩具,但因为它和你见过的其他玩具很像,所以你知道它是什么。例如,如果你见过许多不同种类的毛绒动物,那么即使从未见过眼前这个具体的玩具,你也可能认出它。同样,计算机可以利用自己对相似事物的了解,对新事物作出有依据的推测,从而学会识别新事物。
这就像你第一次看到一个新玩具,妈妈或爸爸告诉你它叫什么、有什么用途。只听过一次之后,你就记住了它,并能在下次见到时认出它。计算机也能以同样的方式学习识别新事物:只需向它展示少量示例,它就能从中学习。
Few-shot learning 就像只看少量示例,便学会做一件新事情。例如,假设你想学习怎样画一只猫,但以前只见过几张猫的图片。借助 few-shot learning,即使你没有见过很多猫,也仍然可以学会画猫。它就像一种魔法能力,即使没有大量示例可供学习,也能帮助你快速掌握新事物!
下面展示了我向 GitHub Copilot 提供示例与不提供示例时,分别发生了什么:
# Create a list of the first 10 prime numbers
primes = []
for num in range(2, 30):
if all(num % i != 0 for i in range(2, num)):
primes.append(num)
print(primes)
在上面的代码片段中,GitHub Copilot 会准确返回前 10 个质数,但这种做法效率不高,因为它会遍历 2 到 30 之间的全部 29 个数字。通过提供一个具体示例,说明我们希望 GitHub Copilot 做什么,可以得到更高效的结果。
# Create a list of the first 10 prime numbers
# Example: [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
primes = []
for num in range(2, 30):
if all(num % i != 0 for i in range(2, num)):
primes.append(num)
if len(primes) == 10:
break
print(primes)
在上面的代码片段中,GitHub Copilot 会返回前 10 个质数,并在找到全部 10 个之后停止运行。我的目标是快速获得准确的结果。在我稍加引导、为它指明正确方向之后,GitHub Copilot 成功实现了这一目标。
如果最初的 prompt 没有得到期望的响应,就删除生成的代码建议,在注释中补充更多细节和示例,然后再试一次!这对你和 GitHub Copilot 来说都是一个学习过程。使用次数越多,你就越擅长与 GitHub Copilot 沟通。
目前,GitHub Copilot 还无法获取整个代码库的上下文。不过,它可以读取你当前所在的文件,以及 IDE 中已经打开的其他文件。我发现,把希望 GitHub Copilot 参考的相关文件标签页保持为打开状态很有帮助。例如,如果我正在编写一个使用其他文件中变量的函数,就会在 IDE 中保持那个文件处于打开状态。这有助于 GitHub Copilot 提供更准确的建议。
这条建议来自 BitRise 的 Developer Advocate Leilah Simone。我还没有在 GitHub Copilot 中尝试过这种方法,但这是一条很有帮助的建议。它有助于控制用户将会收到哪种类型的响应。在 Leilah 的案例中,她会要求 ChatGPT 扮演一名资深 iOS 工程师。她说:“这帮助她减少了语法和 linting 问题。”
正如我们从上面的许多示例中看到的那样,GitHub Copilot 会遵循代码中的模式。AI 爱好者兼开发者内容创作者 YK(也就是 CS Dojo)分享了他如何利用这一点:
声明变量或函数时,应使用能够具体体现其用途的名称。这有助于 GitHub Copilot 理解变量的上下文,并生成更相关的建议。例如,不要使用像 value 这样宽泛的变量名,而应该使用 input_string 或 output_file 这样更具体的名称。
GitHub Copilot 也会沿用你在代码中采用的命名规范。例如,如果变量采用 camelCase,GitHub Copilot 就会建议 camelCase 形式的变量;如果变量采用 snake_case,它就会建议 snake_case 形式的变量。
虽然 GitHub Copilot 可以成为生成代码建议的强大工具,但请务必记住,它无法替代你自己的编程技能和专业经验。AI 模型的表现取决于它接受训练时所使用的数据。因此,应该把这些工具当作辅助,而不能完全依赖它们。我建议每一位 GitHub Copilot 用户都做到以下几点:
运行单元测试、集成测试,以及其他任何程序化的代码测试
手动测试代码,确保其行为符合预期
遵循良好的编码实践,因为 GitHub Copilot 会把你的编码风格和模式作为生成建议时的参考
目前,GitHub Copilot 是一款可以在大多数主流 IDE 中使用的扩展。此外还有 GitHub Copilot Labs,这是一款独立的实验性扩展,拥有 GitHub Copilot 使用权限的用户可以使用它。Copilot Labs 可以帮助你翻译、调试、测试、记录和重构代码。另外,我们最近还推出了 Copilot X,这是一套能够在 IDE 之外提升开发者生产力的功能。Copilot X 包括:
Copilot for Docs——让开发者不必再费力翻阅海量文档。
Copilot for Pull Requests——帮助你编写更好的 PR 描述,并帮助团队更快地审查和合并 PR。
Copilot Chat——在编辑器中提供类似 ChatGPT 的体验,让你可以与 GitHub Copilot 聊天。
Copilot for CLI——帮助你回忆 shell 命令和 flags,从而更快地在终端中运行命令。
Copilot Voice——通过语音编写和编辑代码、浏览代码库,以及控制 Visual Studio Code。
Copilot X 的功能和产品目前仍处于技术预览阶段。如果你希望使用上述某项功能,可以在 GitHub Copilot X 预览页面加入候补名单。
学习如何以最佳方式使用 GitHub Copilot,最有效的方法就是开始使用它。你可以申请 GitHub Copilot 的使用权限。
如果你是企业负责人,并希望让整个团队都能使用 GitHub Copilot,可以申请 GitHub Copilot for Business。
感谢你阅读这篇文章。我很期待听到你的想法!关于人工智能、GitHub Copilot 和 prompt engineering,我仍在不断学习。如果你是 GitHub Copilot 的爱好者,并且已经学会如何用它改善自己的开发工作流,欢迎在下方评论区分享你的技巧!
如果你喜欢这类内容,欢迎在 DEV.to 上关注 GitHub 和我!此外,也可以查看以下资源,进一步了解 prompt engineering:
如何让 Codex 生成你想要的代码
OpenAI 的 Prompt Design
Prompt Engineering 101:Codex 入门
Elvis Saravia 编写的 Prompt Engineering Guide
如需采取进一步措施,你可以考虑屏蔽此人和/或举报滥用行为。