diff --git a/metagpt/roles/architect.py b/metagpt/roles/architect.py index f18430c1c..465beff05 100644 --- a/metagpt/roles/architect.py +++ b/metagpt/roles/architect.py @@ -34,6 +34,7 @@ class Architect(Role): def __init__(self, **kwargs) -> None: super().__init__(**kwargs) + self.enable_memory = False # Initialize actions specific to the Architect role self.set_actions([PrepareDocuments(send_to=any_to_str(self), context=self.context), WriteDesign]) @@ -54,6 +55,3 @@ class Architect(Role): self.rc.todo = self.actions[idx] return bool(self.rc.todo) return False - - async def _observe(self, ignore_memory=False) -> int: - return await super()._observe(ignore_memory=True) diff --git a/metagpt/roles/product_manager.py b/metagpt/roles/product_manager.py index 4fa8cb041..4beab5366 100644 --- a/metagpt/roles/product_manager.py +++ b/metagpt/roles/product_manager.py @@ -32,7 +32,7 @@ class ProductManager(Role): def __init__(self, **kwargs) -> None: super().__init__(**kwargs) - + self.enable_memory = False self.set_actions([PrepareDocuments(send_to=any_to_str(self)), WritePRD]) self._watch([UserRequirement, PrepareDocuments]) self.rc.react_mode = RoleReactMode.BY_ORDER @@ -47,6 +47,3 @@ class ProductManager(Role): self.config.git_reinit = False self.todo_action = any_to_name(WritePRD) return bool(self.rc.todo) - - async def _observe(self, ignore_memory=False) -> int: - return await super()._observe(ignore_memory=True) diff --git a/metagpt/roles/project_manager.py b/metagpt/roles/project_manager.py index e7b453c48..70bd3bf8b 100644 --- a/metagpt/roles/project_manager.py +++ b/metagpt/roles/project_manager.py @@ -34,7 +34,7 @@ class ProjectManager(Role): def __init__(self, **kwargs) -> None: super().__init__(**kwargs) - + self.enable_memory = False self.set_actions([PrepareDocuments(send_to=any_to_str(self), context=self.context), WriteTasks]) self._watch([UserRequirement, PrepareDocuments, WriteDesign]) @@ -52,6 +52,3 @@ class ProjectManager(Role): self.rc.todo = self.actions[idx] return bool(self.rc.todo) return False - - async def _observe(self, ignore_memory=False) -> int: - return await super()._observe(ignore_memory=True) diff --git a/metagpt/roles/qa_engineer.py b/metagpt/roles/qa_engineer.py index c1e50347b..06befc5f7 100644 --- a/metagpt/roles/qa_engineer.py +++ b/metagpt/roles/qa_engineer.py @@ -43,6 +43,7 @@ class QaEngineer(Role): def __init__(self, **kwargs): super().__init__(**kwargs) + self.enable_memory = False # FIXME: a bit hack here, only init one action to circumvent _think() logic, # will overwrite _think() in future updates @@ -188,8 +189,3 @@ class QaEngineer(Role): sent_from=self.profile, send_to=MESSAGE_ROUTE_TO_NONE, ) - - async def _observe(self, ignore_memory=False) -> int: - # This role has events that trigger and execute themselves based on conditions, and cannot rely on the - # content of memory to activate. - return await super()._observe(ignore_memory=True) diff --git a/metagpt/roles/role.py b/metagpt/roles/role.py index e92c9958e..4dc0e34d9 100644 --- a/metagpt/roles/role.py +++ b/metagpt/roles/role.py @@ -34,7 +34,14 @@ from metagpt.context_mixin import ContextMixin from metagpt.logs import logger from metagpt.memory import Memory from metagpt.provider import HumanProvider -from metagpt.schema import AIMessage, Message, MessageQueue, SerializationMixin +from metagpt.schema import ( + AIMessage, + Message, + MessageQueue, + SerializationMixin, + Task, + TaskResult, +) from metagpt.strategy.planner import Planner from metagpt.utils.common import any_to_name, any_to_str, role_raise_decorator from metagpt.utils.project_repo import ProjectRepo @@ -134,6 +141,9 @@ class Role(SerializationMixin, ContextMixin, BaseModel): constraints: str = "" desc: str = "" is_human: bool = False + enable_memory: bool = ( + True # Stateless, atomic roles, or roles that use external memory can disable this to save memory. + ) role_id: str = "" states: list[str] = [] @@ -400,11 +410,12 @@ class Role(SerializationMixin, ContextMixin, BaseModel): msg = response else: msg = AIMessage(content=response, cause_by=self.rc.todo, sent_from=self) - self.rc.memory.add(msg) + if self.enable_memory: + self.rc.memory.add(msg) return msg - async def _observe(self, ignore_memory=False) -> int: + async def _observe(self) -> int: """Prepare new messages for processing from the message buffer and other sources.""" # Read unprocessed messages from the msg buffer. news = [] @@ -413,7 +424,7 @@ class Role(SerializationMixin, ContextMixin, BaseModel): if not news: news = self.rc.msg_buffer.pop_all() # Store the read messages in your own memory to prevent duplicate processing. - old_messages = [] if ignore_memory else self.rc.memory.get() + old_messages = [] if not self.enable_memory else self.rc.memory.get() self.rc.memory.add_batch(news) # Filter out messages of interest. self.rc.news = [