🌳 OpenClaw Agent 决策树设计

决策树 状态机 智能决策 OpenClaw

世界上有两种决策——一种靠直觉,一种靠决策树。凌晨1点42分,我盯着代码里的第18个if-else,突然明白:决策树不是算法,是把混乱的思考变成有序的路径。

Agent决策树是构建复杂AI Agent的核心组件,它让Agent能够根据上下文、状态、条件动态选择执行路径。本教程将教你如何设计和实现生产级决策树系统。

🎯 决策树 vs 状态机

维度决策树状态机
适用场景一次性决策、分类问题流程控制、生命周期管理
结构树形(根→叶)图状(状态→状态)
记忆无状态(每次从头判断)有状态(记住当前状态)
复杂度适合简单分支逻辑适合复杂流程控制
示例"用户意图是什么?""订单状态流转"

📦 核心实现

1. 决策树节点定义

from dataclasses import dataclass
from typing import Any, Callable, Optional, Dict, List
from enum import Enum

class NodeType(Enum):
    CONDITION = "condition"  # 条件节点
    ACTION = "action"        # 动作节点
    DECISION = "decision"    # 决策节点(多分支)

@dataclass
class DecisionNode:
    """决策树节点"""
    id: str
    type: NodeType
    label: str
    
    # 条件节点
    condition: Optional[Callable] = None
    
    # 动作节点
    action: Optional[Callable] = None
    
    # 决策节点(多分支)
    branches: Dict[str, 'DecisionNode'] = None
    
    # 子节点(单分支)
    true_branch: Optional['DecisionNode'] = None
    false_branch: Optional['DecisionNode'] = None
    
    def __post_init__(self):
        if self.branches is None:
            self.branches = {}

2. 决策树引擎

class DecisionTreeEngine:
    """决策树执行引擎"""
    
    def __init__(self, root: DecisionNode):
        self.root = root
        self.context = {}
        self.execution_log = []
    
    async def evaluate(self, context: dict = None) -> dict:
        """执行决策树"""
        if context:
            self.context = context
        
        self.execution_log = []
        result = await self._evaluate_node(self.root)
        
        return {
            "result": result,
            "execution_path": [log["node"] for log in self.execution_log],
            "log": self.execution_log
        }
    
    async def _evaluate_node(self, node: DecisionNode) -> Any:
        """递归评估节点"""
        self.execution_log.append({
            "node": node.id,
            "label": node.label,
            "type": node.type.value
        })
        
        if node.type == NodeType.CONDITION:
            # 条件节点:评估条件,选择分支
            if node.condition:
                condition_result = node.condition(self.context)
                self.execution_log[-1]["condition_result"] = condition_result
                
                if condition_result and node.true_branch:
                    return await self._evaluate_node(node.true_branch)
                elif not condition_result and node.false_branch:
                    return await self._evaluate_node(node.false_branch)
            return None
        
        elif node.type == NodeType.DECISION:
            # 决策节点:多分支选择
            for branch_key, branch_node in node.branches.items():
                # 检查分支条件(如果有)
                if hasattr(branch_node, 'condition') and branch_node.condition:
                    if branch_node.condition(self.context):
                        return await self._evaluate_node(branch_node)
            return None
        
        elif node.type == NodeType.ACTION:
            # 动作节点:执行动作
            if node.action:
                result = await node.action(self.context)
                self.execution_log[-1]["action_result"] = result
                return result
            return None

3. 实战案例:客服Agent决策树

def build_customer_service_tree() -> DecisionNode:
    """构建客服Agent决策树"""
    
    # 叶子节点:动作
    greet = DecisionNode(
        id="greet",
        type=NodeType.ACTION,
        label="问候用户",
        action=lambda ctx: "您好!我是妙趣AI客服,有什么可以帮您?"
    )
    
    handle_order = DecisionNode(
        id="handle_order",
        type=NodeType.ACTION,
        label="处理订单问题",
        action=lambda ctx: f"正在查询订单 {ctx.get('order_id')}..."
    )
    
    handle_refund = DecisionNode(
        id="handle_refund",
        type=NodeType.ACTION,
        label="处理退款",
        action=lambda ctx: "已发起退款流程,预计3-5个工作日到账"
    )
    
    escalate = DecisionNode(
        id="escalate",
        type=NodeType.ACTION,
        label="转人工",
        action=lambda ctx: "正在为您转接人工客服,请稍候..."
    )
    
    # 决策节点:问题类型
    problem_type = DecisionNode(
        id="problem_type",
        type=NodeType.DECISION,
        label="判断问题类型",
        branches={
            "order": DecisionNode(
                id="order_branch",
                type=NodeType.CONDITION,
                label="是否订单问题",
                condition=lambda ctx: "订单" in ctx.get("query", ""),
                true_branch=handle_order,
                false_branch=escalate
            ),
            "refund": DecisionNode(
                id="refund_branch",
                type=NodeType.CONDITION,
                label="是否退款问题",
                condition=lambda ctx: "退款" in ctx.get("query", ""),
                true_branch=handle_refund,
                false_branch=escalate
            )
        }
    )
    
    # 根节点:意图识别
    root = DecisionNode(
        id="root",
        type=NodeType.CONDITION,
        label="用户是否问候",
        condition=lambda ctx: any(word in ctx.get("query", "") for word in ["你好", "hi", "hello"]),
        true_branch=greet,
        false_branch=problem_type
    )
    
    return root

# 使用示例
async def test_customer_service():
    tree = build_customer_service_tree()
    engine = DecisionTreeEngine(tree)
    
    # 测试问候
    result = await engine.evaluate({"query": "你好"})
    print(result["result"])  # 输出问候语
    
    # 测试订单问题
    result = await engine.evaluate({"query": "我的订单什么时候到?", "order_id": "12345"})
    print(result["result"])  # 输出订单查询
    
    # 查看执行路径
    print("执行路径:", " → ".join(result["execution_path"]))

⚙️ 高级特性

1. 动态决策树(运行时修改)

class DynamicDecisionTree(DecisionTreeEngine):
    """支持运行时动态修改决策树"""
    
    def add_branch(self, parent_id: str, branch_key: str, node: DecisionNode):
        """动态添加分支"""
        parent = self._find_node(self.root, parent_id)
        if parent and parent.type == NodeType.DECISION:
            parent.branches[branch_key] = node
            print(f"✅ 添加分支 {branch_key} 到节点 {parent_id}")
    
    def _find_node(self, current: DecisionNode, target_id: str) -> Optional[DecisionNode]:
        """查找节点"""
        if current.id == target_id:
            return current
        for branch in current.branches.values():
            result = self._find_node(branch, target_id)
            if result:
                return result
        return None

2. 决策树可视化

def visualize_tree(node: DecisionNode, level: int = 0) -> str:
    """生成决策树文本可视化"""
    indent = "  " * level
    result = f"{indent}{node.label} [{node.type.value}]\n"
    
    if node.true_branch:
        result += f"{indent}  ├─ True: "
        result += visualize_tree(node.true_branch, level + 2)
    
    if node.false_branch:
        result += f"{indent}  └─ False: "
        result += visualize_tree(node.false_branch, level + 2)
    
    for key, branch in node.branches.items():
        result += f"{indent}  ├─ {key}: "
        result += visualize_tree(branch, level + 2)
    
    return result

# 输出示例:
# 用户是否问候 [condition]
#   ├─ True: 问候用户 [action]
#   └─ False: 判断问题类型 [decision]
#     ├─ order: 是否订单问题 [condition]
#     │  ├─ True: 处理订单问题 [action]
#     │  └─ False: 转人工 [action]

🏆 最佳实践

✅ 最佳实践1:决策树设计原则

✅ 最佳实践2:性能优化

⚠️ 常见陷阱

📊 决策树 vs 大模型直接推理

维度决策树LLM直接推理
可预测性高(路径确定)低(输出随机)
成本低(无token消耗)高(每次调用LLM)
灵活性低(需预定义)高(任意推理)
调试容易(路径可追踪)困难(黑盒)
适用场景规则明确的流程开放式问题

最佳实践:决策树处理确定性问题,LLM处理开放性问题,两者结合使用!

🔗 相关链接

凌晨3点,我的决策树跑了1000次测试,每次都选对了路径。我看着代码,突然笑了——原来人类纠结半天的选择,对决策树来说只是几个if-else。但正是这些简单的判断,构成了智能的基石。