如何更好地使用GitHub Copilot:Prompts、技巧和用例

本文出于学习的需求, 原封不动的翻译了来自Github的一篇Blog, 所有的Credits都属于原文作者, 如果您有任何想法和建议, 请至原文发表评论, 如果本文作为指引有帮助到您, 也请感谢原文的作者 Rizel Scarlett 和 Michelle Mannering…

如何更好地使用GitHub Copilot:Prompts、技巧和用例

本文出于学习的需求, 原封不动的翻译了来自Github的一篇Blog, 所有的Credits都属于原文作者, 如果您有任何想法和建议, 请至原文发表评论, 如果本文作为指引有帮助到您, 也请感谢原文的作者 Rizel ScarlettMichelle Mannering , 原文地址:

How to use GitHub Copilot: Prompts, tips, and use cases - The GitHub Blog
In this prompt guide for GitHub Copilot, two GitHub developer advocates, Rizel and Michelle, will share examples and…

生成式AI编程工具正在改变开发人员日常Coding的方式。从写文档到生成单元测试,这些工具正在帮助我们大幅提升工作效率。然而,就像任何新兴技术一样,总会有一个学习曲线。因此,无论是初学者还是经验丰富的开发人员在使用AI辅助编程助手不能生成他们想要的输出时。可能会感到沮丧。 (说的是你吗? 😂 )

例如,当我们要求GitHub Copilot使用p5.js来绘制一个冰淇淋锥型🍦,这是一个用于设计创意的JavaScript库,我们总是收到无关的建议 — 或者有时根本没有建议。但是当我们了解了GitHub Copilot处理信息的方式后,我们意识到我们必须调整与它沟通的方式。

以下是GitHub Copilot生成无效解决方案的一个示例:

当我们调整了Prompt 后, Copilot 给出了更精确的结果:

在这个GitHub Copilot指南中,我们将涵盖:

  • 什么是Prompt,以及什么是Prompt Engineering(提示工程取决于您是在与开发人员交谈还是与机器学习研究人员交谈)。
  • 使用GitHub Copilot进行提示时的三个最佳实践和三个额外的提示。
  • 一个示例,您可以尝试在提示GitHub Copilot帮助您构建浏览器扩展时进行操作。

进步胜于完美/聊胜于无 Progress over perfection

即使我们在使用AI方面有经验,我们也认识到每个人在使用生成式AI技术时都会有试错阶段。我们也知道提供通用的Prompt-crafting技巧是一个挑战,因为模型各不相同,开发人员所处理的个体问题也是各异的。这并不是一个全面的指南。相反,我们在分享我们在Prompt-crafting方面的所学,以加速在这个新时代的软件开发中的集体学习。

什么是Prompt,什么是Prompt Engineering? 这取决于使用对象是谁。

在生成式AI 编程工具的背景下,”Prompt”可能有不同的含义,这取决于你是在询问正在构建和微调这些工具的机器学习(ML)研究人员,还是在询问将它们用于集成开发环境(IDE)的开发人员。

在本指南中,我们将从使用集成开发环境中的生成式AI编程工具的开发人员的角度定义这些术语。但为了让您有一个完整的画面,我们在下面的图表中也添加了机器学习研究人员的定义。

使用GitHub Copilot进行提示构建的三个最佳实践:

1 . 设置一个High-level的目标。🖼️

如果您有一个空白文件或空的代码库,这会非常有帮助。换句话说,如果GitHub Copilot对您要构建或完成的内容没有任何上下文,与AI结对编程设置阶段会非常有用。在您详细介绍细节之前,通过大致描述您希望它生成的代码来为GitHub Copilot铺平道路。

在提示GitHub Copilot时,将这个过程看作是与某人进行对话:我应该如何拆分问题,以便我们一起解决它?我应该如何与这个人一起进行结对编程?

例如,在构建Next.js中的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编辑器。我们可以在后续为组件添加样式:

Note: 这种详细程度可以帮助您创建更符合预期的输出,但结果仍可能是非确定的。例如,在注释中,我们提示GitHub Copilot创建默认文本,显示“在此键入Markdown”,但它实际上生成了“Markdown预览”作为默认文字。

2 . 让您的请求简单明确。旨在从GitHub Copilot获得简短的输出。🗨️

一旦您向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']

与GitHub Copilot进行提示构建的另外三个技巧

以下是三个额外的提示,以帮助引导您与GitHub Copilot的对话。

1 . 尝试不同的Prompt。

就像对话更多是一门艺术而不是科学一样,提示构建也是如此。因此,如果您在第一次尝试时没有得到您想要的结果,请按照上面的最佳实践重新构建您的提示。

例如,下面的提示很模糊。它没有为GitHub Copilot生成相关建议提供任何上下文或界限。

# Write some code for grades.py

我们对提示进行了迭代,使其更具体,但我们仍然没有得到我们正在寻找的确切结果。这是一个很好的提醒,即使听起来增加提示的具体性也比较困难。从一开始就很难知道您应该包括哪些有关目标的细节,以从GitHub Copilot生成最有用的建议。这就是为什么我们鼓励进行尝试。

下面版本的提示比上面的版本更具体,但它并没有明确定义输入和输出要求。

# Implement a function in grades.py to calculate the average grade

我们再次尝试了提示,通过设定界限和概述我们希望函数执行的操作。我们还重新表述了注释,使函数更加清晰(为GitHub Copilot提供明确的验证意图)。

这一次,我们得到了我们所期望的结果。

# Implement the function calculate_average_grade in grades.py that takes a list of grades as input and returns the average grade as a floating-point number

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生成了一条注释,上面写着“代码放在这里。”

def rndpwd(l): 
    # Code goes here

总结

生成式AI编程工具背后的大型语言模型(LLMs)被设计用于从其训练数据中找到并推断出模式,将这些模式应用于现有语言,然后生成遵循这些模式的代码。鉴于这些模型的规模之大,它们可能会生成甚至尚不存在的代码序列。就像您会审查同事的代码一样,您应该始终评估、分析和验证由AI生成的代码。