1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

LLM-as-a-Judgeを意識したプロンプトでCodeRabbitによるPRレビューを改善しようとした話

Last updated at Posted at 2025-07-14

はじめに

個人開発でWebアプリケーションを作っており、PRレビューにはAIツールのCodeRabbitを活用しています。
今回は、LLM-as-a-Judgeの考え方を意識したプロンプト設計によって、CodeRabbitのレビュー品質がどのように変化したかをまとめます。


LLM-as-a-Judgeとは

LLM-as-a-Judgeは、AI(大規模言語モデル)の出力を、AI自身で評価するという仕組みです。
文章生成AIは、同じ質問に対しても多様な応答がありえ、単純に評価を行うことが難しいです。

また、人間がすべての出力を評価するのは現実的ではないため、評価基準を明確にプロンプトで与え、AI自身にセルフチェックさせることで、
一貫性のあるレビューやフィードバックを自動化できるというのがLLM-as-a-Judgeの考え方です。


CodeRabbitへのプロンプト適用方法

CodeRabbitでカスタムプロンプトを適用するには、
CodeRabbitの設定画面 にアクセスし、
「Path Instructions」セクションで「Path」にプロンプトを適用したいファイルの拡張子(例:**/*.ts)を記載し、
「Instructions」に使用したいプロンプト文を記載します。
この設定を保存すると、すべてのリポジトリに対してプロンプトが適用されます。

特定のリポジトリだけにプロンプトを適用したい場合は、CodeRabbit上で各リポジトリの個別設定画面に移動し、
同様に「Path」と「Instructions」を設定してください。
これにより、選択したリポジトリだけにプロンプトを適用することができます。


プロンプト改善に取り組んだ理由

CodeRabbitのデフォルトレビューは、抽象的な修正案や指摘はあるものの、
指摘の粒度や重要度がバラバラで、「本当に必要な対応」にしぼりきれないことが多く、
開発者としてどこを優先して直すべきか迷う場面がありました。

そこで、レビューの精度を高め、重要な問題だけに集中できるようにするため、
LLM-as-a-Judgeの考え方を取り入れたプロンプト作成に挑戦しました(プロンプトの作成においてもAIを活用しております)。


実験内容

同じ内容のPRを2つ作成し、
1つは従来のCodeRabbit(プロンプトなし)
もう1つはLLM-as-a-Judgeプロンプトを適用したCodeRabbit
でレビューを実施し、コメント内容を比較しました。
PR内には故意にXSS脆弱性・非同期処理のエラー・メモリリーク等の問題を含ませております。


実際に使用したプロンプト

レビューする際には、以下のprefix(接頭辞)をつけてください
[must]  
[imo] (in my opinion)  
nits 
[ask]  
[fyi]

レビューの品質向上のため、以下の基準に従ってコメントしてください:

【必須レビュー項目】(必ずコメントすべき問題)
- セキュリティ脆弱性(XSS、SQLインジェクション、認証不備など)
- メモリリーク、無限ループなどの重大なバグ
- パフォーマンスを著しく悪化させる処理
- データ損失の可能性がある処理
- 本番環境で障害を起こす可能性のあるコード

【判断基準】(以下に該当する場合のみコメント)
1. 機能要件を満たしていない場合
2. エラーハンドリングが不適切で例外が発生する可能性
3. ビジネスロジックに明らかな誤りがある場合
4. コードの保守性を著しく下げる実装(可読性、拡張性)
5. 既存の設計原則やアーキテクチャから大きく逸脱している場合

【コメント不要】(以下は指摘しない)
- 個人の好みやスタイルの違い(フォーマッタで解決可能なもの)
- 軽微な命名の改善提案(機能に影響しない場合)
- 「良い実装ですね」「問題ありません」などの承認コメント
- 既にLintルールで検出される問題
- 動作に影響しない小さなリファクタリング提案
- PRの説明文に既に記載されている内容の確認

【コメント形式】
- 問題を指摘するだけでなく、具体的な解決策も提示する
- 「〜すべきです」ではなく「〜することで〜の問題を解決できます」の形で書く
- コードサンプルを含める(可能な場合)

【LLM as a Judge: セルフチェック必須】
コメントを投稿する前に、以下の評価基準で自分のコメントを100点満点で採点してください(採点結果をコメント内に必ず含めるようにしてください):

■ 評価基準(各20点満点)
1. 【必要性】: このコメントは本当に必要か?(20点)
2. 【具体性】: 解決策が具体的で実行可能か?(20点)
3. 【建設性】: 開発者の成長に寄与するか?(20点)
4. 【正確性】: 指摘内容が技術的に正しいか?(20点)
5. 【効率性】: レビュー時間を有効活用しているか?(20点)

■ 投稿基準
- 90点以上: 即座に投稿
- 70-89点: 改善してから投稿
- 70点未満: 投稿しない(削除)

■ 改善プロセス
70-89点のコメントは以下を実行:
1. 低得点の項目を特定
2. より具体的な解決策を追加
3. 学習価値を高める説明を追加
4. 再評価して90点以上になるまで改善
5. 改善できない場合は投稿しない

具体的なコメント比較

XSS脆弱性

As-Is

⚠️ Potential issue

XSS脆弱性: HTMLエスケープ処理が実装されていません

sanitizeUserInputメソッドは入力をそのまま返しており、XSS攻撃に対して脆弱です。HTMLエンティティのエスケープ処理を実装する必要があります。

+  public sanitizeUserInput(input: string): string {
+    return input
+      .replace(/&/g, '&')
+      .replace(/</g, '&lt;')
+      .replace(/>/g, '&gt;')
+      .replace(/"/g, '&quot;')
+      .replace(/'/g, '&#x27;')
+  }

To-Be

[must] XSS脆弱性: HTMLエスケープが実装されていません

現在の実装では入力をそのまま返しているため、悪意のあるスクリプトが実行される危険があります。
HTMLエスケープを実装することで、XSS攻撃を防ぐことができます。

+  public sanitizeUserInput(input: string): string {
+    return input
+      .replace(/&/g, '&amp;')
+      .replace(/</g, '&lt;')
+      .replace(/>/g, '&gt;')
+      .replace(/"/g, '&quot;')
+      .replace(/'/g, '&#x27;')
+  }

自己採点: 100点

非同期処理のエラー

As-Is

⚠️ Potential issue

非同期処理のエラー: awaitが不足しています

response.json()にawaitがないため、Promiseが返されます。また、エラーハンドリングとステータスチェックも必要です。

+    try {
+      const response = await fetch(`/api/users/${userId}`)
+      if (!response.ok) {
+        throw new Error(`HTTP error! status: ${response.status}`)
+      }
+      const data = await response.json()
+      return data
+    } catch (error) {
+      console.error('ユーザープロファイルの取得に失敗しました:', error)
+      throw error
+    }
   }

To-Be

[must] 非同期処理のバグ: awaitが不足しており、エラーハンドリングも必要です

response.json()にawaitがないため、Promiseが返されてしまいます。
また、ネットワークエラーやレスポンスエラーの処理も実装することで、堅牢性を向上できます。

+  public async fetchUserProfile(userId: string) {
+    try {
+      const response = await fetch(`/api/users/${userId}`);
+      if (!response.ok) {
+        throw new Error(`HTTP error! status: ${response.status}`);
+      }
+      const data = await response.json();
+      return data;
+    } catch (error) {
+      console.error('Failed to fetch user profile:', error);
+      throw error;
+    }
+  }

自己採点: 100点

メモリリーク

As-Is

⚠️ Potential issue

メモリリークのリスク: キャッシュサイズ制限がありません

キャッシュが無制限に成長し、メモリ不足を引き起こす可能性があります。LRUキャッシュの実装やサイズ制限の追加を検討してください。

+  private readonly MAX_CACHE_SIZE = 1000
+  
   public cacheUserData(userId: string, data: any): void {
+    // キャッシュサイズチェック
+    if (Object.keys(this.cache).length >= this.MAX_CACHE_SIZE) {
+      // 最も古いエントリを削除(簡易的な実装)
+      const firstKey = Object.keys(this.cache)[0]
+      delete this.cache[firstKey]
+    }
     this.cache[userId] = data
-    // TODO: キャッシュサイズ制限なし
   }

To-Be

[must] メモリリーク: キャッシュサイズ制限とクリア機能が必要です

現在の実装では無制限にデータが蓄積され、メモリリークを引き起こします。
LRUキャッシュまたはサイズ制限を実装することで、メモリ使用量を管理できます。

+  private readonly MAX_CACHE_SIZE = 1000;
+  private cacheOrder: string[] = [];
+
+  public cacheUserData(userId: string, data: any): void {
+    if (this.cacheOrder.length >= this.MAX_CACHE_SIZE) {
+      const oldestKey = this.cacheOrder.shift();
+      if (oldestKey) {
+        delete this.cache[oldestKey];
+      }
+    }
+    const existingIndex = this.cacheOrder.indexOf(userId);
+    if (existingIndex > -1) {
+      this.cacheOrder.splice(existingIndex, 1);
+    }
+    this.cache[userId] = data;
+    this.cacheOrder.push(userId);
+  }

自己採点: 100点

結果と考察

  • LLM-as-a-Judgeプロンプト適用後、PRコメント数は35件から24件に減少しました(!)
  • セルフチェック(自己採点)の記載が追加されており、内部的に自己採点を行っていることが伺えます(上記のコメント数減少からも)
  • 両方のパターンで、XSS脆弱性・非同期処理・メモリリークなど、重要な問題に対しては**具体的な修正案(コード例付き)**が提示されていました
  • 改善後のコメントは、修正案の提示に加えて「なぜ直すべきか」「どう直すか」の説明がより明確になり、コメントの体裁も統一されていました
  • 不要な指摘や好みの違いによるコメントが激減したかどうかは、今回の検証のコメント内容だけでは判断できませんでした。今後も継続して比較・検証していきたいと思います

まとめ

LLM-as-a-Judgeの考え方をプロンプトに落とし込むことで、
CodeRabbitのPRレビューは「本当に必要な対応」に絞られ、
優先度・具体性・学習価値・品質が大きく向上しました。

AIレビューを「ただの指摘者」から「成長を促す技術メンター」へ進化させたい方は、
ぜひプロンプト設計にこだわってみてください。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?