はじめに
LLMを使ったデモを作るだけなら、いまや半日もかかりません。PDFを読み込ませて、チャンクに分けて、ベクトル化して、検索してプロンプトに詰める。動くものはすぐにできます。
問題はその先です。「動くもの」を「業務で使えるもの」に引き上げようとした瞬間に、検索がノイズを拾う、コストが跳ね上がる、レイテンシが読めない、たまに堂々と嘘をつく、といった現実がまとめて押し寄せてきます。この落差を埋める方法論は、フレームワークのチュートリアルにはほとんど書かれていません。
本書『実践 LLMアプリケーション開発』は、まさにそのギャップを主題に据えた一冊です。タイトルにある「プロトタイプを脱却し」という副題が、本書の性格をそのまま言い表しています。
本記事では、設計・アーキテクチャに関心のあるエンジニアの視点から、本書の構成と読みどころを整理してご紹介します。
書籍情報
| 項目 | 内容 |
|---|---|
| 書名 | 実践 LLMアプリケーション開発 ―プロトタイプを脱却し、実用的な実装に迫るための包括的な手引き |
| 原書 | Designing Large Language Model Applications |
| 著者 | Suhas Pai |
| 監訳 | 金本 勝吉 |
| 訳 | オライリー・ジャパン編集部 |
| 出版社 | オライリー・ジャパン |
| ISBN | 978-4-8144-0131-4 |
| 構成 | 3部・全13章 |
著者のSuhas Pai氏は、AI&フィンテック系スタートアップHudson LabsのCTO兼機械学習研究責任者です。オープンソースLLMのBLOOMプロジェクトにも関わっており、研究と実装の両側から書かれた本になっています。
本書の立ち位置
本書のスタンスは「はじめに」で明確に宣言されています。
- 対象読者は、AIアプリケーション開発に転向するソフトウェアエンジニア、機械学習の実務者・研究者、プロダクトマネージャー
- 前提知識はPythonと、基本的な機械学習・深層学習の理解のみ
- 数式は最小限に抑え、直感的な理解を優先する
- 演習が80以上、参照した研究論文は800本以上
また、あえて扱わない領域も明示されています。多言語モデル、マルチモーダルモデル、理論的・数学的な深掘り、そして論理的推論モデル(Reasoning Model)の詳細です。最後の点について著者は、執筆時点ではまだ黎明期で有効な手法が定まっていないから、という理由を挙げています。この「時代の変化に耐えられそうにないトピックは意図的に外す」という編集判断は、動きの速い分野の技術書としてかなり誠実だと感じました。
一方で、この判断は本書の賞味期限に直結する部分でもあります。特に推論モデル周りは本書執筆後の一年で大きく状況が変わっているため、そこは別の情報源で補う必要があります。
全体構成
3部構成で、階層がはっきり分かれています。
| 部 | 章 | テーマ |
|---|---|---|
| 第1部 | 1〜4章 | LLMの構成要素(データ・語彙・アーキテクチャ) |
| 第2部 | 5〜9章 | LLMの活用(選定・ファインチューニング・アライメント・推論最適化) |
| 第3部 | 10〜13章 | アプリケーションのパラダイム(ツール利用・埋め込み・RAG・デザインパターン) |
面白いのは、この構成が「下のレイヤーから積み上げる」という順序になっている点です。アプリケーション開発が目的の本でありながら、事前学習データやトークナイザーの話から始まります。
著者はその理由を、事前学習の段階で下された選択が下流タスクの性能に直結するからだと説明しています。食品を買うときに成分表示を確認するのと同じで、業務で使う前にそのモデルが何からできているのかを知っておくべきだ、という比喩が使われていました。
この構成は、アーキテクチャに関心のある読者ほど納得しやすいはずです。ミドルウェアの内部構造を知らないままチューニングしても限界があるのと、まったく同じ話だからです。
第1部:LLMの構成要素
1章 イントロダクション
言語モデルの定義、スケーリング則、簡単な歴史、プロンプティング手法の整理が並びます。
歴史パートでは1960年代のELIZAまで遡り、ルールベースの正規表現マッチングだけでどこまで会話が成立するかを実際に触ってみるよう促されます。LLM全盛の今でもルールベースを使うことをためらう必要はない、という指摘は現実的です。
章の終盤で「Chat with my PDF」という最小構成のチャットボットを作り、そのプロトタイプが本番運用ではなぜ通用しないのかを列挙します。そして、その不具合の一つひとつが以降のどの章に対応するのかを対応表のように示してくれます。本書全体の地図がここで提示される形です。
- 専門ドメインに弱い → 6章・7章(ファインチューニング)
- 嘘をつく → 8章(ハルシネーション対策)
- 遅い・高い → 9章(推論最適化)
- 検索がノイズを拾う → 11章(埋め込みとチャンク分割)
- 外部システムと繋ぎたい → 10章(ツール利用)
読み終えたあとに1章へ戻り、最初に作ったプロトタイプを改善してみる、という読み方が推奨されています。この往復構造はよくできていると思いました。
2章 事前学習データ
事前学習データセットの構築工程が、パイプラインとして分解されます。
- 言語識別
- テキスト抽出とクリーニング
- 品質フィルタリング
- 重複排除
- 個人識別情報(PII)の除去
- 評価セット混入の除去
- データの混合
このリストは、そのままデータ基盤の設計チェックリストとして読めます。特に「評価セットの混入除去」は、ベンチマークスコアの信頼性を左右する話で、モデル選定の際に効いてきます。
3章 語彙とトークン化
トークナイザーの二つの役割(語彙の構築と、推論時のテキスト→トークン列変換)を押さえたうえで、BPEやWordPieceといったアルゴリズムを扱います。
実際に語彙の中身を覗いてみると、モデルが扱うトークンは人間が直感的に思う「単語」とは一致しない、という体験が用意されています。日本語では1文字がさらにバイト列に分解されることもある、という訳注も付いていて、非英語圏の実装者にはありがたい配慮です。
4章 アーキテクチャと学習目的
自己注意、位置符号化、フィードフォワード・ネットワーク、レイヤー正規化と、Transformerの構成要素を一つずつ解説します。エンコーダのみ/エンコーダ・デコーダ/デコーダのみの三系統に加えて、混合エキスパート(MoE)モデルにも触れています。
章の締めくくりでは、チェスの棋譜だけを学習させた「Chess-GPT」をゼロから訓練する話が出てきます。次トークン予測という枠組みが、離散的な系列であれば言語以外にも適用できるという実例です。有限の語彙で離散系列として表現できる現象なら何でもモデル化できるかもしれない、という視点は応用を考えるうえで刺激的でした。
第2部:LLMの活用
5章 LLMをユースケースに合わせる
モデル選定の章です。オープンソースとプロプライエタリの比較、評価ベンチマークの読み方、ロード方法、デコーディング戦略(貪欲法、ビームサーチ、Top-k、Top-p)、構造化出力までを扱います。
評価について書かれていた指摘が、実務的で印象に残りました。リーダーボードは更新のたびにモデルを乗り換える必要はない、上位モデル同士の差はごくわずかで、実際の成否はデータの整形や理解といった別の要因で決まることがほとんどだ、という趣旨です。
ベンチマークがゲーム化されやすいという問題にも触れつつ、既存のベンチマークを出発点として自分たちの目的に即した独自ベンチマークを作るべきだ、という順序を示しています。
解釈可能性のパートでは、GoogleのLIT-NLPを使って注意機構の可視化、サリエンスマップ、反事実分析を行う手順が紹介されます。「なんとなく精度が出ない」を「どのトークンが誤答に効いているか」まで落とし込む道具立てです。
6章・7章 ファインチューニング
6章が基礎、7章が応用という分担です。
6章では、ハイパーパラメータ選択のトレードオフを一通り通したうえで、インストラクション・チューニング用データセットの作り方を扱います。公開データセットの活用と、LLM自身に生成させる方法の両方が出てきます。
7章では以下が扱われます。
- 継続事前学習(リプレイ/メモリ、パラメータ拡張による破滅的忘却の抑制)
- PEFT(ボトルネック・アダプター、プレフィックス・チューニング、プロンプト・チューニング、重みのサブセット選択)
- モデルのアンサンブル、マージ/フュージョン、アダプターのマージ
重要なのは、両章の締めくくりで「ファインチューニングは万能ではない」と繰り返し釘を刺している点です。新しい能力や知識を効果的に学習できるとは限らない、と明言されています。
8章 アライメントと論理的推論
ハルシネーションと推論能力の限界を、緩和手法とセットで扱う章です。
ハルシネーション対策として、自己整合性、検証の連鎖、Recitation、サンプリング手法、レイヤーを対照させたデコーディングが並びます。さらに「コンテキスト内ハルシネーション」「無関係な情報によるハルシネーション」といった、外部から与えた情報が原因で起きるケースも分類されています。RAGを組む人にとってはここが実質的な前提知識になります。
推論については、演繹・帰納・アブダクション・常識という四つの型に整理したうえで、検証器の導入、推論時の計算量スケーリング、推論のためのファインチューニングを紹介しています。
9章 推論の最適化
非機能要件の章です。最適化手法が目的別に整理されています。
| 目的 | 手法 |
|---|---|
| 計算量の削減 | KVキャッシュ、早期終了、知識蒸留 |
| デコーディングの高速化 | 投機的デコーディング、並列デコーディング |
| メモリ使用量の削減 | 対称量子化、非対称量子化 |
スマートフォンのようなエッジデバイスでの制約にも言及があります。この分類のしかたは、性能問題に直面したときに「どの軸で殴るか」を決めるための地図として使えます。
第3部:LLMアプリケーションのパラダイム
ここからがアーキテクチャの話になります。個人的にはこの第3部が本書の主戦場だと感じました。
10章 LLMから外部ツールを利用する
エージェントの章です。まず著者は、あえて保守的な定義を採用すると宣言します。エージェントとは、タスクを完了するために環境と相互作用しながら自律的な行動をとることができるLLMベースのソフトウェアシステムである、という定義です。
条件を満たしていなくても「エージェント型」を名乗る風潮への牽制が、はっきり書かれています。要件は二つ、自律性と、環境と相互作用する能力です。
そのうえで、エージェント型システムを六つの構成要素に分解します。
- モデル ── 役割ごとに複数使い分ける。簡単なタスクは小型モデルへ
- ツール ── コードインタプリタ、検索、DB、各種API
- データストア ── 外部知識の置き場
- エージェント・ループ ── ReAct、リフレクションなどのシステムプロンプト設計
- ガードレールと検証器 ── 有害表現検出、PII検出、入力フィルタ、出力検証
- オーケストレーション・ソフトウェア ── 状態管理、ツール呼び出し、ログ記録
この分解は、そのままコンポーネント図として使える粒度になっています。「エージェント」という曖昧な言葉を、責務を持ったモジュールの集合に落とし込んでくれるのが、この章の一番の価値だと思いました。
実装上の注意も率直です。
- ReActは広く使われているが万能ではない
- リフレクションは有効性が過大評価されがちで、多用するとモデルが推測に推測を重ねる
- LLMに自分自身の出力を検証させるアプローチには注意が必要
- プロトタイピングならLangChainやLlamaIndexが使いやすいが、本番前提ならゼロから構築するか既存OSSを拡張することも検討すべき
そして、エージェント型システムこそKISS原則を強調すべきかもしれない、説得力のある理由がない限りアーキテクチャを複雑にするな、と結ばれています。フレームワークを重ねがちなこの領域で、この一文は効きます。
11章 表現学習と埋め込み
埋め込み、意味検索、類似度、埋め込みモデルのファインチューニング、そしてチャンク分割を扱います。
チャンク分割の戦略が、難易度順に並んでいるのが親切です。
- スライディング・ウィンドウ(隣接チャンクの文脈を取りこぼさない)
- メタデータ利用(段落・節の境界で切る)
- レイアウト利用(CVで見出しやフォントサイズを抽出して切る)
- 意味的なチャンク分割
- レイトチャンク分割
埋め込み検索では各ベクトルが孤立した島のように存在し、島同士の関係が見えない、という説明が挿入されていて、なぜこれらの工夫が必要なのかが腑に落ちます。
この章で最も実務的だと感じたのは、文書のパース処理に関する記述です。RAGの失敗の多くはパース品質の低さに起因すること、著者自身がNLPパイプラインで最も時間と労力を費やしたのがこの工程だったこと、決して華やかではないが軽視すると後で代償を払うこと。ここは太字で読みたいくらいの指摘でした。
埋め込みの容量最適化として、マトリョーシカ埋め込み、バイナリ/整数埋め込み、直積量子化も紹介されています。ベクトルDBの選定と合わせて、コスト設計に直結する部分です。
12章 RAG
本書で最も分量が割かれている章です。RAGのパイプラインを六段構えで定義します。
書き換え → 検索 → リランク → リファイン → 挿入 → 生成
Rewrite → Retrieve → Rerank → Refine → Insert → Generate
各ステップの役割は次のとおりです。
| ステップ | 役割 |
|---|---|
| 書き換え | クエリ空間とドキュメント空間の語彙ギャップを埋める |
| 検索 | 再現率重視で候補を広く取る |
| リランク | 適合率重視で上位k件に絞る |
| リファイン | コンテキスト長に収め、モデルが使いやすい形に整える |
| 挿入 | プロンプトへの入れ方と順序を設計する |
| 生成 | 応答を生成。検索と生成を交互に繰り返す構成もある |
各ステップの出力に対して「検証」を挟める点、そして検索と生成以外はすべて任意で、性能とレイテンシのトレードオフで採否を決める点も明記されています。この「全部入りが正解ではない」という書き方が良いところです。
RAGの限界についても、逃げずに書かれています。
- 断片に依存するため、問題空間を深く理解せず表層的な応答になりうる
- 検索がパイプライン全体の性能上限を決めてしまう
- 取得した情報がモデル内部の知識と矛盾したとき、真の正解を知らない状態での解消は困難
最後の点に関連して、RECALLというベンチマークの知見が紹介されます。論理的に矛盾する情報を与えられた場合はモデル内部の知識を優先し、事実的に矛盾する場合はプロンプト中の情報を優先する傾向がある、という報告です。さらに、矛盾に直面するとモデルの確信度が明確に下がるため、出力確率を後段の判断材料に使えるという実装上のヒントも添えられています。
「RAGかロング・コンテキストか」の議論では、Needle in a Haystackテストの限界が指摘されます。あの手のテストは想起能力しか測っておらず、現実の問題は針を干し草から探す形をしていないことが多い、という趣旨です。また、実世界では隣接する段落は互いに関連しているのに、テストでは無関係な文が詰められている、という指摘も的確でした。
コスト観点での比喩がわかりやすかったので紹介します。検索を捨ててロング・コンテキストに全面依存するのは、ディスクを使わずファイルをすべてRAMに置くようなものだ、というものです。
「RAGかファインチューニングか」については、外部知識を必要とするタスクではRAGのほうが一貫して良い結果を出したという比較研究を引きつつ、多くのユースケースではRAGだけで十分でファインチューニングは第一選択ではない、と結論づけています。そのうえで、ドメイン特化やフォーマット制御のためにファインチューニングしてからRAGで知識を補う、という併用パターンも提示されます。
13章 デザインパターンとシステムアーキテクチャ
最終章はアーキテクチャの総まとめです。
マルチLLMアーキテクチャとして、三つのパターンが提示されます。
LLMカスケード
入力をまず小型モデルに通し、確信度がしきい値を超えれば採用、下回れば中型・大型へ順に送る構成です。多くの入力が小型で処理できる場合に効果を発揮します。確信度の測り方として、エンコーダモデルなら確率スコア、デコーダモデルなら自己整合性、あるいはマージンサンプリング(最有力トークンと次点との確率差)が挙げられています。
ルーター
入力を最初に分類し、適切なモデルへ一度だけ振り分ける構成です。カスケードと違って逐次実行が不要なぶん効率的ですが、振り分け精度に性能が支配されます。インテント分類として実装する例や、RAGパイプラインで複数のリトリーバーを振り分ける使い方も紹介されています。
タスク特化型LLM
複雑なクエリを高性能モデルでサブタスクに分解し、ルーターが各サブタスクを特化モデルに割り当てる構成です。
この三つは、コストとレイテンシを設計変数として扱うための語彙になります。章内の演習では、あるエージェントをタスクに分解し、各タスクに必要な能力を満たす最小のモデルを割り当てて、最大モデルで全部処理した場合とのコスト差を試算せよ、という課題が出されます。実務でそのまま使える演習です。
後半はプログラミングパラダイムとして、DSPyとLMQLを扱います。
DSPyは、アプリケーションの制御フローと、プロンプト調整のような反復作業が必要な可変要素を分離するフレームワークです。制御フローを担うのがモジュール、可変要素を更新するのがオプティマイザ、という役割分担になっています。
import dspy
# 入出力の仕様をシグネチャとして宣言する
summarizer = dspy.ChainOfThought("document -> summary")
document -> summary のように入出力仕様を宣言し、CoTのようなプロンプティング手法はモジュールとして抽象化されます。オプティマイザは指示文・フューショット事例・モデルパラメータを、指定した評価指標に沿って更新します。
ただし著者は現状の課題も指摘しています。オプティマイザが反復作業をすべて自動化できるとは限らず、手動調整が必要になることが多い。多くのケースで独自オプティマイザを書くことになるだろう、と。
LMQLはPythonのスーパーセットで、プロンプト・出力制約・制御フローを宣言的に書ける言語です。where 句で停止条件などの制約を与えられます。
そして章全体の結論として、開発者コミュニティはまだ成熟の途上にあり、実績のあるデザインパターンが登場するにはもう少し時間が必要だ、と率直に述べています。パターンを提示する本でありながら、それが暫定解であることを認めているわけです。
設計視点で刺さったポイント
改めて、アーキテクチャに関心のある読者向けに要点を整理します。
1. LLMを独立コンポーネントとして扱わない
本番運用に耐えるシステムは、複数のソフトウェアとモデルから構成される「システム」です。単体のLLMをどう賢くするかではなく、どう組み合わせるかが設計の主題になる、という視点が一貫しています。
2. コストとレイテンシを設計変数として明示的に扱う
カスケード、ルーター、タスク特化型という語彙を得ることで、「とりあえず最強のモデルを叩く」以外の選択肢が具体化します。既存システムでいうキャッシュ階層やCDNの設計に近い発想です。
3. 地味な工程が品質を決める
文書のパース処理がRAG品質を左右するという指摘は、データパイプラインを組んだことがある人ほど響くはずです。前処理の品質が下流すべてを規定するという構図は、LLM以前から変わりません。
4. 手法の限界を必ずセットで語る
ファインチューニングは万能ではない、ReActは万能ではない、リフレクションは過大評価されがち、RAGは限界がある、デザインパターンはまだ成熟していない。売り込みではなくトレードオフとして書かれているので、判断材料として使えます。
5. 過去のアイデアは循環する
監訳者まえがきで強調されている視点です。RAGの背後にあるリトリーバー・リーダー方式は2017年、BM25は1994年、TF-IDFは1972年まで遡ります。いま最先端に見えるものの多くは、既存分野の蓄積の上に乗っています。情報検索の基礎を知っている人ほど、この分野での立ち上がりは速いはずです。
読み方の提案
本書は関心に応じた読み進め方が提示されています。それを踏まえつつ、目的別に整理し直すと次のようになります。
| 目的 | 推奨する章 |
|---|---|
| LLMの全体像を掴みたい | 1〜5、10、11章 |
| プロダクト企画の判断材料が欲しい | 1〜3、5、8、10〜13章 |
| 研究テーマを探したい | 7〜12章 |
| モデルをゼロから構築したい | 2〜5、7章 |
| アプリケーションを設計・実装したい | 5、8〜13章 |
設計・アーキテクチャ目的であれば、第3部(10〜13章)から読み始めて、詰まったところで前に戻る読み方も十分に成立します。ただし8章のハルシネーション分類は12章の前提になっているので、RAGを組む前に目を通しておくことをおすすめします。
演習は80以上ありますが、全部やろうとすると相当な時間がかかります。自分の関心領域の章だけでも手を動かすと、読むだけの場合とは理解の質が変わります。
注意点
いくつか、購入前に把握しておくとよい点があります。
- 原書のGitHubリポジトリが未完成:訳書の注記によれば、2025年8月時点でサンプルコードやデータセットが揃っていない箇所があります。演習を全部こなす前提で買うと期待とずれる可能性があります
- 翻訳の制作にAI翻訳が使われている:訳書には検証を経ている旨の記載がありますが、この点は明示されています
- 推論モデルの扱いは軽い:意図的な判断ではあるものの、この領域は本書執筆後に大きく動いています
- 日本語・多言語の話題は対象外:英語のLLMに焦点が当てられており、日本語特有の課題は別途調べる必要があります
- 網羅性ゆえに厚い:全13章それぞれが独立した解説として成立するボリュームで、通読には腰を据える必要があります
まとめ
本書の価値は、LLMアプリケーション開発を「システム設計の問題」として扱い切った点にあると思います。
プロンプトの書き方でもなく、特定フレームワークの使い方でもなく、コンポーネントの責務分割・トレードオフ・非機能要件という、これまで積み上げてきた設計の語彙でLLMアプリケーションを語り直してくれます。だからこそ、モデルの詳細に詳しくないバックエンドやアーキテクチャ寄りのエンジニアにとって、入口として機能します。
特に次のような状況にある方には、費用対効果が高い一冊だと思います。
- 社内PoCは動いたが、本番化の判断ができずに止まっている
- RAGを組んだが精度が出ず、どこから手を付けるべきか分からない
- 「エージェントを作る」と言われたものの、何を作るのか輪郭が掴めない
- 生成AI関連のコストが読めず、削減の打ち手を探している
逆に、特定フレームワークのハンズオンを期待している方や、最新の推論モデルの動向を追いたい方には、狙いがずれます。本書は「いま何を使うか」ではなく「どう判断するか」を扱う本です。
監訳者まえがきにある「モデルの気持ちになりきる」という言葉が、読了後に効いてきます。内部が見えないブラックボックスに対して、訓練データや語彙やアーキテクチャの知識を手がかりに挙動の見当をつける。それは、ミドルウェアやOSの内部を知っている人がシステムの不調を推測する営みと、そう変わりません。
LLMを「よくわからないが賢いAPI」として扱う段階を抜けて、設計対象として向き合いたい方におすすめします。