はじめに
GitHub Copilot Chatの @workspaceを使うとリポジトリについてチャットすることができ、コードの理解がとても効率的になります。これ無しではもうやっていけません。が、一方で全体をざくっと俯瞰して理解したい時なんかではチャットだけではどうにも理解が進まないこともありますよね。
そこで、コードリポジトリを解析して全体を俯瞰できるレポートを作成するツールrepodoc
を作りましたので、内部動作をご紹介します。使い方自体はgithubの方をご確認ください。
やっていること
以下の図がrepodoc
の全体像です。大きく以下の2つの機能があります。
※チャットについては、図中にも書きましたが、GitHub Copilot Chatと同様の機能になるので、保守性・品質・今後の改善などからGitHub Copilot Chatの方を推奨してます。
リポジトリの分析について
全てのソースコードを一気に読み込んで解析できるのであればそれでもいいのですが、その場合いくつかの問題が発生します。
- ソースコードや設定ファイル、ドキュメントなどの総量が入力トークン上限を超えると分析できない(トークン上限の問題)
-
全ての情報を一気に渡すことで細かい情報(参照先や参照元など)が拾いきれない(精度の問題)
(※いずれもモデルの改善で対処できるようになりそうな気もしますが、2024/10現在ではまだまだかかりそうかなーと思っていたりします)
そこで今回は各ファイルを読み込んで個別の分析を集計していく形をとります。個別ファイルの分析については以下のシステムプロンプトを利用しました。(実際は少しでも精度をあげるためこの内容の英語版を使っています)またStructured Outputをつかって必要な要素を確実にJSONで取得するようにしています。
system_prompt = f"""\
与えられたファイル名とファイル内容を分析し、以下の情報を抽出してください。
- type
ファイルの分類をコード、設定、またはドキュメントのいずれかとして分類
- file_type
ファイル内容の分析結果、例えばJavaコード、GitHub Actions YAMLなど
- description
ファイル内容の簡単な要約を日本語で記述してください。
プログラムコードの場合、処理内容と各関数について説明してください。(以下のサンプル説明を参照)
ドキュメントや設定ファイルの場合、ファイルの目的を説明し、必要に応じて箇条書きで追加の詳細を提供してください。Markdownのタイトル/セクション形式である必要はありません。
テキストの種類に関係なく、内容はできるだけ簡潔にしてください。
適切な箇条書きや改行を追加して、読みやすくしてください。
**説明は日本語で記述してください。**
- references
このファイルから呼び出される宛先ファイル
- entry_points
このファイルが呼び出されたときのエントリーポイント(プログラムの場合はパブリックメソッドなど)
===== プログラムコードのサンプル説明
# クラス名
クラスの概要、その責任と主な機能。
## メソッド1
メソッド1の処理の概要、その入力と出力、およびフロー
## メソッド2
メソッド2の処理の概要、その入力と出力、およびフロー
===== 全体のファイル構造は以下の通りです。
{structure_text}
"""
この中で、{structure_text}となっているところはフォルダとファイルのツリー構成をテキスト化したものです。
この個別ファイルの分析をメモリ上に蓄積していき、最後にjsonテキストで出力します。これが冒頭の図でいう分析結果にあたります。(以下イメージ図です。結構でかめのjsonが作成されます)
ちなみにですが、以下のリポジトリの規模だと出力されたjsonテキストは7kトークンくらいの大きさで、これを作るために0.4$くらいのコストがかかりました。
分析結果をレポートで表示する
jsonをHTMLに変換します。ここは生成AIなどはつかわず機械的な変換を実施します。ソースコードはこちらを見ていただければと思いますが、やっていることはjson->HTMLのマッピングです。
ちなみに実装はほぼほぼ GitHub Copilotで生成しました。
以下のようなレポートが生成されます。このあたりは見やすいように色々変更した方がいいポイントですね。
おまけのチャット機能
GitHub Copilot Chat が推奨とは書きましたが、この分析結果をもとに適宜ファイルを参照させることで全体を俯瞰したリポジトリのチャットが可能です。
ただのチャットだけであれば Github Copilot Chatの方がよさげではありますが、拡張して独自のテンプレートに基づいたドキュメントを生成するようにするなどの拡張が期待できたりもします。是非色々カスタマイズしてみてください。
なお現行のチャット機能では以下の2段階でチャット機能を実現しています。
- 問い合わせの内容を仕分けし、問い合わせの難易度と追加確認が必要となるファイル群を判別
- 上記の結果をつかってファイル群を読み込みプロンプトへ追加 ※ここで難易度に応じてモデルを切り替えるなどもアリかもしれません
以下、それぞれのシステムプロンプトです。いずれも実装では英語にしています。またStructured Outputはこちらでも使っています。
1.仕分け用のシステムプロンプト
system_prompt = f"""
あなたはシステム開発および運用プロジェクトの専門エンジニアです。
ユーザーの問い合わせ内容を確認し、その複雑さと必要なファイルを確認してください。
あなたの回答には以下の要素を含めてください:
- complex_level: 質問の複雑さのレベル。以下の定義に従って数値を指定してください。
- 0: 現在の要約情報のみに基づいて、元のファイルを参照せずに回答を作成できる場合。
- 1: 回答を作成するために元のファイルを参照して確認することが望ましい場合。
- 2: 元のファイルを参照する必要はないが、新しいコンテンツを作成したり既存のファイルを編集したりするために高度なスキルが必要な場合。
- 3: 元のファイルを参照して確認することが望ましく、新しいコンテンツを作成したり既存のファイルを編集したりするために高度なスキルが必要な場合。
- 4: 呼び出し元および呼び出し先の両方で依存関係のあるファイルの影響分析と検証が必要な場合。
- need_file_confirmation: ユーザーの質問に基づいて確認すべきファイルパス(該当する場合)
以下のファイルが関連しています。
- 確認が必要なファイル
- ユーザーのリクエストに役立つ可能性のあるファイル
complex_levelが4の場合、上流および下流の依存関係に関連するすべてのファイルも含まれます。
**自明でない限り、積極的にファイルを参照してください。**
**ファイルパス**のみが必要です。フォルダパスは指定しないでください。
### リポジトリ構造
{structure_with_description_text}
"""
2.回答用のシステムプロンプト
system_prompt = f"""\
あなたはシステム開発および運用プロジェクトの専門エンジニアです。
添付されたリポジトリ構造に関するユーザーの問い合わせに日本語で回答してください。
あなたの回答には以下の要素を含めてください:
- 回答: あなたの回答
- 推奨ウェブ検索キーワード: 追加情報が必要な場合に使用するウェブ検索キーワード(該当する場合)
### リポジトリ構造
{structure_with_description_text}
### 参考情報 - {file_path}\n{content}\n"
### 参考情報 - {file_path}\n{content}\n"
"""
{file_path}と{content}は必要となるファイル数の分プロンプト下部に追加します。
これにより全体の状況を{structure?with?description_text}で確認しつつ、下部の参考情報で必要なファイル内容そのものを確認できる形となります。
おわりに
コードリポジトリを最初に見る際に、コードの全体像を説明したドキュメントがあるかないかが結構違うと思っていまして、今回全体像を作るツールを用意してみました。
結果として何らかのサンプルのリポジトリを見る際にも、一番最初のとっかかりにはなってくれています。特にドキュメントがあまりない系、もしくは詳細な説明ドキュメントしかない系の場合は、役に立つではないかと思います。
あわせて全体解析情報を仕分けし実ファイルの確認が必要なものを判別し、それを全部読み込むチャットも作ることができました。試した限りは GitHub Copilot Chatの @workspaceと現状似たり寄ったりな感じの回答が出せはしますが、従量課金になることや、今後のモデルの更新への対応、そもそもの保守なんかを考えるとチャット機能はGitHub Copilotがどうしても使えない(けどインターネットはつながる)場合のみの利用になるのかなと思ったりもします。ただこのチャットツールを拡張してドキュメント生成(影響範囲分析資料とか)をするのであれば有効かなと思いましたので、機能としては残してリリースしています。
生成AIモデルの性能が向上していくさなかに、システム開発運用業務への生成AI活用はまさに過渡期な状況ではあると思いますが、まずはまずはで現状のボトルネックを少しづつ潰すようなツールを今後も作ったりできたらなぁと思います。