From 7d523b392274b4642fd4d0fe674cb874537445bc Mon Sep 17 00:00:00 2001 From: better629 Date: Wed, 27 Dec 2023 15:03:34 +0800 Subject: [PATCH] fix role add actions --- examples/debate.py | 22 ++++++++----------- metagpt/roles/role.py | 5 ++--- .../serialize_deserialize/test_role.py | 5 +++++ .../test_serdeser_base.py | 7 ++++++ 4 files changed, 23 insertions(+), 16 deletions(-) diff --git a/examples/debate.py b/examples/debate.py index c1d4769e1..eb0a09839 100644 --- a/examples/debate.py +++ b/examples/debate.py @@ -7,6 +7,7 @@ Author: garylin2099 """ import asyncio import platform +from typing import Any import fire @@ -20,7 +21,7 @@ from metagpt.team import Team class SpeakAloud(Action): """Action: Speak out aloud in a debate (quarrel)""" - PROMPT_TEMPLATE = """ + PROMPT_TEMPLATE: str = """ ## BACKGROUND Suppose you are {name}, you are in a debate with {opponent_name}. ## DEBATE HISTORY @@ -30,9 +31,7 @@ class SpeakAloud(Action): Now it's your turn, you should closely respond to your opponent's latest argument, state your position, defend your arguments, and attack your opponent's arguments, craft a strong and emotional response in 80 words, in {name}'s rhetoric and viewpoints, your will argue: """ - - def __init__(self, name="SpeakAloud", context=None, llm=None): - super().__init__(name, context, llm) + name: str = "SpeakAloud" async def run(self, context: str, name: str, opponent_name: str): prompt = self.PROMPT_TEMPLATE.format(context=context, name=name, opponent_name=opponent_name) @@ -44,17 +43,14 @@ class SpeakAloud(Action): class Debator(Role): - def __init__( - self, - name: str, - profile: str, - opponent_name: str, - **kwargs, - ): - super().__init__(name, profile, **kwargs) + name: str = "" + profile: str = "" + opponent_name: str = "" + + def __init__(self, **data: Any): + super().__init__(**data) self._init_actions([SpeakAloud]) self._watch([UserRequirement, SpeakAloud]) - self.opponent_name = opponent_name async def _observe(self) -> int: await super()._observe() diff --git a/metagpt/roles/role.py b/metagpt/roles/role.py index d74a2d801..1d37228e3 100644 --- a/metagpt/roles/role.py +++ b/metagpt/roles/role.py @@ -163,6 +163,7 @@ class Role(BaseModel): def check_actions(cls, actions: list[Union[dict, Action]]) -> list[Action]: new_actions = [] for action in actions: + new_action = action if isinstance(action, dict): item_class_name = action.get("builtin_class_name", None) if item_class_name: @@ -171,9 +172,7 @@ class Role(BaseModel): if item_class_name == registery_class_name: new_action = subclass(**action) break - new_actions.append(new_action) - else: - new_actions.append(action) + new_actions.append(new_action) return new_actions @model_validator(mode="after") diff --git a/tests/metagpt/serialize_deserialize/test_role.py b/tests/metagpt/serialize_deserialize/test_role.py index 3b7f9aca0..3e3d04dbc 100644 --- a/tests/metagpt/serialize_deserialize/test_role.py +++ b/tests/metagpt/serialize_deserialize/test_role.py @@ -17,9 +17,11 @@ from metagpt.roles.role import Role from metagpt.schema import Message from metagpt.utils.common import format_trackback_info from tests.metagpt.serialize_deserialize.test_serdeser_base import ( + ActionOK, RoleA, RoleB, RoleC, + RoleD, serdeser_path, ) @@ -31,6 +33,9 @@ def test_roles(): assert len(role_a.rc.watch) == 1 assert len(role_b.rc.watch) == 1 + role_d = RoleD(actions=[ActionOK()]) + assert len(role_d.actions) == 1 + def test_role_serialize(): role = Role() diff --git a/tests/metagpt/serialize_deserialize/test_serdeser_base.py b/tests/metagpt/serialize_deserialize/test_serdeser_base.py index 87ec76842..dc8cc76d6 100644 --- a/tests/metagpt/serialize_deserialize/test_serdeser_base.py +++ b/tests/metagpt/serialize_deserialize/test_serdeser_base.py @@ -91,3 +91,10 @@ class RoleC(Role): self._watch([UserRequirement]) self.rc.react_mode = RoleReactMode.BY_ORDER self.rc.memory.ignore_id = True + + +class RoleD(Role): + name: str = Field(default="RoleD") + profile: str = Field(default="Role D") + goal: str = "RoleD's goal" + constraints: str = "RoleD's constraints"