PR-Agent × Azure OpenAI API でコードレビューを自動化する

## はじめに
生成AIを活用して業務効率化をする取り組みの一環として、コードレビューの自動化に取り組みました。

私の職場ではソフトウェアエンジニアにMSDNアカウントが付与されており、Azureクレジットの範囲内でAzure OpenAIを実質無料で使えたため、Azure OpenAI APIが使えるコードレビューのサービスとしてPR-Agentを選択しました。
PR-AgentとAzure OpenAI APIというワードで検索すると、QiitaやZenなどで数件ヒットするものの、内容の通りに実装しても動かない…ということがありましたので、備忘録として残しておきます。

:::note warn
この記事は2024年3月末時点の情報です。
PR-Agentが動作しないようであれば、より最新の記事を参照したり、PR-Agentの公式ドキュメントを読むことをおすすめします。
:::


## 課題
今回解決したい課題は、以下の1点です。
- 実装からレビューされるまでのタイムラグをなくす

実装者（レビューイ）が実装を完了して、いざレビューしてもらうときに、いくつかの要因（レビューア側が優先度の高い他のタスクを抱えている、修正量が多くてすぐにはレビューできない）によって、実装者にすぐフィードバックできないことがあります。
実装してからレビューされるまでの期間が長いと、レビューイは実装の細かいところを忘れてしまうので、有意義なフィードバックになりづらかったり、トータルのコストがかかってしまいます。

![review.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3722996/e7720770-5c1c-c0f9-705e-9194cff01c71.png)

## 解決方法
課題を解決するために、初回レビューを生成AIに任せる方法をとりました。
- GitHub ActionsでPR-Agentを動かし、初回レビューを自動化する
- PR-AgentのAPIにAzure OpenAI APIを使用する

![review2.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3722996/22370729-a201-92f8-2285-8c03cec01e7e.png)

## 設定方法
1. Azure OpenAIを作成し、使用したいモデルのデプロイを作成する
2. Azure OpenAI API まわりの設定値をsecretsに追加する
3. リポジトリに`.github/workflows/*.yaml`を追加する

### Azure OpenAIを作成し、使用したいモデルのデプロイを作成する
1. Azureにログインし、Microsoft Formsから、Azure OpenAI Serviceを有効にする
2. Azure OpenAI Serviceインスタンスを生成し、デプロイを作成する

### Azure OpenAI API まわりの設定値をsecrets、variablesに追加する
アカウント、もしくはリポジトリのSecrets and variablesに以下を格納します。
- APIキー
- APIのbase URL
- デプロイ名
- モデル名（`gpt-4-1106-preview`など）
- APIバージョン（`2023-05-15`など）

### リポジトリに`.github/workflows/code-review.yaml`を追加する
ファイル名はなんでもよいです。今回は`code-review.yaml`としました。

```yaml
name: Code Review

permissions:
  issues: write
  pull-requests: write

on:
  pull_request:
    types:
      - opened
      - ready_for_review
      - reopened
  issue_comment:
    types:
      - created
      - edited

jobs:
  review:
    runs-on: ubuntu-latest
    timeout-minutes: 15
    name: Run pr agent on every pull request
    if: ${{ github.event.sender.type != 'Bot' }}
    env:
      COMMON_INSTRUCTIONS: >-
        日本語を使用してください。
        あなたは [言語] や [フレームワーク] に精通したプログラマーです。
        渡されたコードについて改善点を見つけ、変更する理由を説明した上で、変更後のコード例を示してください。
        あなたが提案するコード（Suggestion Change）には、適切にインデントを含めるようにしてください。
        [コード規約] に従ってください。
        改善点がない場合には絶対にコメントをしないでください。

        特に以下の点を指摘してください:
          - 誤解を招いたり、実態を正確に表していない命名があるか
          - 適度に変数を定義し自己ドキュメントされているか
          - 冗長な書き方のコードがないか
          - ファイル内で @var のようなインスタンス変数しか定義していないのに var のような変数名を使っていないか、またはその逆
          - N+1問題（N+1 query problem）を引き起こす箇所
          - 読んで理解が難しい箇所にコメントが適切にされているか
          - コメントの内容は日本語として読んでわかりやすく、簡潔に説明できているか
          - 理解の難しい複雑な条件式が作られていないか
          - 新しいメソッドを定義したときにテストコードを書いているか
          - テスト内の説明文は、テストの内容をわかりやすく適切に表しているか
          - 明らかなセキュリティの問題があるか

        誰にとっても読みやすいコードになるよう、改善点を見つけたら積極的にレビューしてください。
        あなたに渡されるコードは一部分であるため、未定義のメソッドやクラスなどの指摘については消極的にしてください。
    steps:
      - name: PR Agent action step
        id: pragent
        uses: Codium-ai/pr-agent@main
        env:
          OPENAI_KEY: ${{ secrets.AZURE_OPENAI_API_KEY }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          OPENAI.API_TYPE: 'azure'
          OPENAI.API_VERSION: ${{ vars.AZURE_API_VERSION }}
          OPENAI.API_BASE: ${{ vars.AZURE_API_BASE }}
          OPENAI.DEPLOYMENT_ID: ${{ vars.AZURE_API_DEPLOYMENT_ID }}
          CONFIG.MODEL_TURBO: ${{ vars.AZURE_API_MODEL }}
          CONFIG.AI_TIMEOUT: 600
          github_action_config.auto_describe: false
          github_action_config.auto_review: false
          github_action_config.auto_improve: true
          pr_description.extra_instructions: ${{ env.COMMON_INSTRUCTIONS }}
          pr_reviewer.extra_instructions: ${{ env.COMMON_INSTRUCTIONS }}
          pr_code_suggestions.extra_instructions: ${{ env.COMMON_INSTRUCTIONS }}
          pr_code_suggestions.summarize: false
          pr_code_suggestions.max_context_tokens: 128000
          pr_code_suggestions.num_code_suggestions: 10

```
- `COMMON_INSTRUCTIONS`には、Azure OpenAI APIにわたすプロンプトを指定しています
- 今回はPull Request作成時にコード提案のみしてほしかったので、`github_action_config.auto_improve`のみtrueにしています

## 結果
試しに、Laravelで簡単なHello, worldを実装したコードをレビューさせてみました。
「ルーティングに直接記述するんじゃなくて、ちゃんとMVCモデルを使おうね」みたいなレビューが返ってきました。
![スクリーンショット 2024-04-01 013427.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3722996/e991c843-abb7-84fe-630a-6e520bd7d878.png)

## おわりに
以下のような指摘・提案をしてくれました。
静的解析ツール+αくらいの利便性はありそうです。
- タイポ
- 抽象的すぎる名前付け
- コーディング規約に則った指摘
- 例外処理不足

ただ、生成AIの提案を鵜呑みにするのではなく、提案を受けて自分で考えて判断する必要があります。（言語やフレームワークの理解に繋がるので、レビューイとしてはむしろありがたいかも）
提案文はまともなことを言っているが、肝心のコード提案が微妙、なんてことは結構ありました。

余談になりますが、実際にやってみた中で一番苦労したことは、プロンプトの日本語化でした。
最初はGPT3.5を使っていたのですが、なにをやっても日本語化されませんでした。
どうやらGPT3.5を使う場合はプロンプトが効かないみたいです。

## 参考
[PR-Agent を使用してプルリクを AI で自動レビューする](https://zenn.dev/taroshun32/articles/pr-agent-pull-request-ai-review)
[PR-Agent を使って Pull Request をAIレビューしてみた。（日本語対応もしてみた）](https://tech.layerx.co.jp/entry/2023/09/01/102612)