【PR-Agent】AIによる自動コードレビューを導入してみた

# 概要

開発を進める中で、検索APIの中で使用されているクエリが複雑化し、パフォーマンスが落ちる問題が起こりました。

このようなことを事前に見越して、予防するためにPR-Agentを導入したためその方法をまとめます。


# 実現したいこと

- PRを作成したときに、AIによる自動レビューが実施される
- Golang対応（goファイルに埋め込まれたSQLを読んでほしい）、できればSQLファイルも対応していると嬉しい
- 自然言語によるレビュー観点の指示が可能

### +α
- その他幅広い言語に対応できるとよりよい
- 価格が安い
- 新しいモデルを使用できる

# PR-Agentとは

PR-Agentは、AIによるフィードバックと提案を提供することで、プルリクエストの効率的なレビューと処理を支援することを目的としています。

https://github.com/qodo-ai/pr-agent

# PR-Agentの導入

PR-Agentの無料版は、パブリックリポジトリでの利用を主な対象としています。

プライベートリポジトリで無料版を使用する場合、自己ホスト型のPR-Agentを導入することで対応可能です。
また、OPENAIやAmazon Bedrock等が提供する各種モデルが利用できます。

## ソースコードは学習に利用されないのか

されないようです。

https://qodo-merge-docs.qodo.ai/faq/

> 
> **Q: Will you store my code? Are you using my code to train models?**
> 
> ### **Answer:[¶](https://qodo-merge-docs.qodo.ai/faq/#answer4)**
> 
> No. Qodo Merge strict privacy policy ensures that your code is not stored or used for training purposes.
> 
> For a detailed overview of our data privacy policy, please refer to [this link](https://qodo-merge-docs.qodo.ai/overview/data_privacy/)
> 
> Q: 私のコードは保存されますか？私のコードを使ってモデルをトレーニングするのですか？
> 
> Qodo Mergeの厳格なプライバシーポリシーにより、**お客様のコードがトレーニングの目的で保存または使用されることはありません。**
> Qodo Merge のプライバシーポリシーの詳細については、[こちら](https://qodo-merge-docs.qodo.ai/overview/data_privacy/)をご覧ください。
> 

https://qodo-merge-docs.qodo.ai/overview/data_privacy/#qodo-merge-chrome-extension

> 自己ホスト型PR-Agent
OpenAI（または他のLLMプロバイダ）のAPIキーを使用してPR-Agentをセルフホストする場合、それはあなたとプロバイダの間のものです。**コードデータをQodoサーバーに送信することはありません。**
> 

ということで、自己ホスト型を導入してみる。

ドキュメント:

https://qodo-merge-docs.qodo.ai/installation/#qodo-merge


## GitHub ActionsからBedrockを利用してAIレビュー

参考

https://inside.dmm.com/articles/introduce-pr-agent-to-monorepo/

https://docs.github.com/ja/actions/security-for-github-actions/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services#adding-the-identity-provider-to-aws

https://dev.classmethod.jp/articles/shuntaka-pr-agent-with-bedrock/


### 1. AWS への ID プロバイダーの追加

IDプロバイダにGitHub OIDC プロバイダーが存在しない場合は、追加する必要があります。

AWSコンソールで、IAM > IDプロバイダ > プロバイダの追加 へ遷移して以下のように入力します。

- プロバイダのタイプには`OpenID Connect` を選択
- プロバイダURLには `https://token.actions.githubusercontent.com` を指定
- 「対象者」には `sts.amazonaws.com` を指定([公式のアクション](https://github.com/aws-actions/configure-aws-credentials)を利用する場合)

![スクリーンショット 2025-03-19 12.00.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475547/c53a1992-5ffb-45db-8769-2ea2a7f0e02e.png)


### 2. ロールと信頼ポリシーの構成

`AWS_ACCOUNT_ID`や`GITHUB_OWNER`は適宜差し替えてください。

以下のようなポリシーを作成します。

```json

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "bedrock:InvokeModel",
                "bedrock:InvokeModelWithResponseStream"
            ],
            "Resource": [
                "arn:aws:bedrock:*::foundation-model/*",
                "arn:aws:bedrock:*:AWS_ACCOUNT_ID:inference-profile/*"
            ]
        }
    ]
}

```

上記のポリシーを割り当てたIAMロールを作成します。
また、信頼ポリシーは以下のように設定します。

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::AWS_ACCOUNT_ID:oidc-provider/token.actions.githubusercontent.com"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringEquals": {
                    "token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
                },
                "StringLike": {
                    "token.actions.githubusercontent.com:sub": "repo:GITHUB_OWNER/*"
                }
            }
        }
    ]
}

```




### 3. `.github/workflows/pr_agent.yml` を作成

作成したIAMロールのarnなどは、適宜githubのsecrets等に登録してください。

参考：

https://qodo-merge-docs.qodo.ai/usage-guide/changing_a_model/#amazon-bedrock

```yml
on:
  pull_request:
    types: [opened, reopened, ready_for_review]
  issue_comment:
jobs:
  pr_agent_job:
    # ボットによるコメントには反応しない、PRの説明文に"[ai-review]"が含まれている場合のみ実行
    if: ${{ github.event.sender.type != 'Bot' && contains(github.event.pull_request.body, '[ai-review]') }}
    runs-on: ubuntu-latest
    permissions:
      issues: write
      pull-requests: write
      contents: write
      id-token: write
    name: Run pr agent on every pull request, respond to user comments
    env: 
      REVIEW_INSTRUCTIONS: >-
        日本語を使用してください。
        以下に記載した観点からレビューを行ってください。
        ただし、改善点がなければ回答は不要です。
        クエリやgormが利用されている場合、以下2つの観点から改善提案してください。
        - クエリそのもののパフォーマンス改善
        - 検索対象テーブルにインデックスを追加すべきカラムがあるか
        その他ファイル対して、以下の観点でレビューしてください。
        - 命名は分かりやすく実態を表しているか
        - typo
        - 可読性
        - セキュリティ上の脆弱性がないか
        - トランザクションの貼り方が適切か
        - nilチェックが適切にされているか
        - 理解しにくい、または実装と命名が乖離している箇所があるか
        - 冗長なコードがないか
        - メソッド名・関数名だけで実装が理解しにくい場合、分かりやすい日本語でコメントされているか
        - ネストが深い（3以上）条件文などがないか
    steps:
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: ${{ secrets.AWS_ROLE_ARN_PR_REVIEW }}
          aws-region: us-east-1
      - name: PR Agent action step
        id: pragent
        uses: qodo-ai/pr-agent@main
        env:
          AWS.BEDROCK_REGION: us-east-1
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          litellm.drop_params: 'true'
          # 出力の詳細度    
          config.verbosity_level: 1 
          # レビューの労力見積もりを必須としない設定です
          pr_reviewer.require_estimate_effort_to_review: 'false'  
          # ファイル要約をインライン表示する設定が有効になっています
          pr_description.inline_file_summary: 'false'  
          # 説明マーカーの使用を無効化しています
          pr_description.use_description_markers: 'false'  
          # 「Generated by」ヘッダーの追加を無効化しています
          pr_description.include_generated_by_header: 'false'  
          # 最終更新メッセージの表示を無効化しています
          pr_description.final_update_message: 'false'  
          # ヘルプテキストの表示を無効化しています
          pr_description.enable_help_text: 'false'  
          # 自動レビュー機能を有効化しています
          github_action_config.auto_review: 'true'  
          # 自動説明生成機能を有効化しています
          github_action_config.auto_describe: 'false'  
          # 自動改善機能を有効化しています
          github_action_config.auto_improve: 'true'  
          # レビュワーには回答を日本語で行うよう指示しています
          pr_reviewer.extra_instructions: ${{ env.REVIEW_INSTRUCTIONS }}
          # コード提案のは回答を日本語で行うよう指示しています
          pr_code_suggestions.extra_instructions: ${{ env.REVIEW_INSTRUCTIONS }}
          # 対応モデルとmax_tokenの参考（https://github.com/qodo-ai/pr-agent/blob/main/pr_agent/algo/__init__.py）
          config.model: bedrock/us.anthropic.claude-3-5-haiku-20241022-v1:0
          config.model_turbo: bedrock/us.anthropic.claude-3-5-haiku-20241022-v1:0
          config.fallback_models: bedrock/us.anthropic.claude-3-5-haiku-20241022-v1:0
          config.custom_model_max_tokens: 100000


```

### 4. PRの説明文に[ai-review]文字列を入れる

PRの説明文に`[ai-review]`が含まれる場合のみ、自動レビューが実行されるようymlで設定したので、説明文テンプレートに`[ai-review]`を追加します。

変更の少ないPRや、レビューをスキップしたい場合は`[ai-review]`を消すことで対応できます。

この辺りの条件は運用しながら調整でいいかもしれませんが、なるべく使い方を覚えなくてもいいように設定するのが親切かと思います。

# 実際に動かしてみた

あえて品質の悪いコードをAIに生成させて、プルリクエストを作成してみます。

すると、以下のようにレビューやコード修正の提案をしてくれます。


![スクリーンショット 2025-03-25 21.21.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475547/85208e4d-823d-41b1-ba67-989d6679f87e.png)

![スクリーンショット 2025-03-25 21.22.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475547/7dda9b47-dc9e-41c4-ac86-d0693d287f53.png)

![スクリーンショット 2025-03-25 21.23.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475547/d4649f17-3bdc-450d-b664-4735da2c6582.png)



## Copilot コードレビューとの違い
Copilotの対応言語は以下の通り。PR-Agentはプロンプト次第でそれ以外も対応可能です。

(C#、Go、Java、JavaScript、Markdown、Python、Ruby、TypeScript)

[Copilot コード レビュー について](https://docs.github.com/ja/copilot/using-github-copilot/code-review/using-copilot-code-review#copilot-%E3%82%B3%E3%83%BC%E3%83%89-%E3%83%AC%E3%83%93%E3%83%A5%E3%83%BC-%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6)

Copilotコードレビューは、20250318時点ではプロンプトによる細かいレビュー観点の指示は一部ユーザー以外はできません。

[コーディング ガイドラインを使用した Copilot のレビューのカスタマイズ](https://docs.github.com/ja/copilot/using-github-copilot/code-review/using-copilot-code-review#%E3%82%B3%E3%83%BC%E3%83%87%E3%82%A3%E3%83%B3%E3%82%B0-%E3%82%AC%E3%82%A4%E3%83%89%E3%83%A9%E3%82%A4%E3%83%B3%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%97%E3%81%9F-copilot-%E3%81%AE%E3%83%AC%E3%83%93%E3%83%A5%E3%83%BC%E3%81%AE%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%9E%E3%82%A4%E3%82%BA)

## 料金

今回はClaude 3.5 Haikuを設定しており、以下の料金がかかります。
> 入力トークン 1,000 個あたりの価格0.0008 USD
> 1,000 出力トークンあたりの料金0.004 USD

https://aws.amazon.com/jp/bedrock/pricing/

参考までに、実験でo3-mini-2025-01-31を利用していたときは小さいPRで1レビューあたり0.03$前後かかりました。
同じPR内容だとClaude 3.5 Haikuの方が若干安くなると予想できます。

> $0.00110/1K input tokens
> $0.00440/1K output** tokens

https://openai.com/ja-JP/api/pricing/