Chain-of-Thought (CoT) は「一歩一歩考える」パターン。複雑な推論を中間ステップに分解することで、最終的な答えの精度を上げる。シンプルだが強力。ただし万能じゃない。推論不要の問題には無駄。


5 分で掴む核心

  1. CoT = 推論を中間ステップに分解。「Think step by step」で発動
  2. なぜ効くか:各ステップでエラーを検出しやすい、複雑さを分割
  3. Zero-shot CoT: プロンプトに「Let's think step by step」と追加するだけ
  4. Few-shot CoT: 例を示して推論の「型」を教える
  5. いつ使うか:多段階の推論が必要なとき。単純な事実検索には不要

10 分コース:12.1-12.3 → 12.5 → Shannon Lab


12.1 なぜ「一歩一歩」が効くのか?

質問:「12 個のリンゴを 3 人で分けたら、一人何個?」

LLM への入力:

Q: 12 個のリンゴを 3 人で分けたら、一人何個?
A:

直接回答:4

CoT 回答:

12 個のリンゴを 3 人で分けます。
12 ÷ 3 = 4
一人あたり 4 個です。

この簡単な例では差がないように見える。でも問題が複雑になると、差が大きくなる。

複雑な例

質問:

太郎は最初 100 万円持っていた。
株で 20% 利益を得た。
その後、その利益の半分を寄付した。
税金で元本の 10% を払った。
最終的にいくら残った?

直接回答(よく間違える):

108 万円

CoT 回答

ステップ 1: 初期資産 = 100 万円
ステップ 2: 株の利益 = 100  × 20% = 20 万円
ステップ 3: 利益後の資産 = 100  + 20  = 120 万円
ステップ 4: 寄付額 = 利益の半分 = 20  ÷ 2 = 10 万円
ステップ 5: 寄付後の資産 = 120  - 10  = 110 万円
ステップ 6: 税金 = 元本の 10% = 100  × 10% = 10 万円
ステップ 7: 最終資産 = 110  - 10  = 100 万円

最終的に 100 万円残った。

なぜ CoT が効くのか?

  1. エラー検出:各ステップが見えるので、どこで間違えたか分かる
  2. 複雑さの分割:一度に考えることを減らす
  3. ワーキングメモリ:中間結果を「書き留める」ことで追跡しやすい
  4. 暗黙の知識の引き出し:ステップを踏むことで関連知識が活性化される

12.2 Zero-shot CoT vs Few-shot CoT

Zero-shot CoT

例を示さず、プロンプトで「考えさせる」だけ:

func zeroShotCoT(query string) string {
    prompt := fmt.Sprintf(`%s

Let's think step by step.`, query)
    return callLLM(prompt)
}

日本語では「一歩一歩考えてみましょう」「順を追って考えてみましょう」も効く。

メリット:シンプル、プロンプト作成が楽 デメリット:推論の「型」を制御しにくい

Few-shot CoT

例を示して、推論の「型」を教える:

func fewShotCoT(query string) string {
    examples := `## Example 1
Q: 8 人の子供が 24 個のキャンディを分けます。一人何個?
A: 全部で 24 個のキャンディがあります。
8 人で分けるので、24 ÷ 8 = 3。
一人あたり 3 個です。

## Example 2
Q: 店で 300 円のノートを買い、500 円を出しました。おつりは?
A: ノートは 300 円です。
500 円を出しました。
おつり = 500 - 300 = 200 円です。

`
    prompt := fmt.Sprintf(`%s

## Your Turn
Q: %s
A:`, examples, query)
    return callLLM(prompt)
}

メリット:推論の「型」を制御できる、ドメイン固有の推論パターンを教えられる デメリット:良い例を作るのに労力がかかる

比較

方式プロンプト作成推論の制御適用範囲
Zero-shot簡単低い汎用的な推論
Few-shot例の準備が必要高いドメイン固有の推論

12.3 Shannon での CoT 実装

Shannon では、CoT を推論パターンの一つとして実装している:

type ChainOfThoughtConfig struct {
    Mode           string   // "zero-shot" or "few-shot"
    Examples       []Example // few-shot モード用
    MaxSteps       int      // 最大推論ステップ数
    ExtractAnswer  bool     // 最終答えを抽出するか
}

func ChainOfThought(ctx workflow.Context, query string, config ChainOfThoughtConfig) (*CoTResult, error) {
    var prompt string

    if config.Mode == "few-shot" && len(config.Examples) > 0 {
        prompt = buildFewShotPrompt(query, config.Examples)
    } else {
        prompt = buildZeroShotPrompt(query)
    }

    // LLM 呼び出し
    response, err := callLLM(ctx, prompt)
    if err != nil {
        return nil, err
    }

    // 推論ステップを抽出
    steps := extractSteps(response)

    // 最終答えを抽出(オプション)
    var finalAnswer string
    if config.ExtractAnswer {
        finalAnswer = extractFinalAnswer(response)
    }

    return &CoTResult{
        FullResponse:  response,
        Steps:         steps,
        FinalAnswer:   finalAnswer,
        StepCount:     len(steps),
    }, nil
}

推論ステップの抽出

func extractSteps(response string) []string {
    // パターン 1: "Step 1:", "Step 2:", ...
    stepPattern := regexp.MustCompile(`Step\s*\d+[:.]\s*(.+?)(?=Step\s*\d+|$)`)

    // パターン 2: 番号付きリスト "1.", "2.", ...
    numberedPattern := regexp.MustCompile(`\d+\.\s*(.+?)(?=\d+\.|$)`)

    // パターン 3: 箇条書き "- ", "* "
    bulletPattern := regexp.MustCompile(`[-*]\s*(.+?)(?=[-*]|$)`)

    // 優先順位で試す
    if matches := stepPattern.FindAllStringSubmatch(response, -1); len(matches) > 0 {
        return extractMatches(matches)
    }
    // ... 他のパターン
}

12.4 CoT の改良版

Self-Consistency CoT

同じ質問に複数回 CoT を実行し、多数決で答えを決める:

func selfConsistencyCoT(ctx context.Context, query string, n int) (string, error) {
    answers := make(map[string]int)

    for i := 0; i < n; i++ {
        result, err := chainOfThought(ctx, query)
        if err != nil {
            continue
        }
        answers[result.FinalAnswer]++
    }

    // 最も多い答えを選ぶ
    var bestAnswer string
    var maxCount int
    for answer, count := range answers {
        if count > maxCount {
            maxCount = count
            bestAnswer = answer
        }
    }

    return bestAnswer, nil
}

メリット:推論のばらつきを減らす、信頼性が上がる デメリット:コストが n 倍

CoT + Verification

推論の各ステップを検証する:

func verifiedCoT(ctx context.Context, query string) (*Result, error) {
    result, _ := chainOfThought(ctx, query)

    // 各ステップを検証
    for i, step := range result.Steps {
        isValid := verifyStep(ctx, step, result.Steps[:i])
        if !isValid {
            // 問題のあるステップから再推論
            return rerunFrom(ctx, query, result.Steps[:i])
        }
    }

    return result, nil
}

12.5 いつ CoT を使うべきか?

タスクタイプCoT が効くか理由
算数の文章題効く多段階の計算が必要
論理パズル効く推論のチェーンが必要
コード生成(複雑)効くロジックを分解できる
因果推論効く因果の連鎖を追跡
事実の検索効かない推論不要
単純な変換効かないワンステップで完了
創作(詩、物語)効きにくい創造性に推論は不要

判断基準

この問題を解くのに、
複数のステップを頭の中で踏む必要があるか?

YES  CoT を試す価値あり
NO  直接回答で十分

12.6 よくある落とし穴

落とし穴 1:不要なときに使う

// 悪い例:単純な質問に CoT
// Q: 日本の首都は?
// A: 日本という国があります。首都とは...(長い推論)...東京です。

// 良い例:直接回答
// A: 東京

func shouldUseCoT(query string) bool {
    // 複雑度を推定
    complexity := estimateComplexity(query)
    return complexity > threshold
}

落とし穴 2:推論が正しいと仮定する

// 悪い例:推論を検証しない
steps := extractSteps(response)
return steps[len(steps)-1]  // 最後のステップ = 答え、と仮定

// 良い例:答えを明示的に抽出、または検証
finalAnswer := extractFinalAnswer(response)
if config.VerifyAnswer {
    isValid := verifyAnswer(query, finalAnswer)
    if !isValid {
        return retry(query)
    }
}

落とし穴 3:ステップ数が多すぎる

// 悪い例:無限に推論し続ける
prompt := "Think through this step by step, don't stop until you're sure."
// 結果:20 ステップの推論でトークンを使い果たす

// 良い例:ステップ数を制限
prompt := "Think through this in 3-5 steps, then give your final answer."

12.7 CoT と Planning の違い

一見似ているが、目的が違う:

特徴CoTPlanning
目的推論の精度を上げる実行を制御する
出力推論ステップ + 答え行動計画
実行推論のみ(ツール呼び出しなし)ツール呼び出しあり
再実行なし(一度で完結)ステップごとに実行
典型的なタスク数学、論理パズルリサーチ、自動化

組み合わせ

Planning の計画段階で CoT を使う:

func planWithCoT(ctx context.Context, query string) (*Plan, error) {
    // CoT で計画を立てる
    prompt := fmt.Sprintf(`Task: %s

Think step by step about how to accomplish this task:
1. What information do we need?
2. What tools should we use?
3. In what order should we do things?

Then provide a structured plan.`, query)

    reasoning := callLLM(prompt)
    plan := extractPlan(reasoning)

    return plan, nil
}

この章のまとめ

核心は一言で:Chain-of-Thought は「一歩一歩考える」ことで、複雑な推論の精度を上げる。シンプルだが強力。

要点

  1. 基本原理:推論を中間ステップに分解
  2. Zero-shot:「Let's think step by step」で発動
  3. Few-shot:例を示して推論の「型」を教える
  4. 使いどころ:多段階の推論が必要なとき
  5. 注意:不要なときに使うと逆効果

Shannon Lab(10 分で始める)

このセクションで、本章の概念を Shannon のソースコードにマッピングする。

必読(1 ファイル)

  • patterns/chain_of_thought.goChainOfThought 関数を見て、Zero-shot と Few-shot の実装を理解する。extractSteps でステップ抽出のロジックを確認する

選読で深掘り(興味に応じて 2 つ)


演習

演習 1:CoT プロンプト設計

以下の問題に対する Few-shot CoT プロンプトを設計せよ。例を 2 つ含めること。

問題:ある会社の従業員は昨年 100 人だった。今年 20% 増えて、
来年さらに 10% 増える予定。来年の従業員数は?

演習 2:CoT vs 直接回答

以下のタスクについて、CoT を使うべきか判断し、理由を説明せよ:

  1. 「Python で Hello World を出力するコードを書いて」
  2. 「3 人の子供が 15 個のクッキーを平等に分けた後、各子供が 2 個ずつ食べた。残りは全部で何個?」
  3. 「今日の天気を教えて」
  4. 「AさんがBさんより背が高く、BさんがCさんより背が高い。AさんとCさんではどちらが背が高い?」

演習 3(上級):Self-Consistency の実装

Self-Consistency CoT の擬似コードを書け。以下を考慮すること:

  • 同じ質問に n 回 CoT を実行
  • 答えを抽出して集計
  • 多数決で最終答えを決定
  • 信頼度(最も多い答えの割合)も返す

もっと深く学びたい?


Part 4 のまとめ

これで Part 4「単一 Agent パターン」が完了した。3 つのパターンを学んだ:

パターン核心いつ使うか
Planning先に考え、後で行動タスクが複雑で、実行計画が必要なとき
Reflection出力して、振り返り、改善品質を反復的に高めたいとき
Chain-of-Thought一歩一歩考える多段階の推論が必要なとき

これらは組み合わせて使える:

  • Planning + Reflection: 計画を立て、各ステップの出力を改善
  • Planning + CoT: 計画段階で推論を分解
  • Reflection + CoT: 推論の各ステップを評価・改善

次章の予告

Part 4 では「単一 Agent」がいかに賢く動くかを学んだ。でも、一人じゃできないこともある。

Part 5 では マルチエージェント編成 に入る。複数の Agent がどう協力するか、誰がリーダーになるか、どうコミュニケーションするか。

第 13 章「編成の基礎」で、オーケストレーターの役割とルーティング判断を学ぶ。

準備はいい?次のパートへ進もう。

この記事を引用する / Cite
Zhang, W. (2026). 第 12 章:Chain-of-Thought. In AI Agent アーキテクチャ:単体からエンタープライズ級マルチエージェントへ. https://waylandz.com/ai-agent-book-ja/第12章-Chain-of-Thought
@incollection{zhang2026aiagent_ja_第12章_Chain_of_Thought,
  author = {Zhang, Wayland},
  title = {第 12 章:Chain-of-Thought},
  booktitle = {AI Agent アーキテクチャ:単体からエンタープライズ級マルチエージェントへ},
  year = {2026},
  url = {https://waylandz.com/ai-agent-book-ja/第12章-Chain-of-Thought}
}