知识模块
🤖 Agent 知识模块
思维树(ToT)

Tree-of-Thought(思维树)

Tree-of-Thought(ToT) 是 CoT 的扩展,由 Yao et al. 和 Long et al. 于 2023 年提出。其核心思想是将推理过程组织成树状结构,每个节点代表一个思考状态,通过搜索算法(BFS/DFS)探索多条推理路径,支持回溯和剪枝。


一、核心原理

1.1 ToT 的设计哲学

ToT 解决了 CoT 的线性推理限制:

┌─────────────────────────────────────────────────────────────┐
│                    CoT vs ToT 结构对比                       │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   Chain-of-Thought(线性):                                │
│   ┌─────────────────────────────────────────────────────┐  │
│   │                                                     │  │
│   │   问题 ─→ 思考1 ─→ 思考2 ─→ 思考3 ─→ 答案          │  │
│   │                                                     │  │
│   │   ❌ 单一路径,无法回溯                             │  │
│   │   ❌ 一旦走错,全盘皆输                             │  │
│   │                                                     │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
│   Tree-of-Thought(树状):                                 │
│   ┌─────────────────────────────────────────────────────┐  │
│   │                                                     │  │
│   │                   问题                              │  │
│   │                    │                                │  │
│   │          ┌─────────┼─────────┐                     │  │
│   │          ↓         ↓         ↓                     │  │
│   │       思考1a     思考1b     思考1c                  │  │
│   │          │         │         │                     │  │
│   │          ↓         ↓         ↓                     │  │
│   │       思考2a     思考2b     思考2c                  │  │
│   │          │         │                               │  │
│   │          ↓         ↓                               │  │
│   │       思考3a     思考3b                             │  │
│   │          │         │                               │  │
│   │          ↓         ↓                               │  │
│   │       答案A      答案B                              │  │
│   │                                                     │  │
│   │   ✅ 多路径探索,支持回溯                           │  │
│   │   ✅ 剪枝优化,资源可控                             │  │
│   │                                                     │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
└─────────────────────────────────────────────────────────────┘

1.2 ToT 核心组件

组件作用说明
Thought Generation生成候选思考为当前状态生成多个可能的下一步思考
State Evaluation状态评估评估当前思考状态的价值/可行性
Search Algorithm搜索算法BFS(广度优先)或 DFS(深度优先)
Backtracking回溯机制遇到死路时回退到上一状态

1.3 搜索策略对比

┌─────────────────────────────────────────────────────────────┐
│                    BFS vs DFS 搜索策略                       │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   BFS(广度优先搜索):                                     │
│   ┌─────────────────────────────────────────────────────┐  │
│   │                                                     │  │
│   │                   问题                              │  │
│   │                    │                                │  │
│   │          ┌─────────┼─────────┐                     │  │
│   │          ↓         ↓         ↓   ← 第 1 层         │  │
│   │       思考1a     思考1b     思考1c                  │  │
│   │          │         │         │                     │  │
│   │          ↓         ↓         ↓   ← 第 2 层         │  │
│   │       思考2a     思考2b     思考2c                  │  │
│   │                                                     │  │
│   │   特点:逐层探索,保证找到最短路径                   │  │
│   │   适用:需要全局最优解                              │  │
│   │                                                     │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
│   DFS(深度优先搜索):                                     │
│   ┌─────────────────────────────────────────────────────┐  │
│   │                                                     │  │
│   │                   问题                              │  │
│   │                    │                                │  │
│   │                    ↓                                │  │
│   │                 思考1a                              │  │
│   │                    │                                │  │
│   │                    ↓                                │  │
│   │                 思考2a  ──→ 评估:差,回溯          │  │
│   │                    ↑                                │  │
│   │                 思考1b  ← 回退                       │  │
│   │                    │                                │  │
│   │                    ↓                                │  │
│   │                 思考2b                              │  │
│   │                    │                                │  │
│   │                    ↓                                │  │
│   │                  答案                               │  │
│   │                                                     │  │
│   │   特点:深入探索,快速找到可行解                     │  │
│   │   适用:需要快速找到解,深度可控                    │  │
│   │                                                     │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
└─────────────────────────────────────────────────────────────┘

二、工作流程

2.1 完整工作流程图

┌─────────────────────────────────────────────────────────────────────┐
│                    ToT 完整工作流程                                  │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│   ┌─────────────┐                                                  │
│   │  用户输入   │                                                  │
│   │  (Query)    │                                                  │
│   └──────┬──────┘                                                  │
│          │                                                         │
│          ↓                                                         │
│   ┌─────────────────────────────────────────────────────────────┐ │
│   │                    初始化搜索树                              │ │
│   │   root_state = {thought: None, children: [], depth: 0}      │ │
│   └─────────────────────────────────────────────────────────────┘ │
│          │                                                         │
│          ↓                                                         │
│   ┌─────────────────────────────────────────────────────────────┐ │
│   │                    ToT 搜索循环                              │ │
│   │                                                             │ │
│   │   while not search_complete:                                │ │
│   │                                                             │ │
│   │       ┌─────────────────────────────────────────────────┐  │ │
│   │       │ 1. 选择待扩展状态                                │  │ │
│   │       │    current = select_state(frontier)             │  │ │
│   │       └─────────────────────────────────────────────────┘  │ │
│   │                          │                                  │ │
│   │                          ↓                                  │ │
│   │       ┌─────────────────────────────────────────────────┐  │ │
│   │       │ 2. 生成候选思考                                  │  │ │
│   │       │    thoughts = generate_thoughts(current, k)     │  │ │
│   │       │    // k = 每次生成的候选数量                     │  │ │
│   │       └─────────────────────────────────────────────────┘  │ │
│   │                          │                                  │ │
│   │                          ↓                                  │ │
│   │       ┌─────────────────────────────────────────────────┐  │ │
│   │       │ 3. 评估每个候选                                  │  │ │
│   │       │    for thought in thoughts:                     │  │ │
│   │       │        score = evaluate(thought)                │  │ │
│   │       │        if score < threshold:                     │  │ │
│   │       │            prune(thought)  // 剪枝              │  │ │
│   │       └─────────────────────────────────────────────────┘  │ │
│   │                          │                                  │ │
│   │                          ↓                                  │ │
│   │       ┌─────────────────────────────────────────────────┐  │ │
│   │       │ 4. 更新搜索树                                    │  │ │
│   │       │    add_children(current, valid_thoughts)        │  │ │
│   │       └─────────────────────────────────────────────────┘  │ │
│   │                          │                                  │ │
│   │                          ↓                                  │ │
│   │       ┌─────────────────────────────────────────────────┐  │ │
│   │       │ 5. 检查终止条件                                  │  │ │
│   │       │    - 找到目标状态?                              │  │ │
│   │       │    - 达到最大深度?                              │  │ │
│   │       │    - 资源耗尽?                                  │  │ │
│   │       └─────────────────────────────────────────────────┘  │ │
│   │                                                             │ │
│   └─────────────────────────────────────────────────────────────┘ │
│          │                                                         │
│          ↓                                                         │
│   ┌─────────────────────┐                                          │
│   │   返回最优解        │                                          │
│   │   (Best Solution)   │                                          │
│   └─────────────────────┘                                          │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

2.2 关键步骤详解

步骤输入处理输出
1. 状态选择搜索边界(frontier)根据策略选择下一个要扩展的状态当前状态
2. 思考生成当前状态 + 问题LLM 生成 k 个候选思考候选思考列表
3. 状态评估候选思考LLM 评估每个思考的价值评分列表
4. 剪枝候选 + 评分移除低分候选有效候选列表
5. 树更新当前状态 + 有效候选将候选添加为子节点更新后的树

三、代码实现

3.1 基础 ToT 实现

"""
Tree-of-Thought 基础实现
支持 BFS 和 DFS 两种搜索策略
"""
 
from typing import List, Optional, Callable
from dataclasses import dataclass, field
from enum import Enum
import heapq
 
from langchain_openai import ChatOpenAI
 
 
class SearchStrategy(Enum):
    """搜索策略"""
    BFS = "bfs"  # 广度优先
    DFS = "dfs"  # 深度优先
    BEST_FIRST = "best_first"  # 最佳优先
 
 
@dataclass
class ThoughtNode:
    """思维树节点"""
    thought: str                          # 当前思考内容
    depth: int                            # 深度
    score: float = 0.0                    # 评分
    parent: Optional['ThoughtNode'] = None
    children: List['ThoughtNode'] = field(default_factory=list)
    is_solution: bool = False             # 是否是解
    solution: Optional[str] = None        # 解的内容
    
    def path(self) -> List[str]:
        """获取从根到当前节点的路径"""
        if self.parent is None:
            return [self.thought] if self.thought else []
        return self.parent.path() + [self.thought]
    
    def __lt__(self, other):
        """用于优先队列比较"""
        return self.score > other.score  # 分数高的优先
 
 
class TreeOfThought:
    """
    Tree-of-Thought 推理器
    支持 BFS、DFS 和 Best-First 搜索
    """
    
    THOUGHT_GENERATION_PROMPT = """
你正在解决以下问题:
{problem}
 
当前推理路径:
{current_path}
 
请生成 {k} 个不同的下一步思考。每个思考应该是:
1. 有意义的推理步骤
2. 有助于解决问题
3. 与之前路径不同
 
请按以下格式输出:
思考1: ...
思考2: ...
思考3: ...
"""
    
    EVALUATION_PROMPT = """
你正在评估一个推理步骤的有效性。
 
问题:{problem}
当前路径:{path}
待评估思考:{thought}
 
请评估这个思考对解决问题的贡献程度。
评分标准:
- 1分:错误或无意义的思考
- 2分:部分正确但有缺陷
- 3分:正确但进展有限
- 4分:很有帮助的思考
- 5分:关键性的突破
 
只输出一个数字(1-5):
"""
    
    SOLUTION_CHECK_PROMPT = """
基于以下推理路径,问题是否已经解决?
 
问题:{problem}
推理路径:{path}
 
如果问题已解决,请给出最终答案。
如果问题未解决,请回答"继续推理"。
 
输出格式:
状态:已解决/继续推理
答案:(如果已解决)
"""
    
    def __init__(
        self,
        model_name: str = "gpt-4",
        strategy: SearchStrategy = SearchStrategy.BFS,
        max_depth: int = 5,
        num_thoughts: int = 3,
        beam_width: int = 3,
        score_threshold: float = 2.0
    ):
        """
        初始化 ToT 推理器
        
        Args:
            model_name: 模型名称
            strategy: 搜索策略
            max_depth: 最大深度
            num_thoughts: 每次生成的候选思考数量
            beam_width: Beam 宽度(保留的候选数量)
            score_threshold: 剪枝阈值
        """
        self.llm = ChatOpenAI(model=model_name, temperature=0.7)
        self.strategy = strategy
        self.max_depth = max_depth
        self.num_thoughts = num_thoughts
        self.beam_width = beam_width
        self.score_threshold = score_threshold
    
    def generate_thoughts(self, problem: str, current_path: List[str]) -> List[str]:
        """生成候选思考"""
        prompt = self.THOUGHT_GENERATION_PROMPT.format(
            problem=problem,
            current_path="\n".join(current_path) if current_path else "(开始)",
            k=self.num_thoughts
        )
        
        response = self.llm.invoke(prompt)
        
        # 解析输出
        thoughts = []
        for line in response.content.split('\n'):
            if line.strip().startswith('思考'):
                # 提取思考内容
                parts = line.split(':', 1)
                if len(parts) > 1:
                    thoughts.append(parts[1].strip())
        
        return thoughts[:self.num_thoughts]
    
    def evaluate_thought(self, problem: str, path: List[str], thought: str) -> float:
        """评估思考"""
        prompt = self.EVALUATION_PROMPT.format(
            problem=problem,
            path="\n".join(path),
            thought=thought
        )
        
        response = self.llm.invoke(prompt)
        
        # 解析评分
        try:
            score = float(response.content.strip())
            return max(1, min(5, score))  # 限制在 1-5 范围
        except:
            return 3.0  # 默认中等评分
    
    def check_solution(self, problem: str, path: List[str]) -> tuple[bool, Optional[str]]:
        """检查是否找到解"""
        prompt = self.SOLUTION_CHECK_PROMPT.format(
            problem=problem,
            path="\n".join(path)
        )
        
        response = self.llm.invoke(prompt)
        content = response.content
        
        if "已解决" in content:
            # 提取答案
            for line in content.split('\n'):
                if '答案' in line:
                    answer = line.split(':', 1)[1].strip() if ':' in line else line
                    return True, answer
            return True, content
        
        return False, None
    
    def solve(self, problem: str) -> dict:
        """
        使用 ToT 解决问题
        
        Args:
            problem: 问题文本
            
        Returns:
            包含解题过程的字典
        """
        # 初始化根节点
        root = ThoughtNode(thought="", depth=0, score=5.0)
        
        # 根据策略选择数据结构
        if self.strategy == SearchStrategy.BFS:
            frontier = [root]  # 队列
        elif self.strategy == SearchStrategy.DFS:
            frontier = [root]  # 栈
        else:  # BEST_FIRST
            frontier = []  # 优先队列
            heapq.heappush(frontier, root)
        
        visited_states = set()
        best_solution = None
        best_score = 0
        
        while frontier:
            # 选择下一个状态
            if self.strategy == SearchStrategy.BFS:
                current = frontier.pop(0)
            elif self.strategy == SearchStrategy.DFS:
                current = frontier.pop()
            else:
                current = heapq.heappop(frontier)
            
            # 检查深度限制
            if current.depth >= self.max_depth:
                continue
            
            # 获取当前路径
            path = current.path()
            
            # 检查是否已找到解
            is_solved, solution = self.check_solution(problem, path)
            if is_solved:
                current.is_solution = True
                current.solution = solution
                if current.score > best_score:
                    best_solution = current
                continue
            
            # 生成候选思考
            thoughts = self.generate_thoughts(problem, path)
            
            # 评估并筛选
            candidates = []
            for thought in thoughts:
                score = self.evaluate_thought(problem, path, thought)
                if score >= self.score_threshold:
                    node = ThoughtNode(
                        thought=thought,
                        depth=current.depth + 1,
                        score=score,
                        parent=current
                    )
                    candidates.append(node)
            
            # 按 Beam 宽度保留
            candidates.sort(key=lambda x: x.score, reverse=True)
            candidates = candidates[:self.beam_width]
            
            # 添加到树和边界
            for node in candidates:
                current.children.append(node)
                if self.strategy == SearchStrategy.BEST_FIRST:
                    heapq.heappush(frontier, node)
                else:
                    frontier.append(node)
        
        return {
            "problem": problem,
            "strategy": self.strategy.value,
            "solution": best_solution.solution if best_solution else None,
            "path": best_solution.path() if best_solution else None,
            "tree": self._tree_to_dict(root)
        }
    
    def _tree_to_dict(self, node: ThoughtNode) -> dict:
        """将树转换为字典格式"""
        return {
            "thought": node.thought,
            "depth": node.depth,
            "score": node.score,
            "is_solution": node.is_solution,
            "children": [self._tree_to_dict(c) for c in node.children]
        }
 
 
# 使用示例
if __name__ == "__main__":
    # BFS 策略
    tot_bfs = TreeOfThought(
        strategy=SearchStrategy.BFS,
        max_depth=4,
        num_thoughts=3,
        beam_width=2
    )
    
    result = tot_bfs.solve(
        "用 24 根火柴棍摆成 9 个正方形,如何实现?"
    )
    
    print(f"问题:{result['problem']}")
    print(f"策略:{result['strategy']}")
    print(f"解答路径:")
    for i, thought in enumerate(result['path'], 1):
        print(f"  {i}. {thought}")
    print(f"最终答案:{result['solution']}")

3.2 使用 LangChain 实现

"""
使用 LangChain 实现 ToT
"""
 
from langchain.chains import LLMChain
from langchain.prompts import PromptTemplate
from langchain_openai import ChatOpenAI
from typing import List, Optional
from pydantic import BaseModel
 
 
class ThoughtEvaluation(BaseModel):
    """思考评估结果"""
    thought: str
    score: float
    reasoning: str
 
 
class LangChainToT:
    """基于 LangChain 的 ToT 实现"""
    
    def __init__(self, model_name: str = "gpt-4"):
        self.llm = ChatOpenAI(model=model_name, temperature=0)
        self._setup_chains()
    
    def _setup_chains(self):
        """设置推理链"""
        
        # 思考生成链
        thought_prompt = PromptTemplate(
            input_variables=["problem", "history", "n"],
            template="""
问题:{problem}
 
已进行的思考:
{history}
 
请生成 {n} 个可能的下一步思考。
每个思考应该是独立的、有意义的推理步骤。
 
格式:
1. [思考内容]
2. [思考内容]
...
"""
        )
        self.thought_chain = LLMChain(llm=self.llm, prompt=thought_prompt)
        
        # 评估链
        eval_prompt = PromptTemplate(
            input_variables=["problem", "thought", "history"],
            template="""
问题:{problem}
 
已进行的思考:
{history}
 
待评估思考:{thought}
 
请评估这个思考对解决问题的价值(1-10分)。
只输出一个数字。
"""
        )
        self.eval_chain = LLMChain(llm=self.llm, prompt=eval_prompt)
        
        # 最终答案链
        answer_prompt = PromptTemplate(
            input_variables=["problem", "reasoning"],
            template="""
问题:{problem}
 
推理过程:
{reasoning}
 
请根据以上推理给出最终答案。
"""
        )
        self.answer_chain = LLMChain(llm=self.llm, prompt=answer_prompt)
    
    def solve(self, problem: str, max_depth: int = 5) -> dict:
        """解决问题"""
        thoughts = []
        
        for depth in range(max_depth):
            # 生成候选
            history = "\n".join(thoughts) if thoughts else "开始推理"
            candidates_text = self.thought_chain.run(
                problem=problem,
                history=history,
                n=3
            )
            
            # 解析候选
            candidates = []
            for line in candidates_text.split('\n'):
                line = line.strip()
                if line and line[0].isdigit():
                    thought = line.split('.', 1)[1].strip() if '.' in line else line
                    candidates.append(thought)
            
            if not candidates:
                break
            
            # 评估候选
            best_thought = None
            best_score = 0
            
            for thought in candidates:
                score_text = self.eval_chain.run(
                    problem=problem,
                    thought=thought,
                    history=history
                )
                try:
                    score = float(score_text.strip())
                except:
                    score = 5
                
                if score > best_score:
                    best_score = score
                    best_thought = thought
            
            if best_thought:
                thoughts.append(best_thought)
        
        # 生成答案
        reasoning = "\n".join(thoughts)
        answer = self.answer_chain.run(problem=problem, reasoning=reasoning)
        
        return {
            "problem": problem,
            "thoughts": thoughts,
            "answer": answer
        }

四、适用场景

4.1 最佳适用场景

场景类型具体示例ToT 优势
复杂决策多方案比选、策略制定多路径探索,找到最优解
创意写作故事创作、文案设计支持发散思维和回溯
数学证明复杂几何证明分步推理,验证每步正确性
游戏博弈棋类游戏、解谜状态搜索,前瞻评估

4.2 场景详解

┌─────────────────────────────────────────────────────────────┐
│                    ToT 典型应用场景                          │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  1. 创意写作场景                                            │
│  ┌─────────────────────────────────────────────────────┐   │
│  │ 任务:为一个科幻故事设计三种不同的结局               │   │
│  │                                                      │   │
│  │                      故事开头                        │   │
│  │                          │                           │   │
│  │            ┌─────────────┼─────────────┐            │   │
│  │            ↓             ↓             ↓            │   │
│  │        结局A:       结局B:       结局C:          │   │
│  │        悲剧收场      皆大欢喜      开放结局          │   │
│  │            │             │             │            │   │
│  │            ↓             ↓             ↓            │   │
│  │        详细展开      详细展开      详细展开          │   │
│  │                                                      │   │
│  │   ✅ 可以同时探索多个创意方向                        │   │
│  │   ✅ 不满意可以回溯重写                              │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  2. 数学证明场景                                            │
│  ┌─────────────────────────────────────────────────────┐   │
│  │ 问题:证明三角形内角和为 180°                        │   │
│  │                                                      │   │
│  │                     已知三角形ABC                    │   │
│  │                          │                           │   │
│  │            ┌─────────────┼─────────────┐            │   │
│  │            ↓             ↓             ↓            │   │
│  │        方法1:       方法2:       方法3:          │   │
│  │        作辅助线      坐标法       向量法             │   │
│  │            │             │             │            │   │
│  │            ↓             ↓             ↓            │   │
│  │        过A作BC       建立坐标     向量计算           │   │
│  │        平行线        系计算角度   证明结论           │   │
│  │            │             │                          │   │
│  │            ↓             ↓                          │   │
│  │        利用平行      角度计算                       │   │
│  │        线性质        出结论                         │   │
│  │            │                                          │   │
│  │            ↓                                          │   │
│  │        证明完成                                       │   │
│  │                                                      │   │
│  │   ✅ 尝试多种证明方法                                │   │
│  │   ✅ 一种方法失败可尝试其他方法                      │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘

4.3 与 CoT 的适用场景对比

场景CoTToT推荐
简单计算✅ 足够❌ 过度设计CoT
多步推理✅ 足够⚠️ 可选CoT
需要回溯❌ 不支持✅ 支持ToT
创意探索❌ 单路径✅ 多路径ToT
决策分析⚠️ 局限✅ 适合ToT

五、搜索策略详解

5.1 BFS(广度优先搜索)

┌─────────────────────────────────────────────────────────────┐
│                    BFS 搜索过程                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   优点:                                                    │
│   • 保证找到最短路径                                        │
│   • 全局视角,不会错过浅层解                                │
│                                                             │
│   缺点:                                                    │
│   • 内存消耗大(需存储整层节点)                            │
│   • 可能浪费时间探索无效分支                                │
│                                                             │
│   适用场景:                                                │
│   • 需要最短推理路径                                        │
│   • 解可能在较浅层                                          │
│   • 内存资源充足                                            │
│                                                             │
│   示例:24点游戏                                            │
│   ┌─────────────────────────────────────────────────────┐  │
│   │ 第1层:尝试4个数字作为第一个操作数                   │  │
│   │ 第2层:对每个操作数,尝试3种运算                     │  │
│   │ 第3层:尝试第二个操作数...                           │  │
│   │ 逐层搜索直到找到解                                   │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
└─────────────────────────────────────────────────────────────┘

5.2 DFS(深度优先搜索)

┌─────────────────────────────────────────────────────────────┐
│                    DFS 搜索过程                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   优点:                                                    │
│   • 内存消耗小(只存储当前路径)                            │
│   • 快速深入,可能快速找到解                                │
│                                                             │
│   缺点:                                                    │
│   • 可能陷入深层无效分支                                    │
│   • 不保证最短路径                                          │
│                                                             │
│   适用场景:                                                │
│   • 解可能在深层                                            │
│   • 需要快速找到可行解                                      │
│   • 内存资源有限                                            │
│                                                             │
│   示例:数独求解                                            │
│   ┌─────────────────────────────────────────────────────┐  │
│   │ 选择一个空格 → 尝试填入1 → 继续 → 遇到冲突?        │  │
│   │                          ↓                           │  │
│   │                       回溯                           │  │
│   │                          ↓                           │  │
│   │                    尝试填入2 → 继续...               │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
└─────────────────────────────────────────────────────────────┘

5.3 Best-First Search(最佳优先)

┌─────────────────────────────────────────────────────────────┐
│                    Best-First 搜索                           │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   核心思想:优先扩展评估分数最高的节点                       │
│                                                             │
│   实现:使用优先队列(堆)                                   │
│                                                             │
│   优点:                                                    │
│   • 结合了 BFS 和 DFS 的优点                                │
│   • 更快找到高质量解                                        │
│                                                             │
│   缺点:                                                    │
│   • 依赖评估函数的准确性                                    │
│   • 评估函数可能有误                                        │
│                                                             │
│   评估函数示例:                                            │
│   ┌─────────────────────────────────────────────────────┐  │
│   │ score = 距离目标的相似度 + 路径质量                  │  │
│   │                                                     │  │
│   │ 例如对于创意写作:                                   │  │
│   │ score = 情节连贯性(1-5) + 创意程度(1-5)             │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
└─────────────────────────────────────────────────────────────┘

六、ToT 的优化策略

6.1 剪枝策略

策略描述效果
分数剪枝移除评分低于阈值的节点减少无效探索
重复检测跳过已访问的相同状态避免重复计算
深度限制设置最大深度控制资源消耗
Beam 搜索每层只保留 top-k 节点平衡效果与效率

6.2 评估优化

# 评估策略优化
 
class ImprovedToT(TreeOfThought):
    """改进版 ToT"""
    
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.evaluation_cache = {}  # 缓存评估结果
    
    def evaluate_thought_with_cache(self, problem: str, path: List[str], thought: str) -> float:
        """带缓存的评估"""
        cache_key = f"{problem}|{'|'.join(path)}|{thought}"
        
        if cache_key in self.evaluation_cache:
            return self.evaluation_cache[cache_key]
        
        score = self.evaluate_thought(problem, path, thought)
        self.evaluation_cache[cache_key] = score
        
        return score
    
    def evaluate_batch(self, problem: str, path: List[str], thoughts: List[str]) -> List[float]:
        """批量评估,减少 API 调用"""
        prompt = f"""
问题:{problem}
当前路径:{' → '.join(path) if path else '开始'}
 
请评估以下每个思考的价值(1-5分):
 
{chr(10).join(f'{i+1}. {t}' for i, t in enumerate(thoughts))}
 
请按以下格式输出:
1: 分数
2: 分数
...
"""
        response = self.llm.invoke(prompt)
        
        # 解析批量评分
        scores = []
        for line in response.content.split('\n'):
            if ':' in line:
                try:
                    score = float(line.split(':')[1].strip())
                    scores.append(max(1, min(5, score)))
                except:
                    scores.append(3.0)
        
        # 确保返回数量正确
        while len(scores) < len(thoughts):
            scores.append(3.0)
        
        return scores[:len(thoughts)]

七、面试高频问题

Q1: ToT 与 CoT 的核心区别是什么?

答案要点:

  • 结构:CoT 是线性链,ToT 是树结构
  • 回溯:CoT 不支持回溯,ToT 支持
  • 路径:CoT 单一路径,ToT 多路径探索
  • 适用场景:简单推理用 CoT,复杂决策用 ToT

Q2: BFS 和 DFS 如何选择?

答案要点:

  • BFS:需要最短路径、解在浅层、内存充足
  • DFS:需要快速找到解、解可能在深层、内存有限
  • Best-First:有好的评估函数、需要高质量解

Q3: ToT 的主要开销在哪里?如何优化?

答案要点:

  • 开销

    • 每个节点需要多次 LLM 调用(生成+评估)
    • 树结构导致节点数量指数增长
  • 优化

    • 剪枝:移除低分节点
    • Beam 搜索:每层保留有限节点
    • 缓存:避免重复评估
    • 批量评估:减少 API 调用次数

Q4: ToT 适用于哪些场景?

答案要点:

  • 需要探索多种可能方案的问题
  • 初始方向不确定的问题
  • 需要回溯修正的推理过程
  • 创意性任务(写作、设计)

Q5: ToT 的评估函数如何设计?

答案要点:

  • 可以使用 LLM 自身进行评估
  • 评估维度:正确性、进展程度、创新性
  • 可以结合外部验证器
  • 评估可以分粗评和细评两个阶段

八、小结

概念一句话总结面试关键词
ToT树状推理,支持多路径探索和回溯思维树、搜索算法
BFS广度优先,保证最短路径逐层探索、内存消耗大
DFS深度优先,快速深入回溯、内存消耗小
剪枝移除无效节点,提升效率Beam 搜索、分数阈值

一句话总结:ToT 将推理组织成树结构,通过搜索算法探索多条路径,解决了 CoT 无法回溯的问题,适合复杂决策和创意探索。


最后更新:2026年3月19日