本文是一篇关于 GitHub Copilot 提示词的指南,重点是向大家展示如何与 AI 结对程序员沟通,获得预期的结果。
生成式 AI 编码工具正在改变开发人员处理日常编码任务的方式。从记录代码库到生成单元测试,这些工具都有助于加快工作流程。但是,对新兴技术的学习总不可避免会遇到各种各样的困难,比如 AI 编码助手输出的代码不符合要求。
例如,我们让 GitHub Copilot 使用 p5.js(一个基于 JavaScript 编程语言的创意编程库)绘制一个冰淇淋甜筒,却只得到无意义的建议,有时甚至没有建议。为什么呢?通过进一步了解 GitHub Copilot 处理信息的方式,就会发现我们的沟通方式需要调整。
在下面示例中, GitHub Copilot 生成了无意义的解决方案:
调整提示词后,就可以获得更准确的结果:
我们既是开发人员,也是 AI 爱好者。Rizel 曾使用 GitHub Copilot 构建了一个浏览器扩展,剪刀石头布游戏以及发送推文。Michelle 在 2016 年创办了一家 AI 公司。我们都是 GitHub 开发的拥护者,喜欢分享使用 GitHub Copilot 的心得。
本教程包括以下内容:
- 提示词是什么?提示词工程是什么?(区别在于你的沟通对象是开发人员还是机器学习研究者)
- 编写 GitHub Copilot 提示词的三个最佳实践以及三个技巧。
- 使用 GitHub Copilot 构建浏览器扩展的示例。
保持进步
虽然我们都使用过 AI,但整体仍处于生成式 AI 技术的试错阶段。另外,模型不同导致的问题也各不相同,因此很难制定通用的提示词创建方法。因此,本文并不是一篇通用指南,只是一篇提示词制作经验的分享和集体学习。
提示词是什么?提示词工程又是什么?
答案因沟通对象而异。
在生成式 AI 编码工具中,提示词有不同含义,具体取决于与你沟通的是正在构建和微调这些工具的机器学习(ML)研究人员,还是在 IDE (集成开发环境)中使用这些工具的开发人员。
本教程将以在 IDE 中使用生成式 AI 编码工具的开发人员的角度定义这些术语。另外,为方便读者了解全貌,我们也在图表中添加了 ML 研究人员定义。
提示词 | 提示词工程 | 上下文 | |
---|---|---|---|
开发人员 | 代码块、单行代码或开发人员编写的自然语言注释,目的是让 GitHub 生成特定的建议; | 在 IDE 中提供指令或注释,以生成特定的编码建议; | 开发人员提供的详细上下文信息,目的是让生成式 AI 编码工具按照要求输出内容; |
ML 研究人员 | IDE 代码和相关上下文(IDE 注释、打开文件中的代码等)的编译,由算法持续生成,并发送到生成式 AI 编码工具的模型中; | 创建算法,为大型语言模型生成提示词(IDE 代码和上下文的编译); | 算法作为代码的附加信息发送到大型语言模型(LLM)的细节(如打开文件中的数据以及在你在光标之前和之后编写的代码)。 |
编写 GitHub Copilot 提示词的三个最佳实践
1. 设定一个高层次目标。🖼
如果你有一个空白文件或空代码库,会非常有帮助。换句话说,如果 GitHub Copilot 不知道你想要构建什么,那么最好为 AI 结对程序员设定一个框架。先给 GitHub Copilot 一个大的框架说明,再补充具体细节,就可以让它生成你想要的代码。
给 GitHub Copilot 提示词时,要像与人对话一样思考——怎么先把大问题拆分为小问题,然后一起解决问题?如何与他/她结对编程?
例如,在 Next.jst 中创建 markdown 编辑器时,我们可以编写下列注释:
/*
Create a basic markdown editor in Next.js with the following features:
- Use react hooks
- Create state for markdown with default text "type markdown here"
- A text area where users can write markdown
- Show a live preview of the markdown text as I type
- Support for basic markdown syntax like headers, bold, italics
- Use React markdown npm package
- The markdown text and resulting HTML should be saved in the component's state and updated in real time
*/
这将提示 GitHub Copilot 生成下列代码,并在 30 秒内生成一个非常简单、无样式但功能强大的 markdown 编辑器。然后,我们再设计组件的样式:
注意:给出上述具体的细节有助于获得更理想的输出,但结果仍不确定。例如,在注释中,我们提示 GitHub Copilot 创建“在此键入 markdown”的默认文本,但它却生成了 “markdown 预览”的默认文本。
2. 给出简单具体的要求,以获取简洁的输出为目标。
向 AI 结对程序员传达主要目标时,要具体说明实现该目标的逻辑和所需的步骤。如果你能将目标拆分,GitHub Copilot 就可以更好地理解你的要求。(想象你正在编写一份食谱,需要将烹饪过程拆分成几个步骤,不是只写一段话描述你想要做的菜肴)。
让 GitHub Copilot 根据每个步骤生成代码,而不是一次性生成一堆代码。
下面是我们为 GitHub Copilot 提供的反转函数的逐步说明:
3. 给 GitHub Copilot 提供一两个例子。✍
从示例中学习对人类有效,对 AI 配对程序员也有效。假如我们想从下面的数据数组中提取名称,并将名称存储到一个新数组中:
const data = [
[
{ name: 'John', age: 25 },
{ name: 'Jane', age: 30 }
],
[
{ name: 'Bob', age: 40 }
]
];
如果没有给 GitHub Copilot 提供例子:
// Map through an array of arrays of objects to transform data
const data = [
[
{ name: 'John', age: 25 },
{ name: 'Jane', age: 30 }
],
[
{ name: 'Bob', age: 40 }
]
];
const mappedData = data.map(x => [x.name](http://x.name/));
console.log(mappedData);
// Results: [undefined, undefined]
它生成的是 map 的错误用法:
const mappedData = data.map(x => [x.name](http://x.name/));
console.log(mappedData);
// Results: [undefined, undefined]
如果我们提供了例子:
// Map through an array of arrays of objects
// Example: Extract names from the data array
// Desired outcome: ['John', 'Jane', 'Bob']
const data = [
[{ name: 'John', age: 25 }, { name: 'Jane', age: 30 }],
[{ name: 'Bob', age: 40 }]
];
const mappedData = data.flatMap(sublist => sublist.map(person => person.name));
console.log(mappedData);
我们就获得了想要的结果:
const mappedData = data.flatMap(sublist => sublist.map(person => person.name));
console.log(mappedData);
// Results: ['John', 'Jane', 'Bob']
了解更多 AI 训练的常见方法,例如零样本学习、单样本学习和少样本学习。
编写 GitHub Copilot 提示词的三个技巧
下列是与 GitHub Copilot 沟通的三个技巧。
1. 多试验提示词
对话是一门艺术而非科学,提示词也是如此。因此,如果你在第一次尝试时没有得到想要的结果,请按照上述最佳实践,重新编写提示词。
例如,下列提示词比较模糊,没有为 GitHub Copilot 提供上下文或限制。
# 为 grades.py 写一些代码
我们反复修改提示词,但仍然没有得到想要的结果,由此可见想把提示词修改得更具体并没有那么容易。因为往往在一开始,我们并不知道结果应该包含哪些细节。这也是我们鼓励大家多尝试的原因。
下面的提示词比上面的更具体,但没有明确定义输入和输出的要求。
# 在 grades.py 中执行一个函数来计算平均成绩
我们设置限制并概述希望函数做的任务,再次试验提示词。同时,我们还改写了注释,让函数更加清晰(让 GitHub Copilot 有明确的验证目标)。
这一次终于得到了我们想要的结果。
# 在 grades.py 中执行函数 calculate_average_grade,把成绩列表作为输入, 并以浮点数的形式返回平均成绩。
2. 打开几个相关页面
打开相关页面有助于 GitHub Copilot 将代码上下文关联起来。我们不确定应该打开的页面的数量,但根据我们的经验,打开一到两个页面是有帮助的。
GitHub Copilot 使用了一种相邻页面的技术,允许 AI 配对程序员通过处理 IDE 中打开的所有文件(不仅包括你正在处理的单个文件)来关联代码的上下文。但是,我们并不能保证 GItHub Copilot 会将所有打开的文件都视为你的代码的上下文。
3. 采用好的编码实践
好的编码实践是指提供描述性的变量名和函数、并遵循一致的编码风格和模式的编码实践。我们发现,与 GitHub Copilot 的合作会帮助我们遵循之前学的良好编码规范。
例如,这里我们使用了一个描述性的函数名,并遵循了利用蛇形案例的代码库模式。
def authenticate_user(username, password):
因此,GitHub Copilot 生成了相关的编码建议:
def authenticate_user(username, password):
# Code for authenticating the user
if is_valid_user(username, password):
generate_session_token(username)
return True
else:
return False
可以与下面的示例相比——下面的示例中,我们使用了不一致的编码风格,而且对函数进行了错误的命名:
def rndpwd(l):
GitHub Copilot 没有生成建议代码,而是生成了一个建议:“Code goes here”。
def rndpwd(l):
# Code goes here
认真审查 AI 生成的代码
生成式 AI 编码工具背后的 LLM 旨在从训练数据中发现和推断模式,将这些模式应用于现有语言,然后生成遵循这些模式的代码。因为这些模型的规模非常庞大,它们生成的代码序列甚至可能还不存在。所以,你要像审查同事的代码一样,始终认真评估、分析和验证 AI 生成的代码。
实践案例 👩💻
首先,要在 IDE 中安装并打开 GitHub Copilot。我们还可以使用 GitHub Copilot 聊天工具的早期预览版。每次当我们对代码有疑问时,就会使用它。如果你还没有 GitHub Copilot 聊天功能,可以注册并加入候补名单。在此之前,你可以将 GitHub Copilot 与 ChatGPT 配对使用。
更多生成式 AI 提示词编写指南
原文作者:Rizel Scarlett,Michelle Mannering
原文链接:https://github.blog/2023-06-20-how-to-write-better-prompts-for-github-copilot/
Like it!!!