AIをシステム開発に活かすコツ、全部書く

今や、AIを活用してソフトウェア開発すること自体は一般的になり、一種のブームと化している。

しかし、Web上で見かけるのはワンショットでテトリスを作る程度の小規模なプロジェクトの話がほとんどで、驚けるものの、正直あまり実用性は無いように感じる。

俺たちが本当に知りたいのはテトリスの作り方じゃねえ!現実の中規模以上のシステム開発で、いかに楽に良いものを作れるかだろ!

ということで、まずは弊社から現時点のノウハウを全公開しようと思う。

弊社ではCursorを1年以上活用(サービスがGAになったタイミングから全社員で利用)しており、一定のノウハウを蓄積してきている自負がある。ただ、あくまで一例ではあるので、ぜひみなさんの現場での活用事例も共有してほしい!

免責事項

AIエディタでの開発は、LLMとAIエディタの進化に伴い、常に変化している。
そのため、この記事で述べる方法論は、現時点での、弊社での運用プラクティス・知見であることを念頭に置いてほしい。
具体例はCursorを中心に記載するが、ClineやWindsurfなど、どんなAIエディタを使う場合でも適用可能な話を中心に書く。

ただし、内容が古くならないように、可能な限り、原則的な部分に焦点を当てている。

そもそも、なぜテトリス「なら」一瞬で作れるのか?

テトリスが一瞬で作れるのは、確かにすごい。

しかし、テトリスは「難解」ではあるものの「複雑」ではない。

ブロックの形状、落下速度、操作方法、ゲームの目的など、必要な情報は(周知の事実として)全て事前に定義されているからだ。

このようにシステムの設計が完全情報に近い状態であれば、充分に賢ければテトリスを「攻略」できる。もちろんこれ自体、とてもすごいことなのだけれど。

現実のシステムは、複雑

それでは、現実のシステム開発ではどうだろう?

AIは私達が作りたいと考えているシステムのことを、ちっとも知らないのである。

仕様が曖昧で、変更が頻繁に発生し、多くの依存関係が存在する。おまけにコード量も多いから、AIが把握しきれない。

ここにAIを中・大規模なプロジェクトに適用する難しさがある。

システム開発を完全情報ゲームに近づける

現実のシステム開発を成功に導くには、テトリスのような単純化された環境との隔たりを埋める戦略が不可欠だ。

つまり、充分なコンテキストを与え、システムをAIにとっての「完全情報ゲーム」へと近づける必要がある。

AIのための仕様書

そのために、まず一つのキーとなる方法は「AIのための仕様書」を作成することである。

なぜAIはコードだけではシステムを理解できないのだろうか?

それは、ビジネス要件などの背景情報が欠けているからだ。コードだけでは、どんな目的で、どんな制約のもとに書かれたのかが不明だ。

また、そもそも現在のLLMではコンテキスト長に限界があり、全コードを読み込ませること自体、プロジェクトが小さくない限り難しい。

そのため、仕様書には、システムの全体像が把握できるものやビジネス要件などのコードに現れない要件を中心に記載しておくと良い。

書いた仕様書は、docs/フォルダなどにまとめ、適宜@メンションで参照したり、必ずAIに知っておいてもらいたいような重要なことがらについては.cursorrules(あるいは.windsurfrulesや.clinerules)に書くと良い。

内容的には、例えば以下のような内容がカバーできる仕様書があるとよい:

  • システムの目的と概要

  • 主要な機能とその詳細な説明

  • ユーザーインターフェースの仕様(画面レイアウト、操作フローなど)

  • データモデル(データベースの構造、データの流れなど)

  • システムの制約(パフォーマンス要件、セキュリティ要件など)

  • 関連システムとの連携仕様

具体的な記述のコツ

仕様の記述にはMarkdownを用いると良い。

ほとんど全てのLLMが、Markdownの構造を良く理解できるため、見出しや箇条書き、コードブロックなどを活用することで、AIに明確かつ構造的な情報を伝えられる。

また、Mermaid記法による図やファイルツリー構造を使うのもおすすめだ。これによって、AIにとって、より理解しやすい仕様書を作成できる。

Mermaidは、コードを流し読みしただけでは把握しきれないシステムの構造や処理の流れを視覚的に表現できる。
人間の脳にもやさしいし、AIが仕様を理解するうえでも、言語で記載するよりも明確で伝わりやすい傾向にある。

ファイルツリーも以下のような感じで。(ファイルツリーに関しては重要な情報として、.cursorrules上などに記載しておくと良い)

project_name/
├── docs/                      # プロジェクトのドキュメント
│   ├── overview.md            # プロジェクトの概要
│   ├── features.md          # 主要機能の説明
│   ├── api_reference.md     # APIリファレンス
│   └── ...
├── src/                       # ソースコード
│   ├── components/          # UIコンポーネント
│   ├── utils/               # ユーティリティ関数
│   ├── pages/               # ページコンポーネント
│   └── ...
├── tests/                     # テストコード
│   ├── unit/                # ユニットテスト
│   ├── integration/           # 結合テスト
│   └── e2e/                 # E2Eテスト
├── README.md                  # プロジェクトのREADME
└── ...

AIはファイルツリー構造を読み込むことで、プロジェクト全体の構成を把握しやすくなる。

ファイルツリー構造を整備しておくと、特定のファイルを探す手間が省け、AIがコンテキストをより迅速に把握可能になる。
AIエージェントが具体的なファイルを特定する際の道標にもなり、関連性の高いファイルをスムーズに探し出せるようになる。

※なお、Clineを使用している場合、システムプロンプトに自動的にファイルツリーを記述するような実装がされているため、ファイルツリー情報の記載は不要であると思われる。

仕様書は常に最新に

仕様書を書く上では、何を書くか以上に、常に最新の状態に保つことがとても重要だと思う。

書いた仕様書は、タスク作成時に参照させたり、開発時にAIに(手動・自動で)参照させたり、ドキュメントの更新、仕様を参照してお問い合わせに返答する際など、あらゆる場面で活用できる。

一方で、内容が古くなっていると、AIのシステムの認識がおかしくなってしまう可能性がある。

仕様書はSingle Source of Truthとして、常に最新の状態に保つことをおすすめする。

エクストリームモノレポの薦め

AIエディタ内で管理されていない(レポジトリに書かれていない)コードも、当然AIには対応できない。

だからこそ、フロントエンドとバックエンドのコードを単一リポジトリで管理する、いわゆるモノレポ構成をオススメしたい。
仕様書も含めてしまう、一種のエクストリームモノレポとも言える構成にすることで、AIがプロジェクト全体を俯瞰できるようになる。

ただし、現状のLLMやAIコードエディタの性能を考えると、プロジェクトの規模によっては、コンテキストが広すぎることによる混乱も起こりうる。

そのため、プロジェクトの規模や複雑さ、チームの構成(フロントエンド・バックエンドチームが分かれている、など)に応じて、モノレポ構成が最適かどうかはその都度判断する必要がある。

しかし、いまのAI技術の進歩ペースを考慮すれば、将来的にはモノレポ構成がより有効になる可能性が高いと考えている。

AIの暴走を防ぐガードレールの設置

コンテキストをどれだけ与えても、AIが生成するコードにバグがないとは限らない。時には、意図しない挙動をすることもあるだろう。

そこで重要になるのが、AIが「暴れ回っても」大丈夫なように、事前に「ガードレール」を設置しておくことだ。

ガードレールの設置には、主に以下の2つのポイントがある。

  • テストの実施

  • 静的型付け言語の採用

テストの実施

テスト、特にE2Eテストの実施をおすすめする。

AI開発では、内部実装は容易に変更可能であり、今後はその傾向が加速するだろう。Cursorに加え、Devinのような自律型AIエンジニアの普及により、人手を介さずにリリースされるコードが増加していくはずだ。

そこで重要となるのが、システム挙動をいかに保証するかという点だ。全てを人間が目を通してレビューして慎重に動作確認する、というのは破綻せずとも疲弊するだろう。
E2Eテストは、あるべき挙動が意図せず変更されていないかを手軽に担保する上で有効な手段となる。

さらに、テストはAIにコードの期待される挙動を理解させる手がかりともなり、一石二鳥の効果がある。

静的型付け言語の採用

テストより重要度は落ちるが、可能であれば、TypeScriptなどの静的型付け言語を使用すると良い。

CursorなどのAIエディタは、型エラーを自動で修正してくれる機能も備えている。

画像
たとえばこのように、型エラーに気付いて修正してくれる

また、静的型付け言語は、コードの可読性を向上させる効果もある。型が明示的に定義されていることは、AIにとってもヒントになりえる。

AIと実装するコツ

それでは、実装フェーズにおけるAIとの連携について書いていく。

そもそも、AIの得意な言語やフレームワークを利用する

実装に入る前に、そもそもどのような言語やフレームワークを決められるのであれば、AIに最適な技術選定を検討しよう。

基本的には、AIがよく知っている(Web上に知見が多く公開されている)言語を選定するのが良い。

また、頻繁に大きなアップデートがあるような技術はAIが間違えやすいため、ある程度「枯れた技術」であることも重要だと思う。

例えばo1系列のナレッジカットオフは2023年10月だったりするので結構新情報には弱い。

特にライブラリ選定の際には、古い情報を参照してAIが無限に間違えるのがあるあるなので、留意しておくとよいかもしれない

設計と実装フェーズの分離

ここからが本題。

実装においては、設計具体的な実装という2つのフェーズを明確に分離するとよい。

以下のaiderの記事でも、設計・実装のフェーズ分離によってAIのパフォーマンスが大きく向上することが報告されている。

・An Architect model is asked to describe how to solve the coding problem.
・An Editor model is given the Architect’s solution and asked to produce specific code editing instructions to apply those changes to existing source files.
Splitting up “code reasoning” and “code editing” in this manner has produced SOTA results on aider’s code editing benchmark. Using o1-preview as the Architect with either DeepSeek or o1-mini as the Editor produced the SOTA score of 85%. Using the Architect/Editor approach also significantly improved the benchmark scores of many models, compared to their previous “solo” baseline scores (striped bars).

https://aider.chat/2024/09/26/architect.html

具体的には、Clineでは「Architect」モードとして設計のためのモードが入っているので、活用できる。

ClineのChat欄のArchitectモード

CursorやWindsurfにはそのようなモードは無いが、「Ask」モードを指定すると勝手に実装するような挙動を抑え、設計を考えてもらうことが出来る。

なお、Cursorでは「@」から「Codebase」を指定すると、自動的に関連しているファイルをコンテキストに詰めてくれるため、特に設計時に役立つ。

画像
CursorのChat欄のAskモード

実装方針を立てる際に使うべきモデル

実装方針を立てるときには、Reasoningモデルを使うと良い。

Reasoningモデルは、結論をいきなり吐き出すのでは無く、推論してから結論を出すようなモデルのことである。

例えば以下のようなモデルを指す。

  • o1

  • o1-mini

  • o1-pro

  • o3-mini

  • DeepSeek-R1

  • Gemini 2.0 Flash Thinking

  • Claude 3.7 Sonnet (Thinkingモード)

Reasoningモデルはいきなり答えに飛びつかないため、コンテキスト量が増加しても品質は低下せず、もしろより適切な回答が期待できる。

そのため、多くの場合、通常のモデル(Claude Sonnet 3.7など)を利用するよりも、Reasoningモデルを活用する方が、より適切な技術選定や設計が可能になるだろう。

基本的にはCursor上で特別な追加課金無く使える、deepseek-r1やo3-mini-highを使うと良いと考えている。

ただし、高度な設計が求められる局面においては、ChatGPTのo1-proを活用することを検討すると良い。これについては後述する。

実装方針を一緒に渡して実装する

実装方針を決定したら、その内容を確認して必要に応じて修正した上でAIに実装してもらうことで、AIは実装方針に沿ったコードを生成できる。

なお、実装の指示を出す際には、小規模なタスクであれば、設計の内容をそのままAgentに渡すだけで十分だが、中規模以上になるとコンテキストが長くなり、LLMが混乱する傾向にある(特にClaudeのモデルはロングコンテキストに弱く、そもそもAIエディタ側でコンテキストの長さに実はわりときつめの制限がある

そのため、中規模以上のタスクでは、設計内容をファイルに記述し、AIにそのファイルを@メンションして渡しながら、その中のタスクを一つずつ行っていくことをおすすめする。

この方法であれば、AIは常に設計内容を把握しながら実装できるため、文脈が途切れることなく、一貫性のあるコードを生成することが可能になる。

※ただし、このテクニックについては、LLMが処理できるコンテキスト量や賢さが増すにつれて、不要になる可能性はある。

その他のコツ

難しい問題にはo1-proを活用

もしあなたがChatGPT Proの契約をしているのであれば、o1-proの賢さを活さない手はない。ただ、o1-proはAPIでは提供されていないため、ChatGPT経由で利用する必要がある。

そのため、ChatGPTにコードを効率的に投入できるよう、コードを柔軟に・素早くコピー&ペーストできる環境を整えておくと良いだろう。

RepoPromptを活用すれば、リポジトリ全体をAIに読み込ませ、特定のフォルダやファイルを指定して内容をプロンプトに組み込むのも容易になる。

この方法でo1-proにプロジェクトのコンテキストを含めて伝えれば、複雑な課題に対する、より精度の高い解決策が期待できるだろう。

Docs as Codeによるエンドユーザー向けドキュメント管理

MintlifyのようなDocs as Codeツールを使用することで、(ユーザー向けの)ドキュメントをコードと同じモノレポ内で管理できる。

例えば、弊社で利用しているMintlifyにはモノレポ設定が用意されている。

モノレポでこのドキュメントも管理することで、先述した仕様を基に、AIを通じたエンドユーザー向けドキュメントの作成・更新が可能になる。

レポジトリ内でのタスク管理

レポジトリに仕様とコードが揃っていれば、Cursorを活用することで、タスクの作成精度とスピードが向上させることができる。

具体的には、タスクに関連する仕様やコードをCursorで参照し、タスク内容を箇条書きで記述するだけで、より精度の高いタスク定義が可能になる。

さらに、タスクを記述した後は、仕様書の方の更新も、エージェントに依頼すれば完了する。

弊社では、PdM(私)自身がCursor上でタスクの仕様を記述し、PRをDraftとして上げることで開発者に渡すようなフローにしている。

まとめ

色んなトピックを駆け足で書いたので分かりにくいところもあったかもしれない。
AIを開発に活かす系は無限に書けるので、ニーズがあればまた書こうと思う。

頑張って書いたので、ぜひコメントや、スキ、リツイートなどをもらえると嬉しい。

TwitterでもLLMやAIを活用した開発についてつぶやいているので、ぜひフォローしてください!👇
https://x.com/__kmagai__

宣伝1

弊社はファストノートという「Cursorのライティング版」のようなサービスを開発している。
もちろん、このノートもファストノートの助けを借りながら、AIと一緒に書いた。

全てを「AIでバーン!」と生成してしまうのでは無く、書き手のフローを邪魔せずに「AIと一緒に速く良い文章を書く」という思想でやっているので、ぜひ使ってみてください。

宣伝2

お仕事ください!

なんと弊社、今、暇です!リソース空いてます!チャンスです!(2025年3月現在)

開発全般(AI系、Web、モバイルなど、だいたいなんでも作れます)から、コンサルティングまで、まずはご相談ください。

ぜひ私のTwitterやメールまでご連絡ください。
メール: kmagai@then.co.jp


いいなと思ったら応援しよう!

ピックアップされています

#エンジニア 系記事まとめ

  • 1,210本

コメント

ログイン または 会員登録 するとコメントできます。
AIをシステム開発に活かすコツ、全部書く|kmagai
word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word

mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1