見出し画像

OpenAI Responses API 入門 (8) - Reasoningモデル

「Responses API」の「Reasoningモデル」ついてまとめました。

Reasoning models


前回

1. Reasoningモデル

Reasoningモデル」(o1、o3-miniなど)は、複雑な推論を実行するために強化学習された新しいLLMモデルです。「Reasoningモデル」は答える前に考え、ユーザーに応答する前に長い内部思考チェーンを生成します。そのため、複雑な問題解決、コーディング、科学的推論、エージェントワークフローのマルチステップ計画に優れています。

2. OpenAI API の準備

「Google Colab」での「OpenAI API」の準備手順は次のとおりです。

(1) パッケージのインストール。
「Responses API」と「Agent SDK」のパッケージをインストールします。

# パッケージのインストール
!pip install -U openai openai-agents

(2) 環境変数の準備。
左端の鍵アイコンで「OPENAI_API_KEY」を設定してから、以下のセルを実行してください。

import os
from google.colab import userdata

# 環境変数の準備 (左端の鍵アイコンでOPENAI_API_KEYを設定)
os.environ["OPENAI_API_KEY"] = userdata.get("OPENAI_API_KEY")

(3) クライアントの準備。

from openai import OpenAI

# クライアントの準備
client = OpenAI()

3. Reasoningモデルの実行

(1) メッセージリストの準備

# メッセージリストの準備
messages = [
    {
        "role": "user", 
        "content": "[1,2],[3,4],[5,6]' という形式の文字列として表される行列を受け取り、同じ形式で転置を出力するbashスクリプトを作成してください。"
    }    
]

(2) 推論の実行。

# 推論の実行
response = client.responses.create(
    model="o3-mini",
    reasoning={"effort": "medium"},
    input=messages
)
print(response.output_text)
次のような bash スクリプト例をご参考ください。このスクリプトは、引数として
  "[1,2],[3,4],[5,6]"
のような文字列を受け取り、行列の転置(この場合は "[1,3,5],[2,4,6]")を同じ形式で出力します。

内容は以下の通りです。

------------------------------------------------
#!/bin/bash
# 使い方:
#   ./transpose.sh "[1,2],[3,4],[5,6]"
#
# 入力は "[数字,数字],...[数字,数字]" という形式を期待しています。

if [ "$#" -eq 0 ]; then
    echo "Usage: $0 '[1,2],[3,4],[5,6]'"
    exit 1
fi

# 引数から入力行列の文字列を取得
input="$1"

# 余計な空白やシングル/ダブルクォートがあれば除去
matrix=$(echo "$input" | sed 's/^[[:space:]]*//; s/[[:space:]]*$//; s/^[\'"]*//; s/[\'"]*$//')

# 行の区切り "],[" を改行に変換し、先頭の "[" と末尾の "]" を除去して
# 行ごとに「1,2」などの形式にします。
rows=$(echo "$matrix" | sed 's/],\[/\n/g; s/^\[//; s/\]$//')

# awk を用いて転置を実施
# ・各行をコンマ区切りで分割し、配列 a[行番号, 列番号] に格納
# ・全体の行数と各行の列数(max 列数)を記録
# ・転置では元の列数を新しい行数、元の行数を新しい列数として出力
transposed=$(echo "$rows" | awk -F, '
{
    for (i = 1; i <= NF; i++) {
        a[NR, i] = $i
    }
    if (NF > max) {
        max = NF
    }
    rows = NR
}
END {
    output = ""
    for (i = 1; i <= max; i++) {
        line = "["
        for (j = 1; j <= rows; j++) {
            line = line a[j, i] (j < rows ? "," : "")
        }
        line = line "]"
        output = output (i < max ? line "," : line)
    }
    print output
}')

# 結果を表示
echo "$transposed"

------------------------------------------------

<スクリプトの解説>
1. sed によって入力文字列の前後の不要な空白やクォートを除去し、
   また "],[” を改行に置換して各行に「1,2」のような文字列が入るように整形します。
2. awk はフィールド区切り文字をコンマ (,) にして各行を分解し、
   2 次元配列 a[行,列] に値を格納します。
3. END ブロックで転置を行い、各新しい行(=元の列)の数値を "[" と "]" で囲み、
   行同士はコンマで連結して最終的な文字列として出力します。

実行例:
$ ./transpose.sh "[1,2],[3,4],[5,6]"
[1,3,5],[2,4,6]

これで、入力された行列の転置を同じ形式で出力することができます。

上記の例では、「reasoning_effort」は、プロンプトへの応答を作成する前にモデルが生成すべきReasoningトークンの数に関するガイダンスを提供するために使用されます。このパラメータには、lowmediumhigh のいずれかを指定できます。low は速度とトークンの経済的な使用を優先し、high はより多くのトークンが生成され、応答が遅くなることを犠牲にして、より完全な推論を優先します。デフォルト値は medium で、速度と推論の精度のバランスが取れています。

4. Reasoningのしくみ

4-1. Reasoningのしくみ

「Reasoningモデル」では、入力トークンと出力トークンに加えてReasoningトークンが導入されています。モデルはこれらのReasoningトークンを使用して「考える」ため、プロンプトの理解を分解し、応答を生成するための複数のアプローチを検討します。Reasoningトークンを生成した後、モデルは目に見えるCompletionトークンとして回答を生成し、Reasoningトークンをコンテキストから破棄します。

ユーザーとアシスタント間の複数ステップの会話の例を次に示します。各ステップの入力トークンと出力トークンは引き継がれ、推論トークンは破棄されます。

Reasoningトークンは API 経由では表示されませんが、モデルのコンテキストウィンドウ内のスペースを占有し、出力トークンとして課金されます。

4-2. コンテキストウィンドウの管理

応答を作成するときに、コンテキストウィンドウにReasoningトークン用の十分なスペースがあることを確認することが重要です。問題の複雑さに応じて、モデルは数百から数万のReasoningトークンを生成する場合があります。使用されるReasoningトークンの正確な数は、応答オブジェクトの使用状況オブジェクトの output_tokens_details の下に表示されます。

(1) 使用状況の確認。

# 使用状況の確認
print(response.usage)
ResponseUsage(
    input_tokens=115, 
    output_tokens=2359, 
    output_tokens_details=OutputTokensDetails(
        reasoning_tokens=1536
    ), 
    total_tokens=2474, 
    input_tokens_details={'cached_tokens': 0}
)

4-3. コストの管理

Reasoningモデルでコストを管理するには、max_output_tokens を使用して、モデルが生成するトークンの合計数 (Reasoningトークンと最終出力トークンの両方を含む) を制限できます。

4-4. Reasoning用のスペースの割り当て

生成されたトークンがコンテキストウィンドウの制限または設定した max_output_tokens 値に達すると、ステータスが incomplete で incomplete_details の応答が返され、reason は max_output_tokens に設定されます。これは、目に見える出力トークンが生成される前に発生する可能性があります。つまり、目に見える応答を受信せずに、入力トークンとReasoningトークンのコストが発生する可能性があります。

これを防ぐには、コンテキストウィンドウに十分なスペースがあることを確認するか、max_output_tokens 値をより高い数値に調整します。OpenAI では、これらのモデルで実験を開始するときに、Reasoningと出力用に少なくとも 25,000 トークンを予約することを推奨しています。プロンプトに必要なReasoningトークンの数に慣れてきたら、それに応じてこのバッファを調整できます。

(1) 出力トークン数を制限して推論の実行。

# 推論の実行
response = client.responses.create(
    model="o3-mini",
    reasoning={"effort": "medium"},
    input=messages,
    max_output_tokens=300, # 出力トークン数の制限
)

if response.status == "incomplete" and response.incomplete_details.reason == "max_output_tokens":
    print("トークンがなくなった。")
    if response.output_text:
        print("部分出力:", response.output_text)
    else: 
        print("Reasoning中にトークンがなくなった。")

トークンがなくなった。
Reasoning中にトークンがなくなった。

5. プロンプトのアドバイス

「Reasoningモデル」と「 GPTモデル」をプロンプトする場合、考慮すべき違いがいくつかあります。一般的に、「Reasoningモデル」は、高レベルのガイダンスのみでタスクに対してより良い結果を提供します。これは、非常に正確な指示の恩恵を受けることが多い「GPTモデル」とは多少異なります。

・「Reasoningモデル」は、上級の同僚のようなものです。達成すべき目標を与えて、詳細を解決してくれると信頼できます。
・「GPTモデル」は、後輩の同僚のようなものです。特定の出力を作成するための明示的な指示があれば、最高のパフォーマンスを発揮します。

Reasoningモデルを使用する際のベストプラクティスの詳細については、このガイドを参照してください。

次回



いいなと思ったら応援しよう!