设计的精髓:设计模式与架构决策分析
摘要
AgentScope 的设计体现了深厚的工程智慧。本文将深入分析框架中使用的设计模式、架构决策,以及这些设计背后的考量。你会发现,框架大量使用了模板方法模式、策略模式、观察者模式、元类模式等经典设计模式,同时做出了许多巧妙的架构决策,如模型无关设计、状态与初始化分离、消息作为统一接口等。通过阅读本文,你会理解这些设计如何让框架变得灵活、可扩展、易维护,以及如何在你的项目中应用这些设计思想。

设计模式分析
1. 模板方法模式(Template Method Pattern)
模板方法模式在 AgentScope 中应用广泛,最典型的例子是 AgentBase 和 ReActAgentBase:

ReActAgentBase 的 reply 方法定义了算法骨架,而 _reasoning 和 _acting 由子类实现:
python
# 在 ReActAgentBase 中(伪代码)
async def reply(self, *args, **kwargs) -> Msg:
"""模板方法:定义算法骨架"""
# 1. 前置处理
# 2. 调用抽象方法
msg_reasoning = await self._reasoning(*args, **kwargs) # 抽象方法
# 3. 根据推理结果执行行动
if has_tool_calls:
await self._acting(tool_call) # 抽象方法
# 4. 后置处理
return result
这种设计让框架能够:
- 定义通用的执行流程
- 允许子类定制特定步骤
- 保持代码复用和扩展性
2. 策略模式(Strategy Pattern)
策略模式在模型和格式化器中应用:

这种设计让智能体可以在运行时选择不同的模型和格式化器,而不需要修改代码:
python
# 可以轻松切换策略
agent = ReActAgent(
model=OpenAIChatModel(...), # 策略1
formatter=OpenAIChatFormatter(), # 策略1
)
# 或者
agent = ReActAgent(
model=DashScopeChatModel(...), # 策略2
formatter=DashScopeChatFormatter(), # 策略2
)
3. 观察者模式(Observer Pattern)
观察者模式在 MsgHub 中实现:

当智能体在 MsgHub 中回复时,消息会自动广播给其他参与者:
python:89:93:src/agentscope/pipeline/_msghub.py
def _reset_subscriber(self) -> None:
"""Reset the subscriber for agent in `self.participant`"""
if self.enable_auto_broadcast:
for agent in self.participants:
agent.reset_subscribers(self.name, self.participants)
4. 元类模式(Metaclass Pattern)
元类模式用于自动包装钩子函数:
python:147:162:src/agentscope/agent/_agent_meta.py
class _AgentMeta(type):
"""The agent metaclass that wraps the agent's reply, observe and print
functions with pre- and post-hooks."""
def __new__(mcs, name: Any, bases: Any, attrs: Dict) -> Any:
"""Wrap the agent's functions with hooks."""
for func_name in [
"reply",
"print",
"observe",
]:
if func_name in attrs:
attrs[func_name] = _wrap_with_hooks(attrs[func_name])
return super().__new__(mcs, name, bases, attrs)
这种设计让框架能够:
- 自动为方法添加钩子支持
- 无需手动装饰每个方法
- 保持代码简洁
5. 工厂模式(Factory Pattern)
虽然 AgentScope 没有显式的工厂类,但使用了工厂模式的思想。例如,通过配置创建不同的模型:
python
# 工厂模式的思想:根据配置创建对象
def create_model(config: dict) -> ChatModelBase:
if config["provider"] == "openai":
return OpenAIChatModel(...)
elif config["provider"] == "dashscope":
return DashScopeChatModel(...)
# ...
架构决策分析
1. 状态与初始化分离
这是 AgentScope 的一个核心架构决策:
python:20:39:src/agentscope/module/_state_module.py
class StateModule:
"""The state module class in agentscope to support nested state
serialization and deserialization."""
def __init__(self) -> None:
"""Initialize the state module."""
self._module_dict = OrderedDict()
self._attribute_dict = OrderedDict()
def __setattr__(self, key: str, value: Any) -> None:
"""Set attributes and record state modules."""
if isinstance(value, StateModule):
if not hasattr(self, "_module_dict"):
raise AttributeError(...)
self._module_dict[key] = value
super().__setattr__(key, value)
决策原因:
- 允许对象在不同状态间切换
- 支持状态持久化和恢复
- 便于调试和测试
影响:
- 所有有状态对象都继承
StateModule - 状态管理变得统一和可预测
2. 消息作为统一接口
Msg 类在整个框架中扮演核心角色:
python:21:73:src/agentscope/message/_message_base.py
决策原因:
- 统一智能体间通信格式
- 简化 API 交互(通过 Formatter 转换)
- 便于记忆存储和 UI 显示
影响:
- 所有组件都围绕 Msg 设计
- 减少了数据格式转换的复杂性
3. 模型无关设计
通过抽象接口实现模型无关:
python:13:44:src/agentscope/model/_model_base.py
class ChatModelBase:
"""Base class for chat models."""
model_name: str
stream: bool
@abstractmethod
async def __call__(
self,
*args: Any,
**kwargs: Any,
) -> ChatResponse | AsyncGenerator[ChatResponse, None]:
pass
决策原因:
- 一次编程,适配所有模型
- 降低切换成本
- 提高代码复用性
影响:
- 智能体代码与具体模型解耦
- 新模型只需实现接口即可集成
4. 异步优先设计
AgentScope 1.0 完全拥抱异步:
python
# 所有核心操作都是异步的
async def reply(self, msg: Msg) -> Msg: ...
async def observe(self, msg: Msg) -> None: ...
async def __call__(self, messages, tools) -> ChatResponse: ...
决策原因:
- 支持并发执行(如并行工具调用)
- 支持流式处理
- 提高性能
影响:
- 开发者必须使用异步编程
- 代码更复杂,但更强大
5. 钩子机制设计
通过元类自动添加钩子支持:
python:55:144:src/agentscope/agent/_agent_meta.py
def _wrap_with_hooks(
original_func: Callable,
) -> Callable:
"""A decorator to wrap the original async function with pre- and post-hooks"""
# 自动包装函数,添加钩子支持
...
决策原因:
- 允许在不修改核心代码的情况下扩展功能
- 支持 AOP(面向切面编程)
- 便于调试和监控
影响:
- 开发者可以轻松添加自定义逻辑
- 框架变得更加灵活
设计原则应用
1. 单一职责原则(SRP)
每个类都有明确的职责:
ChatModelBase:只负责模型调用FormatterBase:只负责格式转换MemoryBase:只负责记忆管理Toolkit:只负责工具管理
2. 开闭原则(OCP)
框架对扩展开放,对修改关闭:
- 可以添加新模型(扩展),无需修改现有代码
- 可以添加新工具(扩展),无需修改 Toolkit
- 可以创建自定义智能体(扩展),无需修改 AgentBase
3. 依赖倒置原则(DIP)
高层模块不依赖低层模块,都依赖抽象:
ReActAgent依赖ChatModelBase(抽象),不依赖具体模型ReActAgent依赖FormatterBase(抽象),不依赖具体格式化器
4. 接口隔离原则(ISP)
接口设计精简,只包含必要方法:
ChatModelBase只有一个核心方法__call__MemoryBase只包含记忆操作相关方法
5. 组合优于继承
框架大量使用组合:
python
agent = ReActAgent(
model=ChatModelBase(...), # 组合
formatter=FormatterBase(...), # 组合
toolkit=Toolkit(...), # 组合
memory=MemoryBase(...), # 组合
)
总结
AgentScope 的设计体现了深厚的工程智慧:
- 设计模式:模板方法、策略、观察者、元类等模式的应用让框架灵活而强大
- 架构决策:状态分离、消息统一、模型无关、异步优先等决策让框架清晰而高效
- 设计原则:SRP、OCP、DIP、ISP 等原则的应用让框架可维护、可扩展
这些设计和决策共同构成了 AgentScope 的核心竞争力:透明、模块化、可扩展。理解这些设计,不仅能帮助你更好地使用框架,也能为你的项目设计提供参考。