Go back

「AI System Design」リポジトリを読んで、LLMアプリの設計で押さえる範囲を整理する

Posted on:

LLMやRAG、AIエージェントを使ったシステムの設計を1つのREADMEにまとめたリポジトリが公開されていました。AIまわりの設計の話は、キャッシュ、RAG、エージェント、評価と、記事ごとに別々に読むことが多いです。全体を1枚の地図として見られる資料は意外と少ないので、中身を読んで整理しておきます。

https://github.com/amitshekhariitbhu/ai-system-design/tree/main

どんなリポジトリか

作者はオンライン教育サービスOutcome Schoolの創設者、Amit Shekhar氏です。2026年9月25日に公開され、ライセンスはApache-2.0です。中身はほぼREADME.md 1ファイルで、英語で約4万語あります。各トピックの詳しい説明は、作者のブログ記事へのリンクで補う作りになっています。

対象読者には、AIを組み込んだプロダクトを作りたいソフトウェアエンジニアや、AIシステム設計の面接を控えた人が挙げられています。後半に面接での解き方の手順と頻出問題が載っているので、面接対策の教材という性格も強めです。

AIシステム設計は何が違うのか

READMEは、AIシステム設計を次の式で説明しています。

AI System Design = System Design + The new constraints of AI models.

ロードバランサー、キャッシュ、キュー、データベースといった従来のシステム設計の部品は、そのまま使います。違うのは、真ん中にLLMが入ることで増える制約です。READMEが挙げているのは次の6つです。

  • GPU:LLMはCPUではなくGPUで動き、GPUは高価で数も限られる
  • トークン:入力も出力もトークン単位で課金される
  • 長いリクエスト:1回の呼び出しに数十秒から数分かかる
  • ストリーミング:応答は1トークンずつ流れてくる
  • 非決定的な出力:同じ入力でも出力が変わるので、普通の単体テストが効かない
  • リクエストごとのコスト:ループのバグ1つで一晩に数千ドルが溶けることもある

例として、カスタマーサポートのチャットボットが挙がっていました。LLMのAPIを呼ぶスクリプトなら10行で書けます。しかし10万人のユーザーに対して、1秒以内に応答を返し始め、自社のドキュメントに基づいて答え、個人情報を漏らさず、月の予算に収めるとなると、それはもう設計の問題です。この対比がわかりやすかったです。

扱っている範囲

目次は、下の層から上の層へ積み上げる順に並んでいます。ざっくり分けると次のとおりです。

  • 推論の基盤:推論サーバー(vLLM、SGLangなど)、GPU・TPU・LPU、プリフィルとデコード、並列化とスケーリング
  • コストと速度:KVキャッシュ、プロンプトキャッシュ、セマンティックキャッシュ、LLMルーティング
  • 検索:埋め込み、ベクトルDB、RAG(チャンク分割、ハイブリッド検索、リランキング、GraphRAGなど)
  • コンテキスト:コンテキストウィンドウの管理、コンテキストエンジニアリング、コンパクション
  • 配信:ストリーミング、非同期処理、レート制限、AIゲートウェイ
  • エージェント:エージェントループ、ツール呼び出し、MCP、Agent Skills、メモリ、マルチエージェント、A2A
  • マルチモーダル:音声エージェント、エッジAI
  • 安全と品質:ガードレール、プロンプトインジェクション、プライバシー、オブザーバビリティ、評価
  • 運用:プロンプト管理、コスト最適化、マルチテナント、ファインチューニング、推論の最適化、障害対策

GPUの話からエージェントの話までを1本の流れで読めるのは、この資料ならではです。

読んで押さえておきたいと思った点

全部を紹介すると元のREADMEと変わらないので、APIを使ってアプリを作る側として、特に押さえておきたいと思った点を拾います。

レイテンシは2つの指標で見る

LLMの推論は、入力をまとめて処理する「プリフィル」と、出力を1トークンずつ作る「デコード」の2段階に分かれます。プリフィルは計算量が律速で、最初のトークンが出るまでの時間(TTFT)を決めます。デコードはメモリ帯域が律速で、1トークンごとの生成時間(TPOT)を決めます。

APIを使う側でも、この区別は効きます。長いプロンプトを送ればTTFTが伸び、長い出力を求めればTPOTの積み重ねで全体が伸びます。「遅い」と感じたとき、どちらが原因かを切り分ける物差しになります。

キャッシュは4種類ある

AIのキャッシュは、目的が違う4種類に整理されていました。

  • KVキャッシュ:推論エンジンの内部で、計算済みのKeyとValueを使い回す
  • プロンプトキャッシュ:システムプロンプトなど、毎回同じ先頭部分の処理を使い回す
  • セマンティックキャッシュ:意味が近い質問に、過去の応答を返す
  • 埋め込みキャッシュ:同じテキストの埋め込みを再計算しない

API利用者が直接触れるのは、プロンプトキャッシュとセマンティックキャッシュです。プロンプトキャッシュを効かせるには、変わらない部分をプロンプトの先頭に寄せる設計が要ります。セマンティックキャッシュは、類似度のしきい値と、テナントをまたいで応答を返さない分離が肝になります。

モデルは使い分ける

LLMルーティングは、問い合わせごとに適切なモデルへ振り分ける仕組みです。READMEは5つの方式を挙げています。ルールベース、分類器ベース、埋め込みベース、LLM自身に振り分けさせる方式、そして安いモデルから試して駄目なら上位モデルに上げるカスケードです。

後半のCursorの事例がよい具体例になっていました。タブ補完は小さく速いモデル、チャットとエージェントは大きく賢いモデル、変更の適用は小さく速い専用モデルと、仕事ごとにモデルを分けています。1つの強いモデルで全部をこなすより、速さとコストの両方で有利になります。

AIゲートウェイで入口をまとめる

すべてのLLM呼び出しを1つの層に通す「AIゲートウェイ」も、独立した節で扱われていました。複数プロバイダー間のフェイルオーバー、コストの集計、レート制限、キャッシュ、ガードレール、ログを1か所にまとめる層です。

レート制限の考え方も従来と少し違います。リクエスト数だけでなく、1分あたりのトークン数、同時実行数、金額でも制限をかけます。1リクエストの重さが桁違いにばらつくので、回数だけでは守れないからです。

エージェントとワークフローを分けて考える

エージェントの節では、「AIオーケストレーション」と「AIエージェント」を区別しています。処理の流れを開発者が決めるのがオーケストレーション、LLMが決めるのがエージェントです。READMEの立場は、まず固定のワークフローから始め、手順を事前に決められないときだけエージェントを使う、というものです。実際のシステムでは、全体の流れはワークフローで組み、先の読めない1ステップの中だけをエージェントに任せる形が多いとしています。

もう1つ印象に残ったのは、「LLMはツールを勧めるだけで、実際に呼ぶのはこちらのコード(ハーネス)だ」という整理です。プロンプトインジェクションへの対策も、この考え方の延長で説明されています。権限を最小にする、実行の前にコードで関門を置く、人の承認を挟む、信頼できない入力を読むLLMと実行権限を持つLLMを分ける、という4つです。

評価パイプラインが単体テストの代わり

出力が非決定的なので、AIシステムの品質は単体テストでは測れません。代わりに、期待する回答つきの評価セットを用意し、LLMに採点させる「LLM as a Judge」や、人の目でのサンプル確認を組み合わせます。プロンプト、モデル、チャンク分割のどれかを変えるたびに評価を回さないと、変更が改善なのか後退なのか判断できない、という主張でした。

8ステップの解き方

後半の中心は、AIシステム設計の問題を解くための8ステップです。

  1. 要件(Requirements)
  2. AIの目的(AI Objective)
  3. データ準備(Data Preparation)
  4. アーキテクチャ設計(Architecture Design)
  5. モデル選定とプロンプト(Model Selection and Prompting)
  6. 評価(Evaluation)
  7. デプロイと配信(Deployment and Serving)
  8. 監視(Monitoring)

SaaS企業のサポートチャットボットを例に、各ステップが具体的な数字つきで埋められています。ユーザー10万人、1日5万チャット、最初のトークンまで1秒以内、月の予算5,000ドル、ヘルプ記事500本という条件です。

そこから導かれた構成は次のとおりでした。

User -> Backend -> Embedding Model -> Vector DB (top 50 chunks)
                                              |
                                              v
                                      Reranker (top 5 chunks)
                                              |
                                              v
                          LLM (system prompt + chunks + question)
                                              |
                                              v
                                       Streamed Response

目を引いたのは、選択がかなり地味なことです。この規模なら専用のベクトルDBは要らないとして、PostgreSQLのpgvectorを使います。GPUを自前で持たず、モデルはAPIで済ませます。普段は安いHaiku 4.5で答え、わからないときだけSonnet 4.6に上げる構成です。評価には手で選んだ200問を使い、公開は1割のユーザーから始めるカナリアリリースです。監視のアラートも「1日のコストが200ドルを超えたら」「高評価率が80%を下回ったら」と具体的に決められています。

ステップの最後には、次の注意書きがありました。

Do not over-engineer. Start with the simplest design that works (a single LLM call), and add complexity only when needed.

前半であれだけ多くの部品を紹介したあとに、「まずはLLM呼び出し1回から始めろ」と締めているのが、この資料の一番誠実なところだと感じました。

事例としてのClaude Code

事例の1つ目はClaude Codeでした。コンテキストを集め、行動し、結果を確かめる、というループを軸に、READMEで紹介した部品がどこに使われているかを対応づけています。

  • ツール呼び出し:ファイルの検索・読み込み・編集、コマンド実行
  • 検証:テストを実行して、変更が本当に動くかを確かめる
  • メモリ:CLAUDE.mdをプロジェクトの記憶として毎回読み込む
  • ガードレール:実行前に承認を求める権限設定
  • サブエージェント:大きな検索を別のコンテキストで走らせ、本体を汚さない
  • コンパクション:長いセッションを要約して作業を続ける
  • Agent SkillsとMCP:作業の流儀と外部ツールをつなぐ

普段Claude Codeを使っていると当たり前に見える仕組みが、一般的な設計要素の組み合わせとして説明されているのは新鮮でした。サブエージェントやコンパクションを「コンテキストウィンドウを管理するための手段」として位置づけ直すと、自分でエージェントを組むときにも同じ道具を使えることがわかります。

読んでみて

APIでLLMを使ってアプリを作る立場から見ると、このREADMEは前半と後半で距離感が違います。GPUの種類、並列化、推論エンジンの選び方といった前半の話は、モデルを自前でホストする人向けです。自分の手元で効いてくるのは、キャッシュ、ルーティング、ゲートウェイ、評価、ガードレールといった、LLMの外側を組む話のほうでした。

それでも前半を読む意味はあると思います。プリフィルとデコードの違いやKVキャッシュの仕組みを知っていると、APIの料金体系やプロンプトキャッシュの効き方に納得がいきます。ブラックボックスのまま使うより、中で何が起きているかの見当がつくほうが設計の判断はしやすくなります。

注意点もあります。面接対策の色が強く、各節の詳細は作者のスクールのブログに誘導する作りです。挙がっているモデル名や数字も執筆時点のものなので、そのまま採用するより、考え方の型として読むのがよさそうです。

AIまわりの設計で「何を考えなければいけないか」の抜け漏れを確認するチェックリストとして、手元に置いておきたい資料でした。