設計書をマークダウンに変更したら生成AIと連携できるようになった件
この記事はリクルート ICT統括室 Advent Calendar 2023 2日目の記事です。
はじめに
こんにちは。ICT統括室 インフラソリューションユニットの内海です。社内向けWebシステムの開発・運用を担当しています。私が所属しているチームでは設計書をマークダウンに変更しました。これにより、生成AI(Graffer AI Studio)と連携できるようになり、開発業務の効率化が行えるようになったので、その内容を紹介させていただきます。(※)
※業務においては「リクルートAI活用指針」に基づいて生成AIを利用しています
なぜ設計書をマークダウンに変更したのか?
マークダウンに変更する前の設計書はWordやExcelで作成していました。WordやExcelを利用すると誰でも扱えるメリットがある一方、GitHub等で差分比較が行えないことや書式設定などが面倒というデメリットがありました。このデメリットを解消するため、設計書をマークダウンに変更しました。
マークダウンには以下のような特徴があり、前述のWordやExcelのデメリットを解消できます。
ドキュメントを簡単に素早く作成できる
GitHub等でプレビューや差分比較が可能
Mermaidを利用すれば図を描くことが可能
マークダウンの書式さえ覚えてしまえば簡単にドキュメントを作成することができるようになります。何よりも、生成AIのインプットやアウトプットとして利用できるようになることが一番のメリットです。
生成AIとどう連携できるか?
設計書をマークダウンに変更したことにより、設計書を生成AIにインプットとして与え、その内容に沿ったソースコードを生成させることが可能です。また、ソースコードから設計書を生成させることも可能なため、設計書とソースコードの相互変換が行えます。これにより、設計書とソースコードのどちらか一方を作成すればもう一方は生成AIに生成させることができるようになったため、業務の効率化に繋がりました。
やってみよう
実際にソースコードから設計書への変換をやってみたいと思います。
手元に以前作成したKaggleのチュートリアルであるTitanicのソースコードがあるので、このソースコードから設計書を生成してみます。
プロンプトとソースコードは以下の通りです。プロンプトは深津式プロンプトを参考に作成しました。
プロンプト
# 命令書
あなたはプロのプログラマーです。
次のプログラムがどのような処理をしているかコードを1行ずつ確認し設計書を作成してください。
回答を出力する前に、入力内容や条件が不足していないかチェックしてください。
不足している情報があれば、どんな情報が必要なのか箇条書きで書き出してください。
コード以外は日本語で回答をしてください。
# 条件
・設計書のフォーマットに則って作成してください。
・処理フローはmermaidで作成してください。
# 設計書のフォーマット
# スクリプト概要
## 概要
| 機能名称 | 処理概要 |
|---|---|
| 名称 | 処理概要について記載する |
----
## 処理フロー
```mermaid
graph TD
# 処理フロー図をmermaidで記載する
```
## 処理詳細
1. 読み込み
csvからデータを読み込む。
2. 読み込んだデータを加工する。
xxxの処理を実行する。
- インプット
| 引数 | 概要 |
|---|---|
| 名称 | 引数の用途について記載する |
- アウトプット
| 戻り値 | 概要 |
|---|---|
| 名称 | 戻り値の概要について記載する |
2. 出力
hogeの処理結果をcsvに出力する。
# ソースコード
<ソースコードを記載する>
ソースコード
import lightgbm as lgb
import numpy as np
import pandas as pd
import random
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import KFold
from sklearn.metrics import accuracy_score
TARGET = 'Survived'
SEED = 2022
random.seed(SEED)
# データの読み込み
train = pd.read_csv('train.csv')
train = train.drop(columns=['PassengerId', 'Name'])
# データの加工
train['Cabin'].fillna('No', inplace=True)
le = LabelEncoder()
encode_cols = [
'Sex',
'Ticket',
'Cabin',
'Embarked',
'Title'
]
for col in encode_cols:
train[col] = le.fit_transform(train[col])
# 学習データの分割
test_index = [random.randint(0, len(train)-1) for p in range(0, round(len(train) * 0.4))]
test = train.iloc[test_index]
train = train.loc[~train.index.isin(test_index)]
X = train.drop([TARGET], axis=1)
Y = train[TARGET]
x_test = test.drop([TARGET], axis=1)
y_test = test[TARGET]
# 学習
params = {
'task': 'train',
'boosting_type': 'gbdt',
'objective': 'binary',
'metric': {'auc'},
'learning_rate': 0.1,
'seed':SEED
}
kf = KFold(n_splits=2, shuffle=True, random_state=SEED)
valid_scores = []
models = []
for fold, (train_indices, valid_indices) in enumerate(kf.split(X)):
X_train, X_valid = X.iloc[train_indices], X.iloc[valid_indices]
y_train, y_valid = Y.iloc[train_indices], Y.iloc[valid_indices]
lgb_train = lgb.Dataset(X_train, y_train)
lgb_eval = lgb.Dataset(X_valid, y_valid)
model = lgb.train(
params,
lgb_train,
valid_sets=lgb_eval,
early_stopping_rounds=10,
)
y_valid_pred = model.predict(X_valid)
score = accuracy_score(y_valid, np.round(y_valid_pred))
print(f'fold {fold} AUC: {score}')
valid_scores.append(score)
models.append(model)
print('train score:{}'.format(np.mean(valid_scores)))
# 予測
preds = []
for model in models:
pred = model.predict(x_test)
preds.append(pred)
score = accuracy_score(y_test, np.round(np.mean(preds, axis=0)))
print('pred score:{}'.format(score))
生成された設計書
# スクリプト概要
## 概要
| 機能名称 | 処理概要 |
|---|---|
| タイタニック号の生存者予測 | タイタニック号の乗客データを基に生存者を予測する |
----
## 処理フロー
```mermaid
graph TD
A[データの読み込み] --> B[データの加工]
B --> C[学習データの分割]
C --> D[学習]
D --> E[予測]
```
## 処理詳細
1. データの読み込み
train.csvからデータを読み込み、不要な列を削除する。
2. データの加工
欠損値を補填し、カテゴリカル変数をエンコードする。
3. 学習データの分割
データをランダムに学習データとテストデータに分割する。
4. 学習
LightGBMを用いて学習を行い、検証データに対するスコアを表示する。
5. 予測
学習したモデルを使用してテストデータに対する予測を行い、そのスコアを表示する。
## 入力
- train.csv: タイタニック号の乗客データ。生存(Survived)、性別(Sex)、年齢(Age)、チケットクラス(Pclass)、同乗者数(SibSp, Parch)、料金(Fare)、キャビン番号(Cabin)、乗船港(Embarked)などの特徴量が含まれる。
## 出力
- 学習データに対するスコア(AUC)
- テストデータに対する予測スコア(AUC)
生成された設計書の確認
一目見た感じではかなり良い出来栄えをしているのではと思います。しかし、詳しく見ると悪い点もあります。
良い点
「概要」はソースコードからタイタニックの生存者予測であることを推察して記載している
「処理詳細」はデータ加工の詳細や学習データをランダムに分割していることなどの詳細が記載されている
悪い点
LightGBMの学習に関するパラメータの説明がない
「処理詳細」 -「 1. データの読み込み」で削除した列について、どの列を削除したのか記載がない
ソースコードの大枠はしっかりと記載されていますが、細かい処理内容は抜けている部分があります。細かいところまで全て設計書に書き起こしてもらうようにするためにはプロンプトの改善が必要そうです。100点満点の出力をしてほしかった設計書ではありませんが、ここから少し手を加えれば完成させられそうなため、初めから人が記載するよりは大幅な時間短縮ができます。
普段の業務でも同じように、少し手を加えれば100点満点に仕上げることができるものが生成されるため、生成AIに大枠を作成させ細かい点は人手で修正をしています。
プロンプトの工夫について
ソースコードと設計書の変換のプロンプトを作成するにあたって、以下のような工夫をしています。
Few-shotプロンプトを利用する
初めはZero-shotプロンプトを利用していましたが、なかなかイメージ通りのものが出力されませんでした。そこで、入力にサンプルを加えるFew-shotプロンプトに切り替えたところ出力の品質が大幅に向上しました。今回は設計書の出力フォーマットのみをサンプルとして与えていますが、ソースコードと設計書のサンプルを与え、同じように記載してくださいという命令にした方が精度は向上します。「コードを1行ずつ確認し」の命令を加える
ソースコードの処理に生成AIが理解できない部分があった場合、理解できない処理を省略して処理詳細を記載することがあります。例えば、複雑な条件分岐が含まれている場合、条件分岐に関する処理のみを省いて処理詳細を記載してしまいます。この文言を加えることによって、ソースコードの処理内容をしっかりと確認するようになり、このような省略をある程度防ぐことが可能になります。ただし、必ず防止できる訳ではないので、省略が発生した場合はソースコードの該当部分に処理についてのコメントを記載した方が良いと思います。「回答を出力する前に、入力内容や条件が不足しないか(中略)どんな情報が必要なのか箇条書きで書き出してください。」の命令を加える
設計書の作成に必要な情報が不足している場合、不足部分を未記載で出力することや誤った情報を出力することが多かったです。そこでこの文言を加えることにより、ChatGPTが必要な情報を、ユーザに質問してくれます。質問に適切に回答することで、より精度の高い回答を得ることが可能になります。「条件」を具体的に記載する
今回のサンプルでは最低限しか記載していませんが、ソースコードの実行環境や処理の目的などを記載すればより回答精度が上がります。イメージ通りの出力が行われない場合は、「条件」をより具体的に記載すると精度が向上します。
これらの工夫はソースコードと設計書の変換に限らず、リファクタリングやユニットテストの作成など、生成AIとソースコードについてやり取りする場合は活用できると思います。
おわりに
設計書のマークダウンへの変換と、生成AIを利用したソースコードと設計書の変換について紹介させていただきました。今回はPythonプログラムをサンプルとして紹介していますが、CloudFormationのようなIaCからパラメータシートを作成させることなども可能です。
また、設計書からソースコードを作成することも可能です。その場合も設計書と同様に100点満点のものは出力されませんが、少し手を加えることで十分利用可能なものになります。
最後になりますが、リクルート ICT統括室 Advent Calendar 2023では、リクルートの社内ICTに関する記事を投稿していく予定です。もし興味があれば、ぜひ他の記事もあわせてご参照ください。
この記事が気に入ったらサポートをしてみませんか?