2025年後半から2026年にかけて、Google の「Thinking」モデルシリーズは急速に実用段階に達しました。Gemini 2.5 Flash Thinking は、軽快なレスポンス速度を保ちながら「推論」を行うモデルです。単に答えを返すのではなく、内部で思考プロセスを実行し、その過程を API から取得できるという点が最大の特徴です。
Gemini 2.5 Flash Thinking とは何か
通常の言語モデルは「入力 → 出力」の1ステップで回答を生成します。Thinking モデルは、その前に「内部推論(internal reasoning)」のステップを実行します。
具体的には、問いに対して「どのように考えるべきか」「どの情報が重要か」「矛盾はないか」といった思考プロセスを内部で展開してから最終的な回答を生成します。この思考トレースは thoughtsContent として API から取得できます。
使うべきシーン:
- 複雑な数学的証明や計算問題
- 多段階のロジックが必要なコード生成・デバッグ
- 情報の矛盾を検出するファクトチェック
- 複数の選択肢を比較・評価する意思決定支援
通常モードで十分なシーン:
- シンプルな Q&A や情報検索
- 短いテキスト要約・翻訳
- テンプレートベースのコンテンツ生成
基本的な実装
Python SDK での実装
import google.generativeai as genai
genai.configure(api_key="YOUR_GEMINI_API_KEY")
# Gemini 2.5 Flash Thinking モデルを使用
model = genai.GenerativeModel(
model_name="gemini-2.5-flash-thinking-exp-01-21",
)
# 思考プロセスを含む応答を取得
response = model.generate_content(
"次の数列のn番目の一般項を求めて、その導出過程を説明してください: 1, 4, 9, 16, 25, ...",
generation_config=genai.types.GenerationConfig(
# thinking_config で思考を有効化
)
)
# 通常の応答テキスト
print("=== 最終回答 ===")
print(response.text)
# 思考トレース(候補が複数ある場合は candidates[0])
if response.candidates[0].content.parts:
for part in response.candidates[0].content.parts:
if hasattr(part, 'thought') and part.thought:
print("\n=== 思考プロセス ===")
print(part.text)
TypeScript / Node.js での実装
import { GoogleGenerativeAI } from '@google/generative-ai';
const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY!);
const model = genAI.getGenerativeModel({
model: 'gemini-2.5-flash-thinking-exp-01-21',
});
interface ThinkingResponse {
thoughts: string;
answer: string;
inputTokens: number;
outputTokens: number;
thinkingTokens: number;
}
const generateWithThinking = async (
prompt: string
): Promise<ThinkingResponse> => {
const result = await model.generateContent(prompt);
const response = result.response;
let thoughts = '';
let answer = '';
for (const part of response.candidates?.[0]?.content?.parts ?? []) {
if ('thought' in part && part.thought) {
thoughts += part.text ?? '';
} else {
answer += part.text ?? '';
}
}
const usage = response.usageMetadata;
return {
thoughts,
answer,
inputTokens: usage?.promptTokenCount ?? 0,
outputTokens: usage?.candidatesTokenCount ?? 0,
thinkingTokens: usage?.thoughtsTokenCount ?? 0,
};
};
// 使用例
const result = await generateWithThinking(
"Pythonコードのバグを特定して修正してください:\n\ndef fibonacci(n):\n if n <= 0:\n return []\n elif n == 1:\n return [0]\n seq = [0, 1]\n for i in range(2, n):\n seq.append(seq[i-1] + seq[i-2])\n return seq\n\nprint(fibonacci(0)) # 期待値: []\nprint(fibonacci(1)) # 期待値: [0]\nprint(fibonacci(5)) # 期待値: [0, 1, 1, 2, 3]"
);
console.log('思考プロセス:', result.thoughts);
console.log('最終回答:', result.answer);
console.log(`思考トークン: ${result.thinkingTokens}`);
思考バジェット(thinkingBudget)の制御
Gemini 2.5 Flash Thinking では thinkingBudget パラメータで思考トークン数の上限を設定できます。これがコスト管理の核心です。
const model = genAI.getGenerativeModel({
model: 'gemini-2.5-flash-thinking-exp-01-21',
generationConfig: {
// 思考トークンの最大数を制御(デフォルト: 8192)
// 0: thinking OFF(通常モードと同等)
// 1024: 軽量推論(簡単なタスク向け)
// 8192: 標準推論(バランス型)
// 24576: 深い推論(複雑なタスク向け)
} as any, // thinkingBudget は experimental フィールド
});
// 動的に thinking budget を調整するファクトリ関数
const createThinkingModel = (budget: 'off' | 'light' | 'standard' | 'deep') => {
const budgetMap = {
off: 0,
light: 1024,
standard: 8192,
deep: 24576,
};
return genAI.getGenerativeModel({
model: 'gemini-2.5-flash-thinking-exp-01-21',
generationConfig: {
thinkingBudget: budgetMap[budget],
} as any,
});
};
// タスクの複雑さに応じてモデルを使い分け
const classifyTaskComplexity = (prompt: string): 'light' | 'standard' | 'deep' => {
const wordCount = prompt.split(/\s+/).length;
const hasCode = /```|def |function |class |import /.test(prompt);
const hasMath = /∑|∫|∂|equation|proof|calculate|solve/.test(prompt);
const isMultiStep = /step|then|after|finally|1\.|2\.|3\./.test(prompt);
if (hasCode || hasMath) return 'deep';
if (isMultiStep || wordCount > 100) return 'standard';
return 'light';
};
const smartGenerate = async (prompt: string) => {
const complexity = classifyTaskComplexity(prompt);
const model = createThinkingModel(complexity);
const result = await model.generateContent(prompt);
return { result, complexity };
};
ストリーミング対応の思考トレース表示
ユーザーに「モデルが考えている様子」をリアルタイムで見せることで、長い処理時間を許容してもらいやすくなります。
import { GoogleGenerativeAI } from '@google/generative-ai';
const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY!);
const model = genAI.getGenerativeModel({
model: 'gemini-2.5-flash-thinking-exp-01-21',
});
interface StreamingCallbacks {
onThought?: (chunk: string) => void;
onAnswer?: (chunk: string) => void;
onComplete?: (thoughts: string, answer: string) => void;
}
const generateWithThinkingStream = async (
prompt: string,
callbacks: StreamingCallbacks
) => {
const result = await model.generateContentStream(prompt);
let thoughts = '';
let answer = '';
for await (const chunk of result.stream) {
const parts = chunk.candidates?.[0]?.content?.parts ?? [];
for (const part of parts) {
const text = part.text ?? '';
const isThought = 'thought' in part && part.thought;
if (isThought) {
thoughts += text;
callbacks.onThought?.(text);
} else {
answer += text;
callbacks.onAnswer?.(text);
}
}
}
callbacks.onComplete?.(thoughts, answer);
return { thoughts, answer };
};
// Next.js API Route での実装例
// app/api/thinking/route.ts
export async function POST(req: Request) {
const { prompt } = await req.json();
const encoder = new TextEncoder();
const stream = new ReadableStream({
async start(controller) {
try {
await generateWithThinkingStream(prompt, {
onThought: (chunk) => {
controller.enqueue(
encoder.encode(
`data: ${JSON.stringify({ type: 'thought', text: chunk })}\n\n`
)
);
},
onAnswer: (chunk) => {
controller.enqueue(
encoder.encode(
`data: ${JSON.stringify({ type: 'answer', text: chunk })}\n\n`
)
);
},
onComplete: () => {
controller.enqueue(
encoder.encode(
`data: ${JSON.stringify({ type: 'done' })}\n\n`
)
);
controller.close();
},
});
} catch (error) {
controller.error(error);
}
},
});
return new Response(stream, {
headers: {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
Connection: 'keep-alive',
},
});
}
フロントエンドでの思考トレース表示
// components/ThinkingChat.tsx
'use client';
import { useState } from 'react';
export const ThinkingChat = () => {
const [thoughts, setThoughts] = useState('');
const [answer, setAnswer] = useState('');
const [isThinking, setIsThinking] = useState(false);
const handleSubmit = async (prompt: string) => {
setThoughts('');
setAnswer('');
setIsThinking(true);
const response = await fetch('/api/thinking', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ prompt }),
});
const reader = response.body!.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const lines = decoder.decode(value).split('\n');
for (const line of lines) {
if (!line.startsWith('data: ')) continue;
const data = JSON.parse(line.slice(6));
if (data.type === 'thought') {
setThoughts(prev => prev + data.text);
} else if (data.type === 'answer') {
setIsThinking(false);
setAnswer(prev => prev + data.text);
}
}
}
};
return (
<div className="max-w-2xl mx-auto space-y-4">
{thoughts && (
<div className="bg-amber-50 border border-amber-200 rounded-lg p-4">
<div className="flex items-center gap-2 mb-2">
<span className="text-amber-600 text-sm font-medium">
💭 思考中...
</span>
</div>
<p className="text-amber-800 text-sm leading-relaxed opacity-75">
{thoughts}
</p>
</div>
)}
{answer && (
<div className="bg-white border border-gray-200 rounded-lg p-4">
<p className="text-gray-800 leading-relaxed">{answer}</p>
</div>
)}
</div>
);
};
コスト管理:思考トークンの課金体系を理解する
Gemini 2.5 Flash Thinking では、思考トークンも出力トークンとして課金されます(2026年時点)。コスト設計の基本を理解しておきましょう。
// コスト見積もりユーティリティ
const PRICING = {
'gemini-2.5-flash-thinking-exp': {
input: 0.15 / 1_000_000, // $0.15 per 1M tokens
output: 0.60 / 1_000_000, // $0.60 per 1M tokens (thinking + response)
},
'gemini-2.5-flash': {
input: 0.075 / 1_000_000,
output: 0.30 / 1_000_000,
},
} as const;
const estimateCost = (
model: keyof typeof PRICING,
inputTokens: number,
outputTokens: number,
thinkingTokens: number
) => {
const pricing = PRICING[model];
const inputCost = inputTokens * pricing.input;
const outputCost = (outputTokens + thinkingTokens) * pricing.output;
return {
inputCost,
outputCost,
total: inputCost + outputCost,
thinkingRatio: thinkingTokens / (outputTokens + thinkingTokens),
};
};
思考モデルの費用対効果を最大化する設計
Thinking が真に価値を発揮するのは「通常モデルでは誤る可能性が高い複雑なタスク」です。単純なQ&Aに Thinking を使うのはコストの無駄です。
判断基準として、「通常の Gemini Flash で試して誤りが多い場合」「ステップ数が4以上の複合タスク」「正確性が最優先でコストが二次的な場合」が Thinking モデルへの切り替えタイミングの目安となります。
マルチターン会話での Thinking 活用
const chat = model.startChat({
history: [],
});
// 複雑な問題を段階的に深掘りする
const steps = [
"Eコマースサイトの検索機能を設計してください。まず要件を整理してください。",
"提示された要件に基づいて、データベーススキーマを設計してください。",
"設計したスキーマに対して、全文検索とフィルタリングを最適化するインデックス設計を提案してください。",
];
for (const step of steps) {
const result = await chat.sendMessage(step);
const response = result.response;
// 各ステップの思考トレースを収集
for (const part of response.candidates?.[0]?.content?.parts ?? []) {
if ('thought' in part && part.thought) {
console.log(`[THINKING] ${part.text}`);
} else {
console.log(`[RESPONSE] ${part.text}`);
}
}
}
本番運用での推奨設定
本番システムで Thinking モデルを使用する際は、エラーハンドリングとフォールバック戦略が重要です。
const robustGenerate = async (prompt: string, maxRetries = 3) => {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
const model = createThinkingModel('standard');
return await model.generateContent(prompt);
} catch (error: any) {
const isRateLimit = error.status === 429;
const isOverloaded = error.status === 503;
if ((isRateLimit || isOverloaded) && attempt < maxRetries - 1) {
// 指数バックオフ
await new Promise(r => setTimeout(r, Math.pow(2, attempt) * 1000));
continue;
}
// Thinking が利用不可の場合は通常モードにフォールバック
if (error.message?.includes('thinking')) {
console.warn('Thinking mode unavailable, falling back to standard Flash');
const fallback = genAI.getGenerativeModel({
model: 'gemini-2.5-flash',
});
return await fallback.generateContent(prompt);
}
throw error;
}
}
};
個人開発者の視点から(実体験メモ)
全体を振り返って
Gemini 2.5 Flash Thinking は、スピードとコストのバランスを保ちながら「深く考える」能力を提供する注目のモデルです。思考バジェットを適切に制御し、複雑なタスクに絞って使うことで、精度向上とコスト管理を両立できます。
思考トレースのストリーミング表示は、長い処理時間をユーザーに納得してもらうための優れた UX 設計でもあります。ぜひ本記事の実装例を参考に、あなたのシステムに組み込んでみてください。