PythonとOpenAI APIで実践！はじめてのMCP開発入門【第12回】プロンプトエンジニアリング実践(2) - 複雑な指示もAIに理解させる「ステップバック」と「思考の連鎖（CoT）」概念の実装ヒント

# はじめに：AIに「深く考えさせる」技術 - プロンプトエンジニアリングの次なるフロンティア

皆さん、こんにちは！AI開発の深淵を覗く第12回です。前回（第11回）は、システムメッセージとロールプロンプティングを駆使して、AIに特定の役割や性格を「演じさせる」ことで、応答の質と一貫性を高めるテクニックを学びました。これにより、AIは単なる情報提供者から、より専門的で個性的な対話相手へと進化しましたね。

しかし、私たちがAIに求めるのは、時に役割を演じること以上に、複雑な問題に対する深い洞察や、論理的な思考プロセスそのものです。AIが単に「答えを知っている」だけでなく、「なぜその答えに至ったのか」という思考の道筋を示してくれたら、その信頼性や応用範囲は格段に広がります。

そこで今回は、プロンプトエンジニアリングのさらに一歩進んだテクニックとして、ユーザー様提供のGoogle社の「Prompt Engineering」資料でも紹介されている、 **「ステップバック・プロンプティング（Step-Back Prompting）」と「思考の連鎖（Chain of Thought - CoT Prompting）」** という、AIの推論能力を引き出すための強力な概念とその実装に向けたヒントを、技術的な背景（LLMの推論シミュレーション、プロンプト構造化、トークン消費特性など）と共に詳しく解説します。

これらのテクニックは、AI研究の最前線（2025年5月29日、ここ東京のようなイノベーション拠点でも活発に研究・応用されています）で注目されており、マスターすれば、あなたはAIをより高度な問題解決パートナーとして活用できるようになるでしょう。「いいね！」が止まらない、AIの潜在能力を解放するプロンプト術を探求します！

![はじめに：AIに「深く考えさせる」技術 - プロンプトエンジニアリングの次なるフロンティア - visual selection.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4058228/fcbe9127-a73b-4e72-be20-f7756237393e.png)


# なぜ直接的な質問だけではダメなのか？ AIの「思考」を導く必要性

LLMは驚異的な能力を持っていますが、複雑な質問や多段階の推論が必要な問題に対して、いきなり最終的な答えを求めると、途中の論理が飛躍したり、もっともらしいが誤った結論（ハルシネーション）を導き出したりすることがあります。これは、LLMが本質的には「次に来る確率が最も高いトークン」を予測しているに過ぎず、人間のような明示的な論理演算や深い因果関係の理解を常に行っているわけではないためです。

そこで、AIがより正確で信頼性の高い結論に至るように、その「思考プロセス」をプロンプトによって巧みに誘導する技術が求められます。それがステップバック・プロンプティングやCoTなのです。

# テクニック１：ステップバック・プロンプティング – 「抽象化」による推論の土台作り

- 概念（Zheng et al.の研究に基づく）
    - 特定の具体的な質問（特に少しひねくれたり、複数の知識領域の組み合わせが必要だったりするもの）に直接答える前に、AIに一度「ステップバック」させ、その質問に関連するより一般的な原則、概念、または事実をまず導き出させる手法です。そして、その抽象化された知識を土台として、元の具体的な質問に答えるよう指示します。

- なぜ効果的なのか？（技術的洞察）
    - このアプローチは、LLMが特定の質問の詳細に囚われて早まった結論を出すのを防ぎます。まず一般的な知識や原則を想起させることで、LLMは広範な学習データの中から関連性の高い基盤情報にアテンションを向け、より安定した、論理的な足場を築きます。その上で具体的な問題に取り組むため、推論の質が向上し、より信頼性の高い回答が期待できます。

# プロンプト構造の例
- ユーザーの質問
    - 「体重50gのツバメ（ヨーロッパの種）は、荷物なしで、中世ヨーロッパからココナッツ（平均500g）をマルシア（イングランド中部の古王国）まで運べたでしょうか？」 (モンティ・パイソンの有名な問いですが、推論の良い例です)

## ステップバック・プロンプトの構成案（単一APIコール内、または複数コールで段階的に）

```Plaintext

# === ステップバック・プロンプト構成案 ===
# ユーザーの本来の質問:
# 「体重50gのツバメ（ヨーロッパの種）は、荷物なしで、中世ヨーロッパからココナッツ（平均500g）をマルシア（イングランド中部の古王国）まで運べたでしょうか？」

# AIへの指示 (システムメッセージまたはユーザーメッセージの冒頭):
# 「上記の具体的な質問に答える前に、まず以下の一般的な事実や原則について考察し、リストアップしてください。
#   1. ヨーロッパのツバメの典型的な飛行能力（航続距離、速度、体重に対する運搬能力の限界など）について。
#   2. ココナッツの平均的な重さ、大きさ、そして自然に生育する地域について。
#   3. 中世ヨーロッパとココナッツの原産地との地理的な関係、および当時の交易ルートについて。
#
#   これらの一般的な事実を明確にした上で、元の具体的な質問に対して、あなたの推論を詳細に説明しながら回答してください。」
```
## Python APIコールでの実装ヒント

```Python

# (OpenAIクライアント初期化などは第3,4回参照)
# (call_openai_chat_api関数は第10,11回参照、エラーハンドリングは第8回参照)
import os
from dotenv import load_dotenv
from openai import OpenAI

load_dotenv()
client = OpenAI()

def call_openai_with_stepback_prompt(original_question, stepback_instructions, model="gpt-4o-mini", max_tokens=1500, temperature=0.2):
    # (第10,11回のcall_openai_chat_api関数を参考に、エラーハンドリングを充実させる)
    system_prompt_role = "あなたは、複雑な質問に対して、まず関連する一般原則を考察し、その上で論理的に回答を組み立てる、非常に分析的なAIです。"

    # ステップバック指示と元の質問を組み合わせたユーザープロンプト
    user_prompt_content = f"""
    以下のユーザーの質問に回答してください: 「{original_question}」

    回答を生成する前に、まず以下の「ステップバック指示」に従って、関連する一般的な事実や原則をリストアップしてください。
    <stepback_instructions>
    {stepback_instructions}
    </stepback_instructions>

    その後、これらの事実や原則に基づいて、元のユーザーの質問に詳細な推論と共に答えてください。
    """

    messages = [
        {"role": "system", "content": system_prompt_role},
        {"role": "user", "content": user_prompt_content}
    ]

    try:
        print(f"\n--- 送信するメッセージ (User Content 抜粋) ---\n{user_prompt_content[:300]}...")
        completion = client.chat.completions.create(
            model=model,
            messages=messages,
            max_tokens=max_tokens,
            temperature=temperature
        )
        ai_response = completion.choices[0].message.content
        print(f"--- AI ({model}) のステップバック推論を含む応答 ---")
        print(ai_response)
        print(f"(使用トークン - Total: {completion.usage.total_tokens})")
        return ai_response
    except Exception as e:
        print(f"APIリクエストエラー: {e}")
        return None

# --- 実行例 ---
q = "体重50gのツバメ（ヨーロッパの種）は、荷物なしで、中世ヨーロッパからココナッツ（平均500g）をマルシアまで運べたでしょうか？"
instr = """
1. ヨーロッパのツバメの飛行能力（最大運搬重量、平均航続距離）。
2. ココナッツの平均重量と主な原産地。
3. 中世ヨーロッパとココナッツ原産地の地理的隔たりと、当時の輸送手段。
"""
print("\n=== ステップバック・プロンプティング実行例 ===")
# call_openai_with_stepback_prompt(q, instr) 
# 実行すると、まず一般論、次にそれに基づく結論と理由が出力されるはず
```
## ポイント
このように構造化されたプロンプトを送ることで、AIはまず前提となる知識を整理し、それから本題に入るという、人間が複雑な問題に取り組む際の思考プロセスに近い形で応答を生成するようになります。

# テクニック２：思考の連鎖（Chain of Thought - CoT）プロンプティング – AIに「思考の途中経過」を語らせる

- 概念（Wei et al.の研究に基づく）
    - 特に算術問題、論理パズル、常識的推論など、多段階の思考が必要な問題に対して、AIに最終的な答えだけを求めるのではなく、 **答えに至るまでの中間的な推論ステップ（思考の連鎖）** を明示的に生成させる手法です。

- なぜ効果的なのか？（技術的洞察）
    - LLMに「声に出して考える」ように促すことで、AIは複雑な問題をより小さな、処理しやすいステップに内部的に分解し、各ステップでの判断の確からしさを高めます。これにより、最終的な結論の精度が向上します。また、生成された思考プロセスは人間にとっても理解しやすく、AIの判断根拠の透明性向上やデバッグにも繋がります。

## CoTを引き出すプロンプト戦略

- フューショットCoT
    - プロンプト内に、問題とその思考プロセス、そして最終的な答えを含む「お手本」をいくつか提示します。AIはこのパターンを学習し、新しい問題に対しても同様に思考プロセスを生成しようとします。
- ゼロショットCoT（よりシンプル）
    - お手本なしで、プロンプトの最後に「ステップバイステップで考えてみましょう (Let's think step by step.)」「思考の過程を詳しく説明してください」といった魔法の呪文のような一言を加えるだけでも、CoT的な応答を引き出せる場合があります（特に高性能なモデルの場合）。
## プロンプト構造の例（算術問題）
- ユーザーの質問
    - 「ロジャーはテニスボールを5個持っています。彼はテニスボールの缶をさらに2つ買いました。各缶には3個のテニスボールが入っています。今、ロジャーは何個のテニスボールを持っていますか？」

## CoTプロンプトの構成案

``` Plaintext
# === CoTプロンプト構成案 (ゼロショットCoT) ===
# ユーザーの質問:
# 「ロジャーはテニスボールを5個持っています。彼はテニスボールの缶をさらに2つ買いました。各缶には3個のテニスボールが入っています。今、ロジャーは何個のテニスボールを持っていますか？」

# AIへの指示 (ユーザーメッセージの末尾など):
# 「この問題を解くために、ステップバイステップで考えて、最終的な答えを出してください。」
```
フューショットCoTの場合は、上記のような質問の前に、思考プロセスを含むQ&Aの例を1～数個挿入します。

## Python APIコールでの実装ヒント

```Python

# (OpenAIクライアント初期化などは第3,4回参照)
# (call_openai_chat_api関数は第10,11回参照、エラーハンドリングは第8回参照)

def call_openai_with_cot_prompt(problem_description, model="gpt-4o-mini", max_tokens=500, temperature=0.0):
    # (第10,11回のcall_openai_chat_api関数を参考に、エラーハンドリングを充実させる)
    system_prompt_role = "あなたは、与えられた問題を解決するために、論理的な思考のステップを順を追って説明するAIアシスタントです。"

    # CoTを促す指示を含むユーザープロンプト
    user_prompt_content = f"""
    以下の問題を解いてください:
    「{problem_description}」

    答えを出す前に、あなたの思考プロセスをステップバイステップで詳細に説明してください。
    最後に「最終的な答えは〇〇です。」という形で結論を述べてください。
    """

    messages = [
        {"role": "system", "content": system_prompt_role},
        {"role": "user", "content": user_prompt_content}
    ]

    try:
        # (APIコールと結果表示のコードは call_openai_with_stepback_prompt と同様)
        # ...
        print(f"\n--- 送信するメッセージ (User Content 抜粋) ---\n{user_prompt_content[:200]}...")
        completion = client.chat.completions.create(
            model=model,
            messages=messages,
            max_tokens=max_tokens,
            temperature=temperature # 論理的な推論では低い温度設定が望ましい
        )
        ai_response = completion.choices[0].message.content
        print(f"--- AI ({model}) のCoT推論を含む応答 ---")
        print(ai_response)
        print(f"(使用トークン - Total: {completion.usage.total_tokens})")
        return ai_response
    except Exception as e:
        print(f"APIリクエストエラー: {e}")
        return None
# --- 実行例 ---
problem = "ロジャーはテニスボールを5個持っています。彼はテニスボールの缶をさらに2つ買いました。各缶には3個のテニスボールが入っています。今、ロジャーは何個のテニスボールを持っていますか？"
print("\n=== CoTプロンプティング実行例 ===")
# call_openai_with_cot_prompt(problem)
# 期待される応答：
# ステップ1: ロジャーが追加で買ったテニスボールの数を計算します。彼は2缶買い、各缶には3個入っているので、2 * 3 = 6個のボールを追加で得ました。
# ステップ2: 元々持っていたボールの数と追加で得たボールの数を合計します。元々5個持っていて、6個追加したので、5 + 6 = 11個になります。
# 最終的な答えは11個です。
```
### ポイント
temperatureを低く（例：0.0～0.2）設定することで、AIはより論理的で一貫性のある思考ステップを生成しやすくなります。

# 高度なテクニックの実装と注意点（開発者向け深掘り）

- モデル選択の重要性
    - ステップバックやCoTのような複雑な指示追従や推論は、gpt-4oのような高性能なモデルの方が、gpt-3.5-turboよりも格段に優れた結果を示す傾向があります。タスクの要求に応じて適切なモデルを選択しましょう。
- トークン消費への配慮
    - CoTでは、思考プロセス自体もAIの生成テキスト（Completion Tokens）に含まれるため、応答が長くなり、トークン消費量が増加します。ステップバックも、前提となる一般原則のリストアップでトークンを消費します。精度向上とコスト/速度とのトレードオフを常に意識する必要があります。
- プロンプトのイテレーション
    - これらの高度なテクニックを効果的に引き出すプロンプトの「お作法」は、問題領域やモデルによって微妙に異なります。最適な表現や指示の順序を見つけるには、試行錯誤が不可欠です。OpenAI Playgroundなどを活用し、少量多品種の実験を繰り返しましょう。
- 複数ステップのAPIコール（プログラムによるCoT制御）
    - より複雑な問題では、1回のAPIコールで全ての思考プロセスと最終結論を生成させるのではなく、プログラム側で思考の各ステップに対応するプロンプトを動的に生成し、複数回のAPIコールを通じてAIと対話しながら最終結論に導くアプローチも考えられます。これは、ReAct (Reason and Act) や Tree of Thoughts (ToT) のような、より自律的なAIエージェントの挙動に繋がる考え方です。（これらの詳細な実装は本シリーズの範囲を超えますが、CoTはその第一歩です。）
- CoTの応用「自己整合性（Self-Consistency）」:
    -  CoTで複数の異なる思考経路を生成させ、その中で最も多数派の結論を最終回答とする「自己整合性」というテクニックは、CoTの精度をさらに向上させることが知られています（ただし、APIコール数が増えるためコストも増加します）。

# おわりに：AIの「思考」を引き出し、協調する時代の幕開け

今回は、プロンプトエンジニアリングの応用編として、AIに単なる知識の検索やテキスト生成を超えた、より深い「思考」や「推論」を促すための **「ステップバック・プロンプティング（Step-Back Prompting）」と「思考の連鎖（Chain of Thought - CoT Prompting）」** という強力なテクニックの概念と、その実装に向けたヒントを解説しました。

これらの手法は、LLMの内部的な情報処理プロセスを、プロンプトを通じて間接的にガイドし、その結果として、より信頼性が高く、透明性があり、そしてしばしばより正確な応答を引き出すことを可能にします。これは、AIをブラックボックスとして扱うのではなく、その「思考様式」を理解し、より効果的に「協調」するための重要なスキルセットです。

このコミュニティの皆さんのような探求心旺盛な開発者にとって、これらの高度なプロンプト戦略は、AIの新たな可能性を切り拓くための魅力的な挑戦となるでしょう。ぜひ、様々な問題にこれらのテクニックを応用し、AIの「思考」を引き出す面白さを体験してみてください！

![はじめに：AIに「深く考えさせる」技術 - プロンプトエンジニアリングの次なるフロンティア - visual selection (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4058228/8ee50f20-9f40-48ac-badc-bd23523b2002.png)


## 次回予告
AIの能力を様々な角度から引き出す方法を学んできました。しかし、開発を進める上で避けて通れないのが「お金」の話、そして「やってはいけないこと」です。
次回、第13回「APIキー漏洩は致命的！ソースコードに書かない、サーバサイドでのキー管理とアクセス制御戦略」では、AI開発の生命線であるAPIキーの、より高度で安全な管理方法と、絶対に守るべきセキュリティの鉄則について、改めて徹底的に解説します。安全な開発は、全てのイノベーションの土台です！