Skip to content
🔗 分享本题
查看我的学习进度 →

22 模块 Q15 教学图:什么是 Tree of Thoughts(ToT)?它和 CoT、ReAct 有什么区别?什么时候树搜索得不偿失?

🧠 图解记忆:ToT vs ReAct 核心区别;点击图片可查看原图。

💡 答案要点

三种推理模式对比:

模式核心思想推理结构失败模式适用场景
CoT(链式思维)一步步推导出答案线性链一步错全错简单分类、常识推理
ReAct(行动链)Thought → Action → Observe线性链 + 工具漂移累积、循环检索、简单Agent
ToT(思维树)Branch → Evaluate → Prune树状搜索计算成本高复杂规划、创意搜索

ToT 核心原理:

展开 Python 代码示例(95 行)
python
from typing import Callable
import random

class TreeOfThoughts:
    """"Tree of Thoughts 实现框架"""
    
    def __init__(
        self,
        model,  # LLM
        k: int = 5,  # 每步生成 k 个候选
        max_depth: int = 3,  # 最大深度
        prune_threshold: float = 0.5  # 剪枝阈值
    ):
        self.model = model
        self.k = k
        self.max_depth = max_depth
        self.prune_threshold = prune_threshold
    
    def solve(self, problem: str, evaluator: Callable) -> str:
        """
        problem: 问题描述
        evaluator: 评估函数,返回分数(0~1)
        """
        # 初始化:根节点是原始问题
        root = {
            "thought": problem,
            "depth": 0,
            "score": 1.0,
            "parent": None
        }
        frontier = [root]  # 当前 frontier
        
        for depth in range(self.max_depth):
            print(f"\n=== Depth {depth + 1} ===")
            
            # Step 1: 为每个 frontier 节点生成 k 个候选分支
            all_candidates = []
            for node in frontier:
                branches = self._generate_branches(node["thought"], self.k)
                for thought in branches:
                    candidate = {
                        "thought": thought,
                        "depth": depth + 1,
                        "score": 0.0,
                        "parent": node
                    }
                    all_candidates.append(candidate)
            
            # Step 2: 并行评估所有候选节点
            for candidate in all_candidates:
                candidate["score"] = evaluator(candidate["thought"])
            
            # Step 3: 剪枝 + 更新 frontier
            # 按分数排序,保留 top-k
            all_candidates.sort(key=lambda x: x["score"], reverse=True)
            frontier = all_candidates[:self.k]
            
            print(f"Generated {len(all_candidates)} candidates, kept top {self.k}")
            for c in frontier:
                print(f"  Score {c['score']:.2f}: {c['thought'][:50]}...")
            
            # 如果 top 分数已经很高,提前终止
            if frontier[0]["score"] > 0.95:
                break
        
        # 返回最佳叶节点
        return frontier[0]
    
    def _generate_branches(self, thought: str, k: int) -> list[str]:
        """为当前思考生成 k 个分支"""
        prompt = f"""Current thought: {thought}

Generate {k} different possible next steps or approaches. 
Consider different angles and strategies:
"""
        response = self.model.generate(prompt)
        # 解析出 k 个分支(简化处理)
        branches = [line.strip() for line in response.split('\n') if line.strip()]
        return branches[:k]


# 使用示例:创意写作问题
def evaluate_story(thought: str) -> float:
    """评估故事创意的质量(简化版)"""
    keywords = ["surprise", "emotion", "conflict", "resolution"]
    score = sum(1 for kw in keywords if kw.lower() in thought.lower()) / len(keywords)
    # 加入人工判断或用另一个 LLM 评估
    return min(1.0, score + random.uniform(0, 0.2))


# 问题:写一个"AI取代人类"但"人类最终胜出"的故事开头
problem = "Write a story opening about AI replacing humans, but where humanity ultimately prevails"
tot = TreeOfThoughts(model=llm, k=5, max_depth=3, prune_threshold=0.6)
best = tot.solve(problem, evaluator=evaluate_story)
print(f"\nBest story opening: {best['thought']}")

ToT vs ReAct 核心区别:

ReAct(链式):
  问题 → Thought1 → Action1 → Observe1 → Thought2 → Action2 → ...

           如果 Action2 错了,整个链条可能偏离目标
           没有回退机制,只能一条路走到黑

ToT(树搜索):
                      问题
                    /   |   \
              Branch1 Branch2 Branch3
              / | \    / | \    / | \
            ...  ...  ...  ...  ...

            评估每个分支的得分,剪枝低分分支

            继续探索高分分支,重复直到找到满意解

            全局最优解(不是局部最优)

复杂推理什么时候值得使用 ToT:

场景CoT/ReAct 问题ToT 优势
创意生成一次性生成,风格单一多分支探索,找到最有创意解
复杂规划一步错全错,无法回退树搜索 + 剪枝,找到全局最优
谈判/博弈线性推理无法考虑对手反应多路径博弈树,评估对手策略
调试/修复单次修复尝试可能失败多方案并行试错,找到正确修复
数学证明关键步骤错误导致证明失败探索多条证明路径,回溯无效分支

ToT 的局限性(面试必须能说):

问题影响解决方案
计算成本高每步生成 k 个分支,指数增长Beam Search 限制宽度、及早剪枝
评估函数难设计评估不准确导致错误剪枝用 LLM-as-a-Judge、或训练专用评估模型
不适合简单问题杀鸡用牛刀ToT 用于复杂问题,CoT 用于简单问题
并行开销大需要同时调用 LLM k×depth 次批处理、异步调用

生产级选型决策树:

问题类型?
├── 简单分类/抽取 → 直接回答或结构化输出
├── 需要外部信息/动作 → ReAct 或受控工具循环
├── 候选路径可枚举且能可靠评分 → 才考虑 ToT/搜索
└── 无可靠评估器或预算很紧 → 优先改进分解、工具与验证

面试话术:

"ReAct 通常沿一条观察—行动轨迹推进,ToT 会维护多个候选思路并搜索、评分和剪枝。ToT 的前提是候选能被较可靠地评价;否则搜索会放大 Judge 偏差,同时显著增加 token、延迟和实现复杂度。面试中应说明分支数、深度、终止条件及与重采样等基线的对比。"

📚 参考:Tree of Thoughts: Deliberate Problem Solving with Large Language Models(原论文)


版本: v1.5 | 更新: 2026-05-15 | by 二狗子 🐕