Tree of Thoughts (ToT):わかりやすい実践ガイド
1. ToTとは何か? - 基本概念
Tree of Thoughts(ToT)は、言語AIがより複雑な問題を解決するための手法です。通常のAIの使い方では一度に答えを出そうとしますが、ToTでは人間のように「考えるプロセス」を段階的に分けて、複数の可能性を検討しながら最良の解決策を見つけます。
簡単に言えば、ToTは「一度に一本道で考える」のではなく、「木の枝のように複数の可能性を広げながら考える」方法です。
ToTの特徴
- 複数の思考経路を同時に検討: 一つの答えに直進するのではなく、複数の可能性を「枝」として広げる
- 自己評価能力: AIが自分の思考プロセスの良し悪しを判断できる
- 探索とバックトラック: 行き詰まったら別の可能性に戻って再検討できる
従来手法との比較
手法 | どう考えるか | 例え |
---|---|---|
通常プロンプト | 直線的に一発で回答 | 目的地までの一本道 |
Chain of Thought | 一本道だが段階的に考える | 道順を書きながら進む一本道 |
Tree of Thoughts | 複数の可能性を枝分かれして検討 | 地図を見ながら複数ルートを比較 |
2. ToTの4つの基本ステップ
ToTを実装するには、以下の4つのポイントを考える必要があります:
2.1 問題を適切なステップに分解する
問題を解きやすい単位に分けます。たとえば:
- 数学パズル: 各計算ステップ
- 文章作成: 段落やプロット
- クロスワード: 単語や文字
重要なのは、AIにとって「考えられる大きさ」であることです。書籍全体は大きすぎますし、単語一つは小さすぎるかもしれません。
2.2 複数の可能性(思考)を生成する
各ステップで複数の選択肢を考えます。方法としては:
- バラバラに複数案を生成する: 創造的な問題に向いています
- 関連性を持たせながら複数案を出す: 制約のある問題(数学、クロスワードなど)に向いています
2.3 思考の良し悪しを評価する
生成した思考の中から良いものを選びます:
- 個別評価: 各アイデアを個別に「良い/普通/ダメ」などと評価
- 比較評価: 複数のアイデアを比較して「どれが一番良いか」を判断
2.4 探索方法を選ぶ
問題によって適した探索方法を選びます:
-
幅優先探索: 各ステップで複数の良い案を同時に進める(浅く広く)
- 短い手順で解ける問題に向いている
- 例:簡単な数学パズル、文章の構成を考える
-
深さ優先探索: 一つの案を最後まで試し、ダメなら別の案に戻る(深く掘り下げる)
- 複雑な制約がある問題に向いている
- 例:クロスワードパズル、複雑な計画立案
3. ToTの実装方法
ToTは難しく聞こえますが、実際には3つの方法で実装できます。
3.1 コードによる実装(TypeScript版)
コードを使うと最も自由度が高く細かく制御できます:
// 思考ノードを表すクラス
class ThoughtNode {
content: string;
parent: ThoughtNode | null;
children: ThoughtNode[];
value: number | null;
constructor(content: string, parent: ThoughtNode | null = null) {
this.content = content;
this.parent = parent;
this.children = [];
this.value = null;
}
addChild(content: string): ThoughtNode {
const child = new ThoughtNode(content, this);
this.children.push(child);
return child;
}
}
// 思考を生成する関数
async function generateThoughts(
client: any,
state: string,
numThoughts: number = 5
): Promise<string[]> {
const prompt = `
現在の考え方は以下の通りです:
${state}
可能性のある次の${numThoughts}つの異なる思考を生成してください。
`;
const response = await client.messages.create({
model: "gpt-4",
max_tokens: 1000,
temperature: 0.7,
messages: [
{ role: "system", content: "あなたは問題解決の専門家です。" },
{ role: "user", content: prompt }
]
});
// レスポンスから思考を抽出
const thoughts = parseThoughts(response.content);
return thoughts;
}
// 思考を評価する関数
async function evaluateThoughts(
client: any,
thoughts: string[]
): Promise<number[]> {
const prompt = `
以下の思考が問題解決にどれだけ有望かを評価してください:
${thoughts.join('\n\n')}
各思考を1〜10の尺度で評価し、10が最も有望です。
`;
const response = await client.messages.create({
model: "gpt-4",
max_tokens: 500,
temperature: 0.2,
messages: [
{ role: "system", content: "あなたは評価の専門家です。" },
{ role: "user", content: prompt }
]
});
// レスポンスから評価値を抽出
const evaluations = parseEvaluations(response.content);
return evaluations;
}
// 幅優先探索によるToT実装
async function bfsSearch(
client: any,
rootNode: ThoughtNode,
maxDepth: number = 3,
beamWidth: number = 5
): Promise<string> {
let currentLevel: ThoughtNode[] = [rootNode];
for (let depth = 0; depth < maxDepth; depth++) {
let nextLevel: ThoughtNode[] = [];
// 現在のレベルの各ノードに対して子ノードを生成
for (const node of currentLevel) {
const thoughts = await generateThoughts(client, node.content);
// 各思考に対して子ノードを作成
for (const thought of thoughts) {
const child = node.addChild(thought);
nextLevel.push(child);
}
}
// 子ノードを評価
if (nextLevel.length > 0) {
const evaluations = await evaluateThoughts(
client,
nextLevel.map(node => node.content)
);
// 評価に基づいて上位ノードを選択
const nodeEvalPairs = nextLevel.map((node, i) => ({
node,
eval: evaluations[i]
}));
nodeEvalPairs.sort((a, b) => b.eval - a.eval);
nextLevel = nodeEvalPairs
.slice(0, beamWidth)
.map(pair => pair.node);
}
currentLevel = nextLevel;
}
// 最終レベルの最良ノードを返す
if (currentLevel.length > 0) {
const finalEvaluations = await evaluateThoughts(
client,
currentLevel.map(node => node.content)
);
const bestNodeIndex = finalEvaluations.indexOf(
Math.max(...finalEvaluations)
);
const bestNode = currentLevel[bestNodeIndex];
// 最良パスを再構築
return reconstructPath(bestNode);
}
return "解決策が見つかりませんでした";
}
3.2 LangChainを使用した実装(TypeScript)
LangChainというライブラリを使えば、より簡単に実装できます:
import { ChatOpenAI } from "langchain/chat_models/openai";
import { PromptTemplate } from "langchain/prompts";
import { LLMChain } from "langchain/chains";
// 思考生成用のプロンプト
const thoughtGenerationPrompt = new PromptTemplate({
inputVariables: ["currentState"],
template: `
現在の考え方:
{currentState}
可能性のある次の5つの異なる思考を生成してください。それぞれの思考について、なぜ有望かを説明してください。
`
});
// 思考評価用のプロンプト
const thoughtEvaluationPrompt = new PromptTemplate({
inputVariables: ["thoughts"],
template: `
以下の思考が問題解決にどれだけ有望かを評価してください:
{thoughts}
各思考について:
1. 1〜10の評価
2. 評価の理由を簡潔に
3. 「有効」「無効」「部分的に有効」のいずれかに分類
最後に、思考を最も有望なものから順にランク付けしてください。
`
});
// LLMの初期化
const llm = new ChatOpenAI({
modelName: "gpt-4",
temperature: 0.7
});
// チェーンの作成
const generationChain = new LLMChain({
llm,
prompt: thoughtGenerationPrompt
});
const evaluationChain = new LLMChain({
llm,
prompt: thoughtEvaluationPrompt
});
// LangChainを使ったToT実装
async function totWithLangchain(
initialState: string,
maxDepth: number = 3,
beamWidth: number = 3
): Promise<string> {
let currentStates: string[] = [initialState];
for (let depth = 0; depth < maxDepth; depth++) {
let allNewStates: string[] = [];
// 現在の各状態に対して新しい思考を生成
for (const state of currentStates) {
// 思考の生成
const generationResult = await generationChain.call({
currentState: state
});
const newThoughts = parseThoughts(generationResult.text);
// 新しい状態を作成
const newStates = newThoughts.map(thought =>
updateState(state, thought)
);
allNewStates.push(...newStates);
}
// 生成された全ての新しい状態を評価
if (allNewStates.length > 0) {
const evaluationResult = await evaluationChain.call({
thoughts: allNewStates.join("\n\n")
});
const rankings = parseRankings(evaluationResult.text);
// 評価に基づいて上位の状態を選択
const rankedStates = allNewStates
.map((state, index) => ({
state,
rank: rankings[index]
}))
.sort((a, b) => b.rank - a.rank);
currentStates = rankedStates
.slice(0, beamWidth)
.map(item => item.state);
}
}
// 最終的な解決策を生成
return generateSolution(currentStates[0]);
}
3.3 プロンプトだけで実装する方法
プログラミングなしで、単一のプロンプトでToTを簡易的に実装できます:
【専門家による思考プロセス】
この問題について3人の異なる専門家が考えていると想像してください。
各専門家は段階的に思考し、意見を共有します。
間違いに気づいた専門家は、その時点で議論から抜け、他の専門家の考えを聞きます。
問題は次の通りです:
[問題の詳細]
専門家たちは以下の手順で考えてください:
ステップ1: 各専門家は問題に対する最初の考えを述べます。
ステップ2: お互いの考えを分析し、最も有望なアプローチを発展させます。
ステップ3: さらに考えを深め、最終的な解決策を導き出します。
専門家たちは常に理由を説明し、他の専門家の考えも尊重してください。
最も説得力のある解決策を最終的な答えとしてください。
4. ToTの実際の応用例
4.1 数学パズル「24ゲーム」
4つの数字(例:4, 9, 10, 13)を使って、四則演算だけで「24」という数を作るゲームです。
ToTアプローチ:
- 最初のステップで5つの異なる計算方法を考える(例:13-9=4、4+9=13など)
- 各計算結果から次のステップの計算方法を考える
- 各ステップで「確実に24になる」「たぶん24になる」「絶対に24にならない」と評価
- 有望なパスを優先的に探索
コード実装イメージ:
// 24ゲームの思考評価関数
async function evaluate24GameThought(
client: any,
numbersLeft: number[],
currentResult: number
): Promise<string> {
const prompt = `
残りの数字: ${numbersLeft.join(', ')}
現在の計算結果: ${currentResult}
これらの数字を使って24を作れるかどうか評価してください:
- 「確実」:確実に24を作れる
- 「たぶん」:有望だがまだ確信できない
- 「不可能」:絶対に24にならないと証明できる
理由も簡潔に説明してください。
`;
// 省略(評価ロジック)
return evaluation;
}
結果:
- 通常のChain of Thoughtでは4%の成功率
- ToTでは74%の成功率を達成
4.2 クリエイティブライティング
4つのランダムな文を末尾に持つ4段落の文章を作成するタスクです。
ToTアプローチ:
- 複数の文章構成プランを考える
- プラン同士を比較して最良のものを選ぶ
- 選んだプランに基づいて複数の文章案を作る
- 文章案を比較して最良のものを選ぶ
実装イメージ:
// クリエイティブライティングのToT実装
async function creativeWritingTot(
client: any,
sentences: string[]
): Promise<string> {
// 1. 複数の文章構成プランを生成
const plans = await generateWritingPlans(client, sentences, 5);
// 2. プランを評価して最良のものを選択
const bestPlan = await voteForBestPlan(client, plans);
// 3. 選択されたプランに基づく文章案を生成
const passages = await generatePassages(client, bestPlan, sentences, 5);
// 4. 文章案を評価して最良のものを選択
const bestPassage = await voteForBestPassage(client, passages);
return bestPassage;
}
結果:
- 人間の評価で、ToTが生成した文章の方が一貫性が高いと判断
4.3 クロスワードパズル
ヒントを元に5×5のクロスワードパズルを解くタスクです。
ToTアプローチ:
- 最も確信度の高い単語から埋めていく
- 既に入力した文字との整合性を常にチェック
- 行き詰まったら別の単語に戻ってやり直す(バックトラック)
実装イメージ:
// クロスワードパズルのDFS実装
async function crosswordDfs(
client: any,
clues: {[key: string]: string},
currentBoard: string[][],
depth: number = 0,
maxDepth: number = 10
): Promise<string[][] | null> {
// 完成またはステップ上限に達したらボードを返す
if (depth >= maxDepth || isBoardComplete(currentBoard)) {
return currentBoard;
}
// 次に埋める単語ヒントを選択
const nextClue = selectNextClue(clues, currentBoard);
// 候補となる単語を生成
const wordCandidates = await proposeWords(client, nextClue, currentBoard);
// 確信度に基づいて並べ替え
const sortedCandidates = sortByConfidence(wordCandidates);
// 各候補を試す
for (const [word, confidence] of sortedCandidates) {
// 単語を配置した新しいボードを作成
const newBoard = placeWord(currentBoard, nextClue, word);
// ボードが有効かどうか評価
if (await isBoardValid(client, newBoard, clues)) {
// 探索を続行
const result = await crosswordDfs(
client,
clues,
newBoard,
depth + 1,
maxDepth
);
if (result !== null) {
return result;
}
}
}
// すべての候補が失敗したらバックトラック
return null;
}
結果:
- 通常手法の単語成功率15.6%に対し、ToTは60%を達成
5. 実用的なヒントとベストプラクティス
タスク別の最適なアプローチ
タスクタイプ | おすすめの探索方法 | 思考の単位 | 評価方法 |
---|---|---|---|
数学/論理パズル | 幅優先探索 | 式/ステップ | 確実/たぶん/不可能 |
文章作成 | 浅い木+投票 | 段落/構成 | 人間らしさ/一貫性 |
検索問題(クロスワード等) | 深さ優先+バックトラック | 単語/制約 | 制約満足度 |
計画問題 | 幅優先/深さ優先 | アクション | 目標達成度 |
実装時の注意点
-
思考単位の選択:
- 大きすぎず、小さすぎない適切なサイズを選ぶ
- AIが評価できる具体性を持たせる
-
評価方法の工夫:
- 明確な評価基準を設定する
- 理由付けを求めることで質を高める
- 複数の評価を集約する
-
リソース管理:
- 探索の幅と深さのバランスを取る
- 明らかに不適切な思考は早めに排除する
- 適切なモデルを選択する(温度設定も重要)
6. ToTが他のプロンプト手法より優れている根拠
ToTが従来のプロンプト手法よりも大幅に優れていることは、複数の実験結果や性能比較から明らかになっています。
具体的な性能比較データ
タスク | 通常プロンプト (IO) | Chain of Thought (CoT) | ToT (Tree of Thoughts) |
---|---|---|---|
Game of 24(成功率) | 7.3% | 4.0% | 74% |
クロスワード(単語成功率) | 14% | 15.6% | 60% |
クリエイティブライティング(人間評価) | 21% | 38% | 41% (「より良い」と評価された割合) |
これらの数値は、Princeton大学とGoogle DeepMindの研究者による原論文の実験結果から得られたものです。特にGame of 24では、ToTが従来手法に対して約18倍もの成功率向上を示しており、複雑な問題解決におけるToTの圧倒的な優位性を証明しています。
ToTが優れている理由
-
探索能力の向上:
- 従来の手法は直線的に思考するため、初期の誤りがそのまま最終結果に影響する
- ToTは複数の思考経路を同時に検討するため、より良い解決策を見つけやすい
-
自己修正能力:
- 標準的なAIの使い方では、一度間違えると修正が難しい
- ToTでは各ステップで評価を行い、有望でない経路を早期に捨てられる
-
バックトラッキング:
- 行き詰まりに対処する能力がある(クロスワードパズルで特に効果的)
- これは人間の問題解決アプローチに近い方法
-
問題の性質に合わせた柔軟性:
- 探索アルゴリズムを問題に合わせて選択できる
- 思考の粒度を適切に調整できる
特に効果を発揮する問題タイプ
ToTは以下のような問題タイプで特に優れた性能を発揮します:
- 戦略的先読みが必要な問題: 数学パズル、チェスなどのゲーム
- 複雑な制約がある問題: クロスワード、スケジューリング問題
- 初期の決定が重要な問題: 複数の解決策がある創造的タスク
- 試行錯誤が必要な問題: 一度の推論では解けない複雑な問題
7. 結論
Tree of Thoughts(ToT)は、AIの問題解決能力を大幅に向上させる実用的な手法です。通常のプロンプト技術では難しい複雑な問題でも、複数の思考経路を系統的に探索することで、より質の高い解決策を見つけることができます。
ToTの実装は、コード、LangChain、単純なプロンプトなど、様々な方法で可能です。問題の性質に合わせて適切な思考分解、生成方法、評価基準、探索アルゴリズムを選択することで、AIの潜在能力を最大限に引き出すことができます。
数学パズル、文章作成、クロスワードパズルなどの実例では、ToTが従来手法を大幅に上回る性能を示しており、複雑な問題解決のための強力なツールとして活用できます。
Discussion