diff --git a/examples/st_game/README.md b/examples/st_game/README.md new file mode 100644 index 000000000..f0aef9923 --- /dev/null +++ b/examples/st_game/README.md @@ -0,0 +1,5 @@ +## Stanford Town Game + +执行入口为:`python3 run_st_game.py "Host a activity"` + +`idea`为用户给第一个Agent的用户心声,并通过这个心声进行传播,看最后多智能体是否达到举办、参加活动的目标。 diff --git a/examples/st_game/actions/summarize_conv.py b/examples/st_game/actions/summarize_conv.py new file mode 100644 index 000000000..f5561fcb1 --- /dev/null +++ b/examples/st_game/actions/summarize_conv.py @@ -0,0 +1,12 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# @Desc : summarize the content of agents' conversation + +from metagpt.actions.action import Action +from metagpt.schema import Message + + +class SummarizeConv(Action): + + def __init__(self, name="SummarizeConv", context: list[Message] = None, llm=None): + super().__init__(name, context, llm) diff --git a/examples/st_game/actions/user_requirement.py b/examples/st_game/actions/user_requirement.py new file mode 100644 index 000000000..68e109de5 --- /dev/null +++ b/examples/st_game/actions/user_requirement.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# @Desc : + +from metagpt.actions import Action + + +class UserRequirement(Action): + + async def run(self, *args, **kwargs): + raise NotImplementedError diff --git a/examples/st_game/maze_environment.py b/examples/st_game/maze_environment.py new file mode 100644 index 000000000..a906ac46b --- /dev/null +++ b/examples/st_game/maze_environment.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# @Desc : maze environment + +from metagpt.environment import Environment + + +class MazeEnvironment(Environment): + + pass diff --git a/examples/st_game/memory/associative_memory.py b/examples/st_game/memory/associative_memory.py new file mode 100644 index 000000000..ef1514398 --- /dev/null +++ b/examples/st_game/memory/associative_memory.py @@ -0,0 +1,9 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# @Desc : associative_memory to store conversation、plan detail、reflection result and so on. + +from metagpt.memory.memory import Memory + + +class AssociativeMemory(Memory): + pass diff --git a/examples/st_game/plan/st_plan.py b/examples/st_game/plan/st_plan.py new file mode 100644 index 000000000..27ed0f94f --- /dev/null +++ b/examples/st_game/plan/st_plan.py @@ -0,0 +1,3 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# @Desc : st' planning execution diff --git a/examples/st_game/reflect/st_reflect.py b/examples/st_game/reflect/st_reflect.py new file mode 100644 index 000000000..97efe0dc6 --- /dev/null +++ b/examples/st_game/reflect/st_reflect.py @@ -0,0 +1,3 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# @Desc : st's reflection execution diff --git a/examples/st_game/roles/st_role.py b/examples/st_game/roles/st_role.py new file mode 100644 index 000000000..6f056286e --- /dev/null +++ b/examples/st_game/roles/st_role.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# @Desc : Stanford Town role + +""" +Do the steps following: +- perceive, receive environment(Maze) info +- retrieve, retrieve memories +- plan, do plan like long-term plan and interact with Maze +- reflect, do the High-level thinking based on memories and re-add into the memory +- execute, move or else in the Maze +""" + +from pydantic import Field +from pathlib import Path + +from metagpt.roles.role import Role, RoleContext + +from ..memory.associative_memory import AssociativeMemory + + +class STRoleContext(RoleContext): + + memory: AssociativeMemory = Field(default=AssociativeMemory) + + +class STRole(Role): + + # add a role's property structure to store role's age and so on like GA's Scratch. + + def __init__(self, name="", profile=""): + self._rc = STRoleContext() + + def load_from(self, folder: Path): + """ + load role data from `storage/{simulation_name}/personas/{role_name} + """ + pass + + def save_into(self, folder: Path): + """ + save role data from `storage/{simulation_name}/personas/{role_name} + """ + pass diff --git a/examples/st_game/run_st_game.py b/examples/st_game/run_st_game.py new file mode 100644 index 000000000..eaabeb4bd --- /dev/null +++ b/examples/st_game/run_st_game.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# @Desc : entry of Stanford Town(ST/st) game + +import asyncio +import fire + +from stanford_town import StanfordTown +from roles.st_role import STRole + + +async def startup(idea: str, + investment: float = 30.0, + n_round: int = 500): + + # get role names from `storage/{simulation_name}/reverie/meta.json` and then init roles + roles = [] + # TODO + + town = StanfordTown() + town.wakeup_roles(roles) + + town.invest(investment) + town.start_project() + + await town.run(n_round) + + +def main(idea: str, + investment: float = 30.0, + n_round: int = 500): + """ + idea works as an `inner voice` to the first agent. + """ + + asyncio.run(startup(idea=idea, + investment=investment, + n_round=n_round)) + + +if __name__ == "__main__": + fire.Fire(main) diff --git a/examples/st_game/stanford_town.py b/examples/st_game/stanford_town.py new file mode 100644 index 000000000..c29b3484e --- /dev/null +++ b/examples/st_game/stanford_town.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# @Desc : StanfordTown to works like SoftwareCompany + +from pydantic import Field + +from metagpt.software_company import SoftwareCompany +from metagpt.roles.role import Role +from metagpt.schema import Message + +from maze_environment import MazeEnvironment +from actions.user_requirement import UserRequirement + + +class StanfordTown(SoftwareCompany): + + environment: MazeEnvironment = Field(default_factory=MazeEnvironment) + + def wakeup_roles(self, roles: list[Role]): + self.environment.add_roles(roles) + + def start_project(self, idea): + self.environment.publish_message( + Message(role="User", content=idea, cause_by=UserRequirement) + ) diff --git a/examples/st_game/storage/.gitignore b/examples/st_game/storage/.gitignore new file mode 100644 index 000000000..ecc8de13a --- /dev/null +++ b/examples/st_game/storage/.gitignore @@ -0,0 +1 @@ +# path to store simulation data \ No newline at end of file diff --git a/examples/st_game/utils/const.py b/examples/st_game/utils/const.py new file mode 100644 index 000000000..099607d86 --- /dev/null +++ b/examples/st_game/utils/const.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# @Desc : + +from pathlib import Path + +ROOT_PATH = Path(__file__).parent.parent +STORAGE_PATH = ROOT_PATH.joinpath("storage") diff --git a/examples/st_game/utils/mg_ga_transform.py b/examples/st_game/utils/mg_ga_transform.py new file mode 100644 index 000000000..11b4904e1 --- /dev/null +++ b/examples/st_game/utils/mg_ga_transform.py @@ -0,0 +1,3 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# @Desc : data transform of mg <-> ga under storage diff --git a/metagpt/plan/__init__.py b/metagpt/plan/__init__.py new file mode 100644 index 000000000..2d6c6f223 --- /dev/null +++ b/metagpt/plan/__init__.py @@ -0,0 +1,3 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# @Desc : plan module diff --git a/metagpt/plan/plan.py b/metagpt/plan/plan.py new file mode 100644 index 000000000..caa19416b --- /dev/null +++ b/metagpt/plan/plan.py @@ -0,0 +1,3 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# @Desc : base class of planning diff --git a/metagpt/reflect/__init__.py b/metagpt/reflect/__init__.py new file mode 100644 index 000000000..da486a131 --- /dev/null +++ b/metagpt/reflect/__init__.py @@ -0,0 +1,3 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# @Desc : reflection module diff --git a/metagpt/reflect/reflect.py b/metagpt/reflect/reflect.py new file mode 100644 index 000000000..5abf6e5d8 --- /dev/null +++ b/metagpt/reflect/reflect.py @@ -0,0 +1,3 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# @Desc : base class of reflection