{
  "metadata": {
    "id": "ch31",
    "title": "第31章 单Agent模式",
    "volume": "vol9",
    "volume_title": "Agent设计模式",
    "word_count": 7964,
    "difficulty": "advanced",
    "prerequisites": [
      "ch04"
    ],
    "key_concepts": [
      "概述",
      "ReAct 模式（Reasoning + Acting）",
      "意图",
      "动机",
      "结构",
      "参与者",
      "协作",
      "效果",
      "实现",
      "适用场景",
      "相关模式",
      "Plan-and-Execute 模式",
      "Reflection 模式",
      "Router 模式",
      "Guardrails 模式"
    ],
    "learning_objectives": [],
    "estimated_tokens": 4778,
    "source_file": "vol9/ch31_单Agent模式.md"
  },
  "overview": "",
  "sections": [
    {
      "id": "31.1",
      "title": "31.1 概述",
      "level": 2,
      "content": "单Agent模式是所有Agent设计模式的基石。在复杂的多Agent编排之前，一个设计精良的单Agent就足以解决大量实际业务问题。本章深入探讨六种核心的单Agent行为模式：ReAct、Plan-and-Execute、Reflection、Router、Guardrails 和 Adapter。\n\n单Agent模式的核心挑战在于：**如何让一个Agent既足够智能地处理复杂任务，又足够可控地遵守业务约束**。这六种模式从不同的维度回应了这一挑战——ReAct解决推理与行动的融合，Plan-and-Execute处理长期规划，Reflection实现自我改进，Router处理意图分发，Guardrails确保安全边界，Adapter处理模型异构性。\n\n---",
      "subsections": []
    },
    {
      "id": "31.2",
      "title": "31.2 ReAct 模式（Reasoning + Acting）",
      "level": 2,
      "content": "",
      "subsections": [
        {
          "id": "意图",
          "title": "意图",
          "content": "将**推理（Reasoning）**与**行动（Acting）**交织在一起，使Agent能够在每一步推理后决定下一步行动，形成\"思考-行动-观察-再思考\"的迭代循环。"
        },
        {
          "id": "动机",
          "title": "动机",
          "content": "传统的Chain-of-Thought（CoT）方法虽然在推理能力上表现出色，但它是纯粹的思维链，无法与外部世界交互。Agent需要的不只是\"想\"，还要\"做\"——查询数据库、调用API、搜索网络。另一方面，纯行动的Agent缺乏推理能力，容易陷入盲目试错。\n\nReAct模式由 Yao et al.（2023）提出，核心洞察是：**推理和行动不是对立的，而是互补的**。推理帮助选择行动，行动的结果反过来丰富推理的上下文。实验表明，ReAct在HotpotQA和Fever等基准测试上显著优于纯推理（CoT）和纯行动（Act-only）的方法。\n\n在ReAct的框架下，Agent的每一步都包含三个要素：\n- **Thought**：当前思考状态，包括对已有信息的分析和下一步的计划\n- **Action**：选择要执行的工具或操作\n- **Observation**：执行Action后的环境反馈\n\n这种结构使得Agent的推理过程变得**可追踪、可解释、可调试**——每个决策点都有明确的推理依据，每个行动都有可观察的结果。"
        },
        {
          "id": "结构",
          "title": "结构",
          "content": ""
        },
        {
          "id": "参与者",
          "title": "参与者",
          "content": "- **Agent**：执行推理-行动循环的核心实体，维护对话状态和历史记录\n- **LLM**：提供推理能力的语言模型，负责Thought生成和Action选择\n- **Tool Set**：Agent可以调用的一组工具（搜索、计算、查询等）\n- **Observation Buffer**：存储每步行动的观察结果，形成推理上下文\n- **Prompt Template**：结构化的提示模板，规范Agent的输出格式"
        },
        {
          "id": "协作",
          "title": "协作",
          "content": "1. Agent接收到用户的查询\n2. Agent进行**推理**（Thought）：分析问题，决定需要什么信息\n3. Agent执行**行动**（Action）：调用工具或API获取信息\n4. 系统返回**观察结果**（Observation）\n5. Agent基于观察结果进行**新一轮推理**\n6. 重复步骤3-5，直到推理得出最终答案\n7. Agent输出最终回答（Final Answer）"
        },
        {
          "id": "效果",
          "title": "效果",
          "content": "**优点：**\n- 推理与行动的自然融合，提高决策质量\n- 可解释性强——每一步的推理过程都是透明的\n- 灵活性高——可以根据中间结果动态调整策略\n- 减少幻觉——通过工具获取真实数据来验证推理\n- 天然支持工具使用和知识检索的混合任务\n\n**缺点：**\n- 推理链过长时，上下文窗口可能不够\n- 每一步都需要LLM推理，Token消耗较高\n- 循环次数不受限制时，可能陷入死循环\n- 对工具的描述质量要求高，模糊的工具描述会导致错误选择\n- 长链条的推理可能导致\"注意力漂移\"，忽略原始目标"
        },
        {
          "id": "实现",
          "title": "实现",
          "content": "关键实现要点：\n\n1. **提示模板设计**：将推理、行动、观察的格式嵌入prompt，确保LLM输出结构化\n2. **最大迭代次数**：设置合理的上限（通常5-10次）防止无限循环\n3. **终止条件检测**：检测到\"Final Answer\"关键词时停止循环\n4. **工具描述质量**：清晰的工具名称和参数描述帮助LLM选择正确的工具\n5. **错误恢复**：当工具调用失败时，Agent应该能够调整策略而非放弃"
        },
        {
          "id": "适用场景",
          "title": "适用场景",
          "content": "- 需要多步推理与外部交互的复合任务（如多跳问答）\n- 信息检索与分析类任务（如研究助手、市场调研）\n- 数据查询与计算类任务（如数据分析助手、财务分析）\n- 需要可解释推理链的应用（如法律咨询、医疗辅助）"
        },
        {
          "id": "相关模式",
          "title": "相关模式",
          "content": "- **Plan-and-Execute**：ReAct的即时决策 vs Plan-and-Execute的预规划——前者灵活但消耗高，后者高效但僵化\n- **Reflection**：ReAct关注推理过程，Reflection关注结果质量优化\n- **Tool Registry**（第34章）：ReAct依赖工具集，Tool Registry提供工具注册和管理\n- **Guardrails**：为ReAct循环添加输入输出安全约束\n\n---"
        }
      ]
    },
    {
      "id": "31.3",
      "title": "31.3 Plan-and-Execute 模式",
      "level": 2,
      "content": "",
      "subsections": [
        {
          "id": "意图",
          "title": "意图",
          "content": "将任务求解过程分为**规划（Planning）**和**执行（Execution）**两个明确的阶段，先制定完整计划，再逐步执行。"
        },
        {
          "id": "动机",
          "title": "动机",
          "content": "ReAct模式虽然灵活，但面对复杂的多步骤任务时，\"边想边做\"的策略容易导致以下问题：\n\n1. **缺乏全局视角**：Agent可能\"贪心\"地选择当前最优行动，但忽略了长期目标\n2. **频繁的方向调整**：没有全局计划，Agent可能在多个方向之间反复横跳\n3. **重复推理开销**：每一步都需要完整的推理，Token消耗大\n4. **计划不可审查**：用户无法在执行前审核Agent的计划\n\nPlan-and-Execute模式的核心思想是\"谋定而后动\"——先花时间制定一个高质量的执行计划，然后按计划执行，必要时可以重新规划。这种模式更接近人类专家解决问题的自然方式：面对复杂项目，专家会先规划整体方案，然后分步执行。\n\nPlan-and-Execute的一个重要变体是 **Plan-and-Solve**（Wang et al., 2023），它在计划中加入了更详细的子问题分解和变量跟踪，进一步提高了复杂任务的完成率。"
        },
        {
          "id": "结构",
          "title": "结构",
          "content": ""
        },
        {
          "id": "参与者",
          "title": "参与者",
          "content": "- **Planner**：制定执行计划的组件，通常是一个LLM，可以接受上下文和反馈\n- **Plan**：结构化的执行计划，包含有序的步骤列表，每个步骤有明确的描述和工具需求\n- **Executor**：按顺序执行计划中的每一步，可以是另一个LLM或工具调用\n- **Replanner**：根据执行结果决定是否需要重新规划的逻辑（可以与Planner合并）"
        },
        {
          "id": "协作",
          "title": "协作",
          "content": "1. Planner分析用户请求，生成结构化的执行计划\n2. Executor取计划的第一步并执行\n3. Executor将结果反馈给Planner（或直接继续下一步）\n4. 如果执行遇到问题，Replanner根据错误信息重新规划剩余步骤\n5. 所有步骤完成后，汇总结果输出最终答案"
        },
        {
          "id": "效果",
          "title": "效果",
          "content": "**优点：**\n- 全局视角，计划更完整——减少了短视决策的风险\n- 执行效率高——不需要每步都进行完整推理\n- 计划可审查——用户可以在执行前审核和修改计划\n- 支持计划级别的缓存和复用——相同类型的任务可以共享计划模板\n\n**缺点：**\n- 初始规划成本高——复杂任务可能需要多次规划迭代\n- 静态计划对动态环境适应性不足——执行过程中的新信息可能使原计划失效\n- 规划能力依赖LLM的质量——如果LLM无法理解任务的完整范围，计划就会有缺陷\n- 步骤之间的强依赖可能形成瓶颈——前序步骤失败会导致后续步骤无法执行"
        },
        {
          "id": "实现",
          "title": "实现",
          "content": ""
        },
        {
          "id": "适用场景",
          "title": "适用场景",
          "content": "- 复杂的多步骤任务（如项目规划、研究报告生成、代码重构方案）\n- 任务步骤之间有明确的依赖关系（如数据处理管道、CI/CD流程）\n- 需要可审计执行过程的应用（如合规审查、金融交易）\n- 长期目标追踪（如持续数天的研究任务）"
        },
        {
          "id": "相关模式",
          "title": "相关模式",
          "content": "- **ReAct**：即时决策 vs 预先规划——两者可以组合使用，在计划框架内对每个步骤使用ReAct\n- **Hierarchical**（第32章）：Plan-and-Execute天然支持层级分解——高层计划可以分解为低层子计划\n- **Pipeline**（第32章）：计划中的步骤可以编排为流水线以提高并行度\n\n---"
        }
      ]
    },
    {
      "id": "31.4",
      "title": "31.4 Reflection 模式",
      "level": 2,
      "content": "",
      "subsections": [
        {
          "id": "意图",
          "title": "意图",
          "content": "使Agent能够**审视自己的输出**，识别不足并进行自我优化，形成\"生成-评估-改进\"的迭代提升循环。"
        },
        {
          "id": "动机",
          "title": "动机",
          "content": "LLM的首次输出往往不是最优的——可能遗漏信息、逻辑有误、格式不对、语气不当。人类写文章需要修改，写代码需要调试，做决策需要复盘，Agent也不例外。\n\nReflection模式的研究可以追溯到 Madaan et al.（2023）提出的 Reflexion 框架，其核心思想是：**如果人类通过反思来改进，Agent也可以通过自我反思来提升输出质量**。\n\n在实际应用中，Reflection的价值尤为突出：\n- **代码生成**：首次生成的代码可能有bug，通过自我审查可以发现并修复\n- **内容创作**：初稿往往结构松散，通过反思可以优化逻辑和表达\n- **决策分析**：初始分析可能遗漏重要因素，通过反思可以补全视角\n- **翻译任务**：初译可能不够流畅，通过反思可以提升翻译质量"
        },
        {
          "id": "结构",
          "title": "结构",
          "content": ""
        },
        {
          "id": "参与者",
          "title": "参与者",
          "content": "- **Generator**：生成初始输出的组件（可以是同一个LLM的不同prompt）\n- **Evaluator**：评估输出质量的组件，从多个维度打分并给出改进建议\n- **Reflection Store**：存储反思记录的仓库，用于长期改进和模式识别"
        },
        {
          "id": "协作",
          "title": "协作",
          "content": "1. Generator根据输入生成初始输出\n2. Evaluator从多个维度评估输出质量（准确性、完整性、清晰度等）\n3. 如果评分低于阈值，将评估反馈（评分+改进建议）传回Generator重新生成\n4. 重复步骤2-3，直到达到质量要求或达到最大迭代次数\n5. 输出最终结果，同时记录反思历史"
        },
        {
          "id": "效果",
          "title": "效果",
          "content": "**优点：**\n- 输出质量显著提升——研究表明在代码生成任务上可提升20-40%的通过率\n- 不需要额外的人工标注数据——使用LLM自身作为评估器\n- 反思记录可用于持续改进——分析常见的失败模式可以优化Generator\n- 自适应的质量控制——可以根据任务复杂度调整反思轮数\n\n**缺点：**\n- 每次迭代都消耗Token——成本随反思轮数线性增长\n- 评估标准难以完全自动化——某些质量维度（如创意性）需要人工判断\n- 过度反思可能导致过度优化——在某些创意任务中，\"完美的\"不如\"有趣的\"\n- 评估器本身也可能出错——LLM对自身输出的评估可能不够客观"
        },
        {
          "id": "实现",
          "title": "实现",
          "content": ""
        },
        {
          "id": "适用场景",
          "title": "适用场景",
          "content": "- 内容生成类任务（文章、报告、文案、翻译）\n- 代码生成与自动审查\n- 需要高质量输出的商业应用\n- 数据分析与洞察报告"
        },
        {
          "id": "相关模式",
          "title": "相关模式",
          "content": "- **ReAct**：Reflection可以嵌入ReAct循环的每一步——每次行动后进行自我反思\n- **Human-in-the-Loop**（第33章）：Reflection的自动评估可以与人工评估结合\n- **Guardrails**：Reflection的评估维度可以作为Guardrails的质量检查规则\n\n---"
        }
      ]
    },
    {
      "id": "31.5",
      "title": "31.5 Router 模式",
      "level": 2,
      "content": "",
      "subsections": [
        {
          "id": "意图",
          "title": "意图",
          "content": "根据用户输入的**意图**，将请求**路由**到最合适的处理Agent或处理流程，实现关注点分离和专业化处理。"
        },
        {
          "id": "动机",
          "title": "动机",
          "content": "随着Agent能力的扩展，一个Agent处理所有类型的请求既不高效也不可控。就像Web应用中的路由器将不同URL分发到不同的Controller一样，Agent系统也需要一个智能路由层来分发请求。\n\nRouter模式将\"理解意图\"和\"处理任务\"解耦，使得每个下游Agent可以专注于自己擅长的领域，同时系统整体能力得到灵活扩展。在实践中，Router模式是构建企业级AI系统的必经之路——没有良好的意图分发，系统就无法在保证质量的前提下扩展能力边界。\n\nRouter的实现方式有多种：基于关键词匹配的规则路由、基于嵌入向量的语义路由、基于LLM的智能路由。在生产环境中，通常会组合使用多种方式，以提高准确性和鲁棒性。"
        },
        {
          "id": "结构",
          "title": "结构",
          "content": ""
        },
        {
          "id": "参与者",
          "title": "参与者",
          "content": "- **Router**：意图分类和路由决策组件\n- **Intent Schema**：预定义的意图类别列表及其描述\n- **Specialized Agents**：处理特定类型请求的专业Agent\n- **Fallback Handler**：当置信度不足时的默认处理逻辑"
        },
        {
          "id": "协作",
          "title": "协作",
          "content": "1. 用户发送请求到Router\n2. Router分析请求，识别用户意图并计算置信度\n3. Router根据意图将请求转发给对应的专业Agent\n4. 专业Agent处理请求并返回结果\n5. Router将结果返回给用户（可选地整合多个Agent的结果）"
        },
        {
          "id": "效果",
          "title": "效果",
          "content": "**优点：**\n- 关注点分离，每个Agent职责明确且可独立优化\n- 易于扩展新的处理能力——添加新Agent即可\n- 便于独立测试和维护\n- 支持A/B测试不同处理策略\n\n**缺点：**\n- 路由分类的准确性直接影响用户体验\n- 意图边界模糊时，分类可能不准确\n- 增加了系统的复杂度和延迟"
        },
        {
          "id": "实现",
          "title": "实现",
          "content": ""
        },
        {
          "id": "适用场景",
          "title": "适用场景",
          "content": "- 多领域的对话系统（如企业统一客服平台）\n- 需要专业化处理的复杂系统\n- 多模型协作场景\n- 微服务化的AI架构"
        },
        {
          "id": "相关模式",
          "title": "相关模式",
          "content": "- **Semantic Router**（第34章）：Router模式的语义增强版本\n- **Orchestrator**（第32章）：Router是简单的分发，Orchestrator是复杂的编排\n- **Adapter**：Router分发后，Adapter处理下游Agent的模型差异\n\n---"
        }
      ]
    },
    {
      "id": "31.6",
      "title": "31.6 Guardrails 模式",
      "level": 2,
      "content": "",
      "subsections": [
        {
          "id": "意图",
          "title": "意图",
          "content": "为Agent的输入和输出设置**安全约束**，确保Agent的行为始终在预定义的安全边界内运行。"
        },
        {
          "id": "动机",
          "title": "动机",
          "content": "LLM天生存在不可控性——可能输出有害内容、泄露敏感信息、执行危险操作、偏离预设角色。在生产环境中，这种不可控性是不可接受的。Guardrails模式借鉴了Web安全中的输入验证和输出编码思想，为Agent构建多层安全防线。\n\nGuardrails的核心设计理念是**纵深防御（Defense in Depth）**：不是依赖单一的安全检查点，而是在输入、处理、输出的每个环节都设置安全关卡。任何一个关卡发现异常，都可以拦截、修改或升级处理。\n\n在实际应用中，Guardrails需要覆盖多种安全维度：\n- **话题安全**：防止讨论政治敏感、暴力、违法等话题\n- **隐私保护**：防止泄露用户的个人信息（手机号、身份证、银行卡等）\n- **内容毒性**：防止生成仇恨、歧视、冒犯性内容\n- **格式约束**：确保输出符合预期的格式（JSON、Markdown、特定模板）\n- **业务策略**：确保Agent行为符合业务规则（如不能直接执行删除操作）"
        },
        {
          "id": "结构",
          "title": "结构",
          "content": ""
        },
        {
          "id": "参与者",
          "title": "参与者",
          "content": "- **Input Guard**：校验用户输入的安全性和合规性\n- **Output Guard**：校验Agent输出的安全性和合规性\n- **Guard Rules**：预定义的约束规则集合（话题、PII、毒性、格式等）\n- **Fallback Handler**：违反约束时的处理逻辑（拒绝、修改、转人工）"
        },
        {
          "id": "协作",
          "title": "协作",
          "content": "1. 用户输入到达Input Guard\n2. Input Guard按顺序检查每条约束规则\n3. 如果违规，触发Fallback Handler（拒绝、自动修改或转人工）\n4. 如果全部通过，将（可能被修改后的）输入传递给Agent核心\n5. Agent生成输出\n6. Output Guard检查输出是否合规\n7. 如果违规，要求Agent重新生成或使用Fallback"
        },
        {
          "id": "效果",
          "title": "效果",
          "content": "**优点：**\n- 多层防御，纵深安全——即使某一层被绕过，其他层仍然提供保护\n- 可配置的约束规则——不同的部署环境可以使用不同的规则集\n- 不影响Agent核心逻辑——Guardrails是正交的关注点\n- 便于审计和合规——所有Guard检查都有日志记录\n\n**缺点：**\n- 过严格的约束可能影响用户体验（误拒率）\n- 需要持续维护和更新规则\n- 增加了系统的延迟（每个Guard都需要计算时间）"
        },
        {
          "id": "实现",
          "title": "实现",
          "content": ""
        },
        {
          "id": "适用场景",
          "title": "适用场景",
          "content": "- 面向公众的AI服务\n- 处理敏感数据的应用（金融、医疗、法律）\n- 受监管行业\n- 多租户SaaS平台"
        },
        {
          "id": "相关模式",
          "title": "相关模式",
          "content": "- **Circuit Breaker**（第35章）：Guardrails与Circuit Breaker配合，防止异常请求的级联扩散\n- **Audit Trail**（第35章）：Guardrails的检查记录可以作为审计依据\n- **Human-in-the-Loop**（第33章）：Guardrails检测到严重问题时升级给人类处理\n\n---"
        }
      ]
    },
    {
      "id": "31.7",
      "title": "31.7 Adapter 模式",
      "level": 2,
      "content": "",
      "subsections": [
        {
          "id": "意图",
          "title": "意图",
          "content": "为不同的LLM模型提供**统一的接口适配层**，使Agent核心逻辑不依赖于特定模型的API差异，实现模型的无缝切换。"
        },
        {
          "id": "动机",
          "title": "动机",
          "content": "Agent系统经常需要在不同模型之间切换——OpenAI的GPT系列、Anthropic的Claude、开源的Llama、国内的通义千问等。每个模型的API签名、参数格式、行为特性都不同。Adapter模式借鉴GoF适配器模式的思想，为Agent屏蔽底层模型的差异。\n\nAdapter模式的实际价值体现在多个层面：\n\n1. **供应商锁定规避**：不绑定单一模型供应商，避免供应商涨价或服务中断的风险\n2. **成本优化**：简单任务用便宜的小模型，复杂任务用强大的大模型\n3. **A/B测试**：同时使用多个模型进行对比实验\n4. **降级容灾**：主模型不可用时自动切换到备用模型\n5. **模型迭代**：新模型发布时只需添加新的Adapter，无需修改业务逻辑"
        },
        {
          "id": "结构",
          "title": "结构",
          "content": ""
        },
        {
          "id": "参与者",
          "title": "参与者",
          "content": "- **LLMAdapter Interface**：统一的模型接口抽象\n- **Concrete Adapters**：针对特定模型的具体适配器实现\n- **Agent Core**：使用统一接口的Agent核心逻辑\n- **Model Registry**：模型注册中心，管理可用的适配器实例"
        },
        {
          "id": "协作",
          "title": "协作",
          "content": "1. Agent Core通过统一接口调用LLM方法\n2. LLMAdapter Interface将调用转发给当前激活的具体适配器\n3. 具体适配器处理API差异（参数映射、错误处理、重试逻辑）\n4. 具体适配器返回统一格式化的结果"
        },
        {
          "id": "效果",
          "title": "效果",
          "content": "**优点：**\n- Agent核心逻辑不依赖具体模型——模型是可替换的\n- 模型切换零成本——修改配置即可\n- 便于A/B测试不同模型的效果\n- 支持降级策略——主模型不可用时自动切换\n\n**缺点：**\n- 适配器层增加了维护成本\n- 某些模型特有功能可能无法通过统一接口暴露\n- 统一接口可能成为\"最小公约数\"，限制了对特定模型优势的利用"
        },
        {
          "id": "实现",
          "title": "实现",
          "content": ""
        },
        {
          "id": "适用场景",
          "title": "适用场景",
          "content": "- 需要支持多个LLM供应商的系统\n- 模型A/B测试和效果对比\n- 需要降级容灾的生产系统\n- 多语言、多模型混合部署"
        },
        {
          "id": "相关模式",
          "title": "相关模式",
          "content": "- **Router**：Adapter提供模型级适配，Router提供意图级分发\n- **Configuration Driven**（第35章）：Adapter的配置可以通过配置驱动模式管理\n- **Circuit Breaker**（第35章）：当某个模型持续失败时，Circuit Breaker自动切换到备用模型\n\n---"
        }
      ]
    },
    {
      "id": "31.8",
      "title": "31.8 模式组合指南",
      "level": 2,
      "content": "本章介绍",
      "subsections": []
    }
  ],
  "code_blocks": [
    {
      "id": "code-1",
      "language": "text",
      "description": "这种结构使得Agent的推理过程变得可追踪、可解释、可调试——每个决策点都有明确的推理依据，每个行动都有可观察的结果。",
      "code": "┌─────────────────────────────────────────┐\n│              ReAct Agent                 │\n│                                         │\n│  ┌─────────┐     ┌─────────┐           │\n│  │ Reasoning│────▶│ Action  │           │\n│  │ (思考)   │◀────│ (行动)  │           │\n│  └─────────┘     └────┬────┘           │\n│       ▲                │                │\n│       │         ┌──────▼──────┐         │\n│       └─────────│ Observation │         │\n│                 │  (观察结果)  │         │\n│                 └─────────────┘         │\n│                                         │\n│  ToolSet: [Search, Lookup, Calculate...]│\n└─────────────────────────────────────────┘",
      "section_ref": "结构",
      "runnable": false,
      "dependencies": []
    },
    {
      "id": "code-2",
      "language": "python",
      "description": "5. 错误恢复：当工具调用失败时，Agent应该能够调整策略而非放弃",
      "code": "\"\"\"\nReAct模式 - 推理-行动循环实现\n\"\"\"\nfrom typing import List, Optional, Callable\nfrom dataclasses import dataclass, field\nfrom enum import Enum\nimport json\nimport re\n\n\nclass AgentStepType(Enum):\n    REASONING = \"thought\"\n    ACTION = \"action\"\n    OBSERVATION = \"observation\"\n    FINAL_ANSWER = \"final_answer\"\n\n\n@dataclass\nclass AgentStep:\n    \"\"\"ReAct循环中的单步记录\"\"\"\n    step_type: AgentStepType\n    content: str\n    tool_name: Optional[str] = None\n    tool_input: Optional[dict] = None\n    step_number: int = 0\n\n\n@dataclass\nclass Tool:\n    \"\"\"工具定义\"\"\"\n    name: str\n    description: str\n    function: Callable\n    parameters: dict = field(default_factory=dict)\n\n\nclass ReActAgent:\n    \"\"\"\n    ReAct Agent 核心实现\n    \n    将推理（Thought）与行动（Action）交织在一起，\n    通过\"思考-行动-观察\"循环解决复杂任务。\n    \"\"\"\n    \n    def __init__(\n        self,\n        llm_client,\n        tools: List[Tool],\n        max_iterations: int = 8,\n        verbose: bool = False\n    ):\n        self.llm = llm_client\n        self.tools = {tool.name: tool for tool in tools}\n        self.max_iterations = max_iterations\n        self.verbose = verbose\n        self.history: List[AgentStep] = []\n        self._system_prompt = self._build_system_prompt()\n    \n    def _build_system_prompt(self) -> str:\n        tool_descriptions = \"\\n\".join(\n            f\"- {name}: {tool.description}\"\n            for name, tool in self.tools.items()\n        )\n        return f\"\"\"你是一个能够通过推理和行动来解决问题的AI助手。\n\n你可以使用以下工具：\n{tool_descriptions}\n\n你必须严格按照以下格式回复：\n\nThought: [你的推理过程]\nAction: [工具名称]\nAction Input: {{\"参数名\": \"参数值\"}}\n\n当你得出最终答案时，使用以下格式：\nThought: [总结推理]\nFinal Answer: [最终答案]\n\n重要规则：\n1. 每次只执行一个行动\n2. 在行动前必须说明你的推理\n3. 基于观察结果进行下一步推理\n4. 如果工具返回错误，调整策略重试\"\"\"\n    \n    def _parse_response(self, response: str) -> AgentStep:\n        \"\"\"解析LLM的响应为结构化步骤\"\"\"\n        response = response.strip()\n        \n        # 检查是否是最终答案\n        final_match = re.search(\n            r'Final Answer:\\s*(.+?)(?:\\n|$)', response, re.DOTALL\n        )\n        if final_match:\n            return AgentStep(\n                step_type=AgentStepType.FINAL_ANSWER,\n                content=final_match.group(1).strip()\n            )\n        \n        # 提取推理\n        thought_match = re.search(\n            r'Thought:\\s*(.+?)(?=\\nAction:|\\nFinal Answer:|$)',\n            response, re.DOTALL\n        )\n        thought = thought_match.group(1).strip() if thought_match else \"\"\n        \n        # 提取行动\n        action_match = re.search(r'Action:\\s*(\\w+)', response)\n        action_input_match = re.search(\n            r'Action Input:\\s*(\\{.+?\\})', response, re.DOTALL\n        )\n        \n        if action_match:\n            tool_name = action_match.group(1).strip()\n            tool_input = {}\n            if action_input_match:\n                try:\n                    tool_input = json.loads(action_input_match.group(1))\n                except json.JSONDecodeError:\n                    tool_input = {\"raw\": action_input_match.group(1)}\n            return AgentStep(\n                step_type=AgentStepType.ACTION,\n                content=thought,\n                tool_name=tool_name,\n                tool_input=tool_input\n            )\n        \n        return AgentStep(step_type=AgentStepType.REASONING, content=response)\n    \n    def _execute_tool(self, tool_name: str, tool_input: dict) -> str:\n        \"\"\"执行工具调用\"\"\"\n        if tool_name not in self.tools:\n            return f\"错误：未知工具 '{tool_name}'\"\n        tool = self.tools[tool_name]\n        try:\n            result = tool.function(**tool_input)\n            return str(result)\n        except Exception as e:\n            return f\"工具执行错误：{str(e)}\"\n    \n    def run(self, query: str) -> str:\n        \"\"\"执行ReAct循环\"\"\"\n        messages = [\n            {\"role\": \"system\", \"content\": self._system_prompt},\n            {\"role\": \"user\", \"content\": query}\n        ]\n        \n        for iteration in range(self.max_iterations):\n            response = self.llm.chat(messages)\n            step = self._parse_response(response)\n            step.step_number = iteration + 1\n            self.history.append(step)\n            \n            if self.verbose:\n                print(f\"\\n--- 迭代 {iteration + 1} ---\")\n                print(f\"[{step.step_type.value}] {step.content}\")\n            \n            if step.step_type == AgentStepType.FINAL_ANSWER:\n                return step.content\n            \n            if step.step_type == AgentStepType.ACTION:\n                observation = self._execute_tool(\n                    step.tool_name, step.tool_input or {}\n                )\n                obs_step = AgentStep(\n                    step_type=AgentStepType.OBSERVATION,\n                    content=observation,\n                    step_number=iteration + 1\n                )\n                self.history.append(obs_step)\n                \n                messages.append({\"role\": \"assistant\", \"content\": response})\n                messages.append({\n                    \"role\": \"user\",\n                    \"content\": f\"观察结果: {observation}\\n\\n继续推理和行动。\"\n                })\n        \n        return \"抱歉，在最大迭代次数内未能找到答案。\"\n    \n    def get_trace(self) -> List[dict]:\n        \"\"\"获取完整的推理-行动追踪\"\"\"\n        return [\n            {\"step\": s.step_number, \"type\": s.step_type.value,\n             \"content\": s.content, \"tool\": s.tool_name, \"input\": s.tool_input}\n            for s in self.history\n        ]",
      "section_ref": "实现",
      "runnable": true,
      "dependencies": []
    },
    {
      "id": "code-3",
      "language": "text",
      "description": "Plan-and-Execute的一个重要变体是 Plan-and-Solve（Wang et al., 2023），它在计划中加入了更详细的子问题分解和变量跟踪，进一步提高了复杂任务的完成率。",
      "code": "┌────────────────────────────────────────────┐\n│           Plan-and-Execute Agent            │\n│                                            │\n│  ┌──────────────────┐                      │\n│  │    Planner       │                      │\n│  │  (规划器/LLM)     │────┐                 │\n│  └──────────────────┘    │                 │\n│           │              ▼                 │\n│           │      ┌──────────────┐          │\n│           │      │   Plan       │          │\n│           │      │  Step 1 ──▶  │          │\n│           │      │  Step 2 ──▶  │          │\n│           │      │  Step 3 ──▶  │          │\n│           │      └──────┬───────┘          │\n│           │             │                  │\n│           │             ▼                  │\n│           │      ┌──────────────┐          │\n│           └─────▶│  Executor    │          │\n│   (重新规划)     │  (执行器)     │          │\n│                  └──────┬───────┘          │\n│                         │                  │\n│                         ▼                  │\n│                  ┌──────────────┐          │\n│                  │   Result     │          │\n│                  └──────────────┘          │\n└────────────────────────────────────────────┘",
      "section_ref": "结构",
      "runnable": false,
      "dependencies": []
    },
    {
      "id": "code-4",
      "language": "python",
      "description": "- 步骤之间的强依赖可能形成瓶颈——前序步骤失败会导致后续步骤无法执行",
      "code": "\"\"\"\nPlan-and-Execute 模式实现\n\"\"\"\nfrom typing import List, Optional\nfrom dataclasses import dataclass, field\nimport json\nimport re\n\n\n@dataclass\nclass PlanStep:\n    \"\"\"计划中的单个步骤\"\"\"\n    step_id: int\n    description: str\n    tool_name: Optional[str] = None\n    tool_input: Optional[dict] = None\n    depends_on: List[int] = field(default_factory=list)\n    status: str = \"pending\"  # pending, running, completed, failed\n\n\n@dataclass\nclass ExecutionPlan:\n    \"\"\"完整执行计划\"\"\"\n    goal: str\n    steps: List[PlanStep]\n    current_step: int = 0\n\n\nclass PlanAndExecuteAgent:\n    \"\"\"\n    Plan-and-Execute Agent\n    \n    将任务求解分为规划和执行两个阶段。\n    先制定全局计划，再逐步执行，支持动态重新规划。\n    \"\"\"\n    \n    def __init__(self, llm_client, tools: dict,\n                 max_replan_attempts: int = 3, verbose: bool = False):\n        self.llm = llm_client\n        self.tools = tools\n        self.max_replan_attempts = max_replan_attempts\n        self.verbose = verbose\n    \n    def _planning_prompt(self, goal: str, context: str = \"\") -> str:\n        return f\"\"\"你是一个任务规划专家。请为以下目标制定详细的执行计划。\n\n目标: {goal}\n{f\"上下文信息: {context}\" if context else \"\"}\n\n请以JSON格式返回计划：\n{{\n    \"plan\": [\n        {{\n            \"step_id\": 1,\n            \"description\": \"步骤描述\",\n            \"tool\": \"工具名称（可选）\",\n            \"input\": {{}},\n            \"depends_on\": []\n        }}\n    ],\n    \"reasoning\": \"规划理由\"\n}}\n\n规则：\n1. 步骤应该有序且可执行\n2. 每个步骤的描述要具体明确\n3. 如果需要使用工具，指定工具名称和输入参数\n4. 步骤之间如果有依赖关系，用depends_on标记\"\"\"\n    \n    def create_plan(self, goal: str, context: str = \"\") -> ExecutionPlan:\n        \"\"\"创建执行计划\"\"\"\n        prompt = self._planning_prompt(goal, context)\n        response = self.llm.chat([{\"role\": \"user\", \"content\": prompt}])\n        \n        try:\n            plan_data = self._parse_plan_response(response)\n            steps = [\n                PlanStep(\n                    step_id=s[\"step_id\"],\n                    description=s[\"description\"],\n                    tool_name=s.get(\"tool\"),\n                    tool_input=s.get(\"input\"),\n                    depends_on=s.get(\"depends_on\", [])\n                )\n                for s in plan_data[\"plan\"]\n            ]\n            plan = ExecutionPlan(goal=goal, steps=steps)\n            \n            if self.verbose:\n                print(f\"\\n📋 执行计划 ({len(steps)}步):\")\n                for step in steps:\n                    print(f\"  {step.step_id}. {step.description}\")\n            return plan\n        except (KeyError, json.JSONDecodeError) as e:\n            raise ValueError(f\"计划解析失败: {e}\")\n    \n    def _parse_plan_response(self, response: str) -> dict:\n        json_match = re.search(r'```(?:json)?\\s*(\\{.*?\\})\\s*```',\n                               response, re.DOTALL)\n        if json_match:\n            return json.loads(json_match.group(1))\n        return json.loads(response)\n    \n    def _execute_step(self, step: PlanStep) -> str:\n        \"\"\"执行单个计划步骤\"\"\"\n        step.status = \"running\"\n        if step.tool_name and step.tool_name in self.tools:\n            try:\n                result = self.tools[step.tool_name](**(step.tool_input or {}))\n                step.status = \"completed\"\n                return str(result)\n            except Exception as e:\n                step.status = \"failed\"\n                return f\"执行失败: {str(e)}\"\n        response = self.llm.chat([\n            {\"role\": \"system\", \"content\": \"你是一个任务执行器。\"},\n            {\"role\": \"user\", \"content\": f\"请执行以下步骤: {step.description}\"}\n        ])\n        step.status = \"completed\"\n        return response\n    \n    def _replan(self, original_plan: ExecutionPlan,\n                failed_step: PlanStep, error: str) -> Optional[ExecutionPlan]:\n        \"\"\"根据失败信息重新规划\"\"\"\n        context = f\"\"\"之前的计划在第{failed_step.step_id}步失败。\n失败步骤: {failed_step.description}\n失败原因: {error}\n已完成的步骤:\n{json.dumps([{\"step\": s.step_id, \"desc\": s.description, \"status\": s.status}\n    for s in original_plan.steps[:failed_step.step_id]], ensure_ascii=False)}\"\"\"\n        return self.create_plan(goal=original_plan.goal, context=context)\n    \n    def run(self, goal: str) -> str:\n        \"\"\"执行Plan-and-Execute流程\"\"\"\n        plan = self.create_plan(goal)\n        replan_count = 0\n        results = []\n        \n        for step in plan.steps:\n            if self.verbose:\n                print(f\"\\n▶ 执行步骤 {step.step_id}: {step.description}\")\n            \n            result = self._execute_step(step)\n            results.append({\n                \"step\": step.step_id,\n                \"description\": step.description,\n                \"result\": result,\n                \"status\": step.status\n            })\n            \n            if step.status == \"failed\" and replan_count < self.max_replan_attempts:\n                replan_count += 1\n                if self.verbose:\n                    print(f\"\\n🔄 第{replan_count}次重新规划...\")\n                new_plan = self._replan(plan, step, result)\n                if new_plan:\n                    plan = new_plan\n                    continue\n            elif step.status == \"failed\":\n                break\n        \n        # 汇总结果\n        summary = self.llm.chat([\n            {\"role\": \"system\", \"content\": \"请根据执行结果生成摘要。\"},\n            {\"role\": \"user\", \"content\": f\"目标: {goal}\\n结果: {json.dumps(results, ensure_ascii=False)}\"}\n        ])\n        return summary",
      "section_ref": "实现",
      "runnable": true,
      "dependencies": []
    },
    {
      "id": "code-5",
      "language": "text",
      "description": "- 翻译任务：初译可能不够流畅，通过反思可以提升翻译质量",
      "code": "┌──────────────────────────────────────┐\n│          Reflection Agent            │\n│                                      │\n│  ┌────────┐    ┌────────────┐        │\n│  │Generator│───▶│  Evaluator │        │\n│  │ (生成器) │    │  (评估器)   │        │\n│  └───┬────┘    └─────┬──────┘        │\n│      │               │               │\n│      │    ┌──────────▼──────┐        │\n│      │    │  Reflection     │        │\n│      │    │  Score/Feedback  │        │\n│      │    └──────────┬──────┘        │\n│      │               │               │\n│      │         score < threshold?     │\n│      │          /          \\          │\n│      │        Yes          No        │\n│      │         │            │        │\n│      └─────────┘            ▼        │\n│                    ┌──────────┐       │\n│                    │  Output   │       │\n│                    └──────────┘       │\n└──────────────────────────────────────┘",
      "section_ref": "结构",
      "runnable": false,
      "dependencies": []
    },
    {
      "id": "code-6",
      "language": "python",
      "description": "- 评估器本身也可能出错——LLM对自身输出的评估可能不够客观",
      "code": "\"\"\"\nReflection 模式 - 自我反思优化实现\n\"\"\"\nfrom typing import List\nfrom dataclasses import dataclass\nimport json\nimport re\n\n\n@dataclass\nclass ReflectionResult:\n    \"\"\"反思评估结果\"\"\"\n    score: float           # 0-10 质量评分\n    feedback: str          # 改进建议\n    strengths: List[str]   # 优点列表\n    weaknesses: List[str]  # 不足列表\n    revision_needed: bool  # 是否需要修改\n\n\nclass ReflectionAgent:\n    \"\"\"\n    Reflection Agent\n    \n    通过\"生成-评估-改进\"循环提升输出质量。\n    支持多维度评估和自适应迭代控制。\n    \"\"\"\n    \n    EVALUATION_DIMENSIONS = [\"准确性\", \"完整性\", \"清晰度\", \"相关性\", \"可操作性\"]\n    \n    def __init__(self, llm_client, min_score: float = 7.0,\n                 max_reflections: int = 3, verbose: bool = False):\n        self.llm = llm_client\n        self.min_score = min_score\n        self.max_reflections = max_reflections\n        self.verbose = verbose\n        self.reflection_history: List[dict] = []\n    \n    def generate(self, task: str, context: str = \"\") -> str:\n        \"\"\"生成初始输出\"\"\"\n        prompt = f\"\"\"请完成以下任务：{task}\n{f\"参考上下文: {context}\" if context else \"\"}\n要求：内容准确完整、结构清晰、语言简洁专业。\"\"\"\n        return self.llm.chat([\n            {\"role\": \"system\", \"content\": \"你是一个高质量内容生成助手。\"},\n            {\"role\": \"user\", \"content\": prompt}\n        ])\n    \n    def evaluate(self, task: str, output: str, context: str = \"\") -> ReflectionResult:\n        \"\"\"评估输出质量\"\"\"\n        prompt = f\"\"\"评估以下输出质量：\n任务: {task}\n{f\"上下文: {context}\" if context else \"\"}\n输出: {output}\n维度: {', '.join(self.EVALUATION_DIMENSIONS)}\n\n返回JSON: {{\"score\": 0-10, \"feedback\": \"改进建议\",\n\"strengths\": [\"优点\"], \"weaknesses\": [\"不足\"], \"revision_needed\": true/false}}\"\"\"\n        \n        response = self.llm.chat([\n            {\"role\": \"system\", \"content\": \"你是一个严格的质量评估专家。\"},\n            {\"role\": \"user\", \"content\": prompt}\n        ])\n        \n        try:\n            json_match = re.search(r'\\{.*\\}', response, re.DOTALL)\n            if json_match:\n                d = json.loads(json_match.group(0))\n                return ReflectionResult(\n                    score=float(d.get(\"score\", 5)),\n                    feedback=d.get(\"feedback\", \"\"),\n                    strengths=d.get(\"strengths\", []),\n                    weaknesses=d.get(\"weaknesses\", []),\n                    revision_needed=d.get(\"revision_needed\", False)\n                )\n        except (json.JSONDecodeError, ValueError):\n            pass\n        return ReflectionResult(5.0, \"评估失败\", [], [\"评估异常\"], False)\n    \n    def revise(self, task: str, output: str, feedback: ReflectionResult) -> str:\n        \"\"\"基于反馈修改输出\"\"\"\n        return self.llm.chat([\n            {\"role\": \"system\", \"content\": \"你善于根据反馈改进内容。\"},\n            {\"role\": \"user\", \"content\": f\"\"\"原始任务: {task}\n当前输出: {output}\n不足: {', '.join(feedback.weaknesses)}\n建议: {feedback.feedback}\n请修改输出以提升质量。\"\"\"}\n        ])\n    \n    def run(self, task: str, context: str = \"\") -> dict:\n        \"\"\"执行Reflection循环\"\"\"\n        output = self.generate(task, context)\n        \n        for i in range(self.max_reflections):\n            reflection = self.evaluate(task, output, context)\n            \n            if self.verbose:\n                print(f\"\\n🔄 反思轮次 {i+1}: 评分 {reflection.score}/10\")\n                print(f\"   不足: {', '.join(reflection.weaknesses[:2])}\")\n            \n            self.reflection_history.append({\n                \"round\": i+1, \"score\": reflection.score,\n                \"feedback\": reflection.feedback\n            })\n            \n            if reflection.score >= self.min_score or not reflection.revision_needed:\n                break\n            \n            output = self.revise(task, output, reflection)\n        \n        final = self.evaluate(task, output, context)\n        return {\n            \"output\": output,\n            \"final_score\": final.score,\n            \"reflections\": self.reflection_history,\n            \"total_rounds\": len(self.reflection_history)\n        }",
      "section_ref": "实现",
      "runnable": true,
      "dependencies": []
    },
    {
      "id": "code-7",
      "language": "text",
      "description": "Router的实现方式有多种：基于关键词匹配的规则路由、基于嵌入向量的语义路由、基于LLM的智能路由。在生产环境中，通常会组合使用多种方式，以提高准确性和鲁棒性。",
      "code": "┌─────────────────────────────────────────┐\n│              Router Agent                │\n│                                         │\n│  用户输入 ──▶ ┌──────────┐              │\n│              │ Intent   │              │\n│              │ Classifier│              │\n│              └────┬─────┘              │\n│                   │                     │\n│         ┌────────┼────────┐            │\n│         ▼        ▼        ▼            │\n│    ┌────────┐ ┌────────┐ ┌────────┐   │\n│    │Agent A │ │Agent B │ │Agent C │   │\n│    │(客服)   │ │(技术)  │ │(销售)  │   │\n│    └────────┘ └────────┘ └────────┘   │\n│                                         │\n│         ... 更多专业Agent ...            │\n└─────────────────────────────────────────┘",
      "section_ref": "结构",
      "runnable": false,
      "dependencies": []
    },
    {
      "id": "code-8",
      "language": "python",
      "description": "- 增加了系统的复杂度和延迟",
      "code": "\"\"\"\nRouter 模式 - 意图路由分发实现\n\"\"\"\nfrom typing import Callable, Optional, List, Dict, Any\nfrom dataclasses import dataclass\nfrom enum import Enum\nimport json\nimport re\n\n\nclass IntentCategory(Enum):\n    CUSTOMER_SERVICE = \"customer_service\"\n    TECHNICAL_SUPPORT = \"technical_support\"\n    SALES = \"sales\"\n    GENERAL_QA = \"general_qa\"\n    CREATIVE = \"creative\"\n\n\n@dataclass\nclass Route:\n    \"\"\"路由规则\"\"\"\n    intent: IntentCategory\n    description: str\n    handler: Callable\n    confidence_threshold: float = 0.6\n    examples: List[str] = None\n\n\nclass RouterAgent:\n    \"\"\"\n    Router Agent - 根据用户意图将请求路由到最合适的处理Agent。\n    \"\"\"\n    \n    def __init__(self, llm_client, routes: Optional[List[Route]] = None,\n                 default_handler: Optional[Callable] = None, verbose: bool = False):\n        self.llm = llm_client\n        self.routes: Dict[IntentCategory, Route] = {}\n        self.default_handler = default_handler or self._default_handler\n        self.verbose = verbose\n        self.routing_stats: Dict[str, int] = {}\n        \n        if routes:\n            for route in routes:\n                self.routes[route.intent] = route\n    \n    def register_route(self, route: Route) -> None:\n        \"\"\"注册新的路由规则\"\"\"\n        self.routes[route.intent] = route\n    \n    def classify_intent(self, user_input: str) -> tuple:\n        \"\"\"分类用户意图，返回 (intent_category, confidence)\"\"\"\n        route_desc = \"\\n\".join(\n            f\"- {r.intent.value}: {r.description}\\n  示例: {', '.join(r.examples[:3]) if r.examples else '无'}\"\n            for r in self.routes.values()\n        )\n        \n        prompt = f\"\"\"将以下用户输入分类到最合适的意图类别。\n用户输入: {user_input}\n可选类别:\n{route_desc}\n\n返回JSON: {{\"intent\": \"<类别>\", \"confidence\": 0.0-1.0, \"reasoning\": \"<理由>\"}}\"\"\"\n        \n        response = self.llm.chat([\n            {\"role\": \"system\", \"content\": \"你是一个精确的意图分类器。\"},\n            {\"role\": \"user\", \"content\": prompt}\n        ])\n        \n        try:\n            json_match = re.search(r'\\{.*\\}', response, re.DOTALL)\n            if json_match:\n                result = json.loads(json_match.group(0))\n                return IntentCategory(result[\"intent\"]), float(result.get(\"confidence\", 0.5))\n        except (json.JSONDecodeError, ValueError, KeyError):\n            pass\n        return IntentCategory.GENERAL_QA, 0.3\n    \n    def route(self, user_input: str, context: dict = None) -> Any:\n        \"\"\"路由用户请求到对应Agent\"\"\"\n        intent, confidence = self.classify_intent(user_input)\n        self.routing_stats[intent.value] = self.routing_stats.get(intent.value, 0) + 1\n        \n        if self.verbose:\n            print(f\"🎯 意图: {intent.value} (置信度: {confidence:.2f})\")\n        \n        route = self.routes.get(intent)\n        if route and confidence >= route.confidence_threshold:\n            return route.handler(user_input, context)\n        return self.default_handler(user_input, context)\n    \n    def _default_handler(self, user_input: str, context: dict = None) -> str:\n        \"\"\"默认处理器\"\"\"\n        return self.llm.chat([\n            {\"role\": \"system\", \"content\": \"你是一个通用助手。\"},\n            {\"role\": \"user\", \"content\": user_input}\n        ])",
      "section_ref": "实现",
      "runnable": true,
      "dependencies": []
    },
    {
      "id": "code-9",
      "language": "text",
      "description": "- 业务策略：确保Agent行为符合业务规则（如不能直接执行删除操作）",
      "code": "┌──────────────────────────────────────────┐\n│            Guardrails Agent              │\n│                                          │\n│  Input ──▶ ┌──────────────┐             │\n│            │  Input Guard  │             │\n│            │ (输入校验)     │             │\n│            └──────┬───────┘             │\n│                   │ ✅                    │\n│                   ▼                      │\n│            ┌──────────────┐             │\n│            │    Agent     │             │\n│            │  (核心处理)   │             │\n│            └──────┬───────┘             │\n│                   │                      │\n│                   ▼                      │\n│            ┌──────────────┐             │\n│            │ Output Guard │             │\n│            │ (输出校验)    │             │\n│            └──────┬───────┘             │\n│                   │ ✅                    │\n│                   ▼                      │\n│              Output                     │\n│                                          │\n│  Guard Types:                            │\n│  ├── Topic Guard (话题约束)              │\n│  ├── PII Guard (隐私保护)                │\n│  ├── Toxicity Guard (毒性检测)           │\n│  ├── Format Guard (格式约束)             │\n│  └── Policy Guard (策略约束)             │\n└──────────────────────────────────────────┘",
      "section_ref": "结构",
      "runnable": false,
      "dependencies": []
    },
    {
      "id": "code-10",
      "language": "python",
      "description": "- 增加了系统的延迟（每个Guard都需要计算时间）",
      "code": "\"\"\"\nGuardrails 模式 - 输入输出安全约束实现\n\"\"\"\nfrom typing import List, Optional, Callable, Any\nfrom enum import Enum\nimport re\nimport json\n\n\nclass GuardAction(Enum):\n    ALLOW = \"allow\"\n    DENY = \"deny\"\n    MODIFY = \"modify\"\n    ESCALATE = \"escalate\"\n\n\nclass GuardResult:\n    \"\"\"Guard检查结果\"\"\"\n    def __init__(self, passed: bool, action: GuardAction, \n                 reason: str, guard_name: str = \"\",\n                 modified_content: Optional[str] = None):\n        self.passed = passed\n        self.action = action\n        self.reason = reason\n        self.guard_name = guard_name\n        self.modified_content = modified_content\n\n\nclass TopicGuard:\n    \"\"\"话题约束Guard\"\"\"\n    def __init__(self, blocked_topics: List[str]):\n        self.name = \"TopicGuard\"\n        self.action = GuardAction.DENY\n        self.blocked_topics = blocked_topics\n    \n    def check(self, content: str) -> GuardResult:\n        for topic in self.blocked_topics:\n            if topic in content:\n                return GuardResult(False, self.action,\n                    f\"内容涉及被屏蔽的话题: {topic}\", self.name)\n        return GuardResult(True, GuardAction.ALLOW, \"话题检查通过\", self.name)\n\n\nclass PIIGuard:\n    \"\"\"隐私信息保护Guard - 检测并脱敏\"\"\"\n    PII_PATTERNS = {\n        \"手机号\": r\"1[3-9]\\d{9}\",\n        \"身份证号\": r\"\\d{17}[\\dXx]\",\n        \"银行卡号\": r\"\\d{16,19}\",\n        \"邮箱\": r\"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}\",\n    }\n    \n    def __init__(self, action: GuardAction = GuardAction.MODIFY):\n        self.name = \"PIIGuard\"\n        self.action = action\n    \n    def check(self, content: str) -> GuardResult:\n        detected = []\n        for pii_type, pattern in self.PII_PATTERNS.items():\n            if re.search(pattern, content):\n                detected.append(pii_type)\n        if detected:\n            return GuardResult(False, self.action,\n                f\"检测到隐私信息: {', '.join(detected)}\", self.name)\n        return GuardResult(True, GuardAction.ALLOW, \"隐私检查通过\", self.name)\n    \n    def fix(self, content: str) -> str:\n        content = re.sub(r\"1[3-9]\\d{4}\\d{4}\",\n            lambda m: m.group()[:3] + \"****\" + m.group()[7:], content)\n        content = re.sub(r\"(\\d{6})\\d{11}(\\d{4})\",\n            lambda m: m.group(1) + \"***********\" + m.group(2), content)\n        return content\n\n\nclass FormatGuard:\n    \"\"\"输出格式约束Guard\"\"\"\n    def __init__(self, expected_format: str = \"text\", max_length: int = 5000):\n        self.name = \"FormatGuard\"\n        self.action = GuardAction.MODIFY\n        self.expected_format = expected_format\n        self.max_length = max_length\n    \n    def check(self, content: str) -> GuardResult:\n        issues = []\n        if len(content) > self.max_length:\n            issues.append(f\"长度({len(content)})超过限制({self.max_length})\")\n        if self.expected_format == \"json\":\n            try:\n                json.loads(content)\n            except json.JSONDecodeError:\n                issues.append(\"不是有效的JSON格式\")\n        if issues:\n            return GuardResult(False, self.action, \"; \".join(issues), self.name)\n        return GuardResult(True, GuardAction.ALLOW, \"格式检查通过\", self.name)\n    \n    def fix(self, content: str) -> str:\n        return content[:self.max_length]\n\n\nclass GuardedAgent:\n    \"\"\"被Guardrails保护的Agent\"\"\"\n    \n    def __init__(self, agent_core: Callable,\n                 input_guards: Optional[List] = None,\n                 output_guards: Optional[List] = None,\n                 max_retries: int = 2, verbose: bool = False):\n        self.core = agent_core\n        self.input_guards = input_guards or []\n        self.output_guards = output_guards or []\n        self.max_retries = max_retries\n        self.verbose = verbose\n    \n    def _run_guards(self, guards: list, content: str, direction: str) -> tuple:\n        \"\"\"执行Guard检查链，返回 (passed, content, results)\"\"\"\n        current = content\n        results = []\n        all_passed = True\n        \n        for guard in guards:\n            result = guard.check(current)\n            results.append(result)\n            if self.verbose:\n                status = \"✅\" if result.passed else \"❌\"\n                print(f\"  [{direction}] {status} {guard.name}: {result.reason}\")\n            \n            if not result.passed:\n                if result.action == GuardAction.DENY:\n                    return False, current, results\n                elif result.action == GuardAction.MODIFY:\n                    current = guard.fix(current)\n                    all_passed = False\n        return all_passed, current, results\n    \n    def run(self, user_input: str) -> str:\n        \"\"\"执行被Guard保护的处理流程\"\"\"\n        if self.verbose:\n            print(\"🔍 输入Guard检查:\")\n        passed, safe_input, _ = self._run_guards(self.input_guards, user_input, \"INPUT\")\n        if not passed:\n            return \"抱歉，您的请求未通过安全检查。\"\n        \n        if self.verbose:\n            print(\"\\n🤖 Agent核心处理...\")\n        output = self.core(safe_input)\n        \n        for retry in range(self.max_retries + 1):\n            if self.verbose:\n                print(f\"\\n🔍 输出Guard检查 (尝试 {retry+1}):\")\n            passed, safe_output, _ = self._run_guards(self.output_guards, output, \"OUTPUT\")\n            if passed:\n                return safe_output\n            if retry < self.max_retries:\n                output = self.core(f\"{safe_input}\\n\\n注意: 上次输出未通过安全检查，请生成合规内容。\")\n        \n        return \"抱歉，生成的内容未通过安全检查。请联系人工客服。\"",
      "section_ref": "实现",
      "runnable": true,
      "dependencies": []
    },
    {
      "id": "code-11",
      "language": "text",
      "description": "5. 模型迭代：新模型发布时只需添加新的Adapter，无需修改业务逻辑",
      "code": "┌──────────────────────────────────────────┐\n│              Adapter Agent                │\n│                                          │\n│  ┌────────────────────────────┐          │\n│  │     Agent Core Logic       │          │\n│  │  (不依赖具体模型)           │          │\n│  └────────────┬───────────────┘          │\n│               │                          │\n│               ▼                          │\n│  ┌────────────────────────────┐          │\n│  │   LLM Adapter Interface    │          │\n│  │   chat(messages) -> str    │          │\n│  │   embed(text) -> list      │          │\n│  │   count_tokens(text) -> int│          │\n│  └────────────┬───────────────┘          │\n│               │                          │\n│    ┌──────────┼──────────┐              │\n│    ▼          ▼          ▼              │\n│ ┌──────┐  ┌──────┐  ┌──────┐           │\n│ │OpenAI│  │Claude│  │Llama │           │\n│ │Adapter│ │Adapter│ │Adapter│           │\n│ └──────┘  └──────┘  └──────┘           │\n└──────────────────────────────────────────┘",
      "section_ref": "结构",
      "runnable": false,
      "dependencies": []
    },
    {
      "id": "code-12",
      "language": "python",
      "description": "- 统一接口可能成为\"最小公约数\"，限制了对特定模型优势的利用",
      "code": "\"\"\"\nAdapter 模式 - 模型适配器实现\n\"\"\"\nfrom typing import List, Dict, Optional, Any\nfrom dataclasses import dataclass\nfrom abc import ABC, abstractmethod\nfrom enum import Enum\nimport time\n\n\nclass MessageRole(Enum):\n    SYSTEM = \"system\"\n    USER = \"user\"\n    ASSISTANT = \"assistant\"\n\n\n@dataclass\nclass Message:\n    role: MessageRole\n    content: str\n    name: Optional[str] = None\n\n\n@dataclass\nclass LLMResponse:\n    content: str\n    model: str\n    usage: Dict[str, int]\n    finish_reason: str = \"stop\"\n    latency_ms: float = 0.0\n\n\nclass LLMAdapter(ABC):\n    \"\"\"LLM适配器接口 - 所有模型适配器都必须实现此接口\"\"\"\n    \n    def __init__(self, model_name: str, api_key: str = \"\", **kwargs):\n        self.model_name = model_name\n        self.api_key = api_key\n        self.config = kwargs\n    \n    @abstractmethod\n    def chat(self, messages: List[Message], temperature: float = 0.7,\n             max_tokens: int = 4096, **kwargs) -> LLMResponse:\n        \"\"\"发送聊天请求\"\"\"\n        pass\n    \n    @abstractmethod\n    def count_tokens(self, text: str) -> int:\n        \"\"\"计算Token数量\"\"\"\n        pass\n    \n    @property\n    @abstractmethod\n    def max_context_length(self) -> int:\n        \"\"\"最大上下文长度\"\"\"\n        pass\n\n\nclass OpenAIAdapter(LLMAdapter):\n    \"\"\"OpenAI GPT系列适配器\"\"\"\n    \n    MODEL_CONTEXT_LENGTHS = {\n        \"gpt-4o\": 128000, \"gpt-4o-mini\": 128000,\n        \"gpt-4-turbo\": 128000, \"gpt-3.5-turbo\": 16385,\n    }\n    \n    def __init__(self, model_name: str = \"gpt-4o\", api_key: str = \"\", **kwargs):\n        super().__init__(model_name, api_key, **kwargs)\n    \n    @property\n    def max_context_length(self) -> int:\n        return self.MODEL_CONTEXT_LENGTHS.get(self.model_name, 128000)\n    \n    def chat(self, messages: List[Message], temperature: float = 0.7,\n             max_tokens: int = 4096, **kwargs) -> LLMResponse:\n        start = time.time()\n        openai_msgs = [{\"role\": m.role.value, \"content\": m.content} for m in messages]\n        \n        try:\n            import openai\n            client = openai.OpenAI(api_key=self.api_key)\n            resp = client.chat.completions.create(\n                model=self.model_name, messages=openai_msgs,\n                temperature=temperature, max_tokens=max_tokens, **kwargs\n            )\n            return LLMResponse(\n                content=resp.choices[0].message.content,\n                model=resp.model,\n                usage={\"prompt_tokens\": resp.usage.prompt_tokens,\n                       \"completion_tokens\": resp.usage.completion_tokens,\n                       \"total_tokens\": resp.usage.total_tokens},\n                latency_ms=(time.time() - start) * 1000\n            )\n        except Exception as e:\n            return LLMResponse(f\"[OpenAI Error: {e}]\", self.model_name,\n                             {}, latency_ms=(time.time() - start) * 1000)\n    \n    def count_tokens(self, text: str) -> int:\n        try:\n            import tiktoken\n            enc = tiktoken.encoding_for_model(self.model_name)\n            return len(enc.encode(text))\n        except ImportError:\n            return int(len(text) * 0.4)\n\n\nclass AnthropicAdapter(LLMAdapter):\n    \"\"\"Anthropic Claude系列适配器\"\"\"\n    \n    MODEL_CONTEXT_LENGTHS = {\n        \"claude-3-5-sonnet-20241022\": 200000,\n        \"claude-3-opus-20240229\": 200000,\n        \"claude-3-haiku-20240307\": 200000,\n    }\n    \n    @property\n    def max_context_length(self) -> int:\n        return self.MODEL_CONTEXT_LENGTHS.get(self.model_name, 200000)\n    \n    def chat(self, messages: List[Message], temperature: float = 0.7,\n             max_tokens: int = 4096, **kwargs) -> LLMResponse:\n        start = time.time()\n        system_msg = \"\"\n        claude_msgs = []\n        \n        for m in messages:\n            if m.role == MessageRole.SYSTEM:\n                system_msg = m.content\n            else:\n                claude_msgs.append({\"role\": m.role.value, \"content\": m.content})\n        \n        try:\n            import anthropic\n            client = anthropic.Anthropic(api_key=self.api_key)\n            kwargs_params = {}\n            if system_msg:\n                kwargs_params[\"system\"] = system_msg\n            resp = client.messages.create(\n                model=self.model_name, messages=claude_msgs,\n                max_tokens=max_tokens, temperature=temperature, **kwargs_params\n            )\n            return LLMResponse(\n                content=resp.content[0].text, model=resp.model,\n                usage={\"prompt_tokens\": resp.usage.input_tokens,\n                       \"completion_tokens\": resp.usage.output_tokens,\n                       \"total_tokens\": resp.usage.input_tokens + resp.usage.output_tokens},\n                latency_ms=(time.time() - start) * 1000\n            )\n        except Exception as e:\n            return LLMResponse(f\"[Claude Error: {e}]\", self.model_name,\n                             {}, latency_ms=(time.time() - start) * 1000)\n    \n    def count_tokens(self, text: str) -> int:\n        # Claude的tokenizer约为3.5字符/token\n        return int(len(text) / 3.5)\n\n\nclass ModelRegistry:\n    \"\"\"模型注册中心 - 管理和选择模型适配器\"\"\"\n    \n    def __init__(self):\n        self._adapters: Dict[str, LLMAdapter] = {}\n        self._fallback_chain: List[str] = []\n    \n    def register(self, name: str, adapter: LLMAdapter, is_primary: bool = False) -> None:\n        self._adapters[name] = adapter\n        if is_primary:\n            self._fallback_chain.insert(0, name)\n        else:\n            self._fallback_chain.append(name)\n    \n    def get(self, name: str = None) -> LLMAdapter:\n        \"\"\"获取适配器，支持降级链\"\"\"\n        if name and name in self._adapters:\n            return self._adapters[name]\n        for fallback_name in self._fallback_chain:\n            if fallback_name in self._adapters:\n                return self._adapters[fallback_name]\n        raise ValueError(\"没有可用的模型适配器\")\n\n\n# 使用示例\nregistry = ModelRegistry()\nregistry.register(\"gpt-4o\", OpenAIAdapter(\"gpt-4o\", api_key=\"sk-xxx\"), is_primary=True)\nregistry.register(\"claude\", AnthropicAdapter(\"claude-3-5-sonnet-20241022\", api_key=\"sk-xxx\"))\n\n# Agent核心逻辑只依赖统一接口\nadapter = registry.get()\nmessages = [Message(role=MessageRole.USER, content=\"你好\")]\nresponse = adapter.chat(messages)\nprint(f\"模型: {response.model}, 延迟: {response.latency_ms:.0f}ms\")",
      "section_ref": "实现",
      "runnable": true,
      "dependencies": []
    }
  ],
  "tables": [],
  "key_takeaways": [],
  "common_pitfalls": [],
  "related_chapters": [
    "ch04",
    "ch35"
  ]
}