見出し画像

ChatGPTで実現する!マルチエージェントの考え方を取り入れたプロトタイプ開発

こちらは、公式アドベントカレンダー2024【A】IT技術関連トピック Day.13 の記事です。
公式アドベントカレンダー2024_B 仕事術・キャリア・体験記も毎日記事を公開していますので、ぜひあわせてご覧下さい。

★Day12のアドベントカレンダー記事
CAT のレガシーマイグレーション舞台裏 ー TargetGroupBinding on Amazon EKS(村上 直)


プロジェクトの背景


エディタWebアプリの開発を提案する際に、XMLとJSONを編集するエディタを作成することにしました。提案時に画面イメージだけでなく、実際に動作するものを見せることで説得力が増すと考え、プロトタイプを作ることにしました。限られた予算と時間の中で、生成AIを用いて効率的にプロトタイプ開発を行うことを目指しました。

想定している読者


このブログ記事は、AIを使ってプログラムを作ってみたいけれど、うまくいっていない初心者のソフトウェアエンジニアを対象としています。参考になればと思い、具体的な手順やステップを例に出しています。

「方針決め」と「試行錯誤」

方針決めまでにやったこと、試したこと

  1. AutoGenの利用検討

    • 社内でAutoGenの先行研究があったので使おうとしましたが、ChatGPTのAPI等資源調達ができず断念。

  2. Difyの利用検討

    • 社内Difyの利用を試みましたが、以下の問題点により採用には至りませんでした。

      • デザイン担当、開発担当、テスト担当のエージェントを作りやり取りをさせようとしましたが、イテレータ以外のループを作ることができず、担当間でフィードバックのやり取りができませんでした。

      • 社内Difyで追加予算もないことから、実装されているLLMがGPT-4oではなく、変更できない制約がありました。そのため、準備したプロンプトが想定の挙動をせず、問い合わせを返してしまう場合があり、担当間フィードバックが行えないという問題が顕在化してしまいました。
        ※ Appendixにどのような実装を行ったか記載しています。

  3. [採用!]GPT-4oベースのチャットを用いたプロトタイプ開発

    • 結果的に、GPT-4oベースのチャットを用いてプロトタイプ開発をすることとしました。

プロトタイプ開発の流れ

使用環境:GPT-4oベースのLLMが搭載された社内用チャットボットを用いる。

実際に行ったフロー

  1. エージェントの役割分担

    • 当初は顧客(私)→デザイン担当→開発担当→テスト担当とエージェントを分けて実施しようと考えました。 しかし、プロトタイプ開発ということもあり、決まっていることの方が少なく流動的であるため、テスト担当の役割がなく、最終的に以下のようなフローとなりました。

  2. ペルソナの設定

    • デザイン担当、開発担当にはペルソナとなるプロンプトを与えました。

フローの中でポイントとなったプロンプトを紹介します。

1.デザイン担当としてのペルソナを与えたプロンプト

対象とするスコープ: ユーザーエクスペリエンスとインターフェースデザインの作成
ASSISTANTの役割定義: ユーザーのニーズを理解し、直感的で魅力的なデザインを作成し、ワイヤーフレームやモックアップを作成し、フロントエンド開発者と連携してデザインを実装する

##ゴールと変数の定義
ゴール: ユーザーのニーズに基づいた直感的で魅力的なデザインのワイヤーフレームやモックアップを作成し、フロントエンド開発者と連携してデザインを実装する
変数:
- ユーザーのニーズ 
- デザインの直感性
- デザインの魅力
- ワイヤーフレーム
- モックアップ
- フロントエンド開発者との連携

##手順の実行プロセス
[C1] ユーザーのニーズを調査し、理解する
[C2] 調査結果に基づいて、直感的で魅力的なデザインのコンセプトを作成する
[C3] デザインコンセプトに基づいてワイヤーフレームを作成する
[C4] ワイヤーフレームを基にモックアップを作成する
[C5] フロントエンド開発者と連携し、デザインを実装するための詳細な仕様を作成する
[C6] デザインの実装をサポートし、必要に応じて調整を行う
[CEnd] 最終的なデザインを確認する。

##出力形式
デザインコンセプト、ワイヤーフレーム、モックアップ、実装仕様書

##制約事項
- ユーザーのニーズを正確に反映すること
- デザインの直感性と魅力を高めること

##例外時のアクション
- ユーザーのニーズが不明確な場合は、追加の調査を行う
- デザインの直感性や魅力が不足している場合は、想定を置いたデザインコンセプトにて実装する。

##出力制御
- 手順の途中経過は出力せず、最終的な結果のみを出力すること"

##最初のアクション:
それでは、ユーザーのニーズを教えてください。

2.デザイン担当へのインプット(ユーザニーズ)

JSにてリッチテキストエディタが欲しい。
ASSISTANTの役割定義に則り、設計・実装を行う担当者のインプットのためのアウトプットを作成してください。

以下がユーザーのニーズです。
#要件
 ・日本語を扱う
 ・XMLをインプットファイルとする。
 ・独自の構造化を定義できる「XML構造ルール」として入力を求める。
 ・Json,XML形式でエクスポートできる
 ・編集時にはタグは表示しない、構造化のルールにのっとり自動でタグ付けする。
 ・編集途中に編集前編集後の差分を差分表示領域に表示できる
 ・編集とは別にレンダリングされたプレビューエリアに表示ができる
 ・差分表示領域とプレビューエリアは別のものである。
 ・プレビューエリアの仕様
   1.構造の要素毎に要素名とその範囲を括弧表示で表示する。
   2.要素名と括弧表示は半透明で表示し、編集不可とする。
   3.編集可能な範囲は括弧の中身だけとする。
 ・XML出力ボタンを追加して編集した内容を指定した「XML構造ルール」でダウンロードできるようにしてください。
 ・JSは一つのファイルに統合してファイル名をeditor64.jsとしてください。
 ・「XML構造ルール」の内容は省略せずに反映してください。
 ・inputのsubmitイベントで入力内容が確定した段階でプレビューを再描画するようにしてください。
 ・ローカルでスタンドアロンで動作できるようにしてください。

3.デザイン担当AIの成果物(これが開発担当のインプットとなりました)

#要件
~~~上記デザイン担当へのインプットと同様のため割愛~~~


ここから以下は、デザイン担当からのデザインの方向性です。

## デザインコンセプト
リッチテキストエディタは、日本語を扱い、XMLをインプットファイルとし、独自の構造化ルールに基づいて編集を行うことができるツールです。編集時にはタグを表示せず、構造化ルールに従って自動でタグ付けを行います。編集途中の差分表示や、レンダリングされたプレビューエリアを提供し、編集内容をJsonやXML形式でエクスポートできる機能を持ちます。

## ワイヤーフレーム
1. **メインエディタエリア**
   - テキスト入力フィールド
   - 編集時にはタグは表示されない

2. **差分表示領域**
   - 編集前と編集後の差分を表示

3. **プレビューエリア**
   - 構造の要素毎に要素名とその範囲を括弧表示
   - 要素名と括弧表示は半透明で表示し、編集不可
   - 編集可能な範囲は括弧の中身のみ

4. **コントロールパネル**
   - XML出力ボタン
   - Json出力ボタン
   - インプットファイル選択ボタン
   - 「XML構造ルール」入力フィールド

## モックアップ
以下は、リッチテキストエディタのモックアップです。


+-----------------------------------------------------+
| [インプットファイル選択] [XML構造ルール入力]       |
+-----------------------------------------------------+
| [メインエディタエリア]                              |
| +-----------------------------------------------+   |
| |                                               |   |
| |                                               |   |
| |                                               |   |
| +-----------------------------------------------+   |
+-----------------------------------------------------+
| [差分表示領域]                                     |
| +-----------------------------------------------+   |
| | 編集前: ...                                    |   |
| | 編集後: ...                                    |   |
| +-----------------------------------------------+   |
+-----------------------------------------------------+
| [プレビューエリア]                                  |
| +-----------------------------------------------+   |
| | <要素名> ... </要素名>                          |   |
| | <要素名> ... </要素名>                          |   |
| +-----------------------------------------------+   |
+-----------------------------------------------------+
| [XML出力] [Json出力]                               |
+-----------------------------------------------------+
## 実装仕様書
### 機能要件
1. **日本語対応**: 日本語のテキストを正しく扱えること。
2. **XMLインプット**: XMLファイルをインプットとして読み込む機能。
3. **XML構造ルール**: 独自の構造化ルールを入力し、それに基づいて編集を行う機能。
4. **タグ非表示編集**: 編集時にはタグを表示せず、構造化ルールに従って自動でタグ付けを行う機能。
5. **差分表示**: 編集前と編集後の差分を表示する機能。
6. **プレビューエリア**: 構造の要素毎に要素名とその範囲を括弧表示し、編集可能な範囲を括弧の中身だけとする機能。
7. **エクスポート**: 編集内容をJsonやXML形式でエクスポートする機能。
8. **ローカル動作**: ローカルでスタンドアロンで動作すること。

### 技術要件
- **言語**: JavaScript
- **ファイル名**: editor64.js
- **ライブラリ**: 必要に応じて適切なライブラリを使用

### 実装手順
1. **インプットファイルの読み込み**
   - ファイル選択ボタンを設置し、XMLファイルを読み込む機能を実装。
2. **XML構造ルールの入力**
   - テキストフィールドを設置し、ユーザーが独自の構造化ルールを入力できるようにする。
3. **メインエディタエリアの実装**
   - テキスト入力フィールドを設置し、タグを表示せずに編集できるようにする。
4. **差分表示領域の実装**
   - 編集前と編集後の差分を表示する領域を設置。
5. **プレビューエリアの実装**
   - 構造の要素毎に要素名とその範囲を括弧表示し、編集可能な範囲を括弧の中身だけとする。
6. **エクスポート機能の実装**
   - XML出力ボタンとJson出力ボタンを設置し、編集内容をエクスポートできるようにする。
7. **ローカル動作の確認**
   - ローカル環境でスタンドアロンで動作することを確認。

### コード例
以下は、基本的な構造を示すJavaScriptコードの例です。
....

具体的な開発の手順やステップ

ここまでの流れを受け、開発担当がプログラムを作ってくれましたが、仕様が気に入りませんでした。そこで、あれこれリクエストをして仕様を追加していきました。

1.仕様決め

開発担当とトライアンドエラーを実施して少しずつブラッシュアップしていきました。最初の仕様から、以下の順番で機能を追加していきました。プロンプトと一緒に紹介します。

  • クリアボタンを追加

クリアボタンを追加して。差分があるファイルのみ出力して。
  • テンプレートを読み取り初期表示をする、同時にXML構造をJSONに変換して表示する。

テキスト入力が難しいのでテキストフィールドにテンプレートを表示したい。
テンプレートの初期表示時はテンプレート用のtemp.xmlを読み込み、Jsonに変換して出力しそれを元にテキストフィールドで編集できるようにしてください。
またXML出力時にはテキストフィールドにJSON形式の書式になっているはずなのでXMLにコンバートして出力するようにしてください。
ファイルを開く場合には、初期表示と似ているが、インプットされたXMLからJsonに変換して出力しそれを元にテキストフィールドで編集できるようにしてください。       
  • タグ名を表示・編集するときだけ日本語に置き換える

# メインエディタエリアの仕様を一部変更してください。
  - 初期表示時に読み込んだtemp.xmlファイルをJSON形式に変換し変数syokiJsonで保持する。
  - 変数syokiJsonの要素をcomv.csvに沿って置換する CSVファイル内にあるタグ名がJsonの要素名に対応するため、対応する物をCSVの日本語名に置換し変数xxJsonに格納
  - 変数xxJsonを文字列形式に変換し変数mojiretuに保持する
  - 変数mojiretuの内容をエディタ領域に展開する。
  - エディタ領域が編集された場合に、変数mojiretuに反映後、上記の置換の逆の処理を行いJSONの要素を復元する
  - 変数mojiretuをJSON形式に変換し変数hensyuuedJsonに保持する。
  - hensyuuedJsonとsyokiJsonを比較し現在の実装されている処理に則り差分表示領域に表示する
  • タグ部分は自由自在に編集されると困るので、制限を設けるためエディタ領域をテーブル化してセル単位で制御する

エディタ領域を2列のテーブルにして下さい。
行については可変数あり、列は固定としてください。
テーブルのヘッダ行は不要です。
# 機能
- 初期表示やファイルを読み込んでエディタ領域に展開する際にJsonの要素、記号"{""}"","":"文字と指定した記号より前にある文字は1列目に展開する。
- テキスト情報のValueに相当する部分は2列目に展開する。
- 1列目は編集不可、1列目に「"_text":」の文字列があった場合のみ隣の2列目のセルを編集可能とする。
- 1列目の編集不可を解除しセル単位で編集可能とする条件は "タグ": { と言う文字列が入っていた場合のみ編集可能とし、編集されてフォーカスアウトする際にポップアップを表示してメッセージに{編集した内容}で確定しますか?OK、キャンセルを選択させるようにする。
  確定ポップアップでOKした場合はそのセルは編集不可とする。
- セルの編集可不可に関しては、挿入、削除処理後にも再判定する。
- エディタ領域のテーブルに展開したJSONは編集後テーブルからJSONに変換する相互変換が行えるようにする、変換時に1列目に含まれる"文字は不要なので除去してください、編集後にはテーブルからJSONに変換した情報を元に差分表示やプレビューエリアの描画に利用する。
- 上記仕様により、差分表示領域、プレビューエリア、XML出力、JSON出力にも影響がありエディタ編集後に表示されるべき差分表示、プレビューエリア両方とも表示されなくなる可能性があるため、デバッグして再度実装して仕様通りにレスポンシブルに動作させるようにしてください。
- 右クリックに挿入、削除の機能を追加
	挿入: エディタ上のマウス位置から一番近い「}」がある行の下に以下の内容で3行分行追加する。
"タグ": {
"_text": "入力"
}
	削除: エディタ上のマウス位置から一番近い以下の正規表現で順番通りにマッチする3行を探し1行目のマッチ内容を警告ポップアップを出しOKを選択したなら該当する3行を削除する、キャンセルを選択したら警告ポップアップを閉じる
		条件はいずれも正規表現である。
		1行目 .+: *\{
		2行目 _text: *.*
		3行目 \}  
  • 開発担当引継ぎ  (プロンプトはAppendixに添付)

    • ここまでの機能追加とデバッグでやり取りがかさみ、トークン超過のエラーが出て、それ以降エラー以外何も返答を返さなくなってしまった。そこで試行錯誤の結果、開発担当の引き継ぎをおこなうこととした

  • OSSのJSONEditorを導入してエディタ領域の機能を代替させる

エディタ部分をOSSのJsonEditorのライブラリに置き換えて実装できますか。
ライブラリのURL: https://github.com/josdejong/jsoneditor
初期表示時に読み込んだtmp.xmlをJsonに変換後、このライブラリのtreeモードで描画するようにしてみてください。  

2.デバッグ

  • エディタの編集領域に変更を加えると、差分表示やプレビュー機能に影響が出ているのに編集をしてくれず動作しないバグが複数回発生しました。その都度修正を依頼して直していました。その中で、何度指摘しても同じ内容を返してしまうループにはまりつつ、プロンプト自体を修正して但し書きで修正箇所をあらかじめ指定し、再生成する手法を使って乗り越えました。

成果と振り返り

このようにして、限られた予算と時間の中で、マルチエージェントの考えを用いたChatGPTによるプロトタイプ開発を成功させることができました。以下に、エディタWebアプリの画面イメージを示します。

[完成したプロト-エディタWebアプリの画面]

解決した課題

  1. OSSの適用方法

    • OSSをはじめから適用させようとすると、意図しない実装が複数含まれてしまい訂正が困難でした。ある程度目的の動作をするようになってから、「この要素部分をJSON Editorのライブラリに置き換えて実装してください」と指示した方がうまくいきました。

  2. トークン超過問題

    • AIチャットとのやり取りがかさみ、トークンが超過して受け答えができなくなる問題が発生しました。

      • この問題を解決するために、開発担当が毎回修正箇所以外のファイルもすべて表示しようとしていましたが、出力するファイルを絞るように指示することで多少の高速化とトークンの節約を行いました。

      • ソースの一部分を細かく修正してもらうのではなく、問題となるソースを生成したプロンプト自体を修正して再生成する手法を使うことで、チャットの履歴がたまることなく、また間違った認識をして実装を始めてしまうAIに対して、間違った認識をさせる前に軌道修正をすることができました。

      • 上2件は延命措置ですが、根本的な問題を解消するため、トークンの超過時に担当を引き継ぐプロンプトを作成させ、AIエージェントを引き継ぐことを試み、成功しています。

        • 同じ役割を引き継がせる人員入れ替えのようなことも、工夫次第では実現できるのだという発見がありました。
          ※参考に最下Appendix2に引き継ぐ際に知識を吐き出させたプロンプトを記載しておきます。

結果

  • 最終的にAI開発担当の出力をそのままブラウザで動作させることができた(出力したものに修正や加工を入れることなく)。

  • デモ動画を撮影できる程度には動作するWebアプリになっているので、プロトタイプとしてはありだと感じました。

メリット

  • プロトタイプで何も仕様は決まっていないので、都度、画面の動きをみて要望を出して実装してもらうというプロセスが取れる。

  • "JSON Editor"のOSSのライブラリ適用がチャットのやりとり2往復程度でできた。

  • デザイン修正を途中で挟みたいときにデザイン担当に依頼し、ワイヤーフレームを確認してから開発担当に依頼する流れをとることで、スムーズに実装できた。

デメリット

  • チャット型のやりとりは1往復に時間がかかる。

  • 自動化とは逆のアプローチで、何度も手動での泥臭いトライアンドエラーが必要。

  • マルチエージェントの考えを取り込んではいるが、いわゆるマルチエージェントとは言えない。

所感

  • 少し動かしては、「あれやってこれやって、あの機能つけて」を繰り返す手法はプロトタイプ開発には合っていると感じた。

  • そこそこのものができるのがわかった。本格的な開発をこの手法で行うには、人手でやっている部分を減らす仕組みが重要になってくる。

Appendix: Dify のお試し実装


検討時に社内Difyを利用して、デザイン担当、開発担当、テスト担当のエージェントを作成し、やり取りをさせようとしました。以下はその際に使用したDifyのDSLファイルの実装内容です。

[Difyで実装したのワークフローの様子]

ノードの詳細

  • スタートノード: プロジェクトの全体計画を立て、各エージェントにタスクを割り当てる役割。

  • デザイン担当ノード: ユーザーリサーチを行い、ワイヤーフレームとモックアップを作成する役割。

  • 開発担当ノード: ユーザーインターフェースの設計と実装を行う役割。

  • テスト担当ノード: プロトタイプのテストと品質保証を行う役割。

Appendix: プロトタイプの仕様


積み重ねたチャットの内容をまとめて、有効な仕様のみを開発担当Bにレポートしてもらった結果です。

### 概要
#### 本プロジェクトは、ユーザーがXMLファイルを読み込み、JSON形式に変換して編集し、編集内容を差分表示およびプレビュー表示するためのWebアプリケーションを開発することを目的としています。編集後のデータはXMLまたはJSON形式でエクスポート可能です。

### 機能一覧
1. XMLファイルの読み込み
2. JSON形式でのデータ編集(JSONEditorライブラリを使用)
3. 編集内容の差分表示
4. 編集内容のプレビュー表示
5. 編集内容のXML形式でのエクスポート
6. 編集内容のJSON形式でのエクスポート
7. エディタのクリア機能

### 非機能要件
1. レスポンシブデザインの実装
2. ユーザーフレンドリーなインターフェース
3. 高速なデータ処理と表示
4. 安全なファイル操作

### 制約事項
1. 使用するライブラリはJSONEditorおよびxml-jsとする
2. ブラウザは最新のChrome、Firefox、Edgeに対応する

### 画面設計書
#### 画面一覧
1. メイン画面

#### 各画面のレイアウト
##### メイン画面

+-----------------------------------------------------+
| [インプットファイル選択]                           |
+-----------------------------------------------------+
| +----------------------+ +-----------------------+  |
| | [JSONエディタ]       | | [差分表示領域]        |  |
| |                      | |                       |  |
| |                      | |                       |  |
| |                      | +-----------------------+  |
| |                      | | [プレビューエリア]     |  |
| |                      | |                       |  |
| |                      | |                       |  |
| +----------------------+ +-----------------------+  |
+-----------------------------------------------------+
| [XML出力] [Json出力] [クリア]                      |
+-----------------------------------------------------+


### 基本設計書
#### システム構成図

+-------------------+
|   Webブラウザ     |
|  (HTML, CSS, JS)  |
+-------------------+
         |
         v
+-------------------+
| JSONEditorライブラリ |
+-------------------+
         |
         v
+-------------------+
|   xml-jsライブラリ  |
+-------------------+


### 詳細設計書
#### シーケンス図
XMLファイル読み込みから編集までのシーケンス

ユーザー -> ブラウザ: XMLファイルを選択
ブラウザ -> xml-js: XMLをJSONに変換
xml-js -> ブラウザ: JSONデータを返す
ブラウザ -> JSONEditor: JSONデータをセット


##### 編集内容の差分表示とプレビュー表示のシーケンス

ユーザー -> JSONEditor: JSONデータを編集
JSONEditor -> ブラウザ: 編集イベントを発火
ブラウザ -> 差分表示領域: 差分を表示
ブラウザ -> プレビュー領域: プレビューを表示


#### 詳細なアルゴリズム
XMLファイルの読み込みとJSON変換
1. ユーザーがXMLファイルを選択
2. FileReaderを使用してXMLファイルを読み込む
3. xml-jsライブラリを使用してXMLをJSONに変換
4. JSONEditorに変換したJSONデータをセット

##### 編集内容の差分表示
1. JSONEditorの編集イベントを監視
2. 編集内容を取得し、元のJSONデータと比較
3. 差分を計算し、差分表示領域に表示

##### 編集内容のプレビュー表示
1. JSONEditorの編集イベントを監視
2. 編集内容を取得し、JSONをXMLに変換
3. XMLデータをテキストとしてプレビュー領域に表示

##### XML形式でのエクスポート
1. JSONEditorから編集内容を取得
2. JSONを元のキーに置換
3. xml-jsライブラリを使用してJSONをXMLに変換
4. 変換したXMLをファイルとしてダウンロード

##### JSON形式でのエクスポート
1. JSONEditorから編集内容を取得
2. JSONを元のキーに置換
3. JSONデータをファイルとしてダウンロード

##### エディタのクリア機能
1. JSONEditorをクリア
2. 差分表示領域とプレビュー領域をクリア
3. ファイル入力をクリア

### 利用したOSS
- JSONEditor: https://github.com/josdejong/jsoneditor
- xml-js: https://github.com/nashwaan/xml-js

### 実装言語
- HTML
- CSS
- JavaScript

以上が現在の実装仕様です。

Appendix2: 開発担当引継ぎ時に依頼したプロンプト


あなたは、 フロントエンド開発者を次のAIエージェントに引き継ぐ必要があります。
** 最新のアウトプットと同じものが引継ぎ先のAIエージェントでも行えるように、現時点で確定している情報をすべてプロンプトとして出力してください **
** 古くて現時点で使われていない情報は不要です **

役割、概要、目的、仕様、フォルダ構成、画面レイアウト、基本設計、詳細設計、実装方針、前提条件、ゴールと変数の定義、出力制御、例外時のアクション、最初のアクション 等、途中指摘した内容も有効なものをすべてが対象です。
Javascript、CSS、XMLの出力は手元にあるので不要です、引継ぎ先で最初のアクションのインプットとしてソースを受け取れるようにしてください。
引き継いで改修してくということを引継ぎ先に認識させるようにしてください。
出力するプロンプトは効率的に読み込める形式、例えば**深津式プロンプト**等を用いて引継ぎ先のエージェントの理解を助けるようにしてください。 
** 見出しや強調、スペニット ** を駆使したプロンプトを希望します。

執筆者プロフィール:Haruki Takenouchi
ソフトウェアのエンジニアとして、金融、機械、通信など多岐にわたる業界で経験を積んできました。最近ではテスト自動化や脆弱性評価、負荷試験自動化計画などを担当。その他AIの分野にも注力しています。Java、Python、C#等々その他多言語に精通し、AWSやGCPなどのクラウド環境も活用。最新技術を取り入れたPOCから開発、テストまで一貫して対応し、常に新しい技術を学び続けています。

SHIFTグループ公式アドベントカレンダー2024【A】 IT技術関連トピック Day14は「なんちゃってアジャイルの卒業:経験から学んだ教訓」(塚田 千晶)

お問合せはお気軽に

SHIFTについて(コーポレートサイト)

SHIFTのサービスについて(サービスサイト)

SHIFTの導入事例

お役立ち資料はこちら

SHIFTの採用情報はこちら

出典:GAI-Chatで作成