9.6.3 LangChain / LangGraph
- LangChain がどんな場面に向いているかを理解する
- LangGraph がなぜ複雑な状態フローに向いているのかを理解する
- 「チェーン型の抽象化」と「グラフ型の抽象化」の本当の違いを読み取れるようになる
- いつチェーン型の流れからグラフ型の流れに切り替えるべきか判断できるようになる
なぜ先に LangChain が生まれ、あとから LangGraph が出てきたのか?
Section titled “なぜ先に LangChain が生まれ、あとから LangGraph が出てきたのか?”初期の要件はたいてい直線的
Section titled “初期の要件はたいてい直線的”多くの LLM アプリは、最初はこんな形です。
- 入力を受け取る
- クエリ を書き換える
- 文書を検索する
- モデルに回答させる
この流れは、まるで 1 本の直線のようです。
前のステップの出力を、次のステップに渡す。
この場合、「chain(チェーン)」はとても自然な抽象化です。
でも、システムはすぐに複雑になる
Section titled “でも、システムはすぐに複雑になる”次のような要件が出てきたら、どうでしょう。
- 検索結果が空だったらどうする?
- 回答が信用できないときは再試行する?
- 先に tool を呼び出して、それから Q&A に戻るべき?
- 場合によっては人の確認が必要
こうなると、流れはもはや一直線ではありません。むしろ、
- 分岐がある
- 状態がある
- ループがある
という構造になります。
このとき必要なのは、単に「手順をつなぐ」ことではなく、
状態と辺を明示的に表すこと。
これが LangGraph が重要である理由です。
まず LangChain を理解する:何を抽象化しているのか?
Section titled “まず LangChain を理解する:何を抽象化しているのか?”最も向いているのは「コンポーネントのパイプライン」
Section titled “最も向いているのは「コンポーネントのパイプライン」”LangChain の典型的な強みは、次のようなものをつなげることです。
- prompt テンプレート
- モデル呼び出し
- 出力のパース
- 検索モジュール
- tool モジュール
こう考えるとわかりやすいです。
コンポーネントのオーケストレーション層に近いフレームワーク。
つまり、「プロンプト、モデル、検索器、パーサー」といった部品を、組み立てやすいブロックにしてくれるイメージです。
最小限のチェーン思考の例
Section titled “最小限のチェーン思考の例”次の例は実際の LangChain ではありませんが、LangChain 風の考え方を表しています。
class SimpleChain: def __init__(self, steps): self.steps = steps
def run(self, value): for step in self.steps: value = step(value) return value
def normalize_query(text): return text.strip().lower()
def retrieve_docs(query): if "返金" in query: return {"query": query, "docs": ["コース購入後 7 日以内なら返金できます"]} return {"query": query, "docs": []}
def format_answer(payload): if payload["docs"]: return f"資料によると:{payload['docs'][0]}" return "関連資料が見つかりませんでした。"
chain = SimpleChain([ normalize_query, retrieve_docs, format_answer])
print(chain.run(" 返金ポリシーは何ですか? "))想定出力:
資料によると:コース購入後 7 日以内なら返金できますこの例で一番覚えるべきことは?
Section titled “この例で一番覚えるべきことは?”この例が表しているのは、とてもシンプルな考え方です。
各ステップは 1 つのことだけを行い、全体はステップを順につなぐことでタスクを完了する。
これこそが、LangChain が最も入りやすい理由です。
LangChain はどんなときに便利なのか?
Section titled “LangChain はどんなときに便利なのか?”こんな場合に向いている
Section titled “こんな場合に向いている”- 流れが基本的に直線的
- 分岐が少ない
- 複数のモジュールを組み合わせることが主目的
- すぐにプロトタイプを作りたい
典型例:
- FAQ 検索 Q&A
- テキスト抽出
- 検索後生成
- 単一 tool 強化 Q&A
- すぐに始めやすい
- コンポーネントのエコシステムが豊富
- 小さなモジュールをまずつなげるのに向いている
どこでつらくなり始めるか?
Section titled “どこでつらくなり始めるか?”次のような要件が出てくると、チェーン思考だけでは厳しくなります。
- 長い状態の連鎖
- 複数の分岐条件
- ノードの戻り
- 明示的な中間状態の管理
この段階になると、チェーン型の考え方ではだんだん無理が出てきます。
次に LangGraph を理解する:なぜ「状態機械」に近いのか?
Section titled “次に LangGraph を理解する:なぜ「状態機械」に近いのか?”LangGraph の中心はノードだけではなく、状態
Section titled “LangGraph の中心はノードだけではなく、状態”LangGraph で最も重要なのは、次の視点です。
- 次にどのコンポーネントを呼ぶか
ではなく、
- 今の状態は何か
- この状態はどの辺に進むべきか
- ノード実行後に状態はどう更新されるか
先にこう理解するとよいです。
状態付きのワークフローグラフ。
最小限のグラフ型の例
Section titled “最小限のグラフ型の例”def plan_node(state): if "返金" in state["query"]: state["next"] = "retrieve" else: state["next"] = "fallback" return state
def retrieve_node(state): state["docs"] = ["コース購入後 7 日以内なら返金できます"] state["next"] = "answer" return state
def answer_node(state): state["answer"] = f"資料によると:{state['docs'][0]}" state["next"] = None return state
def fallback_node(state): state["answer"] = "現在、対応するフローが見つかりませんでした。" state["next"] = None return state
nodes = { "plan": plan_node, "retrieve": retrieve_node, "answer": answer_node, "fallback": fallback_node}
state = {"query": "返金ポリシーは何ですか", "next": "plan"}
while state["next"] is not None: current = state["next"] state = nodes[current](state) print(current, "->", state)想定出力:
plan -> {'query': '返金ポリシーは何ですか', 'next': 'retrieve'}retrieve -> {'query': '返金ポリシーは何ですか', 'next': 'answer', 'docs': ['コース購入後 7 日以内なら返金できます']}answer -> {'query': '返金ポリシーは何ですか', 'next': None, 'docs': ['コース購入後 7 日以内なら返金できます'], 'answer': '資料によると:コース購入後 7 日以内なら返金できます'}このコードとチェーン型の例の最大の違いは?
Section titled “このコードとチェーン型の例の最大の違いは?”チェーン型システムでは、
- 次のステップは通常固定されています
一方、グラフ型システムでは、
- 次のステップは現在の状態によって決まります
これが、グラフ型ワークフローの本質的な強みです。

いつ LangChain 思考から LangGraph 思考へ切り替えるべきか?
Section titled “いつ LangChain 思考から LangGraph 思考へ切り替えるべきか?”とても実用的な判断基準
Section titled “とても実用的な判断基準”フローチャートを描いたときに、それがもう 1 本の直線ではなくなっていて、次のような形になっていたら、
- 明確な分岐がある
- 失敗時の戻りがある
- ループがある
- 「中間結果に応じて次を決める」必要がある
そのときは、グラフ型の抽象化を考え始めるべきです。
とてもわかりやすい悪い兆候
Section titled “とてもわかりやすい悪い兆候”コードが次のようになり始めたら、
if ... if ... if ... while ...しかも、その判断がすべて中間状態を中心に動いているなら、たいていはこういうことです。
もう単なる「チェーン型アプリ」ではなく、状態グラフシステムを作っている。
なぜ多くのチームが LangChain と LangGraph を両方話題にするのか?
Section titled “なぜ多くのチームが LangChain と LangGraph を両方話題にするのか?”現実のシステムは、たいてい「どちらか一方」ではないからです。
とてもよくある組み合わせ方
Section titled “とてもよくある組み合わせ方”-
LangChain 風の役割でカプセル化するもの:
- prompt
- 検索担当
- parser
-
LangGraph 風の役割で制御するもの:
- 状態遷移
- 分岐
- リトライ
- 人の確認が必要なノード
そのため、多くの場合、両者は次のような関係に近いです。
コンポーネント層 + ワークフロー層
完全に対立する 2 派というより、役割が違うのです。
実際の開発での選び方
Section titled “実際の開発での選び方”もし今やりたいのが次なら:
Section titled “もし今やりたいのが次なら:”- 単発 FAQ
- シンプルな RAG
- 数ステップの固定フロー
まずはチェーン型の考え方で十分なことが多いです。
もし今やりたいのが次なら:
Section titled “もし今やりたいのが次なら:”- マルチステップ Agent
- tool を使ったループ
- 人の確認ノードがある
- 中間状態に強く依存する
グラフ型の考え方のほうが安定します。
「上級っぽいから」という理由で最初からグラフにしない
Section titled “「上級っぽいから」という理由で最初からグラフにしない”これも大事な判断です。
グラフ型の抽象化は強力ですが、そのぶん次のコストもあります。
- 学習コストが高い
- 構造設計の手間が増える
複雑さが低いなら、チェーン型のほうがむしろ見やすいこともあります。
初心者がよくハマる落とし穴
Section titled “初心者がよくハマる落とし穴”タスク構造を理解する前に、フレームワーク API をたくさん覚える
Section titled “タスク構造を理解する前に、フレームワーク API をたくさん覚える”これだと、最後に身につくのは「フレームワークの文法」だけで、システム設計ではありません。
チェーンで無理やりグラフを支えようとする
Section titled “チェーンで無理やりグラフを支えようとする”if/else がどんどん増えていくのに、グラフ型の抽象化に切り替えたがらないケースです。
最初からグラフ型フレームワークを使いすぎる
Section titled “最初からグラフ型フレームワークを使いすぎる”要件はとてもシンプルなのに、先にシステムを重くしてしまうパターンです。
このページを終えたら、この証拠カードを残します。
- 問題の形
- ワークフローグラフ、検索アプリ、役割チーム、または実験
- フレームワーク選択
- どの抽象化を追加し、何を隠すか
- 追跡記録
- state、node、tool call、message、または run id
- 失敗確認
- フレームワークの魔法が状態、再試行、または権限を隠す
- 判断
- シングルエージェントのループが明確になってからフレームワークを選ぶ
この節で一番大切なのは、フレームワーク名を覚えることではなく、次の判断軸を持つことです。
LangChain はよく使うコンポーネントをつなぐもの、LangGraph は複雑な状態の流れを明示的に描くもの。
タスク構造ではなくフレームワークの流行で判断しなくなったとき、選定はずっと安定します。
- 自分の Agent システムを 1 つ描いてみて、それがチェーンに近いかグラフに近いか判断してみましょう。
- チェーン型の例に「文書が見つからなかったら クエリ を書き換えてもう一度検索する」ロジックを追加し、どれくらい複雑になるか確認してみましょう。
- 自分の言葉で説明してみましょう。なぜ、状態付きループがあるシステムにはグラフ型の抽象化のほうが向いているのでしょうか?
- どんな場合に、チェーン型のほうがグラフ型より適しているかを考えてみましょう。
解法と解説
- 各ステップが固定順で 1 回ずつ進むなら chain 的です。分岐、loop、retry、一時停止、前の状態への戻りがあるなら graph 的です。
- 「文書なし -> query を書き換える -> 再検索」を加えると、chain は複雑になりがちです。条件 routing、loop 上限、状態履歴が必要になるからです。ここで graph abstraction が効き始めます。
- graph abstraction が stateful loop に向くのは、node と edge が遷移を明示するからです。どの state が入り、何を判断し、次にどこへ進み、いつ止まるかを表せます。
- chain が向くのは、タスクが線形で短く、安定していて確認しやすい場合です。たとえば入力整形、retriever 呼び出し、短い回答生成のような流れです。