😫

【失敗】レビューコメントから最強のレビュー AI を作ろう!【反省】

2025/02/19に公開

序章

🧑🏻‍💻「今日もミーティングに要件定義、実装以外でやること盛り沢山だ...」
🧑🏻‍💻「あ、でもこれだけは今日中にレビューしてあげないと...あぁ...もう無理...🤢」

〜〜これはコードレビューから PjM を開放するべく LLM 初心者が立ち向かう物語である〜〜

第1章 脈動

🧑🏻‍💻「あ、このコード前もこうやってレビューしなかっけ・・・?(検索)」
🧑🏻‍💻「やっぱりそうだ、前のレビューコメントへのリンクも貼り付けてっと...」

👼『....L...M...を.使..で....

🧑🏻‍💻「な、なんだこの声は!!!」

👼『LLM を使うのです、過去のレビューを学習させて最強のレビュー AI を作るのです

🧑🏻‍💻「そ、そうか。自分自身の分身(LLM)を作ってそいつにレビューさせれば良いのか・・・!」


こうして男はモデルのチューニングを始めるのであった。

第2章 始動

🧑🏻‍💻「まずは、モデルの作り方から勉強しないとなー。」

ポチポチカタカタ...

🧑🏻‍💻「なるほど、ファインチューニングというものを使うと自分の分身のようなモデルを作ることができるのか。今回はこれが良さそうだ・・・!」

第3章 選別

🧑🏻‍💻「 GitHub API 使ってレビューコメントをとりあえず引っ張ってきたぞ。」
🧑🏻‍💻「んーただ、学習データとして使えないコメントも多いな...。除外するスクリプト作るか。」

今回は以下の基準に当てはまるコメントを除外しました。

  • 1️⃣ GitHub Actions などの bot コメント
  • 2️⃣ LGTM, Approve などが含まれるコメント
  • 3️⃣ PR 作成者とコメント投稿者が同じ & スレッドになっていないコメント
    • レビュー依頼時のレビュワーへ補足コメントなどが多いため
  • 4️⃣ 15 文字以内のコメント
    • ありがとうございます!など学習に十分な情報を含まないコメントが多いため

第4章 創造

🧑🏻‍💻「よし、レビューコメントの抽出が終わったぞ。直近のものを抜き出して 300 件前後か。」
🧑🏻‍💻「これを学習データとして使える形に変換してっと...。」

カタカタ...

🧑🏻‍💻「学習データとして 200 件、検証用のデータとして 100 件。十分な量が作れたかな。」

{
  "contents": [
    {
      "role": "user",
      "parts": [
        {
          "text": {
            "prTitle": "PR のタイトルが入ります",
            "filePath": "filePath が入ります",
            "diff": "filePath の diff が入ります"
          }
        }
      ]
    },
    {
      "role": "model",
      "parts": [
        {
          "text": "role user に対してのレビューコメントが入ります" 
        }
      ]
    }
  ]
}

第5章 錬磨

🧑🏻‍💻「よし、いよいよ学習データを使ってファインチューニングするぞ。(かっこいい)」
🧑🏻‍💻「モデルを決めて...、さっき作った学習データを読み込ませて...。」

第5章で作成した学習データを事前に Cloud Storage へアップロードしておき、選択します。

🧑🏻‍💻「ここまで結構時間かかっちゃたけどようやく学習させるとこまでたどり着いたぞ」
🧑🏻‍💻「あとは『チューニング開始』ボタンを押すだけだ・・・!」

🥷 『眠れる力を呼び覚ます…! 深淵の力をその身に宿せ!チューニング開始!!』

ポチッ。

第6章 審判

...1時間後。

🧑🏻‍💻「お、学習おわったぞ!これで最強のレビュー AIができたはずだ!!!」
🧑🏻‍💻「さらば、コードレビュー。君のおかげでエンジニアとして強くなれたよ...。」

プロンプト、カタカタ、プロンプト送信、ポチっ。

🧑🏻‍💻「んんん、、なんか一般的な当たり障りのないレビューしかしてくれないな。
🧑🏻‍💻「でも学習はしてくれて、チューニング前よりは良い回答になってるんだよね?」

チューニング前の Gemini 1.5 Flash のモデル、ポチっ。プロンプト送信、ポチっ。

🧑🏻‍💻「!!!!!学習済みモデルとほぼほぼ回答内容いっしょじゃん!!!!!
🧑🏻‍💻「これ再学習なしの Gemini 2.0 Flash のほうがレビュー精度高いなんてオチないよな...。」

Gemini 2.0 Flash のモデル、ポチっ。プロンプト送信、ポチッ。

🧑🏻‍💻「うわ、レビュー能力高すぎぃ...😵」

〜〜 ☠️ GAME OVER ☠️ 〜〜

【反省】 なぜ最強のレビュー AI が作れなかったのか

茶番はここまでにして、次への糧としてしっかり反省していきます。
過去のコードレビュー内容を学習させれば最強のレビュー AI が作れると思ったのですが、何が原因で思うようなものが作れなかったのでしょうか。

原因1: 学習データの質が低い

Vertex AIの公式ドキュメントに以下の記載があります。

データセットは量よりも質の方がはるかに重要です。

今回はある程度機械的にフィルタリングしたつもりだったのですが、それでも質の向上という点でフィルタリングの粒度が足りなかったのでしょう。
改めて学習データを見返すと「ここって〇〇という理解で良かったですかね?」「ここの仕様ってこう変わったであってましたっけ?」などモデルに学習させてもしょうがないようなコメントが多く含まれていました。

また、「コーディング規約/仕様」など学習データのジャンルが統一されておらずごちゃごちゃになっており、結局学習データから何をモデルに対して学習してもらいたいかが明確になっていなかったのかと思います。

そのため 「何を学習させたいのか」 という視点を強く持ち、レビューコメントのフィルタリングにもう少し注力できれば結果は変わっていてかもしれません。
※ これ以上のフィルタリングは人間の手でする必要があるためとんでもない工数を割く必要がありそうです。(もしくは分類できるプロンプトを作って LLM にやらせるか...。)

原因2: 学習させたい内容が明確になっていない

原因1にもつながる点です。
Vertex AI の公式ドキュメントの「チューニングとプロンプト設計の比較」に以下のような記載があります。

最適なプロンプトを見つけるには、まずプロンプトの作成から始めることをおすすめします。次に、必要に応じてファインチューニングを行い、パフォーマンスをさらに向上させるか、繰り返し発生するエラーを修正します。例を追加することは有効ですが、データを追加する前に、モデルがどこで誤りを行っているか評価することが重要です。

特に重要なのは 「データを追加する前に、モデルがどこで誤りを行っているか評価することが重要」 この部分でしょう。
今回の場合は単純に過去のレビューコメントを雑に学習させただけで、事前にプロンプトの作成/検証などはしていませんでした。そのため既存モデルの「Gemini 1.5 Flash」のレビューのどの点に問題があるのか特定できていません。

事前に「Gemini 1.5 Flash」にプロンプトを投げレビュー性能を検証したうえで、「どのようなレビューコメントを学習させて、どのようなアウトプットを期待するか」 を十分に検討できていれば結果は変わっていたかもしれません。

少なくとも「特定のコーディングルールを守ってほしいのか」「仕様に関して特化したコメントをしてほしいのか」この程度の目的意識を持って学習データの作成をしたほうが良かったように思います。

今後もファインチューニングで最強のレビュー AI の作成を追求するのか

現段階では「No」です。
今回の検証により以下の点でファインチューニングなどの学習よりも、レビュー用のプロンプトを作成するほうが良いと判断したためです。

ここで言うレビュー用のプロンプトのイメージは以下のとおりです。


以下の要件を参考に、与えられた diff を元にコードレビューをしてください。

## 要件
### コーディング規約
- 変数名はキャメルケースを採用すること
- ディレクトリの設計は以下を遵守すること
  - ....

### その他の要件
- ...

理由1: 学習コスト(時間/お金)が高い

これはもちろん人間にも当てはまりますが、モデル学習そのもののコスト(時間/お金)についてです。

まずモデルの再学習には、初回の学習と同じ時間を要します。
※ 再学習を短時間で終わらせる方法が Vertex AI にあればすみません。

また、パフォーマンス調整のためにコメントのフィルタリングに力を入れるならそれの倍以上は時間が必要となります。
加えて、再学習は無料ではないので学習の都度、費用がかかります。

例えば、プロジェクトに新しいコーディング規約が追加されたりアプリの仕様が変わったりしたらどうでしょうか。とてもじゃないですが、モデルチューニングを専業としていない限り今回の手順を都度繰り返すことは現実的ではありません。

その反面、プロンプトにコーディング規約を埋め込むような運用だと新しい規約が追加されたとしても一瞬でその変更を反映できます。
仕様に関してプロンプトで全部補えるかは難しそうですが、コーディング規約のようなルールベースでのレビューであればプロンプトでも十分可能でしょう。

理由2: モデル自体のアップデートに追従できない

最近では DeepSeek を筆頭に、高性能低価格の LLM が驚くほどのスピードで世の中に誕生しています。
せっかくがんばってモデルのチューニングをしても、それを凌駕するモデルがすぐに誕生するかもしれません。 その場合は、また時間と費用をかけてモデルのチューニングをする必要があります。
最近の LLM の発展スピードを見る限り、レビューにおいてはモデルのチューニングにコストを割くのは得策ではないと思いました。

その反面、プロンプトベースの運用ではプロンプトの変更でモデル自体を変更する必要はないですし、モデルが変わってもプロンプトへの影響は極わずかです。
今後も高性能で低価格な LLM が誕生する可能性は非常に高いため、プロンプトベースでしばらくは運用を続けたほうが世の中のトレンドに追従していけることでしょう。

まとめ

「とりあえずやってみよう」の精神でファインチューニングに挑戦してみましたが、記載の通り失敗に終わりました。
また明日からもコードレビューについては注力するべきタスクとして立ち向かっていく必要がありそうです。

ただ、自社のルールに特化したプロンプトベースのコードレビューを突き詰めることでレビューの負担減につながるかもしれないということがわかったのは収穫でした。
コードレビューについて良いプロンプトなどができたらまたブログに書きたいと思います。

デザイン実装のプロンプトについては過去に書いた記事があるのでぜひ参考にしていただけたらうれしいです。

https://zenn.dev/kikagaku/articles/abc0c85a21880d

宣伝

株式会社キカガクではエンジニアを募集しています!!
少しでも興味がある方がいれば、まずはカジュアル面談でお話しましょう。

https://www.wantedly.com/projects/1040067

株式会社キカガク

Discussion