生成AI でコードや記事をレビューする aictl を作り、ブログ記事をレビューしてもらうようにした

PR でレビューしてくれる編集者を持つ


Posted on Tue, Oct 1, 2024
Tags generative-ai, githubactions

生成AIを使ってブログ記事のレビューを自動化する方法

かれこれ 8年間ほどブログ記事を書いているが、個人で書き進めている関係上、誰かにレビューしてもらうことがない。 そのため、go-zen-chu/aictl を開発し、GitHub Actions で PR を出した記事に対してレビューをしてもらうようにする。

コードレビューを生成AIで行ってくれる製品や Copilot のようなツールはあるものの、ブログ記事をレビューしてもらうためのツールはあまりなさそうなのと、OpenAI のクライアントを利用すれば簡単に実現できそうだったので、自分の学習のためにも作ってみた。

導入方法

導入方法は go-zen-chu/aictl の README に記載しているが、

  1. 下記の yaml を .github/workflows/check-pr.yml に配置する
  2. repository の secret に AICTL_OPENAI_API_KEY を設定する
    1. API KEY については、API Reference - OpenAI API を確認

で導入は完了する(secrets.GITHUB_TOKEN が出てくるが、これは GitHub Actions 実行時にデフォルト存在するので設定不要)

name: check-pr
on:
  pull_request_target:
    types: [opened, synchronize]
jobs:
  aictl-review:
    runs-on: ubuntu-latest
    permissions:
      pull-requests: write
    steps:
      - name: Get number of commits for fetch depth
        run: echo "fetch_depth=$(( commits + 1 ))" >> $GITHUB_ENV
        env:
          commits: ${{ github.event.pull_request.commits }}
      - name: Git checkout until fetch-depth
        uses: actions/checkout@v4
        with:
          fetch-depth: ${{ env.fetch_depth }}
          # need to specify ref to fetch PR head, otherwise you get main branch with no HEAD
          ref: ${{ github.event.pull_request.head.sha }}
      - name: Fetch base branch as origin
        run: git fetch origin ${{ github.event.pull_request.base.ref }}
      - name: Get the diff between PR and origin branch and get commit message too
        id: git-diff
        run: |
          # If fetch-depth is not specified in checkout, HEAD cannot be found
          # Make sure to filter out deleted file in `git diff` since you cannot review deleted files
          diff_files=$(git diff --name-only --diff-filter=ACMR origin/${{ github.event.pull_request.base.ref }}..HEAD | tr '\n' ',' | sed 's/,$/\n/')
          echo "diff_files: ${diff_files}"
          echo "diff-files=${diff_files}" >> "$GITHUB_OUTPUT"

          # In PR, you cannot get `github.event.head_commit.message` so you need to get commit message via git log
          commit_msg=$(git log --format=%B -n 1 ${{ github.event.pull_request.head.sha }})
          echo "commit_msg: ${commit_msg}"
          echo "commit-msg=${commit_msg}" >> "$GITHUB_OUTPUT"           
      - name: Run aictl for code review
        id: aictl-review
        uses: go-zen-chu/aictl@main
        if: ${{ steps.git-diff.outputs.diff-files != '' && !contains(steps.git-diff.outputs.commit-msg, '[skip ai]') }}
        with:
          query: |
            Markdown ファイルはプログラミングなどの技術記事、ライフハック記事や書評などを記載しています。
            より読みやすく、多くの人に読んでもらえるようにする観点でレビューをお願いします。

            その他ファイルは、このブログシステム自体のソースコードになります。
            より良いブログシステムを構築できるように、コードの品質や保守性の観点でレビューをお願いします。            
          language: 日本語
          text-files: ${{ steps.git-diff.outputs.diff-files }}
        env:
          AICTL_OPENAI_API_KEY: ${{ secrets.AICTL_OPENAI_API_KEY }}
      - name: Post aictl review result to PR comment
        if: steps.aictl-review.outcome != 'skipped'
        run: |
          # make sure to checkout to pr branch and resolve detached HEAD state
          git checkout ${{ github.ref_name }}
          # TIPS: surrounding with single quote, you can ignore `code` string in outputs
          cat <<'AICTL_REVIEW_EOF' > response.md
          ${{ steps.aictl-review.outputs.response }}
          AICTL_REVIEW_EOF
          gh pr comment --body-file response.md "${URL}"          
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          URL: ${{ github.event.pull_request.html_url }}

実行結果

上記の説明をすると、

  1. PR 作成時や更新時に実行される
  2. PR で出しているコミットすべてを取得して、ファイルの差分を出す (git-diff)
  3. 2.の差分を aictl で生成AI に問い合わせる。query の内容は自由に決める
    • [skip ai] を commit メッセージに入れると、実行をスキップする
  4. aictl の出力内容を PR に出力する

という流れだ。

実際にこの記事の内容を PR レビューさせたものを画像として載せる。

結構、良いレビューがもらえているのではないだろうか。より詳細にレビューがほしければ、aictl-reviewquery でより具体的にレビューしてもらいたいポイントを指示するようにすればよい。

制限事項や今後の展望

現時点である程度実用的だが、これから aictl で実装していきたいものとして、下記が挙げられる。

  1. 現在は強制的に安いモデルの GPT-4o-Mini になっているので、モデルを自由に選択できるようにする
  2. 他の生成AIもサポートできるようにする(これは時間がかかりそう)
  3. Context を理解するために、過去の PR で出した内容を覚えられるようにする

今後、時間を見つけて開発していきたい所存だ。

Share with


See Also