第27章 Agent Prompt 工程 —— 工具描述也是 Prompt

📖 AI Agent 全栈学习课程 · 可运行讲义

1. 掌握 Agent System Prompt 的结构化设计模板2. 理解「工具描述 = Prompt 工程」的核心理念3. 学会 Few-shot 在 Agent 工具调用中的应用4. 掌握 Chain-of-Thought 在 Agent 规划中的使用🎤 「Agent 的 System Prompt 和普通 LLM 的有什么不同?」🎤 「工具描述写得好不好对 Agent 表现有多大影响?」🎤 「Few-shot 在 Function Calling 中怎么用?」

第27章:Agent Prompt 工程 —— 工具描述也是 Prompt

===================================================

 

 

 

综合 Anthropic Prompt Engineering Guide + 业界实践

 

 

27.1 Agent Prompt 和普通 Prompt 的区别

 

普通 LLM Prompt:

只需要告诉模型「输出什么」

 

Agent Prompt:

需要告诉模型:

  • 你是谁(角色)
  • 2. 你能做什么(工具列表)
    3. 什么时候该做什么(工具选择逻辑)
    4. 什么不该做(边界/安全约束)
    5. 输出格式是什么

     

    类比:

    普通 Prompt = 给厨师一个菜名

    Agent Prompt = 给厨师菜谱 + 厨房设备清单 + 工作流程

     

     

    27.2 Agent System Prompt 模板(面试送分题!)

     

    标准化模板(基于 Anthropic 2025 推荐):

     

    
      你是一个 [角色描述]。
    
    
      你可以使用的工具:[工具列表]
    
    
      每个工具的使用场景和注意事项...
    
    
      解决问题时应该遵循的工作流程...
    
    
      你不能做的事情...
    
    
      输出格式要求...
    

    📝 对应的代码实现
    💻 代码 (64 行)
    add_capabilitiesadd_tool_guidanceadd_workflowadd_constraintsadd_output_formatbuildestimate_tokensAgentPromptBuilder
    import json
    import time
    from typing import Optional
    from dataclasses import dataclass
    
    
    class AgentPromptBuilder:
        """Agent Prompt 构建器 —— 按模块组装,而非手写字符串。"""
    
        def __init__(self, role: str = "AI 助手"):
            self.role = role
            self.sections = {}
    
        def add_capabilities(self, tools: list[dict]):
            """添加工具能力声明。"""
            tool_lines = []
            for t in tools:
                tool_lines.append(f"- {t['name']}: {t.get('description', '')}")
            self.sections["capabilities"] = "\n".join(tool_lines)
    
        def add_tool_guidance(self, guidance: dict[str, str]):
            """添加工具选择指引(什么时候用哪个工具)。"""
            lines = []
            for tool_name, guide in guidance.items():
                lines.append(f"### {tool_name}\n{guide}")
            self.sections["tool_guidance"] = "\n\n".join(lines)
    
        def add_workflow(self, steps: list[str]):
            """添加工作流程。"""
            self.sections["workflow"] = "\n".join(
                f"{i+1}. {step}" for i, step in enumerate(steps)
            )
    
        def add_constraints(self, constraints: list[str]):
            """添加安全约束。"""
            self.sections["constraints"] = "\n".join(
                f"- {c}" for c in constraints
            )
    
        def add_output_format(self, fmt_desc: str):
            """添加输出格式。"""
            self.sections["output_format"] = fmt_desc
    
        def build(self) -> str:
            """构建完整的 Agent System Prompt。"""
            parts = ["<system>"]
            parts.append(f"  <role>{self.role}</role>")
    
            for key in ["capabilities", "tool_guidance", "workflow",
                         "constraints", "output_format"]:
                if key in self.sections:
                    tag = key.replace("_", "-")  # tool_guidance → tool-guidance
                    if tag == "capabilities":
                        tag = "capabilities"
                    parts.append(f"  <{tag}>")
                    parts.append(self.sections[key])
                    parts.append(f"  </{tag}>")
    
            parts.append("</system>")
            return "\n".join(parts)
    
        def estimate_tokens(self) -> int:
            """估算 Prompt 的 token 数。"""
            return len(self.build()) // 4

    27.3 工具描述 = Prompt 工程 —— 本章核心!

     

    工具描述不是给开发者看的文档,是给 LLM 看的「使用说明」。

     

    好工具描述的三个要素:

  • 做什么:准确描述工具的功能
  • 什么时候用:描述适用的场景
  • 什么时候不用:描述边界条件
  •  

    对比(面试金句!):

     

    ✗ 差: "查询天气"

    ✅ 好: "查询指定城市当天的实时天气,包括气温、湿度、风力。

          适用于用户询问天气相关问题时。不支持未来天气预报。
          示例调用:get_weather(city='北京')"

     

    工具描述评分卡:

    描述要素加分
    有功能描述+1
    有使用场景+2
    有边界条件+2
    有调用示例+1
    参数有 enum 限制+2
    参数有详细描述+1
    📝 对应的代码实现
    💻 代码 (113 行)
    score_tool_descriptionToolDescriptionOptimizer
    import json
    import time
    from typing import Optional
    from dataclasses import dataclass
    
    class ToolDescriptionOptimizer:
        """工具描述优化器 —— 系统化提升工具调用准确率。"""
    
        BAD_EXAMPLES = [
            {
                "name": "do_stuff",
                "description": "处理数据",
                "parameters": {
                    "type": "object",
                    "properties": {"data": {"type": "string"}},
                },
            },
            {
                "name": "search",
                "description": "搜索",
                "parameters": {
                    "type": "object",
                    "properties": {"q": {"type": "string"}},
                },
            },
        ]
    
        GOOD_EXAMPLES = [
            {
                "name": "send_email",
                "description": (
                    "向指定邮箱发送邮件。适用于发送通知、报告、提醒等场景。"
                    "不支持发送带附件的邮件。收件人地址必须包含 @。"
                    "示例:send_email(to='user@example.com', subject='日报', body='...')"
                ),
                "parameters": {
                    "type": "object",
                    "properties": {
                        "to": {
                            "type": "string",
                            "description": "收件人邮箱,如 user@example.com",
                        },
                        "subject": {
                            "type": "string",
                            "description": "邮件主题,不超过 100 字",
                        },
                        "body": {
                            "type": "string",
                            "description": "邮件正文,纯文本格式",
                        },
                    },
                    "required": ["to", "subject", "body"],
                },
            },
            {
                "name": "get_stock_price",
                "description": (
                    "查询股票实时价格。适用于查询个股当前报价。"
                    "不支持历史价格查询和批量查询。"
                    "示例:get_stock_price(symbol='AAPL') 返回 '185.50 USD'"
                ),
                "parameters": {
                    "type": "object",
                    "properties": {
                        "symbol": {
                            "type": "string",
                            "description": "股票代码,如 AAPL、TSLA、BABA",
                            "enum": ["AAPL", "TSLA", "GOOGL", "MSFT", "BABA"],
                        },
                    },
                    "required": ["symbol"],
                },
            },
        ]
    
        class="d">@classmethod
        def score_tool_description(cls, tool: dict) -> dict:
            """评估工具描述的质量。
    
            Returns:
                评分详情。
            """
            desc = tool.get("description", "")
            params = tool.get("parameters", {}).get("properties", {})
            scores = {
                "has_description": len(desc) > 10,
                "has_use_case": any(w in desc for w in ["适用于", "用于", "当你", "when"]),
                "has_boundary": any(w in desc for w in ["不支持", "不支持", "不适用于"]),
                "has_example": any(w in desc for w in ["示例", "example", "e.g."]),
                "has_enum": any("enum" in p for p in params.values()),
                "has_param_desc": all(
                    "description" in p for p in params.values()
                ) if params else False,
            }
    
            return {
                "tool_name": tool.get("name", "unknown"),
                "scores": scores,
                "total": sum(scores.values()),
                "max": len(scores),
                "grade": cls._grade(sum(scores.values()), len(scores)),
            }
    
        class="d">@classmethod
        def _grade(cls, score: int, total: int) -> str:
            pct = score / total
            if pct >= 0.8:
                return "A (生产级)"
            if pct >= 0.5:
                return "B (可用)"
            if pct >= 0.3:
                return "C (需改进)"
            return "D (不可用)"

    27.4 对话模板优化 —— 平衡信息密度

     

    Prompt 不是越长越好,需要权衡:

     

    太短 → 信息不足,LLM 靠猜测

    太长 → 信息过载,LLM 抓不住重点

     

    Golden Zone:

    System Prompt: 200-800 tokens

    工具描述: 每个工具 50-200 tokens

    总上下文: 不超过窗口的 70%(留空间给对话历史和生成)

     

    面试金句:

    "好 Prompt 的标准不是'全',是'精'。

    每条信息都要有明确的 token 价值 vs 成本评估。"

     

     

    27.5 本章总结

     

    核心要点回顾:

     

  • Agent Prompt 需要结构化 6 个模块
  • 工具描述是 Agent Prompt 工程的核心
  • 好工具描述 = 做什么 + 什么时候用 + 什么时候不用 + 示例
  •  

    面试速记:

    「Agent 的 System Prompt 怎么设计?」

    → 6 模块模板:role/capabilities/tool_guidance/workflow/constraints/output

    → 核心:工具描述 = Prompt 工程(告诉 LLM 何时用、何时不用)

    → 用 enum 限制参数 → 减少幻觉

    📝 对应的代码实现
    💻 代码 (75 行)
    demo_prompt_engineering
    import json
    import time
    from typing import Optional
    from dataclasses import dataclass
    
    def demo_prompt_engineering():
        """演示 Agent Prompt 工程。"""
        print("=" * 60)
        print("  Agent Prompt 构建演示")
        print("=" * 60)
    
        # 构建一个完整的 Agent Prompt
        builder = AgentPromptBuilder("专业的客服 Agent")
    
        tools = [
            {"name": "search_knowledge_base",
             "description": "在知识库中搜索产品信息,适用于产品规格/使用说明查询"},
            {"name": "check_order_status",
             "description": "查询订单状态,适用于用户询问发货/物流信息"},
            {"name": "create_ticket",
             "description": "创建工单,适用于需要人工处理的复杂问题"},
        ]
        builder.add_capabilities(tools)
        builder.add_tool_guidance({
            "search_knowledge_base": "用户问产品相关问题时使用。转换口语为关键词。",
            "check_order_status": "用户提供订单号时使用。需要先验证订单号格式。",
            "create_ticket": "知识库和订单查询都无法解决时使用。简要描述问题。",
        })
        builder.add_workflow([
            "理解用户意图",
            "判断是否需要工具 → search_knowledge_base 或 check_order_status",
            "如果需要人工介入 → create_ticket",
            "用友好语气给出最终回答",
        ])
        builder.add_constraints([
            "不透露系统内部实现",
            "不执行退款/删除等危险操作",
            "对不确定的信息标注「据我所知」",
        ])
        builder.add_output_format("Markdown 格式,含要点列表")
    
        prompt = builder.build()
        print(prompt)
        print(f"\n  📏 估算 Token: {builder.estimate_tokens()}")
    
        # 工具描述评分
        print(f"\n{'='*60}")
        print(f"  工具描述质量评估")
        print(f"{'='*60}")
        for tool in ToolDescriptionOptimizer.BAD_EXAMPLES:
            result = ToolDescriptionOptimizer.score_tool_description(tool)
            print(f"  {result['tool_name']}: {result['total']}/{result['max']} = {result['grade']}")
    
        for tool in ToolDescriptionOptimizer.GOOD_EXAMPLES:
            result = ToolDescriptionOptimizer.score_tool_description(tool)
            print(f"  {result['tool_name']}: {result['total']}/{result['max']} = {result['grade']}")
    
    
    if __name__ == "__main__":
        print("╔══════════════════════════════════════════════════════╗")
        print("║  第27章:Agent Prompt 工程                              ║")
        print("║  System Prompt 模板 · 工具描述 · Few-shot             ║")
        print("╚══════════════════════════════════════════════════════╝")
        demo_prompt_engineering()
        print("\n▶ 工具描述 Checklist")
        for item in [
            "✅ 有功能描述",
            "✅ 有使用场景(什么时候用)",
            "✅ 有边界条件(什么时候不用)",
            "✅ 有调用示例",
            "✅ 参数有 enum 限制",
            "✅ 参数有详细描述",
        ]:
            print(f"  {item}")
        print("\n✅ 第27章完成!")

    📦 完整源代码 (381 行)
    """
    第27章:Agent Prompt 工程 —— 工具描述也是 Prompt
    ===================================================
    
    📌 本章目标:
      1. 掌握 Agent System Prompt 的结构化设计模板
      2. 理解「工具描述 = Prompt 工程」的核心理念
      3. 学会 Few-shot 在 Agent 工具调用中的应用
      4. 掌握 Chain-of-Thought 在 Agent 规划中的使用
    
    📌 面试高频点:
      - 「Agent 的 System Prompt 和普通 LLM 的有什么不同?」
      - 「工具描述写得好不好对 Agent 表现有多大影响?」
      - 「Few-shot 在 Function Calling 中怎么用?」
    
    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    综合 Anthropic Prompt Engineering Guide + 业界实践
    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    
    
    27.1 Agent Prompt 和普通 Prompt 的区别
    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    
    普通 LLM Prompt:
      只需要告诉模型「输出什么」
    
    Agent Prompt:
      需要告诉模型:
        1. 你是谁(角色)
        2. 你能做什么(工具列表)
        3. 什么时候该做什么(工具选择逻辑)
        4. 什么不该做(边界/安全约束)
        5. 输出格式是什么
    
    类比:
      普通 Prompt = 给厨师一个菜名
      Agent Prompt = 给厨师菜谱 + 厨房设备清单 + 工作流程
    
    
    27.2 Agent System Prompt 模板(面试送分题!)
    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    
    标准化模板(基于 Anthropic 2025 推荐):
    
      <system>
        <role>
          你是一个 [角色描述]。
        </role>
        <capabilities>
          你可以使用的工具:[工具列表]
        </capabilities>
        <tool_guidance>
          每个工具的使用场景和注意事项...
        </tool_guidance>
        <workflow>
          解决问题时应该遵循的工作流程...
        </workflow>
        <constraints>
          你不能做的事情...
        </constraints>
        <output_format>
          输出格式要求...
        </output_format>
      </system>
    """
    
    import json
    import time
    from typing import Optional
    from dataclasses import dataclass
    
    
    class AgentPromptBuilder:
        """Agent Prompt 构建器 —— 按模块组装,而非手写字符串。"""
    
        def __init__(self, role: str = "AI 助手"):
            self.role = role
            self.sections = {}
    
        def add_capabilities(self, tools: list[dict]):
            """添加工具能力声明。"""
            tool_lines = []
            for t in tools:
                tool_lines.append(f"- {t['name']}: {t.get('description', '')}")
            self.sections["capabilities"] = "\n".join(tool_lines)
    
        def add_tool_guidance(self, guidance: dict[str, str]):
            """添加工具选择指引(什么时候用哪个工具)。"""
            lines = []
            for tool_name, guide in guidance.items():
                lines.append(f"### {tool_name}\n{guide}")
            self.sections["tool_guidance"] = "\n\n".join(lines)
    
        def add_workflow(self, steps: list[str]):
            """添加工作流程。"""
            self.sections["workflow"] = "\n".join(
                f"{i+1}. {step}" for i, step in enumerate(steps)
            )
    
        def add_constraints(self, constraints: list[str]):
            """添加安全约束。"""
            self.sections["constraints"] = "\n".join(
                f"- {c}" for c in constraints
            )
    
        def add_output_format(self, fmt_desc: str):
            """添加输出格式。"""
            self.sections["output_format"] = fmt_desc
    
        def build(self) -> str:
            """构建完整的 Agent System Prompt。"""
            parts = ["<system>"]
            parts.append(f"  <role>{self.role}</role>")
    
            for key in ["capabilities", "tool_guidance", "workflow",
                         "constraints", "output_format"]:
                if key in self.sections:
                    tag = key.replace("_", "-")  # tool_guidance → tool-guidance
                    if tag == "capabilities":
                        tag = "capabilities"
                    parts.append(f"  <{tag}>")
                    parts.append(self.sections[key])
                    parts.append(f"  </{tag}>")
    
            parts.append("</system>")
            return "\n".join(parts)
    
        def estimate_tokens(self) -> int:
            """估算 Prompt 的 token 数。"""
            return len(self.build()) // 4
    
    
    """
    27.3 工具描述 = Prompt 工程 —— 本章核心!
    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    
    工具描述不是给开发者看的文档,是给 LLM 看的「使用说明」。
    
    好工具描述的三个要素:
      1. 做什么:准确描述工具的功能
      2. 什么时候用:描述适用的场景
      3. 什么时候不用:描述边界条件
    
    对比(面试金句!):
    
      ✗ 差: "查询天气"
      ✅ 好: "查询指定城市当天的实时天气,包括气温、湿度、风力。
              适用于用户询问天气相关问题时。不支持未来天气预报。
              示例调用:get_weather(city='北京')"
    
    工具描述评分卡:
      ┌────────────────────────┬──────────┐
      │ 描述要素                  │ 加分      │
      ├────────────────────────┼──────────┤
      │ 有功能描述                │ +1       │
      │ 有使用场景                │ +2       │
      │ 有边界条件                │ +2       │
      │ 有调用示例                │ +1       │
      │ 参数有 enum 限制          │ +2       │
      │ 参数有详细描述            │ +1       │
      └────────────────────────┴──────────┘
    """
    
    
    class ToolDescriptionOptimizer:
        """工具描述优化器 —— 系统化提升工具调用准确率。"""
    
        BAD_EXAMPLES = [
            {
                "name": "do_stuff",
                "description": "处理数据",
                "parameters": {
                    "type": "object",
                    "properties": {"data": {"type": "string"}},
                },
            },
            {
                "name": "search",
                "description": "搜索",
                "parameters": {
                    "type": "object",
                    "properties": {"q": {"type": "string"}},
                },
            },
        ]
    
        GOOD_EXAMPLES = [
            {
                "name": "send_email",
                "description": (
                    "向指定邮箱发送邮件。适用于发送通知、报告、提醒等场景。"
                    "不支持发送带附件的邮件。收件人地址必须包含 @。"
                    "示例:send_email(to='user@example.com', subject='日报', body='...')"
                ),
                "parameters": {
                    "type": "object",
                    "properties": {
                        "to": {
                            "type": "string",
                            "description": "收件人邮箱,如 user@example.com",
                        },
                        "subject": {
                            "type": "string",
                            "description": "邮件主题,不超过 100 字",
                        },
                        "body": {
                            "type": "string",
                            "description": "邮件正文,纯文本格式",
                        },
                    },
                    "required": ["to", "subject", "body"],
                },
            },
            {
                "name": "get_stock_price",
                "description": (
                    "查询股票实时价格。适用于查询个股当前报价。"
                    "不支持历史价格查询和批量查询。"
                    "示例:get_stock_price(symbol='AAPL') 返回 '185.50 USD'"
                ),
                "parameters": {
                    "type": "object",
                    "properties": {
                        "symbol": {
                            "type": "string",
                            "description": "股票代码,如 AAPL、TSLA、BABA",
                            "enum": ["AAPL", "TSLA", "GOOGL", "MSFT", "BABA"],
                        },
                    },
                    "required": ["symbol"],
                },
            },
        ]
    
        class="d">@classmethod
        def score_tool_description(cls, tool: dict) -> dict:
            """评估工具描述的质量。
    
            Returns:
                评分详情。
            """
            desc = tool.get("description", "")
            params = tool.get("parameters", {}).get("properties", {})
            scores = {
                "has_description": len(desc) > 10,
                "has_use_case": any(w in desc for w in ["适用于", "用于", "当你", "when"]),
                "has_boundary": any(w in desc for w in ["不支持", "不支持", "不适用于"]),
                "has_example": any(w in desc for w in ["示例", "example", "e.g."]),
                "has_enum": any("enum" in p for p in params.values()),
                "has_param_desc": all(
                    "description" in p for p in params.values()
                ) if params else False,
            }
    
            return {
                "tool_name": tool.get("name", "unknown"),
                "scores": scores,
                "total": sum(scores.values()),
                "max": len(scores),
                "grade": cls._grade(sum(scores.values()), len(scores)),
            }
    
        class="d">@classmethod
        def _grade(cls, score: int, total: int) -> str:
            pct = score / total
            if pct >= 0.8:
                return "A (生产级)"
            if pct >= 0.5:
                return "B (可用)"
            if pct >= 0.3:
                return "C (需改进)"
            return "D (不可用)"
    
    
    """
    27.4 对话模板优化 —— 平衡信息密度
    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    
    Prompt 不是越长越好,需要权衡:
    
      太短 → 信息不足,LLM 靠猜测
      太长 → 信息过载,LLM 抓不住重点
    
    Golden Zone:
      System Prompt: 200-800 tokens
      工具描述: 每个工具 50-200 tokens
      总上下文: 不超过窗口的 70%(留空间给对话历史和生成)
    
    面试金句:
      "好 Prompt 的标准不是'全',是'精'。
       每条信息都要有明确的 token 价值 vs 成本评估。"
    
    
    27.5 本章总结
    ━━━━━━━━━━━━
    
    核心要点回顾:
    
    1. Agent Prompt 需要结构化 6 个模块
    2. 工具描述是 Agent Prompt 工程的核心
    3. 好工具描述 = 做什么 + 什么时候用 + 什么时候不用 + 示例
    
    面试速记:
      「Agent 的 System Prompt 怎么设计?」
      → 6 模块模板:role/capabilities/tool_guidance/workflow/constraints/output
      → 核心:工具描述 = Prompt 工程(告诉 LLM 何时用、何时不用)
      → 用 enum 限制参数 → 减少幻觉
    """
    
    
    def demo_prompt_engineering():
        """演示 Agent Prompt 工程。"""
        print("=" * 60)
        print("  Agent Prompt 构建演示")
        print("=" * 60)
    
        # 构建一个完整的 Agent Prompt
        builder = AgentPromptBuilder("专业的客服 Agent")
    
        tools = [
            {"name": "search_knowledge_base",
             "description": "在知识库中搜索产品信息,适用于产品规格/使用说明查询"},
            {"name": "check_order_status",
             "description": "查询订单状态,适用于用户询问发货/物流信息"},
            {"name": "create_ticket",
             "description": "创建工单,适用于需要人工处理的复杂问题"},
        ]
        builder.add_capabilities(tools)
        builder.add_tool_guidance({
            "search_knowledge_base": "用户问产品相关问题时使用。转换口语为关键词。",
            "check_order_status": "用户提供订单号时使用。需要先验证订单号格式。",
            "create_ticket": "知识库和订单查询都无法解决时使用。简要描述问题。",
        })
        builder.add_workflow([
            "理解用户意图",
            "判断是否需要工具 → search_knowledge_base 或 check_order_status",
            "如果需要人工介入 → create_ticket",
            "用友好语气给出最终回答",
        ])
        builder.add_constraints([
            "不透露系统内部实现",
            "不执行退款/删除等危险操作",
            "对不确定的信息标注「据我所知」",
        ])
        builder.add_output_format("Markdown 格式,含要点列表")
    
        prompt = builder.build()
        print(prompt)
        print(f"\n  📏 估算 Token: {builder.estimate_tokens()}")
    
        # 工具描述评分
        print(f"\n{'='*60}")
        print(f"  工具描述质量评估")
        print(f"{'='*60}")
        for tool in ToolDescriptionOptimizer.BAD_EXAMPLES:
            result = ToolDescriptionOptimizer.score_tool_description(tool)
            print(f"  {result['tool_name']}: {result['total']}/{result['max']} = {result['grade']}")
    
        for tool in ToolDescriptionOptimizer.GOOD_EXAMPLES:
            result = ToolDescriptionOptimizer.score_tool_description(tool)
            print(f"  {result['tool_name']}: {result['total']}/{result['max']} = {result['grade']}")
    
    
    if __name__ == "__main__":
        print("╔══════════════════════════════════════════════════════╗")
        print("║  第27章:Agent Prompt 工程                              ║")
        print("║  System Prompt 模板 · 工具描述 · Few-shot             ║")
        print("╚══════════════════════════════════════════════════════╝")
        demo_prompt_engineering()
        print("\n▶ 工具描述 Checklist")
        for item in [
            "✅ 有功能描述",
            "✅ 有使用场景(什么时候用)",
            "✅ 有边界条件(什么时候不用)",
            "✅ 有调用示例",
            "✅ 参数有 enum 限制",
            "✅ 参数有详细描述",
        ]:
            print(f"  {item}")
        print("\n✅ 第27章完成!")