GitHub Copilot Coding AgentのRAGの仕組みを調べてみた

Table of Contents

調べようと考えたきっかけ

GitHub Copilot Coding Agentを使っていると、言葉足らずでも空気を読んでくれるような印象を持ちました。
特に印象的だったのは、同一のIssueを異なるリポジトリでアサインしたときの振る舞いです。
「循環的複雑度のメトリクスをGitHub Pagesで見られるようにする」とだけ記載したIssueをそれぞれのリポジトリでアサインしたとき、リポジトリによって以下のような違いがありました。

  • 開発リポジトリ:Issueに記載の内容を実現するためのGitHub Actionsのワークフローを作成
  • ブログのリポジトリ:Issueに記載の内容を実現するためのブログ記事を作成

公式のプレスリリースにおいても以下のようにRAGを活用しているという文面がありました。

Issueを割り当てると、エージェントは 👀の絵文字リアクションを追加し、バックグラウンドで作業を開始し、GitHub Actionsを使って仮想マシンを起動し、リポジトリをクローンし、環境を設定し、GitHubコード検索による高度な検索拡張生成 (RAG) でコードベースを分析します。

RAG(Retrieval-Augmented Generation)は、検索で取得した情報を生成AIのコンテキストに含めることで、より正確な回答を生成する手法です。 今回はCoding Agent内部でRAGがどのように活用されているのか、実際のログを分析して調べてみました。

Copilot Coding Agentの振る舞いを観察する

Coding AgentではSessionとGitHub Actionsのログに記録が残ります。
これらの中身を見て、どのような振る舞いをしているのか観察してみました。

なお、以下の例で挙げるのは前述の「循環的複雑度のメトリクスをGitHub Pagesで見られるようにする」というIssueをブログのリポジトリでアサインしたケースです。

検索で参考になりそうなファイルを見定めている

Coding Agentが作業を開始する際、最初に必ず検索が行われています。
以下はCoding AgentのGitHub Actionsログ(の一部)で、blackbird-mcp-serverが使用されています。 ブログのリポジトリにおけるGitHub Actionsログ

BlackbirdはGitHubのコード検索エンジンであり、検索によってリポジトリからインサイトを得ようとしています。
検索では以下のパラメータが渡されています。

{
  "task": "\n----\n*This section details on the original issue you should resolve*\n\n<issue_title>\n循環的複雑度のメトリクスをGitHub Pagesで見られるようにする\n</issue_title>\n\n<issue_description>\n\n</issue_description>\n\n## Comments on the Issue (you are @copilot in this section)\n\n<comments>\n\n</comments>\n\n",
  "owner": "tosi29",
  "repo": "tech-note",
  "numSnippets": 10
}

おそらくtaskが検索クエリであり、主にIssueの内容(タイトル、記述、コメント)が含まれています。
ownerrepoは検索対象のリポジトリ、numSnippetsは取得件数でしょう。

またBlackbirdの検索結果らしきものも表示されており、以下はそれを整形したJSONの一部です。

{
  "contents": "File: `content/post/2020/20200615-introduce-checkstyle.md`\n````markdown\n...\n## 既存のコードに導入するルールの精査\n集計結果だけでは具体性に欠けるので、各ルールの妥当性が判断できません。  \nそこで、実際に既存のコードへ適用できそうなルールかどうかはIntelliJ IDEA+プラグインで一つずつ精査します。  \n検出結果からソースコードへ直接ジャンプできるので、ルール適用の妥当性を判断する際はこちらのほうが効率的です。\n\n\n### IntelliJ IDEA + CheckStyle-IDEAプラグインの準備\n...\n### ルールの選定基準\n...\n### ルールのサンプル\n...\n````File: `content/post/2020/20200615-introduce-checkstyle.md`\n````markdown\n...\n## 既存コードにおけるCheckstyleの適用と、検出結果の集計\n...\nそして、各ルールについて引っかかった件数は以下のような感じで抽出して集計。\n```shell\ncat result.txt | sed \"s/.*\\[/[/g\" | grep \"^\\\\[\" | sort | uniq -c | sort\n```\n\nすると、以下のように表示されます。(※以下はイメージです。実際は約40のルールがそれぞれ1〜1000件程ヒットしました)\n```\n   2 [EmptyCatchBlock]\n   3 [OneStatementPerLine]\n   5 [VariableDeclarationUsageDistance]\n   7 [MethodTypeParameterName]\n  17 [MissingSwitchDefault]\n  32 [FileTabCharacter]\n  44 [NeedBraces]\n 102 [CommentsIndentation]\n```\n...\n````File: `content/post/2020/20200615-introduce-checkstyle.md`\n````markdown\n...\n## まとめ\nというわけで、既存のコードへCheckstyleを導入するときの調査やチューニング方法についてのまとめでした。  \nCheckstyleも既存コードもあまり把握できていない状況から、どうすればリスクを抑えつつ効果的に導入できるかを考えるのは少し大変でした。  \n今回は`google_checks.xml`と`sun_checks.xml`の中からルールを精査しましたが、Checkstyleでは他にも循環的複雑度などの計算にも対応しているようです。  \n折を見て公式のリファレンスを読み、順次適用していきたいと思います。\n...\n````",
  "languageName": "Markdown",
  "path": "content/post/2020/20200615-introduce-checkstyle.md",
  "range": {
    "start": 89,
    "end": 156
  },
  "ref": "refs/heads/master",
  "type": "snippet",
  "url": "https://github.com/tosi29/tech-note/blob/283bf1a244655ddc4c614f8e70d1d2e3ee6ea6f0/content/post/2020/20200615-introduce-checkstyle.md#L89-L156"
}

検索クエリと検索結果の関連性を見るに、おそらくベクトル検索を行っていると考えられます。
contentsにはテキストが1200文字程度格納されており、これが検索でヒットしたチャンクを表していると考えられます。1
また言語名やファイルパス、該当する行数の範囲などの情報も含まれています。
これが配列形式で10個格納されていました。

参考になりそうなファイルを読み、コンテキストに入れている

ブログのリポジトリにてCoding AgentのSessionを見てみると、以下のようになっていました。
ブログのリポジトリにおけるSessionログ

これを日本語にして箇条書きにすると以下の通りで、太字部分は特に驚いた箇所です。

  1. 問題ステートメントの要件を満たすために必要な変更の実装をお手伝いします。これは、GitHub Pagesで循環的複雑度メトリクスの可視化を実現することです。まずはリポジトリの構造と仕組みを理解するために、リポジトリを詳しく見ていきましょう。
  2. ここで、この問題をより具体的に理解してみましょう。タイトルは日本語 (「循環的複雑度のメトリクスを GitHub Pages で見られるように」) で、翻訳すると「GitHub Pages で循環的複雑度のメトリクスを表示できるようにする」となります。問題の説明やコメントがないため、これがどのように実装されるかを理解するには、リポジトリのコンテンツを分析する必要があります。
  3. まず、リポジトリ内に循環的複雑度に関する既存のブログ投稿やコンテンツがあるかどうかを確認しましょう。
  4. さて、Checkstyle の記事にある既存の循環的複雑度の参照を見てみましょう。
  5. コード品質メトリクスに関連しているので、JaCoCo の記事も見てみましょう。
  6. ここで、このリポジトリが Hugo サイトであるかどうかを確認しましょう (設定ファイルに基づくと、その可能性が高いようです)。
  7. 素晴らしいですね。これはMainroadテーマを使ったHugoサイトのようですね。問題の説明と既存のブログ記事の内容から判断すると、GitHub Pagesで循環的複雑度メトリクスを表示する方法を説明する新しいブログ記事を作成する必要があると理解しました。

4.と5.で記事を読み込んでいる(=LLMのコンテキストに入れている)ため、ブログの章立てや文体などの言語化が難しい部分も、他の記事を参考にすることができます。 これはプロンプトエンジニアリングでいうOne-ShotやFew-Shotの手法をうまく組み込んでいると言っても良いかもしれません。

ちなみに、よく見ると3.の開始時点で、このリポジトリがブログであることに薄々感づいているようで面白いです。

Copilot Coding AgentにおけるRAGを考察する

観察した結果から、Copilot Coding Agentは以下のことを行っていると推察されます。

  1. 関連性のありそうな所を広く浅く知る:まずリポジトリ内をベクトル検索し、関連性の高そうなファイルを発見する
  2. 関連性の高そうな箇所を深く知る:検索結果上位のファイルをいくつか参照し、コンテキストに含める

一言でまとめると関連性のありそうな情報を予めコンテキストに含めることで、タスク理解やコード生成の精度を高める仕組みといったところでしょうか。一般的なRAGでは検索でヒットしたチャンクしか参照されないことが課題の一つだと感じていましたが、Coding Agentでは上位の結果についてLongContextのように全体を読み込む方式を採用しています。これは様々な場面で応用できる可能性があると感じました。

そしてこれはよくよく考えてみると、人間の振る舞いと似ているようにも感じられます。
自身が詳しくないリポジトリを触るときに以下のようにアプローチするのは一般的な振る舞いでしょう。

  • どんなファイルが存在するのかを眺めてみる
  • キーワード検索して、自分の目的に関連がありそうなファイルを探す
  • 見つかったファイルをいくつか開いて眺めてみる

人間が採っているアプローチと本質的に近しいことを行っていることは、とても興味深く感じられました。

RAGの応用可能性

Coding Agentで採用されているRAGの方式は、様々な場面での応用が考えられます。
例えば「サポートセンターなどにおいて、問い合わせの回答ドラフトを生成する」といったタスクを考えると、過去の回答内容はとても参考になります。 したがって、問い合わせの文面に基づいて過去の回答をベクトル検索し、いくつかをコンテキストに含めておくことで、それらをリファレンスとした回答を生成することができるようになると考えられます。
これを踏まえると、今後はエージェントにRAGが組み込まれていくことがデフォルトになっていく可能性が高いと考えられるでしょう。

逆にGitHubを文書のリポジトリとすることで、Copilot Coding Agentを文書生成に活用できる可能性も考えられます。 問い合わせ・回答の文面をMarkdownなどで蓄積していけば、Copilot Coding Agentが参照して回答文面のドラフトを作成することができるかもしれません。

まとめ

今回はGitHub Copilot Coding AgentがRAGを以下のように活用していることが分かりました。

  • Issueの内容をベクトル検索のクエリとして使用
  • 作業開始時に検索を実行し、関連ファイルをコンテキストに追加
  • 検索結果の上位ファイルを実際に読み込み、コンテキストに追加

これは、エージェントのタスク理解やコード生成の精度向上に寄与しているものと考えられます。
またこの仕組みは人間のアプローチと本質的に類似しており、今後様々な場面での応用が期待できそうです。


  1. contentsの先頭にファイル名が入っていて、ちょっと不思議なデータ構造です ↩︎

関連記事


  1. GitHub Copilot Coding Agentで消費するプレミアムリクエスト等を集計してみた
  2. GitHub Copilot Coding Agentを試してみた
  3. GenUのRAGにおけるクエリ・応答生成の仕組みを調べてみた
  4. 生成AIの現状を踏まえ、社内活用と未来を考えてみる
  5. Google検索とChatAIにみる、エンタープライズサーチとRAGの未来
  6. Amazon Kendra GenAI Indexへの期待と課題をまとめてみた
  7. TerraformでGitHub ActionsのIPリストを参照する