课程0基础Agent开发课 / Agent基础 / PEAS模型与Agent设计框架
— 17 min read

PEAS模型与Agent设计框架

*PEAS 模型——Performance(性能度量)、Environment(环境)、Actuators(执行器)、Sensors(传感器)*

PEAS 模型与 Agent 设计框架

1.1 为什么需要设计框架:凭直觉的代价

PEAS模型图
PEAS 模型——Performance(性能度量)、Environment(环境)、Actuators(执行器)、Sensors(传感器)

工程师在设计 Agent 时,最常见的路径是:想到什么功能加什么,遇到问题再修补。这种方式在简单场景下还凑合,但在稍复杂的真实场景里会导致系统性的设计缺陷。

凭直觉设计的典型问题

  • 加了很多工具,但没想清楚每个工具的边界,导致 Agent 在相似工具之间选择错误
  • 没有定义"什么叫成功",上线后不知道 Agent 表现好不好,优化方向模糊
  • 忽略了环境的动态性,用缓存数据回答了实时查询,给出过期信息
  • 传感器设计不完整,Agent 无法获取做决策所需的关键信息

这些问题不是因为工程师能力差,而是因为在没有系统化框架的情况下,很容易只关注"Agent 能做什么",而忽略"Agent 在什么环境下做"和"怎么衡量做得好不好"。

PEAS 框架的四个维度及其设计价值

PEAS 框架来自经典 AI 教材《Artificial Intelligence: A Modern Approach》(Russell & Norvig),是在开始编码之前,系统性分析 Agent 设计需求的工具。四个字母分别代表:

P(Performance,性能指标) 解决的问题:怎么衡量 Agent 好不好?这个问题比想象中难——"回答得好"是主观感受,不是可测量的指标。Performance 迫使设计者把模糊的"好"转化为可量化的数字,比如"用户问题解决率 > 80%"。这是后续优化的基础,没有明确的指标,优化就无从入手。

E(Environment,环境) 解决的问题:Agent 在什么条件下工作?环境的特性直接决定 Agent 需要什么能力。动态环境要求实时数据,不能用缓存;部分可观测的环境要求 Agent 能主动澄清歧义;多轮环境要求对话历史记忆。忽略环境分析,就会在错误的假设下设计系统。

A(Actuators,执行器) 解决的问题:Agent 能影响哪些东西?执行器就是工具。这个维度迫使设计者把"Agent 能做什么"完整列出,而不是随意添加——每个工具都应该对应 Environment 里的一个需求。多余的工具增加决策复杂度,缺少的工具会导致 Agent 无法完成任务。

S(Sensors,传感器) 解决的问题:Agent 能感知哪些信息?传感器就是输入。这个维度检验 Agent 是否有足够的信息做出正确决策。如果某个决策需要某类信息,但传感器里没有获取这类信息的渠道,Agent 就会在信息不足的情况下猜测,导致错误。


第 01 篇在文末提到了 PEAS 框架,用它简单分析了天气查询 Agent。本篇做完整展开:PEAS 是什么、怎么用、用它分析一个真实的复杂 Agent(电商客服)会发现哪些设计盲点。

在设计一个 AI Agent 之前,往往面临这样的问题:应该给它配哪些工具?记忆需要持久化吗?失败了怎么处理?这些决策如果凭直觉拍板,等上线之后很可能发现遗漏了关键能力,或者设计了一堆用不上的功能。

PEAS 框架提供了一套系统化的分析方法,在动手实现之前,先把 Agent 所处的环境和需要具备的能力理清楚。

1.2 PEAS 框架

PEAS 来自经典 AI 教材《Artificial Intelligence: A Modern Approach》(Russell & Norvig),是设计理性 Agent 的基础分析工具。四个字母分别代表:

Performance(性能指标):怎么衡量 Agent 表现得好不好?这个问题比想象中难回答。性能指标必须是可测量的,不能停留在"回答得好"这种模糊描述。

Environment(环境):Agent 在什么环境下运行?环境的特性直接决定 Agent 需要什么能力。

Actuators(执行器):Agent 能做什么动作?执行器是 Agent 影响外部世界的手段,对应 AI Agent 中的"工具"概念。

Sensors(传感器):Agent 能感知什么信息?传感器是 Agent 获取外部信息的渠道,对应 AI Agent 中的"输入"概念。

1.3 用 PEAS 分析客服 Agent

以一个电商客服 Agent 为例,逐项填写 PEAS 分析表。

Performance(性能指标)

  • 问题解决率:用户问题在本次对话中被解决的比例(目标 > 80%)
  • 首次解决率(FCR):不需要人工介入就解决的比例
  • 平均对话轮次:解决问题平均需要几轮对话(越少越好)
  • 用户满意度评分:对话结束后的评分(1-5 分)
  • 误触发人工:Agent 不该转人工但转了的比例(越低越好)

Environment(环境)

  • 用户通过微信、APP、网页多渠道发起对话
  • 对话是多轮的,用户的问题可能跨越多条消息
  • 用户情绪多样,包含抱怨、催促、质疑等负面情绪
  • 订单状态实时变化,同一问题在不同时间答案可能不同
  • 有些问题没有标准答案(例如商品质量纠纷的处理)

Actuators(执行器/工具)

  • 查询订单状态 API
  • 查询物流信息 API
  • 发起退款/退货流程
  • 查询商品信息数据库
  • 发送优惠券
  • 转接人工客服
  • 记录工单

Sensors(传感器/输入)

  • 用户的文字消息
  • 用户的历史订单(通过用户 ID 关联)
  • 当前对话的完整历史
  • 知识库(FAQ、退换货政策、产品手册)
  • 用户账户信息(会员等级、历史投诉记录)

PEAS 分析:电商客服 Agent

Performance 性能指标
• 问题解决率 >80%
• 首次解决率
• 对话轮次 <5
• 满意度评分

Environment 环境特性
• 多渠道接入
• 多轮对话
• 实时数据变化
• 情绪多样

Actuators 执行器
• 查询订单/物流
• 发起退款
• 发送优惠券
• 转人工

Sensors 传感器
• 用户消息
• 订单历史
• 对话记录
• 知识库

Agent 决策核心
LLM + Prompt

1.4 环境类型的分类

理解环境特性是设计 Agent 的关键。不同类型的环境需要不同的设计策略。

维度 类型A 类型B 客服 Agent 是哪种
可观测性 完全可观测 部分可观测 部分可观测(不知道用户真实意图)
确定性 确定性 随机性 随机性(用户行为不可预测)
时间性 静态 动态 动态(订单状态实时变化)
连续性 离散 连续 离散(每条消息是独立事件)
主体数量 单 Agent 多 Agent 单 Agent(加人工客服则是多 Agent)

部分可观测性意味着 Agent 不能假设自己知道全部信息。客服 Agent 无法直接读取用户心理——用户说"这个不对",到底是商品有问题、物流延误、还是价格显示错误?需要通过提问来消除歧义。

随机性意味着 Agent 需要为意外情况准备回退策略。工具调用失败了怎么办?用户突然问了一个完全不相关的问题怎么处理?

动态环境意味着 Agent 不能缓存数据太久。查询订单状态时必须调用实时 API,不能用对话开头查到的状态一直用。

1.5 从 PEAS 到设计决策

PEAS 分析完成后,每个组成部分都应该对应具体的设计决策。

从 Performance 推导评估指标:性能指标要转化为可自动测量的数据。"问题解决率"可以用"用户是否在对话结束后给出正面反馈,或者没有再次发起同类问题"来衡量。

从 Environment 推导记忆设计

  • 动态环境 → 不能依赖缓存,关键数据必须实时获取
  • 多轮对话 → 需要对话历史作为短期记忆
  • 用户历史 → 需要用户级别的持久化记忆(历史订单、投诉记录)

从 Actuators 推导工具集:列出的每个工具都要问:这个工具是否有明确的成功/失败判断标准?失败时应该怎么处理?

从 Sensors 推导输入处理:传感器对应 Agent 的输入来源,每种输入来源都需要考虑:数据格式是什么?如何集成到上下文中?

1.6 从 PEAS 到代码

以下代码将 PEAS 分析结果直接转化为 Agent 实现框架。

验证目的:展示 PEAS 分析如何直接驱动代码设计——工具函数对应 Actuators,输入参数对应 Sensors,最大轮次保护对应 Performance,实时查询而非缓存对应 Environment 的动态性。

python
from openai import OpenAI
from typing import Optional
import json

client = OpenAI()


# ============================================================
# Actuators(执行器):工具函数
# 每个工具的设计对应 PEAS 分析中的一个执行动作
# ============================================================

def query_order(order_id: str, user_id: str) -> dict:
    """
    查询订单状态。
    设计说明:动态环境要求实时查询,不能缓存。
    返回结构化数据而非字符串,方便 Agent 提取关键字段。
    """
    # 实际项目中调用订单服务 API
    # 这里用模拟数据演示
    mock_orders = {
        "ORD-001": {
            "status": "已发货",
            "logistics": "顺丰 SF1234567890",
            "estimated_delivery": "2024-01-15",
            "amount": 299.00,
        }
    }
    if order_id in mock_orders:
        return {"success": True, "data": mock_orders[order_id]}
    return {"success": False, "error": f"订单 {order_id} 不存在或不属于该用户"}


def initiate_refund(order_id: str, reason: str, user_id: str) -> dict:
    """
    发起退款申请。
    设计说明:写操作必须校验权限(用户只能操作自己的订单),
    返回申请编号方便后续跟进。
    """
    # 实际场景需要校验订单归属、退款期限等业务规则
    refund_id = f"RF-{order_id}-001"
    return {
        "success": True,
        "refund_id": refund_id,
        "message": f"退款申请已提交,预计 3-5 个工作日到账。申请编号:{refund_id}",
    }


def search_knowledge_base(query: str) -> str:
    """
    搜索知识库。
    设计说明:对应 Sensors 中的知识库输入。
    知识库检索失败应该有 fallback,不能让 Agent 无从作答。
    """
    knowledge = {
        "退换货": "支持 7 天无理由退换货,商品需保持原包装。发起退换后 24 小时内上门取件。",
        "发票": "支持个人和企业抬头开票,订单完成后 15 天内可申请。",
        "运费": "订单满 99 元免运费,不满 99 元收取 6 元运费。",
    }
    for key, value in knowledge.items():
        if key in query:
            return value
    return "未找到相关信息,请联系人工客服获取帮助。"


def transfer_to_human(reason: str, user_id: str) -> dict:
    """
    转接人工客服。
    设计说明:必须记录转接原因,用于后续分析哪些场景 Agent 无法处理。
    这是 Agent 能力边界的重要数据来源。
    """
    return {
        "success": True,
        "queue_number": "A-0042",
        "wait_time": "约 3 分钟",
        "message": "正在为您转接人工客服,排队号:A-0042,预计等待 3 分钟。",
    }


# ============================================================
# PEAS 驱动的 Agent 设计
# ============================================================

class CustomerServiceAgent:
    """
    基于 PEAS 分析设计的客服 Agent。

    Environment: 多轮对话、动态数据、部分可观测
    → 维护对话历史(短期记忆)
    → 所有数据实时查询,不缓存

    Actuators: 查询/退款/知识库/转人工
    → 四个工具函数

    Sensors: 用户消息 + 用户 ID(关联历史数据)
    → 每次调用传入 user_id

    Performance: 问题解决率、对话轮次
    → 设置 max_turns 控制效率,到上限转人工
    """

    SYSTEM_PROMPT = """你是一个专业的电商客服助手。

你的职责:
1. 帮助用户查询订单、物流状态
2. 协助处理退款、退换货申请
3. 回答产品和政策相关问题
4. 遇到无法处理的问题,转接人工客服

处理原则:
- 每次回答前先确认用户的具体问题
- 查询数据时务必使用工具获取实时数据,不能凭记忆作答
- 退款等写操作前,先向用户确认
- 超过 2 次无法解决用户问题,主动提出转人工"""

    TOOLS = [
        {
            "type": "function",
            "function": {
                "name": "query_order",
                "description": "查询订单状态、物流信息和金额",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "order_id": {"type": "string", "description": "订单号,格式如 ORD-001"},
                        "user_id": {"type": "string", "description": "用户 ID"},
                    },
                    "required": ["order_id", "user_id"],
                },
            },
        },
        {
            "type": "function",
            "function": {
                "name": "initiate_refund",
                "description": "为用户发起退款申请",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "order_id": {"type": "string"},
                        "reason": {"type": "string", "description": "退款原因"},
                        "user_id": {"type": "string"},
                    },
                    "required": ["order_id", "reason", "user_id"],
                },
            },
        },
        {
            "type": "function",
            "function": {
                "name": "search_knowledge_base",
                "description": "搜索知识库,获取退换货政策、发票、运费等信息",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "query": {"type": "string", "description": "搜索关键词"},
                    },
                    "required": ["query"],
                },
            },
        },
        {
            "type": "function",
            "function": {
                "name": "transfer_to_human",
                "description": "将用户转接到人工客服,当问题超出处理能力时使用",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "reason": {"type": "string", "description": "转人工的原因"},
                        "user_id": {"type": "string"},
                    },
                    "required": ["reason", "user_id"],
                },
            },
        },
    ]

    def __init__(self, user_id: str, max_turns: int = 10):
        self.user_id = user_id
        self.max_turns = max_turns
        # 短期记忆:当前对话历史(对应 Sensors 中的"对话历史")
        self.messages = [{"role": "system", "content": self.SYSTEM_PROMPT}]
        self.turn_count = 0
        self.tool_map = {
            "query_order": query_order,
            "initiate_refund": initiate_refund,
            "search_knowledge_base": search_knowledge_base,
            "transfer_to_human": transfer_to_human,
        }

    def chat(self, user_message: str) -> str:
        """处理一条用户消息,返回 Agent 的最终回复。"""
        self.turn_count += 1
        self.messages.append({"role": "user", "content": user_message})

        # 保护机制:达到最大轮次,强制转人工
        if self.turn_count >= self.max_turns:
            return "本次对话已超过最大轮次,为您转接人工客服处理。"

        while True:
            response = client.chat.completions.create(
                model="gpt-4o",
                messages=self.messages,
                tools=self.TOOLS,
                tool_choice="auto",
                temperature=0,
            )
            msg = response.choices[0].message
            self.messages.append(msg)

            # 没有工具调用,直接返回文本回复
            if not msg.tool_calls:
                return msg.content

            # 执行工具调用
            for tool_call in msg.tool_calls:
                func_name = tool_call.function.name
                func_args = json.loads(tool_call.function.arguments)

                # 注入 user_id(安全设计:user_id 由系统注入,不依赖 LLM 传入)
                if "user_id" in self.tool_map[func_name].__code__.co_varnames:
                    func_args["user_id"] = self.user_id

                result = self.tool_map[func_name](**func_args)
                self.messages.append({
                    "role": "tool",
                    "tool_call_id": tool_call.id,
                    "content": json.dumps(result, ensure_ascii=False),
                })


# 使用示例
if __name__ == "__main__":
    agent = CustomerServiceAgent(user_id="USER-12345")

    conversations = [
        "我的订单 ORD-001 发货了吗?",
        "什么时候能到?",
        "我想申请退款",
        "退款政策是什么?",
    ]

    for user_input in conversations:
        print(f"\n用户:{user_input}")
        reply = agent.chat(user_input)
        print(f"客服:{reply}")

1.7 PEAS 分析的价值

PEAS 框架的核心价值不在于填表,而在于在动手写代码之前就发现设计遗漏

以下是几个常见的、不经过 PEAS 分析就容易漏掉的设计点:

  • 环境是动态的,忘了设计实时查询,用缓存数据回答——订单状态早变了,Agent 还在说"您的订单在途中"
  • 传感器里有用户历史,没有设计长期记忆——同一用户第二次来,Agent 又从头问一遍
  • 执行器里有退款工具,没有设计权限校验——用户可以退别人的单
  • Performance 没定义,开发完不知道怎么算"好"——上线了靠主观感受评估

小结: PEAS 框架把 Agent 设计从"凭直觉加功能"变成"系统化分析需求"。四个维度分别回答"好的标准是什么、在什么环境下工作、能做什么、能感知什么",每个答案都直接对应代码层面的设计决策。

本页目录