{
  "metadata": {
    "id": "ch21",
    "title": "第21章：状态机与流程编排",
    "volume": "vol7",
    "volume_title": "Agent编程技法",
    "word_count": 2338,
    "difficulty": "intermediate",
    "prerequisites": [
      "ch09"
    ],
    "key_concepts": [
      "引言",
      "本章学习目标",
      "有限状态机（FSM）设计",
      "为什么Agent需要状态机",
      "状态机基础实现",
      "客服Agent状态机实例",
      "TypeScript实现",
      "状态图与转换规则",
      "状态图设计原则",
      "声明式状态图定义",
      "通用状态图引擎",
      "LangGraph的状态图编排",
      "LangGraph简介",
      "使用LangGraph构建研究助手",
      "LangGraph高级模式：带人工审核的工作流"
    ],
    "learning_objectives": [],
    "estimated_tokens": 1403,
    "source_file": "vol7/ch21_状态机与流程编排.md"
  },
  "overview": "",
  "sections": [
    {
      "id": "21.1",
      "title": "21.1 引言",
      "level": 2,
      "content": "当 Agent 系统从简单的\"输入→输出\"模式演进到需要多步骤、多决策的复杂流程时，状态机（State Machine）和流程编排（Orchestration）就成为必不可少的工程工具。状态机赋予 Agent 确定性的行为控制，流程编排则让多个 Agent 或步骤能够协同完成复杂任务。\n\n本章将系统讲解如何使用有限状态机、LangGraph 等工具来设计和实现 Agent 工作流，包括条件分支、循环、人工介入等高级模式。",
      "subsections": [
        {
          "id": "本章学习目标",
          "title": "本章学习目标",
          "content": "- 理解有限状态机（FSM）在 Agent 系统中的作用\n- 掌握状态图的设计与转换规则\n- 使用 LangGraph 实现状态图编排\n- 实现条件分支、循环和人工介入模式\n- 设计可靠的复杂工作流编排模式\n\n---"
        }
      ]
    },
    {
      "id": "21.2",
      "title": "21.2 有限状态机（FSM）设计",
      "level": 2,
      "content": "",
      "subsections": [
        {
          "id": "21.2.1",
          "title": "21.2.1 为什么Agent需要状态机",
          "content": "LLM 本质上是无状态的——每次调用都是独立的。但在实际应用中，Agent 的行为需要依赖上下文和当前所处的阶段：\n\n- **客服系统**：识别问题→收集信息→尝试解决→转人工\n- **代码助手**：理解需求→设计方案→编写代码→审查→修改\n- **数据分析**：接收请求→查询数据→分析结果→生成报告\n\n没有状态管理，Agent 就像一个每次醒来都失忆的助手——无法维持对话的连贯性，也无法在复杂任务中保持正确的执行顺序。"
        },
        {
          "id": "21.2.2",
          "title": "21.2.2 状态机基础实现",
          "content": ""
        },
        {
          "id": "21.2.3",
          "title": "21.2.3 客服Agent状态机实例",
          "content": ""
        },
        {
          "id": "21.2.4",
          "title": "21.2.4 TypeScript实现",
          "content": "---"
        }
      ]
    },
    {
      "id": "21.3",
      "title": "21.3 状态图与转换规则",
      "level": 2,
      "content": "",
      "subsections": [
        {
          "id": "21.3.1",
          "title": "21.3.1 状态图设计原则",
          "content": "设计状态图时需要遵循几个关键原则：\n\n1. **状态最小化**：每个状态代表一个明确的阶段，避免\"万能状态\"\n2. **转换明确**：每个转换都有清晰的条件和动作\n3. **终态可达**：任何状态都能通过某种路径到达终态（完成或失败）\n4. **错误处理**：任何状态都应该能转到失败状态"
        },
        {
          "id": "21.3.2",
          "title": "21.3.2 声明式状态图定义",
          "content": ""
        },
        {
          "id": "21.3.3",
          "title": "21.3.3 通用状态图引擎",
          "content": "---"
        }
      ]
    },
    {
      "id": "21.4",
      "title": "21.4 LangGraph的状态图编排",
      "level": 2,
      "content": "",
      "subsections": [
        {
          "id": "21.4.1",
          "title": "21.4.1 LangGraph简介",
          "content": "LangGraph 是 LangChain 生态中用于构建有状态、多步骤 Agent 应用的框架。它基于图论概念，将 Agent 的工作流建模为节点（Node）和边（Edge）组成的图。\n\n**核心概念：**\n\n- **State**：在图的各个节点之间传递的可变状态对象\n- **Node**：执行特定逻辑的函数，接收状态并可能修改状态\n- **Edge**：连接节点的有向边，可以是固定的或条件性的"
        },
        {
          "id": "21.4.2",
          "title": "21.4.2 使用LangGraph构建研究助手",
          "content": ""
        },
        {
          "id": "21.4.3",
          "title": "21.4.3 LangGraph高级模式：带人工审核的工作流",
          "content": "---"
        }
      ]
    },
    {
      "id": "21.5",
      "title": "21.5 复杂工作流的编排模式",
      "level": 2,
      "content": "",
      "subsections": [
        {
          "id": "21.5.1",
          "title": "21.5.1 编排模式概览",
          "content": "| 模式 | 适用场景 | 特点 |\n|------|----------|------|\n| **顺序模式** | 步骤间有明确依赖 | A→B→C→D |\n| **并行模式** | 步骤间无依赖 | A+B+C→聚合 |\n| **条件分支** | 根据条件选择路径 | A→(条件)→B或C |\n| **循环模式** | 需要反复优化 | A→B→(条件)→A或END |\n| **Saga模式** | 分布式事务 | A→B→C→(失败)→补偿 |\n| **Pipeline模式** | 数据流处理 | ETL风格的连续处理 |"
        },
        {
          "id": "21.5.2",
          "title": "21.5.2 顺序管道模式",
          "content": ""
        },
        {
          "id": "21.5.3",
          "title": "21.5.3 并行扇出-扇入模式",
          "content": ""
        },
        {
          "id": "21.5.4",
          "title": "21.5.4 Saga补偿模式",
          "content": "---"
        }
      ]
    },
    {
      "id": "21.6",
      "title": "21.6 条件分支与循环",
      "level": 2,
      "content": "",
      "subsections": [
        {
          "id": "21.6.1",
          "title": "21.6.1 条件分支",
          "content": ""
        },
        {
          "id": "21.6.2",
          "title": "21.6.2 循环模式",
          "content": "---"
        }
      ]
    },
    {
      "id": "21.7",
      "title": "21.7 人工介入（Human-in-the-Loop）设计",
      "level": 2,
      "content": "",
      "subsections": [
        {
          "id": "21.7.1",
          "title": "21.7.1 HITL的必要性",
          "content": "并非所有决策都应该由 Agent 自主完成。以下场景需要人工介入：\n\n- **高风险操作**：大额资金转账、数据删除、权限变更\n- **模糊决策**：多个方案优劣不明显，需要人类判断\n- **合规要求**：法律、医疗等受监管领域\n- **质量控制**：对关键输出进行人工审核"
        },
        {
          "id": "21.7.2",
          "title": "21.7.2 人工介入框架",
          "content": ""
        },
        {
          "id": "21.7.3",
          "title": "21.7.3 中断-恢复模式",
          "content": "---"
        }
      ]
    },
    {
      "id": "21.8",
      "title": "21.8 最佳实践",
      "level": 2,
      "content": "",
      "subsections": [
        {
          "id": "21.8.1",
          "title": "21.8.1 状态机设计原则",
          "content": "1. **状态应该正交**：每个状态代表一个独立的阶段，不要让两个状态做类似的事\n2. **转换应该幂等**：重复调用同一个转换不应该产生副作用\n3. **始终定义错误状态**：确保任何状态下出错都能到达一个明确的错误处理状态\n4. **可视化状态图**：用 Mermaid 或 Graphviz 画出状态图，确保逻辑正确\n5. **状态持久化**：生产环境中，状态必须持久化到数据库，防止进程崩溃丢失"
        },
        {
          "id": "21.8.2",
          "title": "21.8.2 常见陷阱",
          "content": "**陷阱1：过度设计状态机**\n\n不是所有 Agent 都需要状态机。简单的单轮问答或无状态 API 调用，用状态机反而增加复杂度。\n\n**陷阱2：忽略超时**\n\n状态机中的每个状态都应该有超时机制，否则 Agent 可能永远卡在某个状态。\n\n**陷阱3：状态爆炸**\n\n避免创建过多状态。当状态数量超过 10 个时，考虑是否可以用参数化状态替代。\n\n---"
        }
      ]
    },
    {
      "id": "21.9",
      "title": "21.9 本章小结",
      "level": 2,
      "content": "本章系统介绍了 Agent 状态机与流程编排的核心概念和实现：\n\n1. **有限状态机（FSM）**为 Agent 提供了确定性的行为控制\n2. **LangGraph** 提供了声明式的状态图编排能力\n3. **编排模式**（顺序、并行、条件、Saga）解决了不同类型的工作流需求\n4. **人工介入（HITL）** 是高风险场景下不可或缺的安全阀\n\n> **记住**：好的 Agent 架构不是让 AI 做所有决策，而是在合适的时机引入确定性控制和人类智慧。",
      "subsections": []
    }
  ],
  "code_blocks": [
    {
      "id": "code-1",
      "language": "python",
      "description": "没有状态管理，Agent 就像一个每次醒来都失忆的助手——无法维持对话的连贯性，也无法在复杂任务中保持正确的执行顺序。",
      "code": "from enum import Enum\nfrom typing import Callable, Optional, Any\nfrom dataclasses import dataclass, field\nfrom datetime import datetime\n\n\nclass AgentState(Enum):\n    \"\"\"Agent 状态枚举\"\"\"\n    IDLE = \"idle\"                    # 空闲\n    COLLECTING_INFO = \"collecting\"    # 收集信息\n    PROCESSING = \"processing\"         # 处理中\n    AWAITING_CONFIRMATION = \"confirm\" # 等待确认\n    EXECUTING = \"executing\"           # 执行操作\n    REVIEWING = \"reviewing\"           # 审查结果\n    ESCALATING = \"escalating\"         # 升级处理\n    COMPLETED = \"completed\"           # 已完成\n    FAILED = \"failed\"                 # 失败\n\n\n@dataclass\nclass StateTransition:\n    \"\"\"状态转换规则\"\"\"\n    from_state: AgentState\n    to_state: AgentState\n    condition: Optional[Callable] = None\n    action: Optional[Callable] = None\n    description: str = \"\"\n\n\n@dataclass\nclass StateContext:\n    \"\"\"状态上下文——携带状态间传递的数据\"\"\"\n    session_id: str\n    current_state: AgentState\n    previous_state: Optional[AgentState] = None\n    data: dict = field(default_factory=dict)\n    history: list[dict] = field(default_factory=list)\n    created_at: datetime = field(default_factory=datetime.now)\n    updated_at: datetime = field(default_factory=datetime.now)\n    \n    def transition_to(self, new_state: AgentState):\n        self.previous_state = self.current_state\n        self.current_state = new_state\n        self.updated_at = datetime.now()\n        self.history.append({\n            \"from\": self.previous_state.value,\n            \"to\": new_state.value,\n            \"timestamp\": self.updated_at.isoformat(),\n        })\n\n\nclass AgentStateMachine:\n    \"\"\"Agent 有限状态机\"\"\"\n    \n    def __init__(self, session_id: str):\n        self.context = StateContext(\n            session_id=session_id,\n            current_state=AgentState.IDLE,\n        )\n        self._transitions: list[StateTransition] = []\n        self._invalid_transitions: set[tuple[str, str]] = set()\n        self._state_handlers: dict[AgentState, Callable] = {}\n    \n    def add_transition(self, transition: StateTransition):\n        \"\"\"添加状态转换规则\"\"\"\n        self._transitions.append(transition)\n    \n    def add_invalid_transition(self, from_s: AgentState, to_s: AgentState):\n        \"\"\"添加禁止的转换\"\"\"\n        self._invalid_transitions.add((from_s.value, to_s.value))\n    \n    def set_handler(self, state: AgentState, handler: Callable):\n        \"\"\"设置状态处理函数\"\"\"\n        self._state_handlers[state] = handler\n    \n    def transition(self, target_state: AgentState, **kwargs) -> bool:\n        \"\"\"尝试执行状态转换\"\"\"\n        current = self.context.current_state\n        \n        # 检查是否为禁止转换\n        if (current.value, target_state.value) in self._invalid_transitions:\n            raise InvalidTransitionError(\n                f\"禁止从 {current.value} 转换到 {target_state.value}\"\n            )\n        \n        # 查找匹配的转换规则\n        matching = [\n            t for t in self._transitions\n            if t.from_state == current and t.to_state == target_state\n        ]\n        \n        for rule in matching:\n            if rule.condition and not rule.condition(self.context, **kwargs):\n                continue\n            \n            # 执行转换\n            if rule.action:\n                rule.action(self.context, **kwargs)\n            \n            self.context.transition_to(target_state)\n            \n            # 执行新状态的处理器\n            handler = self._state_handlers.get(target_state)\n            if handler:\n                handler(self.context)\n            \n            return True\n        \n        # 没有匹配的规则\n        raise InvalidTransitionError(\n            f\"没有从 {current.value} 到 {target_state.value} 的转换规则\"\n        )\n    \n    def get_current_state(self) -> AgentState:\n        return self.context.current_state\n    \n    def get_state_history(self) -> list[dict]:\n        return self.context.history\n    \n    def reset(self):\n        \"\"\"重置到初始状态\"\"\"\n        self.context = StateContext(\n            session_id=self.context.session_id,\n            current_state=AgentState.IDLE,\n        )\n\n\nclass InvalidTransitionError(Exception):\n    pass",
      "section_ref": "21.2.2",
      "runnable": true,
      "dependencies": []
    },
    {
      "id": "code-2",
      "language": "python",
      "description": "",
      "code": "# customer_service_fsm.py\n\ndef build_customer_service_fsm(session_id: str) -> AgentStateMachine:\n    \"\"\"构建客服Agent的状态机\"\"\"\n    fsm = AgentStateMachine(session_id)\n    \n    # 定义转换规则\n    fsm.add_transition(StateTransition(\n        from_state=AgentState.IDLE,\n        to_state=AgentState.COLLECTING_INFO,\n        action=lambda ctx, **kw: ctx.data.update({\"query\": kw.get(\"query\", \"\")}),\n        description=\"收到用户查询，开始收集信息\",\n    ))\n    \n    fsm.add_transition(StateTransition(\n        from_state=AgentState.COLLECTING_INFO,\n        to_state=AgentState.PROCESSING,\n        condition=lambda ctx, **kw: ctx.data.get(\"info_complete\", False),\n        description=\"信息收集完毕，开始处理\",\n    ))\n    \n    fsm.add_transition(StateTransition(\n        from_state=AgentState.PROCESSING,\n        to_state=AgentState.AWAITING_CONFIRMATION,\n        condition=lambda ctx, **kw: ctx.data.get(\"solution\", None) is not None,\n        description=\"生成解决方案，等待用户确认\",\n    ))\n    \n    fsm.add_transition(StateTransition(\n        from_state=AgentState.PROCESSING,\n        to_state=AgentState.ESCALATING,\n        condition=lambda ctx, **kw: ctx.data.get(\"need_escalation\", False),\n        description=\"无法处理，升级到人工\",\n    ))\n    \n    fsm.add_transition(StateTransition(\n        from_state=AgentState.AWAITING_CONFIRMATION,\n        to_state=AgentState.EXECUTING,\n        condition=lambda ctx, **kw: kw.get(\"confirmed\", False),\n        description=\"用户确认，执行方案\",\n    ))\n    \n    fsm.add_transition(StateTransition(\n        from_state=AgentState.AWAITING_CONFIRMATION,\n        to_state=AgentState.PROCESSING,\n        condition=lambda ctx, **kw: not kw.get(\"confirmed\", True),\n        description=\"用户不满意，重新处理\",\n    ))\n    \n    fsm.add_transition(StateTransition(\n        from_state=AgentState.EXECUTING,\n        to_state=AgentState.COMPLETED,\n        condition=lambda ctx, **kw: ctx.data.get(\"execution_success\", True),\n        description=\"执行成功\",\n    ))\n    \n    fsm.add_transition(StateTransition(\n        from_state=AgentState.EXECUTING,\n        to_state=AgentState.FAILED,\n        condition=lambda ctx, **kw: not ctx.data.get(\"execution_success\", True),\n        description=\"执行失败\",\n    ))\n    \n    # 设置状态处理器\n    fsm.set_handler(AgentState.COLLECTING_INFO, _handle_collecting)\n    fsm.set_handler(AgentState.PROCESSING, _handle_processing)\n    fsm.set_handler(AgentState.COMPLETED, _handle_completed)\n    \n    return fsm\n\n\ndef _handle_collecting(ctx: StateContext):\n    print(f\"[{ctx.session_id}] 收集信息中... 当前数据: {ctx.data}\")\n\n\ndef _handle_processing(ctx: StateContext):\n    print(f\"[{ctx.session_id}] 处理查询: {ctx.data.get('query', '')}\")\n\n\ndef _handle_completed(ctx: StateContext):\n    print(f\"[{ctx.session_id}] 任务完成！\")\n\n\n# 使用示例\nfsm = build_customer_service_fsm(\"session-001\")\nfsm.transition(AgentState.COLLECTING_INFO, query=\"无法登录账户\")\nfsm.context.data[\"info_complete\"] = True\nfsm.transition(AgentState.PROCESSING)\nfsm.context.data[\"solution\"] = \"重置密码\"\nfsm.transition(AgentState.AWAITING_CONFIRMATION)\nfsm.transition(AgentState.EXECUTING, confirmed=True)\nfsm.context.data[\"execution_success\"] = True\nfsm.transition(AgentState.COMPLETED)\nprint(f\"状态历史: {fsm.get_state_history()}\")",
      "section_ref": "21.2.3",
      "runnable": true,
      "dependencies": []
    },
    {
      "id": "code-3",
      "language": "typescript",
      "description": "",
      "code": "enum AgentState {\n  IDLE = \"idle\",\n  COLLECTING = \"collecting\",\n  PROCESSING = \"processing\",\n  CONFIRMING = \"confirming\",\n  EXECUTING = \"executing\",\n  COMPLETED = \"completed\",\n  FAILED = \"failed\",\n}\n\ninterface TransitionRule {\n  from: AgentState;\n  to: AgentState;\n  condition?: (ctx: StateContext) => boolean;\n  action?: (ctx: StateContext) => void;\n}\n\ninterface StateContext {\n  sessionId: string;\n  current: AgentState;\n  previous?: AgentState;\n  data: Record<string, any>;\n  history: Array<{ from: string; to: string; ts: string }>;\n}\n\nexport class AgentFSM {\n  private ctx: StateContext;\n  private rules: TransitionRule[] = [];\n\n  constructor(sessionId: string) {\n    this.ctx = {\n      sessionId,\n      current: AgentState.IDLE,\n      data: {},\n      history: [],\n    };\n  }\n\n  addRule(rule: TransitionRule): void {\n    this.rules.push(rule);\n  }\n\n  transition(target: AgentState, extraData?: Record<string, any>): boolean {\n    const current = this.ctx.current;\n    const matching = this.rules.filter(\n      r => r.from === current && r.to === target\n    );\n\n    for (const rule of matching) {\n      if (rule.condition && !rule.condition(this.ctx)) continue;\n      \n      if (rule.action) rule.action(this.ctx);\n      if (extraData) Object.assign(this.ctx.data, extraData);\n\n      this.ctx.previous = current;\n      this.ctx.current = target;\n      this.ctx.history.push({\n        from: current, to: target,\n        ts: new Date().toISOString(),\n      });\n      return true;\n    }\n    throw new Error(`Invalid: ${current} → ${target}`);\n  }\n\n  getState(): AgentState { return this.ctx.current; }\n  getData(): Record<string, any> { return this.ctx.data; }\n}",
      "section_ref": "21.2.4",
      "runnable": true,
      "dependencies": []
    },
    {
      "id": "code-4",
      "language": "python",
      "description": "4. 错误处理：任何状态都应该能转到失败状态",
      "code": "from typing import TypedDict\n\n\nclass StateGraphConfig(TypedDict):\n    \"\"\"状态图配置\"\"\"\n    name: str\n    initial_state: str\n    final_states: list[str]\n    states: dict[str, dict]       # 状态定义\n    transitions: list[dict]        # 转换规则\n\n\n# 声明式定义一个订单处理状态图\norder_processing_graph: StateGraphConfig = {\n    \"name\": \"order_processing\",\n    \"initial_state\": \"received\",\n    \"final_states\": [\"completed\", \"cancelled\", \"failed\"],\n    \"states\": {\n        \"received\": {\n            \"description\": \"订单已接收\",\n            \"timeout_seconds\": 300,\n        },\n        \"validated\": {\n            \"description\": \"订单验证通过\",\n        },\n        \"payment_pending\": {\n            \"description\": \"等待支付\",\n            \"timeout_seconds\": 1800,\n        },\n        \"paid\": {\n            \"description\": \"支付完成\",\n        },\n        \"shipped\": {\n            \"description\": \"已发货\",\n        },\n        \"completed\": {\n            \"description\": \"订单完成\",\n        },\n        \"cancelled\": {\n            \"description\": \"订单取消\",\n        },\n        \"failed\": {\n            \"description\": \"处理失败\",\n        },\n    },\n    \"transitions\": [\n        {\"from\": \"received\", \"to\": \"validated\", \"condition\": \"valid_order\"},\n        {\"from\": \"received\", \"to\": \"cancelled\", \"condition\": \"user_cancel\"},\n        {\"from\": \"validated\", \"to\": \"payment_pending\"},\n        {\"from\": \"payment_pending\", \"to\": \"paid\", \"condition\": \"payment_success\"},\n        {\"from\": \"payment_pending\", \"to\": \"cancelled\", \"condition\": \"payment_timeout\"},\n        {\"from\": \"paid\", \"to\": \"shipped\"},\n        {\"from\": \"shipped\", \"to\": \"completed\", \"condition\": \"delivery_confirmed\"},\n        # 错误转换——任何状态都可以转到failed\n        {\"from\": \"*\", \"to\": \"failed\", \"condition\": \"error_occurred\"},\n    ],\n}",
      "section_ref": "21.3.2",
      "runnable": true,
      "dependencies": []
    },
    {
      "id": "code-5",
      "language": "python",
      "description": "",
      "code": "class StateGraphEngine:\n    \"\"\"通用状态图执行引擎\"\"\"\n    \n    def __init__(self, config: StateGraphConfig):\n        self.config = config\n        self._condition_handlers: dict[str, Callable] = {}\n        self._state_entry_handlers: dict[str, Callable] = {}\n        self._state_exit_handlers: dict[str, Callable] = {}\n        self._timeout_timers: dict[str, any] = {}\n    \n    def register_condition(self, name: str, handler: Callable):\n        \"\"\"注册条件判断函数\"\"\"\n        self._condition_handlers[name] = handler\n    \n    def on_enter(self, state: str, handler: Callable):\n        \"\"\"注册状态进入回调\"\"\"\n        self._state_entry_handlers[state] = handler\n    \n    def on_exit(self, state: str, handler: Callable):\n        \"\"\"注册状态退出回调\"\"\"\n        self._state_exit_handlers[state] = handler\n    \n    def execute(self, context: dict) -> str:\n        \"\"\"从初始状态执行状态图\"\"\"\n        current = self.config[\"initial_state\"]\n        \n        while current not in self.config[\"final_states\"]:\n            # 执行进入回调\n            entry_handler = self._state_entry_handlers.get(current)\n            if entry_handler:\n                entry_handler(context, current)\n            \n            # 查找可用的转换\n            next_state = self._find_next_transition(current, context)\n            \n            if next_state is None:\n                # 没有可用的转换，检查是否有默认错误处理\n                if \"failed\" in self.config[\"final_states\"]:\n                    next_state = \"failed\"\n                else:\n                    raise RuntimeError(f\"状态 {current} 无法继续执行\")\n            \n            # 执行退出回调\n            exit_handler = self._state_exit_handlers.get(current)\n            if exit_handler:\n                exit_handler(context, current)\n            \n            context[\"current_state\"] = next_state\n            context.setdefault(\"state_history\", []).append({\n                \"from\": current, \"to\": next_state,\n                \"timestamp\": __import__('datetime').datetime.now().isoformat(),\n            })\n            \n            current = next_state\n        \n        return current\n    \n    def _find_next_transition(self, current: str, context: dict) -> str | None:\n        \"\"\"查找下一个状态\"\"\"\n        for trans in self.config[\"transitions\"]:\n            from_state = trans[\"from\"]\n            if from_state != \"*\" and from_state != current:\n                continue\n            \n            condition_name = trans.get(\"condition\")\n            if condition_name:\n                handler = self._condition_handlers.get(condition_name)\n                if handler and handler(context):\n                    return trans[\"to\"]\n            else:\n                # 无条件转换（第一个匹配的）\n                return trans[\"to\"]\n        \n        return None",
      "section_ref": "21.3.3",
      "runnable": true,
      "dependencies": []
    },
    {
      "id": "code-6",
      "language": "python",
      "description": "- Edge：连接节点的有向边，可以是固定的或条件性的",
      "code": "from typing import TypedDict, Annotated, Literal\nfrom langgraph.graph import StateGraph, END\nfrom langgraph.graph.message import add_messages\nfrom langchain_core.messages import HumanMessage, AIMessage\n\n\nclass ResearchState(TypedDict):\n    \"\"\"研究助手的状态定义\"\"\"\n    messages: Annotated[list, add_messages]  # 对话消息\n    research_topic: str                       # 研究主题\n    search_results: list[dict]                # 搜索结果\n    analysis: str                             # 分析结果\n    report: str                               # 最终报告\n    iteration_count: int                      # 迭代次数\n    max_iterations: int                       # 最大迭代次数\n    needs_more_research: bool                 # 是否需要更多研究\n\n\ndef search_node(state: ResearchState) -> dict:\n    \"\"\"搜索节点——执行信息检索\"\"\"\n    import json\n    topic = state.get(\"research_topic\", \"\")\n    \n    # 模拟搜索（实际中调用搜索API）\n    results = [\n        {\"title\": f\"{topic}的最新进展\", \"relevance\": 0.95},\n        {\"title\": f\"{topic}的技术分析\", \"relevance\": 0.85},\n    ]\n    \n    return {\n        \"search_results\": results,\n        \"messages\": [AIMessage(content=f\"找到了 {len(results)} 条相关结果\")],\n    }\n\n\ndef analyze_node(state: ResearchState) -> dict:\n    \"\"\"分析节点——对搜索结果进行深度分析\"\"\"\n    results = state.get(\"search_results\", [])\n    analysis = f\"基于 {len(results)} 条搜索结果的分析...\"\n    \n    # 决定是否需要更多研究\n    needs_more = (\n        len(results) < 5 \n        or state.get(\"iteration_count\", 0) < state.get(\"max_iterations\", 2)\n    )\n    \n    return {\n        \"analysis\": analysis,\n        \"needs_more_research\": needs_more,\n        \"iteration_count\": state.get(\"iteration_count\", 0) + 1,\n        \"messages\": [AIMessage(content=f\"完成分析，{'需要' if needs_more else '不需要'}更多研究\")],\n    }\n\n\ndef write_report_node(state: ResearchState) -> dict:\n    \"\"\"报告生成节点\"\"\"\n    analysis = state.get(\"analysis\", \"\")\n    report = f\"# 研究报告\\n\\n## 摘要\\n{analysis}\\n\\n## 详细内容\\n...\"\n    \n    return {\n        \"report\": report,\n        \"messages\": [AIMessage(content=\"研究报告已生成\")],\n    }\n\n\ndef should_continue(state: ResearchState) -> Literal[\"search\", \"report\"]:\n    \"\"\"条件边——决定下一步\"\"\"\n    if state.get(\"needs_more_research\", False):\n        return \"search\"\n    return \"report\"\n\n\ndef build_research_graph() -> StateGraph:\n    \"\"\"构建研究助手的状态图\"\"\"\n    graph = StateGraph(ResearchState)\n    \n    # 添加节点\n    graph.add_node(\"search\", search_node)\n    graph.add_node(\"analyze\", analyze_node)\n    graph.add_node(\"report\", write_report_node)\n    \n    # 设置入口\n    graph.set_entry_point(\"search\")\n    \n    # 添加边\n    graph.add_edge(\"search\", \"analyze\")\n    graph.add_conditional_edges(\n        \"analyze\",\n        should_continue,\n        {\"search\": \"search\", \"report\": \"report\"},\n    )\n    graph.add_edge(\"report\", END)\n    \n    return graph.compile()\n\n\n# 使用示例\nresearch_graph = build_research_graph()\nresult = research_graph.invoke({\n    \"messages\": [HumanMessage(content=\"研究量子计算的最新进展\")],\n    \"research_topic\": \"量子计算\",\n    \"max_iterations\": 3,\n    \"iteration_count\": 0,\n})\n\nprint(result[\"report\"])",
      "section_ref": "21.4.2",
      "runnable": true,
      "dependencies": [
        "langgraph",
        "langchain_core"
      ]
    },
    {
      "id": "code-7",
      "language": "python",
      "description": "",
      "code": "from typing import TypedDict\nfrom langgraph.graph import StateGraph, END\nfrom langgraph.checkpoint.memory import MemorySaver  # 持久化\n\n\nclass ApprovalState(TypedDict):\n    \"\"\"带审批的工作流状态\"\"\"\n    request: dict\n    review_result: str\n    approved: bool\n    execution_result: str\n    reviewer_notes: str\n\n\ndef submit_node(state: ApprovalState) -> dict:\n    \"\"\"提交请求节点\"\"\"\n    return {\"review_result\": \"pending\", \"approved\": False}\n\n\ndef auto_review_node(state: ApprovalState) -> dict:\n    \"\"\"自动审查节点\"\"\"\n    request = state.get(\"request\", {})\n    amount = request.get(\"amount\", 0)\n    \n    # 小额自动审批\n    if amount <= 1000:\n        return {\n            \"approved\": True,\n            \"review_result\": \"auto_approved\",\n            \"reviewer_notes\": f\"金额 ¥{amount}，自动审批通过\",\n        }\n    \n    return {\n        \"approved\": False,\n        \"review_result\": \"needs_manual_review\",\n        \"reviewer_notes\": f\"金额 ¥{amount}，需要人工审核\",\n    }\n\n\ndef manual_review_node(state: ApprovalState) -> dict:\n    \"\"\"人工审核节点——返回一个中断点\"\"\"\n    # 在 LangGraph 中，这里会暂停执行等待人工输入\n    return {\n        \"review_result\": \"manual_review_pending\",\n        \"reviewer_notes\": \"等待人工审核...\",\n    }\n\n\ndef execute_node(state: ApprovalState) -> dict:\n    \"\"\"执行节点\"\"\"\n    if state.get(\"approved\"):\n        return {\"execution_result\": \"执行成功\"}\n    return {\"execution_result\": \"已拒绝，未执行\"}\n\n\ndef needs_manual_review(state: ApprovalState) -> str:\n    \"\"\"条件判断：是否需要人工审核\"\"\"\n    if state.get(\"review_result\") == \"needs_manual_review\":\n        return \"manual_review\"\n    return \"execute\"\n\n\ndef is_approved(state: ApprovalState) -> str:\n    \"\"\"条件判断：是否已审批\"\"\"\n    if state.get(\"approved\"):\n        return \"execute\"\n    return END\n\n\ndef build_approval_graph():\n    graph = StateGraph(ApprovalState)\n    \n    graph.add_node(\"submit\", submit_node)\n    graph.add_node(\"auto_review\", auto_review_node)\n    graph.add_node(\"manual_review\", manual_review_node)\n    graph.add_node(\"execute\", execute_node)\n    \n    graph.set_entry_point(\"submit\")\n    graph.add_edge(\"submit\", \"auto_review\")\n    graph.add_conditional_edges(\"auto_review\", needs_manual_review)\n    graph.add_conditional_edges(\"manual_review\", is_approved)\n    graph.add_edge(\"execute\", END)\n    \n    # 使用 MemorySaver 实现持久化和中断恢复\n    return graph.compile(checkpointer=MemorySaver())",
      "section_ref": "21.4.3",
      "runnable": true,
      "dependencies": [
        "langgraph"
      ]
    },
    {
      "id": "code-8",
      "language": "python",
      "description": "| Pipeline模式 | 数据流处理 | ETL风格的连续处理 |",
      "code": "from typing import Generic, TypeVar, Callable\nfrom dataclasses import dataclass\n\nT = TypeVar('T')\nU = TypeVar('U')\n\n\n@dataclass\nclass PipelineResult:\n    success: bool\n    data: any\n    step_name: str = \"\"\n    error: str = \"\"\n\n\nclass Pipeline(Generic[T]):\n    \"\"\"通用顺序管道\"\"\"\n    \n    def __init__(self, name: str = \"pipeline\"):\n        self.name = name\n        self._steps: list[tuple[str, Callable]] = []\n    \n    def add_step(self, name: str, fn: Callable) -> 'Pipeline':\n        self._steps.append((name, fn))\n        return self\n    \n    def execute(self, initial_data: T) -> PipelineResult:\n        data = initial_data\n        \n        for step_name, fn in self._steps:\n            try:\n                data = fn(data)\n                if not isinstance(data, PipelineResult):\n                    # 包装为成功的PipelineResult\n                    data = PipelineResult(success=True, data=data, step_name=step_name)\n                elif not data.success:\n                    return data\n            except Exception as e:\n                return PipelineResult(\n                    success=False, data=data, step_name=step_name,\n                    error=str(e),\n                )\n        \n        return PipelineResult(success=True, data=data, step_name=\"complete\")\n\n\n# 使用示例\npipeline = Pipeline(\"text_processing\")\npipeline.add_step(\"clean\", lambda d: d.strip().lower())\npipeline.add_step(\"tokenize\", lambda d: d.split())\npipeline.add_step(\"filter\", lambda d: [w for w in d if len(w) > 2])\npipeline.add_step(\"count\", lambda d: PipelineResult(True, len(d), \"count\"))\n\nresult = pipeline.execute(\"  Hello World, This is a Test Pipeline  \")\nprint(f\"结果: {result}\")",
      "section_ref": "21.5.2",
      "runnable": true,
      "dependencies": []
    },
    {
      "id": "code-9",
      "language": "python",
      "description": "",
      "code": "import asyncio\nfrom typing import Any\n\n\nclass ParallelFanOut:\n    \"\"\"并行扇出-扇入模式\"\"\"\n    \n    def __init__(self, name: str = \"parallel\"):\n        self.name = name\n        self._tasks: list[tuple[str, Callable]] = []\n        self._aggregator: Callable = None\n    \n    def add_task(self, name: str, fn: Callable):\n        self._tasks.append((name, fn))\n        return self\n    \n    def set_aggregator(self, fn: Callable):\n        self._aggregator = fn\n        return self\n    \n    async def execute(self, input_data: Any) -> dict:\n        # 扇出：并行执行所有任务\n        results = await asyncio.gather(\n            *[fn(input_data) for _, fn in self._tasks],\n            return_exceptions=True,\n        )\n        \n        # 收集结果\n        task_results = {}\n        for i, (name, _) in enumerate(self._tasks):\n            if isinstance(results[i], Exception):\n                task_results[name] = {\"error\": str(results[i])}\n            else:\n                task_results[name] = results[i]\n        \n        # 扇入：聚合结果\n        if self._aggregator:\n            return self._aggregator(task_results)\n        return task_results\n\n\n# 使用示例\nasync def analyze_sentiment(text: str) -> dict:\n    await asyncio.sleep(0.1)  # 模拟延迟\n    return {\"sentiment\": \"positive\", \"confidence\": 0.92}\n\nasync def extract_entities(text: str) -> dict:\n    await asyncio.sleep(0.15)\n    return {\"entities\": [\"Apple\", \"iPhone\", \"Tim Cook\"]}\n\nasync def classify_topic(text: str) -> dict:\n    await asyncio.sleep(0.05)\n    return {\"topic\": \"technology\", \"subtopics\": [\"mobile\", \"AI\"]}\n\nfanout = ParallelFanOut(\"text_analysis\")\nfanout.add_task(\"sentiment\", analyze_sentiment)\nfanout.add_task(\"entities\", extract_entities)\nfanout.add_task(\"topic\", classify_topic)\nfanout.set_aggregator(\n    lambda results: {\n        \"combined\": results,\n        \"summary\": f\"共分析 {len(results)} 个维度\",\n    }\n)\n\nresult = await fanout.execute(\"Apple released new iPhone with AI features\")\n# result: {\"combined\": {...}, \"summary\": \"共分析 3 个维度\"}",
      "section_ref": "21.5.3",
      "runnable": true,
      "dependencies": []
    },
    {
      "id": "code-10",
      "language": "python",
      "description": "",
      "code": "class SagaOrchestrator:\n    \"\"\"\n    Saga 模式——处理分布式事务。\n    每个步骤都有对应的补偿操作，失败时依次回滚。\n    \"\"\"\n    \n    def __init__(self):\n        self._steps: list[tuple[str, Callable, Callable]] = []\n        # (名称, 执行函数, 补偿函数)\n    \n    def add_step(self, name: str, execute_fn: Callable, compensate_fn: Callable):\n        self._steps.append((name, execute_fn, compensate_fn))\n        return self\n    \n    async def execute(self, context: dict) -> dict:\n        completed_steps = []\n        \n        for step_name, execute_fn, compensate_fn in self._steps:\n            try:\n                result = execute_fn(context)\n                if isinstance(result, dict):\n                    context.update(result)\n                completed_steps.append((step_name, compensate_fn))\n            except Exception as e:\n                # 失败，执行补偿\n                print(f\"步骤 {step_name} 失败: {e}，开始补偿...\")\n                for comp_name, comp_fn in reversed(completed_steps):\n                    try:\n                        comp_fn(context)\n                        print(f\"补偿 {comp_name} 成功\")\n                    except Exception as ce:\n                        print(f\"补偿 {comp_name} 失败: {ce}\")\n                \n                context[\"saga_status\"] = \"compensated\"\n                context[\"failed_at\"] = step_name\n                return context\n        \n        context[\"saga_status\"] = \"completed\"\n        return context\n\n\n# 使用示例\nasync def reserve_stock(ctx):\n    print(f\"预留库存: {ctx.get('order_id')}\")\n    return {\"stock_reserved\": True}\n\nasync def cancel_stock(ctx):\n    print(\"释放预留库存\")\n\nasync def charge_payment(ctx):\n    print(f\"扣款: ¥{ctx.get('amount')}\")\n    return {\"payment_charged\": True}\n\nasync def refund_payment(ctx):\n    print(\"退款\")\n\nasync def create_shipment(ctx):\n    print(f\"创建发货单: {ctx.get('order_id')}\")\n    return {\"shipment_created\": True}\n\nasync def cancel_shipment(ctx):\n    print(\"取消发货单\")\n\n\nsaga = SagaOrchestrator()\nsaga.add_step(\"reserve_stock\", reserve_stock, cancel_stock)\nsaga.add_step(\"charge_payment\", charge_payment, refund_payment)\nsaga.add_step(\"create_shipment\", create_shipment, cancel_shipment)\n\nresult = await saga.execute({\"order_id\": \"ORD-001\", \"amount\": 299})",
      "section_ref": "21.5.4",
      "runnable": true,
      "dependencies": []
    },
    {
      "id": "code-11",
      "language": "python",
      "description": "",
      "code": "class ConditionalRouter:\n    \"\"\"条件路由器\"\"\"\n    \n    def __init__(self):\n        self._routes: list[tuple[str, Callable, Callable]] = []\n    \n    def add_route(self, name: str, condition: Callable, handler: Callable):\n        self._routes.append((name, condition, handler))\n        return self\n    \n    def add_default(self, handler: Callable):\n        self._default = handler\n        return self\n    \n    def route(self, context: dict) -> any:\n        for name, condition, handler in self._routes:\n            if condition(context):\n                return {\"route\": name, \"result\": handler(context)}\n        if hasattr(self, '_default'):\n            return {\"route\": \"default\", \"result\": self._default(context)}\n        raise RuntimeError(\"没有匹配的路由且没有默认处理器\")\n\n\nrouter = ConditionalRouter()\nrouter.add_route(\n    \"simple_query\", \n    lambda ctx: ctx.get(\"complexity\", \"high\") == \"low\",\n    lambda ctx: f\"简单回答: {ctx['query']}\"\n)\nrouter.add_route(\n    \"research_required\",\n    lambda ctx: ctx.get(\"complexity\", \"high\") == \"high\",\n    lambda ctx: f\"需要深入研究: {ctx['query']}\"\n)\nrouter.add_default(lambda ctx: \"请提供更多信息\")\n\nresult = router.route({\"query\": \"什么是Python?\", \"complexity\": \"low\"})",
      "section_ref": "21.6.1",
      "runnable": true,
      "dependencies": []
    },
    {
      "id": "code-12",
      "language": "python",
      "description": "",
      "code": "class IterativeLoop:\n    \"\"\"迭代循环控制器\"\"\"\n    \n    def __init__(\n        self,\n        max_iterations: int = 5,\n        convergence_fn: Callable = None,\n    ):\n        self.max_iterations = max_iterations\n        self.convergence_fn = convergence_fn\n        self._step_fn: Callable = None\n    \n    def set_step(self, fn: Callable):\n        self._step_fn = fn\n        return self\n    \n    def execute(self, initial_state: dict) -> dict:\n        state = initial_state\n        history = []\n        \n        for i in range(self.max_iterations):\n            # 执行一步\n            state = self._step_fn(state)\n            history.append({\n                \"iteration\": i + 1,\n                \"state_snapshot\": {k: v for k, v in state.items() if k != \"history\"},\n            })\n            \n            # 检查收敛\n            if self.convergence_fn and self.convergence_fn(state):\n                state[\"converged\"] = True\n                state[\"iterations\"] = i + 1\n                break\n        else:\n            state[\"converged\"] = False\n            state[\"iterations\"] = self.max_iterations\n        \n        state[\"history\"] = history\n        return state\n\n\n# 使用示例：迭代优化Prompt\ndef optimize_prompt_step(state: dict) -> dict:\n    current = state.get(\"current_prompt\", \"\")\n    score = state.get(\"score\", 0)\n    \n    # 模拟优化：每次迭代提升分数\n    new_score = min(1.0, score + 0.15 + (hash(current) % 10) / 100)\n    state[\"score\"] = new_score\n    state[\"current_prompt\"] = f\"{current}\\n[优化 #{state.get('iteration', 0) + 1}]\"\n    state[\"iteration\"] = state.get(\"iteration\", 0) + 1\n    return state\n\n\nloop = IterativeLoop(\n    max_iterations=10,\n    convergence_fn=lambda s: s.get(\"score\", 0) >= 0.9,\n)\nloop.set_step(optimize_prompt_step)\n\nresult = loop.execute({\n    \"current_prompt\": \"你是一个助手\",\n    \"score\": 0.3,\n})\nprint(f\"迭代 {result['iterations']} 次，最终分数: {result['score']}\")",
      "section_ref": "21.6.2",
      "runnable": true,
      "dependencies": []
    },
    {
      "id": "code-13",
      "language": "python",
      "description": "- 质量控制：对关键输出进行人工审核",
      "code": "import time\nfrom enum import Enum\nfrom typing import Optional\nfrom dataclasses import dataclass\n\n\nclass ApprovalStatus(Enum):\n    PENDING = \"pending\"\n    APPROVED = \"approved\"\n    REJECTED = \"rejected\"\n    EXPIRED = \"expired\"\n\n\n@dataclass\nclass HumanApprovalRequest:\n    \"\"\"人工审批请求\"\"\"\n    request_id: str\n    action_type: str           # 操作类型\n    description: str           # 操作描述\n    risk_level: str            # 风险等级: low/medium/high/critical\n    context_data: dict         # 上下文数据\n    status: ApprovalStatus = ApprovalStatus.PENDING\n    created_at: float = field(default_factory=time.time)\n    resolved_at: Optional[float] = None\n    reviewer: Optional[str] = None\n    review_notes: Optional[str] = None\n    \n    @property\n    def is_expired(self) -> bool:\n        \"\"\"超时检查（默认24小时）\"\"\"\n        return (time.time() - self.created_at) > 86400\n\n\nclass HumanInTheLoopManager:\n    \"\"\"人工介入管理器\"\"\"\n    \n    def __init__(\n        self,\n        auto_approve_below: str = \"low\",\n        timeout_seconds: int = 86400,\n    ):\n        self.auto_approve_below = auto_approve_below\n        self.timeout_seconds = timeout_seconds\n        self._pending: dict[str, HumanApprovalRequest] = {}\n        self._risk_handlers: dict[str, Callable] = {}\n        self._reviewer_queue: list[str] = []  # 审核人员队列\n    \n    def set_risk_handler(self, risk_level: str, handler: Callable):\n        \"\"\"为不同风险等级设置处理策略\"\"\"\n        self._risk_handlers[risk_level] = handler\n    \n    def request_approval(\n        self, \n        action_type: str, \n        description: str,\n        risk_level: str,\n        context_data: dict,\n    ) -> HumanApprovalRequest:\n        \"\"\"提交审批请求\"\"\"\n        import uuid\n        request = HumanApprovalRequest(\n            request_id=str(uuid.uuid4())[:8],\n            action_type=action_type,\n            description=description,\n            risk_level=risk_level,\n            context_data=context_data,\n        )\n        \n        # 低风险自动审批\n        risk_order = [\"low\", \"medium\", \"high\", \"critical\"]\n        if (risk_order.index(risk_level) \n            <= risk_order.index(self.auto_approve_below)):\n            request.status = ApprovalStatus.APPROVED\n            request.resolved_at = time.time()\n            request.reviewer = \"system:auto\"\n            request.review_notes = \"低风险自动审批\"\n            return request\n        \n        # 需要人工审核\n        self._pending[request.request_id] = request\n        \n        # 通知审核人员（实际中通过消息队列/邮件/通知）\n        print(f\"[审批请求] ID: {request.request_id}, \"\n              f\"操作: {action_type}, 风险: {risk_level}\")\n        print(f\"  描述: {description}\")\n        \n        return request\n    \n    def approve(self, request_id: str, reviewer: str, notes: str = \"\") -> bool:\n        \"\"\"审批通过\"\"\"\n        request = self._pending.get(request_id)\n        if not request:\n            return False\n        \n        request.status = ApprovalStatus.APPROVED\n        request.resolved_at = time.time()\n        request.reviewer = reviewer\n        request.review_notes = notes\n        del self._pending[request_id]\n        return True\n    \n    def reject(self, request_id: str, reviewer: str, reason: str) -> bool:\n        \"\"\"拒绝\"\"\"\n        request = self._pending.get(request_id)\n        if not request:\n            return False\n        \n        request.status = ApprovalStatus.REJECTED\n        request.resolved_at = time.time()\n        request.reviewer = reviewer\n        request.review_notes = reason\n        del self._pending[request_id]\n        return True\n    \n    def check_pending(self, request_id: str) -> Optional[ApprovalStatus]:\n        \"\"\"检查审批状态\"\"\"\n        request = self._pending.get(request_id)\n        if not request:\n            return None\n        \n        if request.is_expired:\n            request.status = ApprovalStatus.EXPIRED\n            request.resolved_at = time.time()\n            del self._pending[request_id]\n            return ApprovalStatus.EXPIRED\n        \n        return request.status\n    \n    def get_pending_requests(self) -> list[HumanApprovalRequest]:\n        \"\"\"获取所有待审批请求\"\"\"\n        return list(self._pending.values())\n\n\n# 使用示例\nhitl = HumanInTheLoopManager(auto_approve_below=\"low\")\n\n# 低风险操作——自动审批\nreq1 = hitl.request_approval(\n    \"send_email\", \"发送确认邮件给用户\",\n    \"low\", {\"user_id\": \"u123\", \"email\": \"user@example.com\"}\n)\nprint(f\"邮件发送审批: {req1.status.value}\")\n\n# 高风险操作——需要人工\nreq2 = hitl.request_approval(\n    \"refund\", \"退款 ¥5,000\",\n    \"high\", {\"order_id\": \"ORD-001\", \"amount\": 5000}\n)\nprint(f\"退款审批: {req2.status.value}\")\n\n# 模拟人工审批\nhitl.approve(req2.request_id, reviewer=\"manager_zhang\", notes=\"确认用户已退回商品\")\nprint(f\"退款审批: {hitl.check_pending(req2.request_id)}\")",
      "section_ref": "21.7.2",
      "runnable": true,
      "dependencies": []
    },
    {
      "id": "code-14",
      "language": "python",
      "description": "",
      "code": "class InterruptibleWorkflow:\n    \"\"\"\n    可中断的工作流——在特定节点暂停执行，\n    等待外部输入后恢复。\n    \"\"\"\n    \n    def __init__(self):\n        self._nodes: list[tuple[str, Callable]] = []\n        self._interrupt_points: set[str] = set()\n        self._state: dict = {}\n        self._resume_data: dict = {}\n    \n    def add_node(self, name: str, fn: Callable):\n        self._nodes.append((name, fn))\n    \n    def set_interrupt(self, name: str):\n        \"\"\"设置中断点\"\"\"\n        self._interrupt_points.add(name)\n    \n    async def execute(self, initial_state: dict) -> dict:\n        self._state = initial_state\n        execution_pointer = self._state.get(\"_resume_at\", 0)\n        \n        for i in range(execution_pointer, len(self._nodes)):\n            name, fn = self._nodes[i]\n            \n            # 检查是否是中断点\n            if name in self._interrupt_points:\n                if not self._state.get(\"_interrupt_resolved\", False):\n                    self._state[\"_interrupted_at\"] = name\n                    self._state[\"_interrupted_node_index\"] = i\n                    return self._state  # 暂停执行\n            \n            # 执行节点\n            result = fn(self._state)\n            if isinstance(result, dict):\n                self._state.update(result)\n        \n        self._state[\"_completed\"] = True\n        return self._state\n    \n    def resume(self, input_data: dict) -> dict:\n        \"\"\"从中断点恢复\"\"\"\n        self._state.update(input_data)\n        self._state[\"_interrupt_resolved\"] = True\n        return self._state  # 调用方需要再次调用 execute",
      "section_ref": "21.7.3",
      "runnable": true,
      "dependencies": []
    }
  ],
  "tables": [
    {
      "headers": [
        "模式",
        "适用场景",
        "特点"
      ],
      "data": [
        [
          "**顺序模式**",
          "步骤间有明确依赖",
          "A→B→C→D"
        ],
        [
          "**并行模式**",
          "步骤间无依赖",
          "A+B+C→聚合"
        ],
        [
          "**条件分支**",
          "根据条件选择路径",
          "A→(条件)→B或C"
        ],
        [
          "**循环模式**",
          "需要反复优化",
          "A→B→(条件)→A或END"
        ],
        [
          "**Saga模式**",
          "分布式事务",
          "A→B→C→(失败)→补偿"
        ],
        [
          "**Pipeline模式**",
          "数据流处理",
          "ETL风格的连续处理"
        ]
      ]
    }
  ],
  "key_takeaways": [],
  "common_pitfalls": [],
  "related_chapters": [
    "ch09"
  ]
}