はじめに
プログラミングを書き始めた頃は独りよがりなコードを書いていました。当然「可読性の高いコード」とは遥かに遠いコードを書いていました。
ただ、チームプロジェクトに飛び込んだ瞬間、状況は一変し自分のコードが他人の目に触れる現実と、読みづらいコードに悶絶する日々。この経験は誰しもがあるのではないかと思います。
では、可読性の高いコードを書くにはどうすれば良いのか?
を考え始めた時に出会ったのが リーダブルコード でした。
リーダブルコードは、コードを読みやすくするための原則を提唱しています。
この原則を守り、プロジェクト全体で共有することで、コードの可読性を向上させることができます。
が、現実はそう甘くありません。規約が完璧に反映されているコードレビューが実施されないプロジェクトも多いでしょう。
政治的な問題 や 納期の関係 もあり、一度実装されたコードの変更が難しいこともあります。
そこで、今回は「リーダブルコード」の原則を準拠したコードレビューをRAGによって自動化するツールを作成してみることにしました。
作ってみたもの
Slack経由でRAGにコードレビューをしてもらいます。
@Reviewer
とメンションすることで、コードレビューを依頼することができます。
構成図
リーダブルコードとは
RAGの環境構築に入る前に、リーダブルコードについて軽く概要を紹介したいと思います。
リーダブルコード、それはまさにその名の通り「読みやすいコード」を意味します。しかし、ここで言う「読みやすい」とは単に面白いわけではなく、基本を守りつつ他の人にも理解しやすいコードを指します。このアプローチの根底にあるのは、「コードは理解しやすくなければならない」という原則になります。
では、「理解しやすいコード」とはどんな特徴を持つのでしょうか?
- 変更が容易:他の人、または未来のあなたが見たときに、「これは何だったんだろう?」と頭を抱えることなく、簡単に修正や改善ができる。
- 可読性が高い:バグが潜んでいても見つけやすい。清潔で整理された部屋で物を探すようなイメージ。
このようなコードを書くことは、チームにとってのみならず、未来のあなた自身にとっても大きな恩恵をもたらします。継続的に改善し、磨きをかけることで、コードは時を経てもその価値を保ち続けます。
と、私の解釈を交えつつ説明してみました。
コードレビューについて
リーダブルコードの原則の数々の中から、今回は「第Ⅰ部 表面上の改善 第2章 名前に情報を詰め込む」に焦点を当ててコードレビューをしてもらおうと思います。
この章では、変数名がいかに重要であるか、そしてそれにどのように情報を詰め込むかが解説されています。
以下にこの章の原則をまとめたPDFファイルを作成しましたので、これをデータソースとして使用します。
[第Ⅰ部][2章]表面上の改善_名前に情報を詰め込む.pdf
この原則を実践するには、変数名が適切な情報を含んでいるかを確認することが重要です。
そのための方法として、ペアプログラミング や 人によるコードレビュー が挙げられますが、
これらは知識の共有を促し、プロジェクトにおける属人化を防ぎますが、人の目によるチェックには限界 があります。
そこで登場するのが、静的解析ツールの活用です。
特にJavaScriptで人気のある ESLint は、カスタムルールを設定することで、変数名の命名規約や長さをチェックするのに役立ちます。
しかし、変数名の内容自体の精査には限界 があるため、さらに進んだ技術が求められます。
これらの問題を解決するために、AIを利用したコードレビュー が注目されています。
Code Rabbit のようなコードレビューAIを導入することで、従来の人力レビューの限界を超え、コーディング規約に基づく自動的なチェックが可能になります。
そして RAG(Retrieval-Augmented Generation) を活用すれば、リーダブルコードの原則をデータソースとして取り込み、より精密なレビューを実施することができそうです。
RAGにコーディング規約を読み込ませ、原則に違反があるかどうかをAIがチェックし、その結果をさらにLLM(大規模言語モデル)が分析する。
この一連の流れを 「Slack経由でRAGにコードレビューを依頼してみよう」 と思い実装してみました。
RAG構築
では、実際にRAGを構築していきます。
「AWS SAM」でRAGを構築するために以下のリポジトリを作成しましたが、今回は AWSマネジメントコンソールから手動で構築 する手順を説明します。
「AWS SAM」での構築方法については、以下の記事で説明しています。
全ての手順は「東京リージョン」で実施することを前提としているため、AWSのマネジメントコンソールからリージョンを「東京」に変更してから手順を進めてください。
注意
環境構築後は、必ずリソースの削除を行ってください。
リソースが残っていると課金が発生します。
特にKendraは高額な課金が発生するため、削除を忘れないようにしてください。
S3
Kendraのデータソースとして使用するS3バケットを作成します。
S3バケットを作成する
-
S3コンソールに移動して「バケットを作成」をクリックします。
-
バケット名を入力します。
バケット名はリージョン内で一意である必要があるため、
data-source-bucket-{ランダムな文字列}
という形式でバケット名を入力しています。 -
その他の項目はデフォルトのまま「バケットを作成」をクリックします。
S3バケットにファイルをアップロードする
-
以下のリンクからPDFファイルをダウンロードします。
[第Ⅰ部][2章]表面上の改善_名前に情報を詰め込む.pdf
ダウンロードアイコンをクリックしてPDFファイルをダウンロードします。
-
作成したバケットを選択します。
-
「アップロード」をクリックします。
-
PDFファイルを画面にドラッグ&ドロップして、アップロード対象のファイルに追加します。
-
「アップロード」をクリックします。
-
アップロードが完了したら、「閉じる」をクリックします。
Amazon Kendra
RAGの検索エンジンとして使用するKendraを作成します。
Kendraを使用するには「インデックス」と「データソース」を作成する必要があります。
インデックスの作成
-
Kendraコンソールに移動します。
-
「Create an index(インデックスの作成)」をクリックします。
-
Index name(インデックス名)を入力します。
インデックス名は
readable-code-index
と入力します。 -
IAM role(IAMロール)を選択します。
IAMロールは推奨設定で新規作成するため「Create a new role(Recommended)」を選択します。
IAMロール名はAmazonKendra-ap-northeast-1-readable-code-index-role
と入力し、「Next」をクリックします。 -
アクセスコントロールの設定はデフォルトのまま「Next」をクリックします。
-
エディションは「Developer edition」を選択して、「Next」をクリックします。
-
確認画面で「Create」をクリックして、インデックスを作成します。
30秒後に自動でKendraのホーム画面に戻ります。
インデックスの作成には最大30分かかるため、しばらく待ちます。
作成が完了すると、インデックスが Active になります。
データソースの作成
-
作成したインデックスを選択し、「Add data source(データソースの追加)」をクリックします。
-
Amazon S3 connector の「Add connector」をクリックします。
-
Data source name(データソース名)を入力します。
データソース名には
readable-code-data-source
と入力します。 -
ドキュメントのデフォルト言語は「Japanese(ja)」を選択します。
-
IAMロールを選択します。
IAMロールは推奨設定で新規作成するため「Create a new role(Recommended)」を選択します。
IAMロール名はAmazonKendra-readable-code-data-source-role
と入力し、「Next」をクリックします。 -
同期するデータソースの設定を行います。
Browse S3 からデータソース用に作成したS3バケットを選択します。
-
手動でデータソースの同期を行うため、Frequency(頻度)は「On demand」を選択します。
-
Set field mappings - optional はデフォルトのまま「Next」をクリックします。
-
Review and create で「Add data source」をクリックします。
30秒後に自動でKendraのホーム画面に戻ります。
データソースの作成に成功しました。
-
データソースを同期するために、「Sync now」をクリックします。
同期完了まで時間がかかるため、しばらく待ちます。
同期が完了しました。
Bedrock
RAGのLLMとして、東京リージョンのBedrockにあるAnthropic社の Claude を使用します。BedrockのLLMを使用するには モデルアクセスを有効化 する必要があります。
現在、東京リージョンで利用可能なClaudeのバージョンはv2.1となっています。
モデルアクセスの有効化
東京リージョンでBedrockを使用するために、モデルアクセスを有効化します。
-
Bedrockコンソールに移動して「モデルアクセス」を選択します。
-
Anthropic社のモデルを使用するには「ユースケースの詳細」を提出する必要があるため、「ユースケースの詳細」をクリックします。
-
ユースケースの詳細を入力して、「送信」をクリックします
-
「モデルアクセスを管理」をクリックします
-
「Claude」にチェックを入れて、「モデルアクセスをリクエスト」をクリックします。
-
アクセスが付与されたことを確認します。
Lambda
Slack経由でRAGにコードレビューを依頼するLambda関数を作成します。
IAMロールを作成する
-
IAMコンソールに移動して「ロールの作成」をクリックします。
-
エンティティは「AWSのサービス」を選択します。
-
ユースケースは「Lambda」を選択します。
-
許可を追加します。
追加するポリシーは以下の通りです。
- BedrockFullAccess: Bedrockの全ての機能にアクセスするためのポリシー
- AmazonKendraFullAccess: Amazon Kendraの全ての機能にアクセスするためのポリシー
- LambdaBasicExecutionRole: Lambda関数を実行するためのポリシー
-
ロール名を入力します。
ロール名は
review-readable-code-function-role
と入力します。 -
「ロールの作成」をクリックします。
Lambda関数を作成する
-
Lambdaコンソールに移動して「関数の作成」をクリックします。
-
関数の基本的な情報を入力します。
-
関数名:
review-readable-code-function
- ランタイム: Python 3.10
- アーキテクチャ: x86_64
先ほど作成したIAMロールを選択します。
-
関数名:
-
関数URLを有効化します。
- 関数 URL を有効化: チェックを入れる
- 認証タイプ: NONE
-
「関数の作成」をクリックします。
-
タイムアウトを変更する
デフォルトのタイムアウトは「3秒」となっており、処理完了までの時間が足りないため、タイムアウトを「3分」に変更します。
設定 → 一般設定 の「編集」をクリックします。
タイムアウトを「3分」に変更し、「保存」をクリックします。
レイヤーを作成する
Lambda関数からLangChainなどのライブラリを使用するには、レイヤーを作成してライブラリを追加する必要があります。
以下の記事を参考にして、使用するライブラリをレイヤー化してLambda関数に追加する手順を説明します。
レイヤーにライブラリをアップロードするには、ライブラリをまとめたZipファイルを「直接レイヤーにアップロード」するか、または「S3バケットを介してアップロード」する必要があります。
「直接アップロード」する場合、ファイルサイズは「50MB以下」でなければなりません。今回のライブラリが50MBを超えているため、「S3バケットを介してアップロード」する方法を選択します。
Zipファイルの作成環境によっては、Lambdaでレイヤーを使用する際にエラーが発生することがあるため、環境起因のエラーを防ぐ目的で Cloud9環境 でZipファイルを作成します。
-
ライブラリをまとめたZipファイルを置くためのS3バケットを作成する
S3コンソールにアクセスして、「バケットを作成」をクリックします。
バケット名は
lambda-layer-modules-{ランダムな文字列}
と入力します。その他の項目はデフォルトのまま「バケットを作成」をクリックします。
-
Cloud9環境を構築する
Cloud9コンソールにアクセスして、「環境を作成」をクリックします。
名前は
create-layer-modules
として、「新しいEC2インスタンス」を選択します。インスタンスタイプは
t2.micro
を選択し、プラットフォームは「Amazon Linux 2023」を選択します。「作成」をクリックします。
-
Zipファイルを作成する
作成した環境を選択し、「Cloud9 で開く」を選択します。
Cloud9のターミナルにて、以下のコマンドを実行して pip を使えるようにします。
# ライブラリを保管するディレクトリを作成 mkdir tmp-python cd tmp-python # zip 化に必要なツールをインストール sudo yum -y install bzip2-devel xz-devel # pyenv を clone git clone https://github.com/pyenv/pyenv.git ~/.pyenv # pyenv の PATH を通す vi ~/.bashrc # vi でファイルが開かれるので、 I key で INSERT mode に変更。以下を追記する export PATH="$HOME/.pyenv/bin:$PATH" eval "$(pyenv init -)" # 完了したら、ESC key で INSERT mode を終了 # :wq! で保存して終了 # .bashrc の変更を現在のターミナルに適用する source ~/.bashrc # Python 3.10.14 を Install pyenv install 3.10.14 # pyenv で現環境に設定 pyenv global 3.10.14 python -V
以下のコマンドを実行して、ライブラリをインストールします。
pip install --upgrade pip mkdir python pip install langchain==0.1.16 langchain-community==0.0.36 langchain_aws==0.1.2 slack_bolt==1.18.1 -t ./python
以下のコマンドを実行して、Zipファイルを作成します。
zip -r python.zip python/
以下のコマンドを実行して、先ほど作成したS3バケットにZipファイルをアップロードします。
aws s3 cp python.zip s3://{バケット名}
注意
アップロードが完了したら、Cloud9は削除します。
リソースが残っていると課金が発生します。
: -
レイヤーを作成する
Lambdaコンソールに移動し、レイヤーから「レイヤーの作成」をクリックする。
レイヤーの名前は
Layers
を入力する。「Amazon S3 からファイルをアップロードする」を選択します。
S3バケットからアップロードしたZipファイルを選択し、「URLをコピー」をクリックします。
「Amazon S3 からファイルをアップロードする」にコピーしたURLを貼り付けます。
アーキテクチャは「x86_64」を選択し、ランタイムは「Python 3.10」を選択します。
「作成」をクリックすると、レイヤーが作成されます。
レイヤーが作成されました。
コードを実装する
-
関数にレイヤーを関連付けます
Lambdaコンソールに移動し、作成したLambda関数の「レイヤー」から「レイヤーの追加」をクリックします。
「カスタムレイヤー」を選択し、作成したレイヤーを選択して、「追加」をクリックします。
-
以下のコードをコピペして、Lambda関数に貼り付けて、「Deploy」をクリックします。
https://github.com/sakes9/sam-slack-review-rag/blob/main/src/app.py
-
環境変数を設定します。
Kendraコンソールに移動し、作成したインデックスのIDをコピーします。
Lambdaコンソールに戻り、環境変数の「編集」をクリックします。
「環境変数の追加」をクリックします。
環境変数を追加して、「保存」をクリックします。
キー 値 KENDRA_INDEX_ID {KendraのインデックスID}
Slack
Slack経由でRAGにコードレビューを依頼するために、Slackアプリを作成します。
Slackのワークスペースを作成する
既存のワークスペースを使用するか、新規でワークスペースを作成してください。
私は RAG
というワークスペースを作成しています。
アプリを作成する
-
Slack API にアクセスして、「Your apps」をクリックします。
-
アプリを作成する
「Create an App」をクリックします。
「From scratch」を選択する
App Name(アプリ名)は
Reviewer
と入力し、作成したワークスペースを選択し、「Create App」をクリックします。 -
アプリのBot権限を追加する
OAuth & Permissions を選択します。
Scopes の 「Add an OAuth Scope」をクリックします。
メンションメッセージを読み取り、レスポンスを返すための権限を追加する
- app_mentions:read
- channels:read
- chat:write
-
ワークスペースにアプリをインストールする
OAuth & Permissions の OAuth Tokens for Your Workspace にある Install to Workspace をクリックします。
許可するをクリックします。
Lambda環境変数にSlackアプリの情報を設定
-
OAuth & Permissions にある Bot User OAuth Token をメモしておきます。
-
Basic Information にある Signing Secret をメモしておきます。
-
Lambdaの環境変数に以下のキーと値を設定します。
キー 値 SLACK_BOT_TOKEN {Bot User OAuth Token} SLACK_SIGNING_SECRET {Signing Secret}
メンション時のイベントを設定する
-
Slack API から「Event Subscriptions」を選択して、Enable Events を ON にします。
-
Lambdaの関数URLをコピーします。
-
Request URL にコピーした関数URLを貼り付けます。
一度目の検証で失敗するが、Retryしたら2回目で成功する(理由はわからない)
検証に成功すると Verified にチェックがつきます。
-
「Subscribe to bot events」の Add Bot User Event をクリックします。
-
「app_mention」を追加します。
動作検証
-
Slack にアクセスします
-
Slack App をインストールしたワークスペースを開きます
-
チャンネルを作成します
私はreview
というプライベートチャンネルを作成しました。 -
Slack Appを招待します
@Reviewer
をメンションして、Slack App を招待します。「招待する」をクリックします。
Slack App がチャンネルに招待されました。
招待時の初回メッセージに対するレスポンスは無視してください。
-
レビュー依頼を出します
@Reviewer
をメンションして、コードをレビューしてもらうために、以下のメッセージを送信すると、レビューが開始されます。@Reviewer for (var i = 0; i < clubs.length; i++) { for (var j = 0; j < clubs[i].members.length; j++) { for (var k = 0; k < clubs[i].members[j].users.length; k++) { if (clubs[i].members[j].users[k].id === userId) { console.log(`${clubs[i].members[j].users[k].name} が所属しているクラブは ${clubs[i].name}`); } } } }
-
レビュー結果が返却されます
注意
環境構築後は、必ずリソースの削除を行ってください。
リソースが残っていると課金が発生します。
特にKendraは高額な課金が発生するため、削除を忘れないようにしてください。
まとめ
RAGを活用してSlack経由でコードレビューを依頼する方法を以前紹介しました。
今回の検証では期待通りの結果が得られたり、期待している結果とは少しズレた回答が得られたり、コードレビューの精度としてはまだまだ改善がありそうな感想です。おそらっく使用しているデータソースの質が十分でないことが原因だと思うので、実用的に使いたい場合は、データソースをさらに充実させることで、より高精度な結果が期待できると思います。
次回は、AWS SAMを使用してRAG環境を構築する手順についてご紹介したいと思います。
参考資料
- RAG構築
- Kendra作成
- Lambda レイヤー
- Slack連携