こんにちは。
ファインディ株式会社でテックリードマネージャーをやらせてもらっている戸田です。
現在のソフトウェア開発の世界は、生成AIの登場により大きな転換点を迎えています。
GitHub Copilot や Claude Code など、生成AIを活用した開発支援ツールが次々と登場し、日常的なワークフローに組み込まれつつあります。
今では当たり前のように日常の開発業務で生成AIを利用している一方で、生成AIに意図したコードを出力してもらえないという声も耳にします。
そこで今回は、生成AIとのVibeCoding *1 をするうえでのコツを幾つか紹介したいと思います。
それでは見ていきましょう!
適切な情報
生成AIに質の高いコードを出力してもらうためには適切な情報が必要です。現状を具体的に把握させることで、より詳細で質の高い出力内容になります。
例えば次のようなプロンプトがあるとします。
`/src/lib/hoge.ts` と `/src/lib/fuga.ts` の既存の処理を参考にして、`/src/lib/piyo.ts` に新しい機能を追加してください。
このプロンプトだと参考にする既存の処理の何を参考にするべきなのかが曖昧です。参考にするべきポイントを明確に伝える必要があります。
- `/src/lib/hoge.ts` と `/src/lib/fuga.ts` の既存の処理を参考にして、`/src/lib/piyo.ts` に新しい機能を追加してください。 - `/src/lib/hoge.ts` の `function aaa()` の実装を参考にして、データ取得処理を実装してください。 - `/src/lib/fuga.ts` の `class Bbb` の実装を参考にして、取得したデータを加工して返す処理を実装してください。
外部データなどを参照させて情報を補完することも有効です。外部データを生成AIに参照させる際にはMCP(Model Context Protocol)サーバーが非常に有用です。
MCPサーバーを介してIssueやライブラリ、デザインデータなどの情報を取得して生成AIに渡すことで、的確なコンテキストを提供できます。これにより生成AIの理解度が向上し、より正確なコード生成が可能になります。
タスク分解
生成AIに多岐に渡って一度に全部依頼してしまうと、コンテキストが肥大化してしまい出力結果の精度が落ちます。
例えば次のような機能要件があるとします。
組織に紐付くユーザー情報に権限情報を付与して、その情報を更新できるAPIを追加する。権限ごとに実行できるAPIを制限する。admin権限の場合、全てのAPIを実行することができる。editor権限の場合、HTTP MethodがGETかPOSTのAPIのみ実行することができる。member権限の場合、HTTP MethodがGETのAPIのみ実行することができる
この要件の内容を全て一度にプロンプトで実行すると確実に出力精度が落ちます。異なる対応を幾つも抱えており、それ全てを一度に実行するためコンテキスト、認知範囲が広がってしまうからです。
このようなケースでは、まず実行したかったプロンプトを修正内容別に分解しましょう。
- 組織に紐付くユーザー情報に権限情報を付与する - その情報を更新できるAPIを追加する - 権限ごとに実行できるAPIを制限する。admin権限の場合、全てのAPIを実行することができる。editor権限の場合、HTTP MethodがGETかPOSTのAPIのみ実行することができる。member権限の場合、HTTP MethodがGETのAPIのみ実行することができる
次に、各修正内容の詳細度を上げていきましょう。
- 組織に紐付くユーザー情報に権限情報を付与する - org_usersテーブルに次の項目を追加する - role - String - 必須 - enum: [admin, editor, member] - default: member - その情報を更新できるAPIを追加する - PATCH /api/v1/orgs/{org_id}/users/{user_id}/role - リクエストボディ - role - String - 必須 - enum: [admin, editor, member] - レスポンス - 200 OK - 更新後のユーザー情報を返す - 権限ごとに実行できるAPIを制限する - admin権限の場合、全てのAPIを実行することができる。 - editor権限の場合、HTTP MethodがGETかPOSTのAPIのみ実行することができる。 - member権限の場合、HTTP MethodがGETのAPIのみ実行することができる
ここまで分解できれば、あとは大項目ごとに生成AIに依頼してPull requestを作成すると良いです。
このように生成AIに依頼するタスクは、コンテキストを絞った明示的な内容に細分化すると、出力精度が上がる傾向にあります。
軌道修正
生成AIに全部を一気に作らせると、意図しない修正だった場合に変更内容を破棄する範囲が広くなってしまいます。
必要な範囲だけ戻せるようにするのがコツです。そのため指示する内容の粒度を細かくして、定期的にコミットしておくと良いです。これはPull requestの粒度よりも、さらに細かい粒度で考えたほうが良いです。
新しいテーブルを追加するタスクを例に説明します。次のようなプロンプトを実行したとします。
次のテーブルを追加してください。 - テーブル名: users - id: Integer, Primary Key, Auto Increment - 苗字: String, Not Null - 名前: String, Not Null
苗字を last_name で作成されましたが、ちょっと分かりづらいので family_name に変更したいため軌道修正するとします。
しかし、この時点で migrationファイルだけでなくモデルファイルが作成され、しかもlocal環境でmigrationまで実行されていたらどうでしょうか?
軌道修正のためにrollbackを実行して、モデルファイルもmigrationファイルも修正する必要があり、変更の破棄に手間と時間がかかってしまいます。
このようなケースでは、まずモデルファイルだけ作り、そこで認識を合わせてからmigrationファイルを作成するような流れでプロンプトを実行すると良いです。
- Userモデルを作成してください。 - id: Integer, Primary Key, Auto Increment - 苗字: String, Not Null - 名前: String, Not Null
このプロンプトでモデルファイルだけ作成され、仮に苗字の項目名が last_name になっていても、モデルファイルだけなら修正は簡単です。次のプロンプトで軌道修正しましょう。
追加したモデルの苗字の項目名を `family_name` に変更してください。
モデルの内容の軌道修正が完了してからmigrationファイルを作成しましょう。
追加したモデルのテーブルを作成するmigrationファイルを作成してください。
このように生成AIに一度に対応してもらう範囲を細かく区切ることで、軌道修正をスムーズに進めることが出来ます。
セッション管理
生成AIとのやり取りは、セッション管理を意識すると効率的になります。
全く関係のない内容を同一セッションで行うと精度が落ちてしまいますが、同じような修正は同一セッションで行うと効率的で精度が上がります。
例えば次のような修正を行うとします。
- 既存のLayoutComponentをコピーして新しいLayoutComponentを作成する - 新しいLayoutComponentを次のように修正する - propsに次の項目を追加する - current_user - User型 - 必須 - props.current_user.roleが 'admin' の場合、管理者用のナビゲーションメニューを表示する - 既存のLayoutComponentを使用している箇所を全て新しいLayoutComponentに差し替える
このタスクを一度に全て実行しようとすると出力結果の精度は落ちます。既存のLayoutComponentを使用している箇所を全て新しいLayoutComponentに差し替える の部分のコンテキストが広すぎて生成AIの認知負荷が肥大化してしまうからです。
このケースの場合、まずは新しいLayoutComponentの作成までを終わらせているのが良いです。なぜなら、LayoutComponentの作成と差し替えは全く異なるタスクだからです。
次に別セッションにしてからLayoutComponentの差し替えに取り組みます。まず、既存のLayoutComponentを使用している箇所を全てリストアップしてもらうプロンプトを実行して、対象ファイルを洗い出します。
洗い出したリストから1つ選択して、まず1箇所だけ差し替えを実行してもらいます。ここでVibeCodingを行って正しい差し替え内容になるように修正してください。これが大きなポイントです。
1箇所の差し替えを正しく実行できたら、セッションを維持したままで次のようなプロンプトを実行してください。
同じような変更を、リストアップした他の箇所にも適用してください。
このやり方により、コンテキストの範囲が一気に肥大化せず、出力精度が極端に落ちることを防ぎながら1つの修正を横展開することが出来ます。
- 差し替えるための新しいLayoutComponentを作成する
- 差し替え対象となるコードを全てリストアップする
- 差し替え対象から1箇所だけ選び、VibeCodingで正しい差し替えを1件完了させる
- リストアップした変更対象に水平展開させる
このように、生成AIとの会話履歴を意識すると、若干曖昧な表現だとしても会話履歴から補完して精度を保つことが出来るケースがあります。
まとめ
VibeCodingの相手は生成AIですが、結局は人間を相手にしていることとあまり変わらず、明確で簡潔な内容を1個ずつ指定することや、会話履歴を意識することが重要であることが分かったかと思います。
今回の記事が皆さんのVibeCodingのヒントになると嬉しいです。
そしてこの度、11月13日(木)に福岡で Findy AI Meetup の開催が決定 しました。
今回は YAPC::Fukuoka の前日の開催 です。県外からの参加者のみなさん、前日入りしてこちらへの参加もぜひ検討ください。
そしてなんと!これまでの福岡での開催が大盛況だったため、 11/17(月)に東京オフィスでのFindy AI Meetupの開催も決定 しました!
こちらの参加もぜひ検討ください。
現在、ファインディでは一緒に働くメンバーを募集中です。
興味がある方はこちらから ↓
herp.careers
*1:OpenAIのAndrej Karpathy氏が2025年2月に提唱した、生成AIに自然言語で指示を与えながら直感的にコードを作り上げていく開発手法