🧿

開発ドキュメント&ソースコード生成ツールを作ってみた

2024/07/22に公開

はじめに

この記事では私が開発している開発ドキュメント&ソースコード生成ツール「GEAR.indigo」について実装した機能、工夫した点などを紹介します。
さっさと出力された成果物が見たい!という方は成果物まで飛ばしてください。
生成された開発ドキュメントとソースコードを手直しなしでGithubにアップしています。

プロダクトについて


GEAR.indigoは開発ドキュメント&ソースコード生成ツールです。
開発ドキュメントは要件定義書、設計書(基本設計)の2種類を作れるようにしていてそれぞれドキュメントに必要な項目を用意しています。

基本的には項目ごとに前工程の出力+外部ファイルをもとに次の項目を出力し最終的に各ドキュメント、ソースコードを生成するという流れで利用できます。

出力された項目の内容はツール上で編集できるようにしています。
通常生成AIをブラウザで利用する場合は出力(ダウンロード)→ローカルで開いて修正という流れになるところ、アプリケーション切り替えなしで出力内容の確認・修正ができるのは地味ながら使い勝手がいいです。


入力、出力の依存関係を示すナビゲートワークフロー
hoverすると対象ノード、接続されているエッジ、ノードが青くハイライトされてきれい

要件定義書、システム設計書で必要な項目の生成が完了するとdocxファイル、csvファイルとしてダウンロードできます。

すべての項目について出力が完了するとNext.jsのプロジェクト作成→ソースコード生成→githubのレポジトリ作成&pushをすることができます。

技術スタック

フロントエンド

  • Next.js (Pages Router)
  • Tailwindcss
  • shadcn/ui
    今まで作ってきたプロダクトのほとんどでNext.js(Pages Router)を使っているので今回もNext.jsを採用しています。
    コード出力をClaude 3.5 sonnetに大きく依存していたのでよく出力されるshadcn/uiを使用しました。

バックエンド

  • Next.js
    まずは軽量で作ってみたかったのでAPIルートで実装しています。

BaaS

  • Firebase
    ほんとはSupabaseにしたかったのですが当時出力に使用するモデルとしてGeminiをメインにしていたのでGoogleにそろえようとしてFirebaseにしました。
    今はClaudeメインなのでSupabaseでもよかったと思ってます、、、

機能

大きく以下に分けられます。

  1. 項目ごとの生成
  2. ドキュメント化
  3. ソースコード生成

1. 項目ごとの生成


ドキュメントについてそれぞれの項目は以下の通りですが出力する項目の形式が大きくJSON、CSV、Mermaidに分かれます。

  • 要件定義書
    • プロジェクト概要
    • 現行業務フロー
    • 業務要件一覧
    • 導入後業務フロー
    • 機能要件一覧
    • 非機能要件一覧
  • 設計書
    • システム概要
    • テーブル定義
    • ER図
    • 画面遷移
    • 画面一覧
    • バックエンド処理一覧
    • シーケンス図(機能別)

例えばプロジェクト概要はそれぞれの項目を文章で書くだけなのでシンプルなJSONで出力し、機能一覧は表なのでCSV、フローやER図などはMermaidの出力です。

プロジェクト概要(JSON)

機能一覧(CSV)

ER図(Mermaid)
出力にあたっては入力項目をプロンプトに含んで対象の項目を出力させているだけですが、特に後半の出力項目については指示を詳細化し項目間の整合性が崩れないようなプロンプトにしています。
あとこれはただの感想ですがMermaidは素晴らしいなと感じました。
基本的にLLMはText to Textですが図形も元をたどればテキスト(=今回はMermaid)で表現できるということを意識すると出力可能な成果物の幅が広がるような気がします。

2. ドキュメント化

項目を選択しdocxやcsvとしてダウンロードできる機能ですが、そのまんまなので特筆する点はありません。

3. ソースコード生成

これまでの出力をもとにソースコードを生成しGithubリポジトリ作成~pushまで実行する機能です。
生成手順は
Next.jsのプロジェクト作成→フロントエンド作成→バックエンド作成→ファイル統合→Githubリポジトリ作成&push or zipファイル作成&ダウンロードです。

生成中

生成完了

作成されたレポジトリ
出力後早く動かせる状態にしたいという思いから生成するソースコードの技術スタックはフロントエンド(Next.js, tailwind)、バックエンド(Next.js)、BaaS(Supabase)で固定しています。
※今後広く対応できるようにする予定
またよく使うであろうライブラリは最初からPackage.jsonに記載しておくことで立ち上げを早くしています。

Githubにリポジトリ作ったらあとはボタン一つでVercelにデプロイ、といきたいところですがやはりそうもいきません。

必要なライブラリをPackage.jsonに追加しきれていないこと以外にも古い情報を参照していることによるエラーや前提情報を誤って理解しているケースなどがありどうしても手元で修正が必要になります。
これらはプロンプトや処理方法で制御できる範囲が結構あるんじゃないかと思っており特に処理方法、どこでどんな処理がされてどんな情報がどのように連携されるかを設計書の段階で正確に記載できたらいい線行く気がします。

わかりやすいところでいうとフロントエンドにおけるコンポーネント間の協調やダイナミックルーティングを設計しにくかったり、フロントエンドからバックエンドへのAPIリクエストで情報の不整合が起きたりが結構難しいです。
コンポーネント間の協調問題はReact系実装においては結構問題だと思いますが現状はなるべくComponentを使わない実装にしてます。
将来コンテキスト長が大幅に伸びてコストが安くなったら1次生成物を丸ごとなげてリファクタリングさせてしまいたいのですが、、、

成果物

ここではマッチングシステムの議事メモサンプルをもとに生成した成果物を紹介します。

開発ドキュメント

https://github.com/rinte-ringoteto/matching_system/tree/master/related_docs
自社のコミュニケーションやクライアントとの簡単な認識合わせであれば全然いいのですがまだまだクオリティが低いなと思います。
項目ごとの薄っぺらさやMermaidから作成された図表の視認性の悪さがとても気になってます。
内容、デザインともに改善の余地ありです。

ソースコード

https://github.com/rinte-ringoteto/matching_system
※リポジトリ作成と同時にpushされたものなのでローカルで動かすには修正が必要です。

ホーム画面

マッチング画面

管理画面

利用履歴画面

App Routerはまだ少し苦手なようなのでPages Routerで出力してます。
ちょうどこんな記事が出てました。
https://zenn.dev/noko_noko/articles/3ccc64c389259c

動かすまでの手順は以下です。
1.git clone
2.yarn install
3.ファイルの修正

  • ライブラリの追加
  • 細かい文法の修正
  • Supabaseの設定
    • プロジェクト作成
    • テーブル作成&サンプルデータ挿入(プロダクト内でSQLを生成できます)
    • URL、ANON取得
      ---ここまではソースコード生成中にやる---
    • URL、ANON反映

かかる時間はたぶん10分くらいです。
修正にかかる時間は運ゲーなのですが何個か生成させてると必ず出てくるエラーがあります
必ず出てくるエラーに対処するようなプロンプトをコード生成時に仕込むことによって修正時間を短縮していきます。
またプロンプト設計の際は必ず過剰量のプロンプトを作る→ブラッシュアップして削るという方法を取りました。
AIが知らないことは絶対に答えられないのでまずは可能な限り情報を与えるようにしています。
まだブラッシュアップしてないのですがpagesディレクトリのファイルを作成するプロンプトはこんな感じです。

 let prompt = `
以下の制約条件と入力に基づいて、${projectData.frontend}のコードのみを生成してください。

**入力:**

\`\`\`json
${JSON.stringify(screenData, null, 2)}
\`\`\`

**参考情報:**

システム概要:${JSON.stringify(systemAbstraction, null, 2)}
画面遷移図:${JSON.stringify(screenTransition, null, 2)}
テーブル定義:${JSON.stringify(tableDefinition, null, 2)}
コーディング規則:${JSON.stringify(codingRules, null, 2)}
フロントエンドのファイル名:${JSON.stringify(fileName, null, 2)}
 
**制約条件:**

- ${userLanguage}で出力する。
- コンポーネント名は${JSON.stringify(fileName, null, 2)}と同じにする。
- 文頭の\`\`、ファイル形式、出力コードの説明などは不要でコードのみを出力する。
- TypeScriptを使用する。
${projectData.frontend === "Next.js" || projectData.frontend === "React"
            ? `
- hooksやcomponentを外部ファイルからimportせずすべて単一ファイルに記載する。` : ""}
- Topbarを用意し他の画面に遷移できるようにする。遷移先のURLはフロントエンドのファイル名を参考にする。
- 必要に応じてSidebarを用意し他の画面に遷移できるようにする。遷移先のURLはフロントエンドのファイル名を参考にする。
${database === "Supabase"
            ? `
- 例外としてsupabase.tsを@/supabaseのパスでimportする。` : ""}
${frontend === "Next.js" || frontend === "React"
            ? `
- hooksやcomponentを外部ファイルからimportせずすべて単一ファイルに記載する。
- 例外としてTopbarを@/components/Topbarのパスでimportする。
- Topbarをimportする際はimport {Topbar}ではなくimport Topbarの形式でimportする。
- CSSはtailwindcssを使用する。
- 必要に応じてreact-iconsのアイコンを活用する。`
            : ``}
- 基本的なスタイリングはコーディング規則を参考にする。
- 現代風の洗練されたデザインにする。
- 適切な箇所に画像を配置して視認性を高めてください。
- 必要に応じてプレースホルダー画像を使用する。
- 画像のPlaceholderはplacehold.coから取得した画像を利用する。
${projectData.frontend === "Next.js" || projectData.frontend === "React"
            ? `
- Linkタグのなかにaタグを使用しない。` : ""}
- 最上位タグのスタイリングにはmin-h-screen h-fullを必ず含める。
- テーブル定義に存在するデータのみを表示する。
- 画面に必要なライブラリがあれば、import文を追加する。
- 画面遷移に必要なライブラリがあれば、import文を追加する。
${database === "Supabase"
            ? `
- Supabaseをデータベースとして使用し、データベース操作にはSupabase Clientライブラリを使用する。` : ""}
- 取得するデータ項目はテーブル定義に沿って取得する。
- バックエンドとの通信が必要な場合は、axiosを使用する。
- APIリクエスト及びデータ取得に失敗した場合、システムに即した具体的なサンプルデータを表示する。
- APIリクエストが必要な場合のエンドポイントは${JSON.stringify(relatedBackendHandles.map(handle => handle.fileName), null, 2)}を参考にする。
- 遷移先のリンクは${JSON.stringify(screensList.map(screen => screen.fileName), null, 2)}のファイル名を参考にする。ただし遷移先の指定に.tsxは不要です。
- ファイルがNext.jsのtsxファイルとして不完全な形式である場合再度生成を試みる。
    `;
    if (appOption) { // appOptionがtrueの場合のみ追記
        prompt += `
        ${frontend === "Next.js"
                ? `
- App Routerであることを前提にコードを書く。
- 必要に応じて\"use client\"を文頭に書く。
- useStateやuseEffectなどHooksを使う場合は必ず\"use client\"を文頭に書く。
- use clientを書く際は必ず\"\"でuse clientを囲む。
- routerは'next/navigation'からimportする。;
`: ""
            }
        `;
        return prompt;
    } else {
        prompt += `
        ${frontend === "Next.js"
                ? `
- Pages Routerであることを前提にコードを書く。` : ""}`
        prompt += "  "; // 最後の改行を削除

        return prompt;
    }
}

ソースコード生成にかかったコストは計26ファイルで1.21$です。
入力が雑なのでもう少し安くできると思います。

ソースコード生成前

ソースコード生成後

大変だったこと

正直LLMに直接関わるところはそんなに大変ではなかったです。
というのも入力内容が整っていたらてきとうに投げてもいい感じに回答してくれるからです。
プロンプトによる制御は過度な期待をしていません。
なのでどんな入力でどんな出力をさせるか丁寧にそろえていくのが大変でした。
あと大変だったのは普通のプロダクト開発と一緒ですが慣れてないライブラリ関わるところくらいですね。
開発にはもちろん生成AIを使っていてClaude,Geminiを使いました。
フロントはClaude、バックエンド及び長文になったフロントはGeminiっていう感じです。
ただClaudeのデザイン性能は頭抜けてる感覚があります。
これはブラウザ版ではなくAPIを直叩きすると顕著に出ます。

類似プロダクト

生成AIを使ってプログラミング、というのは現在の生成AI活用において群を抜けて有用だと思いますし、となると要件定義書からソースコード生成まで、のような発想に至るのはごく自然なことだと思います。実際ほとんど同じ機能を持つプロダクトはすでにいくつかあるので少し紹介します。

海外だとOpen DevinやFactoryあたりが有力プロジェクトかと思います。
https://www.factory.ai/
https://github.com/OpenDevin/OpenDevin
特にfactoryはそれぞれの工程を緻密に設計しておりそれなりに質の高いアウトプットが出てくるのではないかと思います。
(デモのアポとらないと使えないぽいので触れてない)

国内で自分が特に参考にしているのが元木さんがやっているBabel&Zoltraakというプロダクトです。

https://x.com/ai_syacho/status/1814371039939534983

簡単なプロンプトをもとに要件定義からソースコード生成まで実行できるようになっており(Zoltraak)、追加開発で使用するグラフィカルエディターまで用意する(Babel)ことでさらにAIの持つ能力をエンパワメントしようというプロジェクト、だと理解してます。
生成AI界隈で知らない人はいないと思いますがとにかくXでの発信量が多く自分のプロダクト開発で参考になる部分も多いのですが課題感ややりたい方向で共感できる部分もありつつ根本のプロダクト思想が違うと感じる部分もありつつで見ていて楽しいです。
特にエディターは追加開発におけるAI活用という観点で非常に重要な領域だと思うのですが今の自分は技術的にもリソース的にも(特に技術的に)厳しいので、別のアプローチを検討しています。

最近Qiitaで紹介されていたこちらのツール(CodeAGI)はSIerで使われそうなツールになっていて毛色が異なりつつ似た取り組みだったのでおもしろそうだと思います。
https://qiita.com/nqdior/items/1bef77d46e199f8ec97c
手動で作成された設計書をインプットにソースコード、テストコードを生成できるようです。
フロントエンド、バックエンド、DBも様々な種類に対応しておりThe 日本企業の開発工程では非常に有用なツールになりそうです。

で、こんなにたくさん類似プロダクトがあるのになんで同じもの作ってんの?という話ですが、自分が作っている理由は以下です。
・似てるけど微妙に欲しい機能が異なる
・生成AIのおかげで実装工数が大幅削減されている

自分はこのツールを使ってオフショア受託を高速化/効率化していきたいと思っているのですが、ドキュメンテーションしっかりしたいし翻訳機能欲しいしついでに開発管理できたらいいな、みたいに考えると100点のプロダクトは見つかりません。従来であれば要件に一番近い80点のプロダクトを選ぶことになりますが生成AIのおかげで実装工数が大幅削減されてるし作ってしまえばいいんじゃないかという考えに至りました。

最新の技術で作られた包丁より長年使って切れ味を自分好みに研いだ包丁の方が感触が手に馴染む、という感覚に近いかもしれません。
モデルのアップデートへの対応は意外と重くないので自分の中に”土台”としてプロダクトを作っておいてのちのち拡張していきます。

今後について

サービスとしての方針

上記で書いた通り自分が使いやすいツール、というのが大きなコンセプトになっていますが、せっかく作ったのでもろもろ整えて一応リリースしようと思います

同じようなプロダクトはいくつかありますが自分の感覚と近い課題感を持ってる方がいるかもしれないですしユーザーにとって選択肢が増えることはいいことだと思ってます。
なんだかんだいろんな人に使ってもらえたらとっても嬉しいです。

このプロダクトとは別で数年前から考えているやってみたい取り組みがあるので一部機能(作成プロジェクト数上限とか?)を有料にしようと思いますが、基本的な開発ドキュメント生成からソースコード生成までに必要な機能は無料ユーザーでも使えるようにする予定です。
ぜひ私のXをフォローしてリリースをお待ちいただけると嬉しいです!
https://x.com/rinte0321

あと最近こもり気味だったので交流増やす目的でこのプロダクトのLTしたいなって思ってます!
もしLT会主催される方いらっしゃればエントリーしたいのでぜひご連絡ください!

プロダクトとしての方針

追加で開発したい機能は山ほどあります。
依存関係の正確性を向上させたりドキュメントとコードの連動を図ったり先ほど少し触れたCodeAGIのように様々な言語、フレームワーク、DBに対応したり、figma AIのようにデザインを生成させたり開発管理のためのタスクボードを導入したり、、、などなどです。
開発スピードが爆速化しているとはいえさすがにやりたいことが多すぎるので少しずつやっていこうと思います。
何も決めてないのですが開発にご興味ある方がいらっしゃればぜひご連絡ください。

おまけ

どうでもいいけど用意した機能

本質的ではないけど欲しくて作った(偶発的にできた)機能を紹介します。

- スマホからGithubにpushできる!!!


Webアプリなのでスマホからブラウザ開いてポチポチやるだけでGithub上にNext.jsのリポジトリが作成されます。
全然狙ってなかったしユースケースほぼない気がしますがこれ結構すごくないですか?
(あんまないと思うけど)客先オフラインでヒアリングして帰りの電車の中で文字起こしデータをインプットにポチポチやってリポジトリ作成。

- 英語対応

海外メンバーがこのツールを使う可能性があるため開発しました。
プロダクトグロースのためにはいらないと思います。
英語にして触ってるとイケてる海外プロダクト触ってる気分になります。
でも作ったからProduct Huntに出してみようかな?という下心ができています。

かっこいい

- LLM選択

各項目・ソースコード生成の際にClaude,Gemini,ChatGPTどのLLMを使うか選べます。
正直いらないと思いますが各社で新しいモデルがでたときに素早く試せるのはいいかも。
これは最初Geminiで作っててClaudeメインに乗り換えた時についでにChatGPTも対応したって感じです。

- DB操作の記述場所設定

BaaSを使っていてもセキュリティなどの都合でバックエンドからDB操作(CRUD)を行いたいケースがあると思います。
Supabaseをしっかり触っているわけじゃないので強く必要性を感じているわけではないですが一応DB操作(CRUD)をフロントエンドでやるかバックエンドでやるか選択できるようにしています。
これは将来的にBaaS以外のDBに対応することを見越した設定でもあります。

- チームメンバー追加

ドキュメント生成は開発におけるコミュニケーションコスト低減につながる機能なので大枠でみたらチームメンバー追加機能は今後必要になってくると思いますが、初期ではないかもしれません。

- ロゴ

こだわったわけじゃないですがClaudeでsvg出力させたのちに微修正しています。
最初はreact-iconsの歯車で仮置きしてたのでクオリティが格段に上がった気持ちになりました。

- キービジュアル

ロゴとほぼ一緒ですがかっこよくて気に入ってます。ロゴ生成と同じく上記で出力したsvgをClaudeになげてオブジェクトにアニメーションを加えたのち、背景デザインの要件を伝えてコード出力で実装してます。

プロダクト名の由来

GEAR.indigoというプロダクト名ですが、まず人が使う強力なツールとして作りたいと思っていたので武器や道具を連想する言葉であるGEARを選びました。
※私の好きなゲームであるスプラトゥーンで使われている用語でもあります。
indigoは特に意味はなく開発中にClaudeにデザインさせたらtailwindでindigoを使ってきたのですがとてもスタイリッシュでかっこいい雰囲気になったのでそのままプロダクト名に入れました。
つなげると何とも言えない中二感漂うのも気に入っています。

Discussion