From 88474fdf3ce8a0f4d33b2b4eb733e3bfd70eb11a Mon Sep 17 00:00:00 2001 From: better629 Date: Mon, 4 Mar 2024 13:46:46 +0800 Subject: [PATCH] update --- examples/st_game/README.md | 2 ++ examples/st_game/README_CN.md | 4 +++- examples/st_game/memory/agent_memory.py | 4 ++++ examples/st_game/roles/st_role.py | 19 +++++++++++++------ examples/st_game/stanford_town.py | 7 +++---- 5 files changed, 25 insertions(+), 11 deletions(-) diff --git a/examples/st_game/README.md b/examples/st_game/README.md index ea6547f42..28c4efec4 100644 --- a/examples/st_game/README.md +++ b/examples/st_game/README.md @@ -19,6 +19,8 @@ # updated ### Backend service startup The execution entry is `python3 run_st_game.py "Host a open lunch party at 13:00 pm" "base_the_ville_isabella_maria_klaus" "test_sim" 10` +or +`python3 run_st_game.py "Host a open lunch party at 13:00 pm" "base_the_ville_isabella_maria_klaus" "test_sim" 10 --temp_storage_path path/to/ga/temp_storage` `idea` is the user's voice to the first Agent, and it is disseminated through this voice to see whether the final multi-agents achieve the goal of hosting or participating in the event. diff --git a/examples/st_game/README_CN.md b/examples/st_game/README_CN.md index 4c4c2a41b..4e1b3f439 100644 --- a/examples/st_game/README_CN.md +++ b/examples/st_game/README_CN.md @@ -17,7 +17,9 @@ # 更新为 这样可用实现不改变GA代码情况下,实现仿真数据的对接。不然得修改GA的代码来适配MG的输出路径。 ### 后端服务启动 -执行入口为:`python3 run_st_game.py "Host a open lunch party at 13:00 pm" "base_the_ville_isabella_maria_klaus" "test_sim" 10` +执行入口为:`python3 run_st_game.py "Host a open lunch party at 13:00 pm" "base_the_ville_isabella_maria_klaus" "test_sim" 10` +或者 +`python3 run_st_game.py "Host a open lunch party at 13:00 pm" "base_the_ville_isabella_maria_klaus" "test_sim" 10 --temp_storage_path path/to/ga/temp_storage` `idea`为用户给第一个Agent的用户心声,并通过这个心声进行传播,看最后多智能体是否达到举办、参加活动的目标。 diff --git a/examples/st_game/memory/agent_memory.py b/examples/st_game/memory/agent_memory.py index d4f346fe3..d212232f4 100644 --- a/examples/st_game/memory/agent_memory.py +++ b/examples/st_game/memory/agent_memory.py @@ -39,6 +39,8 @@ class BasicMemory(Message): keywords: list[str] = Field(default=[]) # keywords filling: list = Field(default=[]) # 装的与之相关联的memory_id的列表 + __hash__ = object.__hash__ # support hash in AgentMemory + @model_validator(mode="before") @classmethod def check_values(cls, values): @@ -46,6 +48,8 @@ class BasicMemory(Message): values["last_accessed"] = values["created"] if "content" in values: values["description"] = values["content"] + if "filling" in values: + values["filling"] = values["filling"] or [] return values @field_serializer("created", "expiration") diff --git a/examples/st_game/roles/st_role.py b/examples/st_game/roles/st_role.py index 2a9722a8f..af4188733 100644 --- a/examples/st_game/roles/st_role.py +++ b/examples/st_game/roles/st_role.py @@ -40,6 +40,7 @@ from metagpt.environment.api.env_api import EnvAPIAbstract from metagpt.logs import logger from metagpt.roles.role import Role, RoleContext from metagpt.schema import Message +from metagpt.utils.common import any_to_str if TYPE_CHECKING: from metagpt.environment.stanford_town_env.stanford_town_env import ( # noqa: F401 @@ -171,13 +172,19 @@ class STRole(Role): logger.info(f"Role: {self.name} saved role's memory into {str(self.role_storage_path)}") - async def _observe(self) -> int: + async def _observe(self, ignore_memory=False) -> int: if not self.rc.env: return 0 + news = [] + if not news: + news = self.rc.msg_buffer.pop_all() + old_messages = [] if ignore_memory else self.rc.memory.get() + # Filter out messages of interest. + self.rc.news = [ + n for n in news if (n.cause_by in self.rc.watch or self.name in n.send_to) and n not in old_messages + ] - observed = self.rc.env.memory.get_by_actions(self.rc.watch) - self.rc.news = self.rc.memory.remember(observed) - if len(self.rc.news) == 1 and self.rc.news[0].cause_by == UserRequirement: + if len(self.rc.news) == 1 and self.rc.news[0].cause_by == any_to_str(UserRequirement): logger.warning(f"Role: {self.name} add inner voice: {self.rc.news[0].content}") await self.add_inner_voice(self.rc.news[0].content) @@ -318,7 +325,7 @@ class STRole(Role): # Get event poignancy. event_poignancy = await generate_poig_score(self, "event", desc_embedding_in) - logger.info(f"Role {self.name} event_poignancy: {event_poignancy}") + logger.debug(f"Role {self.name} event_poignancy: {event_poignancy}") # If we observe the persona's self chat, we include that in the memory # of the persona here. @@ -579,7 +586,7 @@ class STRole(Role): async def _react(self) -> Message: # update role env - ret = self.update_role_env() + ret = await self.update_role_env() if not ret: # TODO add message logger.info(f"Role: {self.name} update_role_env return False") diff --git a/examples/st_game/stanford_town.py b/examples/st_game/stanford_town.py index 799113512..446b60ce0 100644 --- a/examples/st_game/stanford_town.py +++ b/examples/st_game/stanford_town.py @@ -2,9 +2,8 @@ # -*- coding: utf-8 -*- # @Desc : StanfordTown to works like SoftwareCompany -from typing import Any +from typing import Any, Optional -from pydantic import Field from examples.st_game.roles.st_role import STRole from examples.st_game.utils.const import MAZE_ASSET_PATH @@ -15,10 +14,10 @@ from metagpt.team import Team class StanfordTown(Team): - env: StanfordTownEnv = Field(default=None) + env: Optional[StanfordTownEnv] = None def __init__(self, context: Context = None, **data: Any): - super(StanfordTown, self).__init__(**data) + super(Team, self).__init__(**data) ctx = context or Context() if not self.env: self.env = StanfordTownEnv(context=ctx, maze_asset_path=MAZE_ASSET_PATH)