GitHub Copilotを上手に活用するために知っておきたいこと

みなさん、GitHub Copilotを使っていますか？
私は数ヶ月ほど前から使っているのですが、コードの自動補完にメリットを感じつつも、うーんそうじゃないんだよな、となることもあったりします。
そこで、もっと上手に使いこなせたらいいなと思い、GitHub Copilotについて調べたり試したりをしてみた結果、GitHub Copilotを使う際に知っておいたほうが良さそうなことをまとめました。

# 書いてあること
- GitHub Copilotとは
- GitHub Copilotでの活用事例
- GitHub Copilotの難しいところ
- GitHub Copilotを上手に使うためのテクニック

# GitHub Copilotとは  

OpenAIのLLMをベースとしたAI開発支援ツールです。
VisualStudioCodeといったIDEなどで使用することができます。GitHub Copilotのクライアントがエディタ上のコンテキストを入力とし、バックエンドを通して、OpenAIのLLMをもとにコードの提案をする仕組みです。
GitHub Copilotができることは、大きく次の3つになります。
1. コードの自動補完
2. コメントからコードの提案
3. AIとのチャット

# GitHub Copilotでの活用事例

3つできることがあると書きましたが、その中で主に活用しているケースを紹介します。

## コードの自動補完

自動補完の中でも特にGitHub Copilotが得意だなと思うのは、以下のようなコードです。

### よく書かれる典型的なコード

デザインパターンや各言語で用意されている組み込みの機能を使うなど、一般的によく書くようなコードは特に補完してくれます。

### 同じような繰り返しのコード

例えば単体テストで、ある関数のテストを別の条件で複数書くときに同じようなコードを繰り返し書くことがあると思います。そんな時、最初に書いたテストケースをもとに次のテストケースを補完してくれます。

### その他の事例

関数の処理を実装する際も、処理内容がわかるような関数名を定義すれば、まるっとコードを補完してくれます。
また、関数の実装を先に書いておくと、関数のコメントも補完してくれます。

![comment.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3735277/ae4ed24a-83a3-37f2-b646-2c8f5f818068.gif)


## コメントからコードの提案

コメントに十分な情報を書いておけば、ある程度複雑なロジックでもコードを提案してくれます。
この処理はどう実装したらいいか分からないなという時でも、実装したい内容をコメントに書けばそれらしいコードの提案をしてくれるので、プロトタイピングにも向いていると思います。

## 単体テストの作成

単体テストを作成するときにも活用できます。

### テストデータの作成
データの型や形式がテストしたい関数やテストファイルに書いてあれば、それをもとにテストデータの作成をしてくれます。
  
### 豊富なテストケースの提案
テストケースの数やテストの詳細などをコメントで書くと、コメントに合わせたテストケースを提案してくれます。

![test1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3735277/bbb71be4-6e67-f24d-6c7f-820f4e2f6ab7.gif)

## リファクタリングの提案

コードの可読性や、処理のパフォーマンスを高めるためのリファクタリングをする際にも活用できます。

### キラキラマークを選択
キラキラマークを選択すると、コードの内容に応じてリファクタリングしたい内容を選べます。（選べない場合はインラインチャットが開きます。）例えば、コードブロックを選択していれば変数や関数の抽出、関数を選択していれば関数の別ファイルへの切り出しやテストやドキュメント生成、構文エラーがあればその修正などができます。

![error.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3735277/f6b92249-71e6-b552-4271-e5bb865519c7.gif)

### チャットで直接質問
リファクタリングしたいコードをカーソルで選択した状態でチャットに質問すると、提案してくれます。

![refactor.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3735277/096bc17b-6b34-1fc4-49d1-3b334a83f272.gif)

### シンボルの移動、リネーム
変数名や関数名のリネームをしたいときも、「シンボルの移動」で代替名を提案してくれます。

![rename.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3735277/08ea041c-7003-4daf-ef7c-acc792bf6e79.gif)

## デバッグのサポート

デバッグ時やテスト実行時に出たエラーメッセージをチャット上にコピペすると、エラーの原因や修正箇所を提案してくれます。
ターミナル上でも直接チャットできたりもします。

![debug.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3735277/575ad69b-0878-6b57-83f8-61dd3b8068c8.png)


## ドキュメントの作成

コーディング以外にもドキュメントを作成する作業も多いと思います。ReadMeやその他のドキュメントを作るときにも、書きたいことを補完してくれたり、すでに書いたコードをもとに提案してくれたりします。

# GitHub Copilotの難しいところ

GitHub Copilotがどれだけ優秀なco-pilotかを紹介しました。しかし、どんな時でも最適な提案をしてくれるとは限りません。

## GitHub Copilotの提案が最適であるとは限らない

### 精度よりも速度重視

前提として、GitHub Copilotは次のような考え方をもとに作られています。
- 提案の精度よりも提案の**速度**を重視
- 納得がいかない提案は破棄して次の提案を促すような使い方を想定

確かに、ChatGPTのような対話型AIに比べてレスポンスは速いですよね。このレスポンスが速くないと、いくらコードを補完してくれても自分で書いたほうが速いと感じるようになり、結局コーディングの速度を高められなくなってしまいます。

### コードを推測するためのコンテキストが足りていない

そして、なぜ提案の精度が常に高いわけではないかというと、GitHub Copilotに与えられたコンテキストとなる情報が不足していることが1つ挙げられます。
GitHub CopilotのベースとなるLLM(Large Language Model)の基本的な概念は次の通りです。
- 与えられたコンテキスト（入力情報）を補完し、文脈に基づいた意味を生成する
- 求める回答の精度を高めるためにはコンテキストが重要となる

しかし、GitHub Copilotは提案の速度をよりはやくするために、与えられるコンテキストの量(トークン数)に限りがあります。また、与えられたトークン数が多ければ確実に精度が上がるわけでもないということです。

そのため、GitHub Copilotから最適な提案をもらうためには、コーディングに必要なコンテキストを限られたトークン数でどれだけ与えられるかが重要となってきます。

他にも、GitHub Copilot Chatはコーディングに関係のない質問には答えないように制御されている点や、過去の対話履歴をコンテキストとして読まないようになっている点は、ChatGPTと違って使いづらいと感じています。

# GitHub Copilotを上手に使うためのテクニック

「Prompt Crafting」という言葉をGitHubが定義しています。Prompt Craftingとは、AIの提案を最適化するために、与えるコンテキストを調整していくテクニックのことです。

Prompt Craftingで最適な提案をしてもらうには、まずはGitHub Copilotがどんな優先度でコンテキストを使っているかを理解することが大事なのではないかと思います。

## コンテキストの優先度

:::note warn
2024年3月時点の情報をもとに書いています。
:::

https://logmi.jp/tech/articles/329426 (2023/8/30時点)
https://speakerdeck.com/yuhattor/github-copilot-behind-the-scene?slide=16 (2023/9/13時点)

### プログラミング言語情報
現在アクティブなファイルがどのプログラミング言語で書かれているかです。現在書かれている言語以外のファイルはコンテキストとして読まれないそうです。

- 例：HTML
    ```html
    <!DOCTYPE html>
    ```
- 例：Python
    ```python
    #\!/usr/bin/env python3
    ```

### 現在のファイルへのパス

例えば、現在アクティブなファイルがcontrollersディレクトリに存在するなら、「コントローラーを書いていそうだ」と推測できます。

### 非アクティブなオープンしているタブ

非アクティブでオープンしているタブとは、現在カーソルが指しているファイル以外に開いているタブのことです。最大で直近20個のタブをコンテキストとして与えられます。基本的にFIFO(First In, First Out)で、直近アクセスしたタブが優先されます。

ここで必要なファイルをコンテキストとして与えるためのTipsは次の通りです。
- 参照する必要があるファイルを開いておく
- 不要なファイルを閉じる
- 参照したい他の拡張子のファイル (例: .md, .csv) がある場合は、現在アクティブなファイル上にコピペする
- 「定義に移動」をして関数定義を見に行くことで関連するファイルを開く

## 精度を高めるためのデザインパターン

あとは、GitHub Copilotが提案しやすいデザインパターンを知っておくといいかもしれません。基本的に、人間でも読みやすいコードはAIも読みやすいのだと思っています。

- 変数名、関数名はシンプルかつ、意味のあるものにする
- 一貫性のあるコーディングスタイルで書く
  - インデント、タブ、命名規則、コメントのフォーマットなどを統一する
- 複雑な大きいコードを書くのではなく、小さなまとまりで作業する
  - 複雑なアルゴリズムを小さく関数等に分割して書く
- ハイレベルなアーキテクチャを先に設計し、各部分の機能と目的をコメントに書く
  - APIの概要やインタフェースの定義などの大枠を先に書いておき、その機能や目的をコメントに書く

その他にもいくつかパターンがあるので、気になる方はこちらを参照ください。

https://patterns.hattori.dev/ja/design-pattern/


## さらにGitHub Copilot Chatでのテクニック

GitHub Copilot Chatでこれらを上手く使うと、与えるコンテキストを調整することができます。

### エージェント
チャット上で質問したい内容によってエージェントを指定することができます。
例えば、ワークスペース全体に関する`@workspace`、VisualStudioCodeの機能や使い方に関する`@vscode`、ターミナルに関する`@terminal`があります。

![agent.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3735277/9a104050-0875-09ca-0b80-f750b63e21ae.png)

### スラッシュコマンド
提案してほしいことを具体的に示すことができます。
例えば、`/tests`はテストケースの作成、`/fix`はエラーの修正、`/doc`はドキュメントの作成です。
このあたりは、キラキラマークでも選択リストに出てくることがあります。

![command.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3735277/72f51efa-60e9-b7e3-6e5b-79d5b5afb977.gif)

### コンテキスト変数
コンテキストとして与える場所を指定することができます。
例えば、`#editor`はエディタ上、`#file`はファイル、`#selection`はカーソルで選択しているエリアです。何も指定しないと、カーソルで指定しているエリアが優先され、次にカーソルのある付近のコードがコンテキストとなります。

![param.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3735277/439fd5be-579a-ba19-dddc-c9cad768c9bc.png)

これら使えるコマンド等は、随時アップデートされています。

https://speakerdeck.com/yuhattor/ai-powered-development-with-github-copilot-20240202?slide=21

## Tips: よく使うショートカット

特に、インラインチャットは、コードエディタ上でシームレスにチャットできるので便利です。
| キー | 内容 |
|:-:|:-:|
| command + I   | インラインチャットを開く |
| command + →  | 単語単位で提案を採用 |
| option + →  | 次の提案を見る      |
| option + ←  | 前の提案を見る      |

# まとめ

GitHub Copilotが得意なケースはどんどん活用していくと良いと思います。
また、良い提案がもらえなくても深く悩む必要はありません。納得がいかない提案はどんどん破棄して次の提案をもらいましょう。
より良い提案をもらうためにはコンテキストを適切に与えることが重要であり、そのためのテクニックをいくつか紹介しましたが、以前に比べたら圧倒的に読み取るコンテキストの量や提案精度が向上しているように感じています。今後のアップデートにも期待しています！

# おまけ： GitHub Copilot Enterpriseの機能がすごそう

先日GAとなったEnterprise版では、例えばブラウザでのGithub.com上でGitHub Copilotが使えるようになりました。
また、組織のリポジトリ全体をコードベースとして与えられたりするので、与えられるコンテキストの種類が増え、よりいろんな使い方ができそうですね。コードレビューするときとかに良さそうです。

https://developers.cyberagent.co.jp/blog/archives/46542/

# 参考資料

https://patterns.hattori.dev/ja/

https://speakerdeck.com/yuhattor/ai-powered-development-with-github-copilot-20240202

https://code.visualstudio.com/updates/