PR-Agentを活用したdbtのコードレビュー自動化

こんにちは、株式会社CARTA MARKETING FIRMのVP of Dataの @pei0804 です。

CARTA MARKETING FIRMのデータ基盤Vision では、DataOpsを推進しています。DataOpsとは、データ分析やAI/ML開発のライフサイクル全体を最適化し、品質と速度を向上させるプラクティスです。

speakerdeck.com

弊社の考えるDataOpsが実現されている世界観は、「利用者は価値創出に集中でき、基盤チームは仕組み作りに集中できる状態である。」です。

過去に発表した資料があるので、直近どういう取り組みをしているのか興味がある方は、こちらのスライドを御覧ください。 引用: 中央集権体制からDataOpsへの転換 / centralized-to-dataops-transformation - Speaker Deck

この世界観を実現するには、データ基盤の開発者が全てのPull Request(以下PR)に目を通さないといけない状態や、データ基盤の利用者が都度基盤開発者に問い合わせなければいけない状態をなくしていく必要があります。

こういった課題に、PR-Agentが非常に役に立つ場面があったので、今回はそれについてシェアします。

PR-Agentとは

pr-agent-docs.codium.ai

PR-Agentは、PRを効率的にレビューし処理するためのオープンソースツールで、GitHub Actionsを利用して自動的にコードレビューを行えます。

OpenAIのGPTモデルを活用し、人間のレビュアーがよくチェックする項目を自動的に確認します。

GPTモデルは自然言語処理に優れており、単純なルールベースのチェックよりも柔軟で洞察力のあるレビューが可能です。

解決したかった問題

dbt_project_evaluator や様々なCIでのチェック等ではカバーしきれないような考慮事項です。

具体的には、「コードの変更内容としては正常。しかし、意図していない場合に事故になる可能性がある。」ケースです。

例えば、データモデルのマテリアライゼーションをincrementalから別のものに変更するパターンです。

incrementalからtableやviewに変更が行われると、元々の積み上げられていたテーブルはdropされ、同じ名前でtableまたはviewが作成されます。ケースによっては正常な操作かもしれませんが、意図してない破壊的変更の場合には事故に繋がります。

破壊的変更を意図してますか?という問いかけをするのに、PR-Agentが役立ちました。

コード

実際に解決したPR-AgentのGitHubActionは以下の通りです。

name: pr-agent

on:
  pull_request:
    types: [opened, reopened, synchronize]
  issue_comment:
    types: [created, edited]
  workflow_dispatch:

permissions:
  pull-requests: write

jobs:
  pr_agent:
    runs-on: ubuntu-latest
    name: PR-Agentによるレビュー
    if: ${{ github.event.sender.type != 'Bot' }}
    steps:
      - id: pr-agent
        uses: Codium-ai/pr-agent@609fa266cf833b6199dab8ed3fa1e0344f42b290
        env:
          OPENAI_KEY: ${{ secrets.OPENAI_API_KEY }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          config.model: 'gpt-4o'

          github_action_config.auto_describe: true
          pr_description.inline_file_summary: true
          pr_description.use_description_markers: true
          pr_description.publish_labels: false
          pr_description.extra_instructions: >-
            説明はすべて日本語で記述してください。
            タイトルには、以下のようなcommitlintパターンの接頭辞をつけてください:
            `feat:`、`chore:`、`test:`、`fix:`、`ci:`、`docs:` など

            例:
            - feat: 新機能の追加
            - fix: バグの修正
            - docs: ドキュメントの更新
            - chore: 定期的なメンテナンス作業
            - test: テストの追加や修正
            - ci: CI設定の変更

            これらの接頭辞を使用することで、変更の種類が一目でわかるようになります。
            適切な接頭辞を選択し、その後に具体的な変更内容を簡潔に記述してください。

            また、「変更内容の詳細」セクションでは、各ファイルの変更点を簡潔かつ分かりやすく説明し、
            重要な変更や潜在的な影響を強調してください。
            技術的な専門用語は必要に応じて使用しますが、できるだけ平易な日本語で説明するよう心がけてください。
          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
          pr_reviewer.extra_instructions: >-
            すべての説明、コメント、フィードバックは日本語で記述してください。

          github_action_config.auto_improve: true
          pr_code_suggestions.extra_instructions: >-
            すべての説明、コメント、フィードバックは日本語で記述してください。
            SQLファイル形式のdbt(Data Build Tool)設定を以下の観点でレビューしてください:
            1. マテリアライゼーションの変更:
              - `{{ config(materialized='incremental') }}`から他の種類への変更を特定してください。
              - 変更が見つかった場合、次のようにコメントしてください:「このモデルのマテリアライゼーションが'incremental'から変更されています。データ損失の可能性があります。この変更が意図的かどうか確認してください。」
            2. 動的テーブルの設定:
              - `{{ config(materialized='dynamic_table') }}`に対して、`target_lag`パラメータに`set_dynamic_table_lag()`が使用されていることを確認してください。
              - 使用されていない場合、次のようにコメントしてください:「dynamic_tableマテリアライゼーションでは、target_lagパラメータにset_dynamic_table_lag()関数を使用する必要があります。これは正しい機能のために必須の設定です。」
            3. Snowflakeウェアハウスの変更:
              - `{{ config(snowflake_warehouse='...') }}`が新しく設定されているか、変更されているかを確認してください。
              - 変更が見つかった場合、次のようにコメントしてください:「snowflake_warehouseパラメータが変更されています。以下のコマンドを使用して、このモデルのパフォーマンスを検証してください:`make build SELECT=+{対象のモデル名} TARGET=dev_d`」
            4. 命名の正確性:
              - モデル名とカラム名のタイポを注意深く確認してください。
              - 疑わしい名前が見つかった場合、次のようにコメントしてください:「'{疑わしい名前}'が正しいモデル名/カラム名かどうか確認してください。タイポは重大な問題を引き起こす可能性があります。」
            各点について包括的なフィードバックを提供し、潜在的な問題を強調し、必要な対応策を推奨してください。
            すべてのフィードバックとコメントは日本語で提供することを忘れずに。

この設定で重要なのは、以下の3つの要素です。

  1. pr_description: PRの説明を自動生成します。
  2. pr_reviewer: PRの全体的なレビューを行います。
  3. pr_code_suggestions: コードの具体的な改善案を提示します。

危険な変更をしている可能性を指摘する

pr_code_suggestions.extra_instructions の部分。

dbtの内部の実装にある程度詳しい方であれば、例えばマテリアライゼーションを、incremental から view に変えるのは危険であるということは分かると思います。

しかし、様々なレベル感のユーザーが触るという環境下では、これらの操作が危険であると承知せずに行われる可能性がありますし、弊社では実際に起きました。

危険レベルでいうと高くはないですが、地味にtypoのチェックも大事で、カラム名やモデル名のtypoは後々面倒なことに繋がりかねないので、「これtypoじゃない?」って一応確認を取るようにしています。

こういった変更内容としては正常に動くコードだけど、実は意図してない操作をしてないかを、一度立ち止まって考えさせるというのをPR-Agentにさせています。

これを入れるだけで、回避できるリスクは恐らく数多くあるはずで、またこれらのリスクにいちいちスクリプト組んでチェックするよりは、さくっとプロンプト組んで対策できるのがPR-Agentの魅力です。

レビューの観点については、あえて一般論にした

pr_reviewer.extra_instructions の部分。

ここはあえて多くのプロンプトを含めていません。 これはリポジトリの設計次第ですが、弊社のVisionのリポジトリはモノレポになっているので、dbt以外にもSnowflakeを管理しているTerraformから、データパイプライン周りのCDKのコードまで様々あります。

何度か実験して分かったのですが、pr_reviewer.extra_instructionsにdbtのことを書きすぎると、Terraformしか変更されてなくても ⚡ Key issues to review にはdbtに関するレビュー観点が出てきてノイズになっていたからです。

そこで、レビューの観点に関しては、PR-Agentが想定している普遍的な観点に任せることにしましたし、実際それで十分という状況になっています。

これにより、リポジトリ内の多様なコードに対して、より柔軟で適切なレビューが可能になっています。

PRの説明をこれまで人力でやっていたものをAIに任せる

pr_description.extra_instructions

これまでは、以下のフォーマットでPRの作成をしていました。

## issueのリンク

- issueリンク

## やったこと

<!-- つまり何をしたかを書く -->

## なぜこの変更が必要なのか

<!-- なぜを端的に説明すると? -->

## レビューしてほしいポイント

<!-- 何を見てほしくてレビュー依頼してますか?-->

PR-Agentが導入されてからは、機械的に判断できる「やったこと」については任せるスタイルになりました。これにより、人によって書いている内容にブレがあったところの品質が一定になったのと、単純に作業的な内容だったので、楽ができるようになったことが良かったです。

新しいフォーマットは以下のようになりました。

## issueのリンク

- issueリンク

## なぜこの変更が必要なのか

<!-- なぜを端的に説明すると? -->

## レビューしてほしいポイント

<!-- 何を見てほしくてレビュー依頼してますか?-->

## やったこと

<!-- この項目はPullRequestがOpenされると、AIが入力するので、そのままにしてください。 -->

pr_agent:summary

### 変更内容の詳細

<!-- この項目はPullRequestがOpenされると、AIが入力するので、そのままにしてください。 -->

pr_agent:walkthrough

ただし、「なぜこの変更が必要なのか」と「レビューしてほしいポイント」は依然として人間が記入する項目としています。 これは、変更の背景にある文脈や、特に注意を払ってほしい箇所といった部分には、開発者に意識して書いてほしいというのもあります。

将来的には、issueから背景を抽出すれば、AIに任せれるとかもありそうですが、それは今後考えたいところです。

日本語でのレビュー

地味に大事な日本語でのレビュー。

プロンプトを最初は、英語で指示を書いていたのですが、そうするとかなりの確率で英語で回答してくるという現象が発生しました。

そこで、日本語で指示をしたところ、日本語で回答をしてくれる確率がかなり上がりました。 ですが、プロンプトが長くなると、また英語で回答してくるという状況に見舞われ、「ハンバーガー記法(勝手に名付けた)」で、日本語で書いてくださいという指示を本質のプロンプトの最初と最後に入れると、かなりの確率で日本語で回答してくれるようになりました。

※なぜ効果があるのかは解明できていないので、効果を実感できない可能性があります。

まとめ

DataOpsの実践において、色んなレベル感の人でも安心して開発する環境作りにPR-Agentは非常に強力です。

ちなみに、まだ変なコメントしてしまうケースもあります。ですが、少しずつ改善していきたいと思います。

皆様の組織でも、ぜひPR-Agentの導入を検討してみてはいかがでしょうか。効率的で品質の高いデータパイプライン管理に大いに貢献するはずです。

宣伝

今度DataOpsについて話をする予定なので、興味ある方は参加していただけると嬉しいです。

findy.connpass.com