思维链的演进脉络

大语言模型的推理能力不完全是"涌现"出来的,很多时候取决于我们如何引导它思考。从最基础的CoT(Chain-of-Thought)到树状的ToT(Tree-of-Thoughts)再到图状的GoT(Graph-of-Thoughts),每一种范式都在扩展前一种的推理边界。

CoT:线性推理的基石

核心思想

CoT的本质是让模型"展示推理过程"。通过在输出最终答案前生成中间推理步骤,降低模型跳过关键逻辑的风险。

# Zero-shot CoT
提示: 一个教室有32个学生,其中3/8是女生。又来了4个女生。现在女生占多少?
附加: 让我们一步一步思考。

# 模型输出
原女生数: 32 × 3/8 = 12
加入后女生数: 12 + 4 = 16
总人数: 32 + 4 = 36
比例: 16/36 = 4/9 ≈ 44.4%

Few-shot CoT模板

COT_TEMPLATE = """
# 示例1
问题: {q1}
思考: {reasoning1}
答案: {a1}

# 示例2
问题: {q2}
思考: {reasoning2}
答案: {a2}

# 请解答
问题: {new_question}
思考: """

CoT的边界

CoT是线性的——一条路径走到底,无法回溯。这在以下场景中会出问题:

  • 需要比较多种可能方案的决策问题
  • 某步骤的推理错误会导致后续全部推理偏移
  • 需要在不同阶段间交叉引用信息

ToT:树状探索推理

核心思想

ToT将推理过程建模为一棵搜索树。在每个决策节点生成多个候选思路,通过评估函数筛选有前途的分支,再继续展开。

                    [初始状态]
                   /     |     \
              [思路A]  [思路B]  [思路C]
              评估:0.9  评估:0.3  评估:0.7
             /     \         |
        [A1]   [A2]        [C1]
        ...

工程实现

from dataclasses import dataclass
from typing import Callable

@dataclass
class ToTNode:
    state: str          # 当前推理状态描述
    thought: str        # 本步思考
    score: float = 0.0  # 评估分数
    parent: str | None = None
    children: list[str] = None

class TreeOfThoughts:
    def __init__(self, llm_generate, llm_evaluate, 
                 n_branches: int = 3, max_depth: int = 5, beam_width: int = 2):
        self.generate = llm_generate    # 生成候选思路
        self.evaluate = llm_evaluate    # 评估思路质量
        self.n_branches = n_branches
        self.max_depth = max_depth
        self.beam_width = beam_width

    async def search(self, problem: str) -> str:
        root = ToTNode(state=problem, thought="初始状态")
        frontier = [root]

        for depth in range(self.max_depth):
            # 扩展:为每个前沿节点生成候选思路
            candidates = []
            for node in frontier:
                thoughts = await self.generate(
                    problem, node.state, n=self.n_branches
                )
                for t in thoughts:
                    score = await self.evaluate(problem, t)
                    candidates.append(ToTNode(
                        state=t, thought=t, score=score,
                        parent=node.state
                    ))

            # 剪枝:保留beam_width个最优
            candidates.sort(key=lambda x: x.score, reverse=True)
            frontier = candidates[:self.beam_width]

            # 检查是否找到解
            if frontier[0].score > 0.95:
                return self._trace_path(frontier[0])

        return self._trace_path(frontier[0])

    def _trace_path(self, node: ToTNode) -> str:
        path = []
        while node:
            path.append(node.thought)
            node = node.parent
        return " → ".join(reversed(path))

ToT适用场景

  • 数学证明:需要尝试不同证明路径
  • 策略游戏:需要评估多个走法的前景
  • 创意写作:需要比较不同情节发展方向

GoT:图状关联推理

核心思想

GoT(Graph of Thoughts)将推理结构从树推广到有向图。节点之间可以有交叉引用、合并和循环,更接近人类解决复杂问题时的真实思维模式。

[信息收集A] → [分析模块1] ↘
                          [综合判断] → [决策]
[信息收集B] → [分析模块2] ↗     ↑
     ↓                        |
[信息收集B] → [交叉验证模块] ──┘

关键操作

GoT定义了三种核心图操作:

操作 说明 类比
Aggregation 合并多个节点的推理 多角度汇总
Refinement 对某节点迭代优化 自我修正
Backtracking 从某节点回退重试 反思纠错
class GraphOfThoughts:
    def __init__(self, llm, max_nodes: int = 20):
        self.llm = llm
        self.graph: dict[str, dict] = {}  # 邻接表
        self.max_nodes = max_nodes

    async def aggregate(self, node_ids: list[str], question: str) -> str:
        """合并多个推理路径的结论"""
        thoughts = [self.graph[nid]["thought"] for nid in node_ids]
        prompt = f"综合以下多个分析视角,给出统一结论:\n"
        prompt += "\n".join(f"视角{i+1}: {t}" for i, t in enumerate(thoughts))
        prompt += f"\n问题: {question}"
        
        merged = await self.llm(prompt)
        new_id = f"agg_{len(self.graph)}"
        self.graph[new_id] = {"thought": merged, "parents": node_ids}
        return new_id

    async def refine(self, node_id: str, feedback: str) -> str:
        """对特定节点迭代优化"""
        original = self.graph[node_id]["thought"]
        refined = await self.llm(
            f"原始推理: {original}\n改进建议: {feedback}\n请优化上述推理。"
        )
        new_id = f"ref_{node_id}_{len(self.graph)}"
        self.graph[new_id] = {"thought": refined, "parents": [node_id]}
        return new_id

三种范式对比

维度 CoT ToT GoT
结构 线性链 搜索树 有向图
复杂度 O(n) O(b^d) 变参,最坏O(n^2)
回溯能力 有(剪枝+回溯) 有(显式backtracking)
合并能力 有(aggregation)
LLM调用次数 1次 多次(扩展+评估) 多次+合并
适用问题 简单推理 搜索空间明确 需多视角综合
工程复杂度

选择指南

根据问题特征选择

问题是否需要多步推理?
├─ 否 → 直接提问,不需要思维链
└─ 是 → 推理路径是否唯一?
    ├─ 是 → 用CoT,线性推理足够
    └─ 否 → 是否需要合并不同视角?
        ├─ 否 → 用ToT,树搜索最优路径
        └─ 是 → 用GoT,图结构综合推理

成本考量

CoT几乎无额外开销,ToT的LLM调用次数是O(n_branches × max_depth),GoT更难预估。在生产中,建议:

  • 默认用CoT,覆盖80%的推理任务
  • 需要高质量决策的场景用ToT+beam search
  • 离线复杂分析可用GoT,在线服务慎用

总结

思维链优化的核心不是"哪种范式最好",而是匹配问题复杂度与推理结构。CoT是基石,ToT扩展了搜索空间,GoT补全了多视角综合能力。从工程角度看,CoT→ToT→GoT的演进路线也对应着从低延迟到高延迟、从低成本到高成本的梯度。在实际系统中,合理搭配才能在质量和成本间取得最优。