Resources

Mark Wang - Using GitHub Copilot in R Shiny Development

video
Oct 31, 2024
20:04

image: thumbnail.jpg

Transcript#

This transcript was generated automatically and may contain errors.

Okay. Hello everyone. Today, I will talk about the use of GitHub Copilot in R Shiny Development.

Now, raise your hand if you think this is a shiny app. Raise your hand if you think this is a shiny app. Well, this is. I see your hands. Okay. This is a shiny app. This is a very ugly shiny app. It looks like the first ugly shiny app that we probably have created 5-10 years ago. It's a very simple app. It allows the user to pick a few tech stocks and see the recent price changes.

Now, how about this one? Raise your hand if you think this is also a shiny app. Okay. I see fewer hands. This is actually a shiny app, but you are correct because this was not a shiny app. It was initially created using another front-end framework, JCode, but then I used Copilot to convert it to a shiny UI. And this is a very interesting use case here because oftentimes, if your organization has an online presence that was created using another front-end framework, but as an asset data analyst or data developer, you want to create a shiny app that looks like it without spending too much time with CSS or HTML, actually Copilot can be a lot of help.

Now, today I want to convince you that if you are a data professional with a background in analytics or statistics, if you want to try out Copilot, then R Shiny is a great place for you to start. And if you, like many of us in this room, have already been playing around with Copilot and R, I want to share my tips and tricks with you.

Why? Because the R language, the R programming language is unique in that it is predominantly used for data analytics purposes. And according to a survey, 75% of all R users use it for analytics purposes and half of them use it for educational purposes. This means the front-end, the web app is essential for us. It's critical for us to communicate our data and our findings to our students, our clients, our stakeholders. But it is typically, in often cases, it's not where our specialty is.

By using Copilot, we'll be able to automate a lot of things on the front-end, automate a lot of things that are routine, tedious, for example, tests or documentation, and focus our time and energy on where our value added is, which is data analytics and statistics.

and focus our time and energy on where our value added is, which is data analytics and statistics.

And to borrow the term used by Melissa yesterday, if you are Gen AI fearful or Gen AI skeptical, listen to my talk. I want to convince you to try out Copilot for R Shiny.

What is GitHub Copilot?

Now, before diving into the details of Copilot, just quickly go through. Copilot was collaboratively developed by OpenAI, GitHub, and Microsoft, and it shares the base GPT model. But it was specifically trained to provide code as a response. And throughout the session, we will see the superpower of large language models. But keep in mind, it was trained to provide the code as a response.

Now, it is supported by the most widely used R IDE, which is RStudio. And if you are interested in trying out this positron, also with Copilot, it's not currently supported. But there are a lot of alternative online or local LAMs that have extensions for positron. And if you still want to stick with Copilot, you can use the chat R package as an alternative. So chat R package provides this interactive interface between the R user and large language models through the IDE.

The basic workflow: prompt and response

Now, I divide the basic workflow of using Copilot in R Shiny into four parts. Prompt, response, context, and iteration. I will go through them now.

The first part is a prompt response workflow. So what's a prompt? We have all the great prompts given by Melissa, given by Joe. And a prompt is something that we write either in human language or in code with a direct purpose for Copilot to provide a response.

Now, according to Microsoft, there are three principles of writing effective prompts, single, short, and specific. And in the context of using Copilot for R Shiny, three types of prompts that I find the most useful and I want to share with you now, command type, question type, and the leading type. And here on the screen, you see the command type. It's very straightforward. It tells Copilot what to do.

So in this case, I want to create, I want to use Copilot to create the UI for this very simple stock price app. And I divide this task into three single steps. The overall UI, the visualizations, and the user input. And each sentence is short.

Now, what do I mean by specific? So specific means you tell Copilot not only what to do, but also how to do, because there are oftentimes more than one thing, more than one way to do a thing in R Shiny, and especially when the specifications are not in very detail.

Okay, so suppose I'm not sure how to create the user input, the part that let the user select the stock ticker. What do I do to be more specific? Well, I can ask Copilot. So there's a second type of prompt, the question type. Remember, Copilot was created to provide code as a response. Therefore, if you want to see human language response, you need to be very specific. You tell Copilot answering English instead of code.

And the second type of prompt, the question, and then I ask my question. And I'm also using the third type of prompt here, lead in. So what's lead in? You are leading in Copilot to provide the response you want to see by starting with the first few letters or the first few words that you want Copilot to provide. So in this case, I type answer to make sure Copilot knows it needs to give an answer in human language instead of continuing to write your question. So if you don't do this, oftentimes Copilot will continue to write your question. And as we can see, Copilot's great at telling us the very basic function, very basic package that we can use in this case.

Context

All right, the next part, context. So context is different from prompt in that it's typically not something we specifically create to let Copilot have a response. Most likely, it's something that you already have. And the most important source of context is a code in your code base.

So here, I'm using the example of asking Copilot to create this UI. So I want Copilot to convert the front end of my personal blog from HTML, JQL, to R Shiny. Now, the most important context in this case is the index.html file, which is where the web page comes from. And there are other files in the code base as well.

Okay, Copilot attaches different levels of importance to the context in your code base. And the most important context should be in the current active tab. So make sure that you open the current active tab, which is the index file. The other open tabs in your IDE, in this case, the CSS file, the JS file, they are referred to by the HTML file. So they are also important, open them in the IDE. And when you initially set up Copilot for your RStudio, you have the option to index project file. What does that mean? It means you provide all the files, all the code in your project as a context for Copilot to use.

Now, when I set, when I put the most important context in the currently open tab, I point to the context, right? I tell Copilot, okay, what it is. And then also I tell Copilot why it is important. So in this case, I want to create R code that comes from this HTML. I actually do not create, I do not start with an R script first because I want to stay in the same file as the most important context. So I actually ask Copilot to create the R code inside the HTML file. And when the suggestions are complete, when the code is complete, I then copy and paste the code to an R script. And this is a very useful use pattern in this case.

Now, the second source of context is knowledge on the internet. So in this case, the important knowledge is in this specific documentation. And the power of large language models we see is that we don't do copy and paste anything from the internet. We just need to provide the URL and under the hood, the large language models have already associated with the URL, with the actual text in that webpage. And I then tell Copilot why this is important.

The third type or the third source of context are examples. So sometimes the stuff in either things that are online, right? We just saw, for example, documentations, academic papers, Stack Overflow, pages, GitHub issues, those things may be not very specific, not very specific to what you want to do. In this case, you can provide to the point, short and concise examples. So in this case, a very simple example is the conversion between HTML tag and Shiny UI. This is exactly all that Copilot needs to do in order to complete the task here.

Now, a tale of caution here, not all context helps. There are some types of context that can actually stop Copilot or large language models from working. And as we can see here, I'm already a hundred lines into letting Copilot providing correct working R code that to reproduce the HTML file, but it stopped line 101, mail two, and then no completions available. How come tags A is hyperlink, right? Hyperlink is very common. It shouldn't have any difficulty creating the right hyperlink using R.

Why? Well, if you have some experience using Copilot for data analytics, you can probably spot the red flag, which is mail two, because email is a piece of personal information. Similar things that can cause problems for Copilot to let it stop include your address, IP address, things that can cause bias, for example, your gender identity, immigration status. Those things can trigger the internal safety measures, anti-bias measures of the large language models and make it stop working.

Now, this means it's very important for you to know your context, number one. And if you're not sure, you ask Copilot. So in this case, I use the question type of prompt, tell Copilot answer in English. I also lead in with the word answer, and Copilot will tell me where in the context I can have this concern about privacy or bias. And it's very important for us whenever we use large language models to be aware and mitigate those risks.

Iteration

Okay, the last part of this basic workflow is iteration. So iteration is the continuous improvement of your prompt or your context in order to improve the quality of your response. So the use of Copilot is not a one-time thing. You gradually improve your prompt and your response.

Now, to demonstrate, so I have three ideas to share with you when it comes to iteration. Number one, you do documentation first to enrich your context, the important part of iteration. Number two, you iterate from static data to dynamic data. And number three, you iterate from something that's task or project-specific to something that can be used across the board as an internal prompt dictionary. To demonstrate these points, I will use Copilot to create tests for this very simple Shiny app.

The Shiny app we saw of stock prices is very simple, and there are three types of tests I want to show, unit, browser, and server. And the first test is a unit test, a very simple test. I'm pretty sure 90% of you know what's a unit test. It looks at the input and the output of the function.

Now, I want to create a unit test for this very simple function to transform data from wide form to long form. Now, what do I do? I actually do not ask for unit test first. Instead, I ask Copilot to create documentation. Why? Because number one, Copilot is typically very good at generating documentations for functions or specifically for Shiny modules as well. And number two, when we have the documentation, we put the documentation up there, right? It goes back, it becomes part of the context, and it makes the next step, which is creating the unit test, more effective. And in this case, we can see Copilot is great at creating a proper unit test for this function.

Now, the next type of test I want to share is browser test. So what's a browser test? A browser test, if you use Shiny in your work, you probably do it. It uses the shinytest2 package. It basically creates a virtual server and a virtual browser, and take a snapshot of your app, either literally as an image or take a snapshot of the HTML output.

So in this case, I want to have a browser test of the HTML table in the middle. It's a big table, it has a lot of numbers. A lot of numbers are stock prices. Now, what's the problem here? It's actually a common issue when we use the shinytest2 package. That is, the data is not static. Data is dynamic. The next time we run the test, right, what happens is stock prices have changed, but we assume it doesn't change. So the test will fail.

In this case, I go into the place where the comparison is made, and I ask Copilot to create this function, transform HTML. It transforms the HTML output, extract the part that is predictable, the number of rows, number of columns, row headers, but it discards the part that will change over time, the data, of course. And this way, the next time I run the browser test, it will not fail. This is a very powerful solution to many of the problems when we use shinytest2.

Okay, the third test, type of test, is server test. A lightweight test looks at the input, the output, and the reactive values, reactive expressions, and how they interact with each other. So the first situation, I tell Shiny what to do. Without any more information, sorry, Copilot is not creating any test at all. It's not effective at all.

And on the top of that, the second iteration, I added reference to knowledge on the internet. And with this iteration, we can see, I had to use the correct functions, but the expected function is outside the server, so still a small problem there. And then on the top of that, the third iteration, I added examples, a very short example. I copy and pasted it from the Mastering Shiny book, but with this example, it's basically a very simple app. The server function and the server test as well. And with this last iteration, finally Copilot's able to use the correct functions, test that test server, and also the actual test are also correct.

Now, pay attention to this because all the context, all the prompt we have here are not specific to the task. They can be used elsewhere whenever we use, we want to create a server test. And the same principle goes to things like security and the compliance conventions of your organization, how you do coding and documentation and how you deploy your applications. All those things can be used elsewhere and we collect them as part of prompt dictionary into our knowledge base.

Summary

Okay, in summary, by adopting the best practices when it comes to these four parts of the basic workflow of using Copilot and investing, your organization investing the time and energy into creating the internal knowledge base will be able to make our use of Copilot more effective and save our time and our energy so that we can focus on the important things, data analytics and statistics. Thank you, this is my contact information.

Q&A

All right, thank you, Bart. You still have a couple of minutes for some questions. Let me just check, so the crowd has some, hopefully something good from the crowd.

Yeah, can you explain a little bit more about how to optimize prompts to, sorry, can you explain a little bit more how to optimize prompts to improve Copilot's accuracy in Shiny development?

Yeah, great question. So number one, follow the principles, right? Short, specific and single, and also more specifically for Shiny. So it is, so the way large language models work is that the more stuff out there, the more accurate or the more powerful the suggestions will be. So Shiny is only part of the R ecosystem, right? So when sometimes we do need to do more iteration, providing examples or reference to source on the internet, it really depends on the deeper you go, the longer you are, longer meaning not that many things on the internet out there, the more specific you need to be, the more iterations you probably need to do to have a more satisfactory response from Copilot.

Got it, and as a follow-up to that, are there any examples where a small prompt made significant difference?

Yeah, so I think two things that we all can do when we use Copilot, and this is actually not limited to R Shiny. One is to do the lead-in. So I always find if you don't do lead-in, meaning typing the first few words or letters, what happens is Copilot continues to write what you want to, what you are writing instead of answering you. So that's something, I think it's a small trick, but it goes a long way. And the other is, I guess, examples, sometimes very small examples, but it also goes a long way.

So I always find if you don't do lead-in, meaning typing the first few words or letters, what happens is Copilot continues to write what you want to, what you are writing instead of answering you. So that's something, I think it's a small trick, but it goes a long way.

All right. Thank you, Mark.