GitHub Copilot | Part 2 - Advanced Prompt Engineering for Developer Happiness
Last week, I wrote a short post about my personal experience in using GitHub Copilot, including some tips for getting started.
This post is about having fun with GitHub Copilot by trying out long and complex prompts. After all, there is a clear link between developer productivity and developer happiness.
The prompts in this post may not be very useful for everyday work. Nevertheless, knowing how to engineer complex prompts will help in using GitHub Copilot more effectively. The goal is to gain the expertise to translate thoughts into working code as fast as possible (and have fun in the process!)
What is Prompt Engineering?
Prompt engineering is the process of structuring text that can be interpreted and understood by a generative AI model. A prompt is natural language text describing the task that an AI should perform (source: Wikipedia.)
In layman’s terms, a prompt is the message we send to the GenAI model and prompt engineering is the process of creating a message (a “prompt”) so that GenAI gives us the desired output.
Let’s begin.
Advanced Prompt Engineering with GitHub Copilot
Generate Java Classes and Mermaid Diagram
Azure OpenAI shares a very good article about advanced prompt engineering. Inspired by this article, I wrote this prompt.
Example of an Advanced Prompt for GitHub Copilot Chat: Generate Java Classes and Mermaid Diagram (source here)
Think about this for a moment… The contents of the above multiline prompt are similar to the thoughts that are in our heads before writing code. Prompt engineering is simply articulating these thoughts into a “prompt” so that GenAI can convert the pseudo code in our heads into a target programming language code!
@GitHub Copilot:
Based on the requirements, we need to create two classes: Order and LineItem.
The Order class will have the following fields:
A list of LineItem objects A double for the total amount of the order A string for the status of the order The LineItem class will have the following fields:
An integer for the item ID A double for the item price An integer for the item quantity We also need to ensure that the list of LineItem objects in an Order has between 1 and 10 items, and that each LineItem has a quantity and price greater than 0.
Here is the Java code for these classes:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import java.util.List;
public class Order {
private List<LineItem> lineItems;
private double totalAmount;
private String status;
public Order(List<LineItem> lineItems, double totalAmount, String status) {
if (lineItems.size() < 1 || lineItems.size() > 10) {
throw new IllegalArgumentException("Order must have between 1 and 10 line items.");
}
this.lineItems = lineItems;
this.totalAmount = totalAmount;
this.status = status;
}
// getters and setters omitted for brevity
}
public class LineItem {
private int itemId;
private double itemPrice;
private int itemQuantity;
public LineItem(int itemId, double itemPrice, int itemQuantity) {
if (itemQuantity <= 0 || itemPrice <= 0) {
throw new IllegalArgumentException("Item quantity and price must be greater than 0.");
}
this.itemId = itemId;
this.itemPrice = itemPrice;
this.itemQuantity = itemQuantity;
}
// getters and setters omitted for brevity
}
Mermaid Markdown for class diagram:
1 2 3 4 5 6 7 8 9 10 11 12 classDiagram Order "1" -- "1..10" LineItem : contains class Order { +List<LineItem> lineItems +double totalAmount +String status } class LineItem { +int itemId +double itemPrice +int itemQuantity }
By placing the above Mermaid markdown in an MD file, we get the following visual class diagram:
classDiagram
Order "1" -- "1..10" LineItem : contains
class Order {
+List<LineItem> lineItems
+double totalAmount
+String status
}
class LineItem {
+int itemId
+double itemPrice
+int itemQuantity
}
Fix the Mermaid Class Diagram and Generate Java Classes
The generated classes and mermaid diagram above look great, but not perfect. Using the Markdown Preview Enhanced extension, we can place the Mermaid diagram in an .md
document and modify it in real time. After the improvements, we can ask GitHub Copilot to regenerate the Java classes.
Generate Java Classes from Mermaid Diagram (md file here)
Now that looks better!
GitHub Copilot Chat does not “always” take the current file into context. When this happens, you can either
- force it by using
@workspace
in the prompt (see here for more info.)- go to the text editor and Select All (CTRL+A), then open the Copilot Inline Chat (CTRL+I) and type the prompt there.
Generate a Java API and OpenAPI YAML Specification
GitHub Copilot Chat remembers the messages and responses in the conversation history. This means we can ask it to make revisions or generate additional code with follow-up messages like below:
@GitHub Copilot:
Sure, here’s a simple Java API using Spring Boot and the corresponding OpenAPI YAML specification.
Java API:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api")
public class OrderController {
@GetMapping("/orders")
public List<Order> getAllOrders() {
// implementation not shown
return null;
}
@PostMapping("/orders")
public Order createOrder(@RequestBody Order order) {
// implementation not shown
return null;
}
@GetMapping("/orders/{id}")
public Order getOrderById(@PathVariable Long id) {
// implementation not shown
return null;
}
@PutMapping("/orders/{id}")
public Order updateOrder(@PathVariable Long id, @RequestBody Order order) {
// implementation not shown
return null;
}
@DeleteMapping("/orders/{id}")
public void deleteOrder(@PathVariable Long id) {
// implementation not shown
}
}
OpenAPI YAML specification:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
openapi: 3.0.0
info:
title: Order API
version: 1.0.0
paths:
/orders:
get:
summary: Returns a list of orders
responses:
'200':
description: A JSON array of order objects
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Order'
post:
summary: Creates a new order
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Order'
responses:
'201':
description: Order created
/orders/{id}:
get:
summary: Returns a specific order
parameters:
- name: id
in: path
required: true
schema:
type: integer
responses:
'200':
description: A single order object
content:
application/json:
schema:
$ref: '#/components/schemas/Order'
put:
summary: Updates a specific order
parameters:
- name: id
in: path
required: true
schema:
type: integer
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Order'
responses:
'200':
description: Order updated
delete:
summary: Deletes a specific order
parameters:
- name: id
in: path
required: true
schema:
type: integer
responses:
'204':
description: Order deleted
components:
schemas:
Order:
type: object
properties:
id:
type: integer
status:
type: string
totalAmount:
type: number
lineItems:
type: array
items:
$ref: '#/components/schemas/LineItem'
LineItem:
type: object
properties:
itemId:
type: integer
lineItemPrice:
type: number
lineItemQuantity:
type: integer
Please note that the actual implementation of the methods in the Java API is not shown. You would need to implement these methods according to your application’s business logic.
How cool is that? Makes you hope technical documentation are fully written using Markdown and Mermaid, right? 😎
Generate Terraform Infra-as-Code
Let’s change gears and make this more relevant to Infrastructure Teams. Code generation is not limited to application code. In this example, I tried generating a Terraform infra-as-code (IaC).
Generate Terraform Infra-as-Code (source here), using Copilot Inline Chat
Of course, we can also use GitHub Copilot to generate bash scripts, powershell scripts, and other types of Infra-as-Code (Azure Bicep, AWS CloudFormation, etc.)
Generate GitHub Actions YAML File
How about making this relevant to teams practicing DevOps? Let’s try generating a CI/CD pipeline using GitHub Actions.
Generate GitHub Actions YAML (source here), using Copilot Inline Chat
Let’s try adding a pipeline step to to ask for manual approval using ekeel/approval-action.
Add Step to GitHub Actions, using Copilot Inline Chat
Nice. The generated YAML file is not perfect, but it’s a good starting point for a pipeline engineer to work on.
Scaffolding a New Project
With the introduction of agents, we can now use GitHub Copilot to scaffold an entire VS Code workspace using @workspace /new
. This removes the process of having to search for working starter codes online when starting a new project.
Prompt: @workspace /new Scaffold a new chat ReactTS application that integrates with Azure OpenAI
From this experiment, we see a basic ReactTS code structure generated. I did hope that it will also generate initial Chatbot and OpenAI SDK implementation code, but it didn’t. I also tried scaffolding with a more complex prompt that contains detailed instructions, but it still only generated minimal templated code… so maybe in the future? 🤭
I believe that the current intent of this new scaffolding feature (i.e. @workspace /new
) is simply for generating the initial project file structure. Developers can then continue to use GitHub Copilot to work on the files individually. It is a copilot after all, not an autopilot.
Generating a New Jupyter Notebook
Now let’s try using the @workspace /newNotebook
command to generate a a new Jupyter Notebook, something that AI/ML engineers and Python developers will find very useful.
Generate a new Jupyter Notebook (source here)
In this experiment, GitHub Copilot picked up the Python libraries to use for calling Azure AI Speech Services and Azure Storage. I also liked that it generated Markdown sections before each Python code cell to make the code readable.
Please Share Your Prompts!
It is my hope that this fun exploration has inspired you to try advanced prompts of your own. Please do share your interesting prompts in the comments below. I am constantly looking for new ideas myself!
To see my other prompt explorations, check out this repo.