add role steps

This commit is contained in:
better629 2023-09-27 19:57:41 +08:00
parent 2b8df1c181
commit a223352b7c
5 changed files with 132 additions and 3 deletions

View file

@ -0,0 +1,25 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Desc : dummy action to make every STRole can deal DummyMessage which is caused by DummyAction
from dataclasses import dataclass
from metagpt.actions import Action
from metagpt.schema import Message
class DummyAction(Action):
async def run(self, *args, **kwargs):
raise NotImplementedError
@dataclass
class DummyMessage(Message):
"""
dummy message to pass to role and make them to have a execution every round
"""
def __init__(self, content: str = "dummy", cause_by=DummyAction):
super(DummyMessage, self).__init__(content=content,
cause_by=cause_by)

View file

@ -15,12 +15,16 @@ from pydantic import Field
from pathlib import Path
from metagpt.roles.role import Role, RoleContext
from metagpt.schema import Message
from ..memory.associative_memory import AssociativeMemory
from ..actions.dummy_action import DummyAction
from ..actions.user_requirement import UserRequirement
from ..maze_environment import MazeEnvironment
class STRoleContext(RoleContext):
env: 'MazeEnvironment' = Field(default=None)
memory: AssociativeMemory = Field(default=AssociativeMemory)
@ -28,8 +32,22 @@ 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=""):
def __init__(self,
name: str = "Klaus Mueller",
profile: str = "STMember",
has_inner_voice: bool = False):
self._rc = STRoleContext()
super(STRole, self).__init__(name=name,
profile=profile)
self._init_actions([])
if has_inner_voice:
# TODO add communication action
self._watch([UserRequirement, DummyAction])
else:
self._watch([DummyAction])
def load_from(self, folder: Path):
"""
@ -42,3 +60,36 @@ class STRole(Role):
save role data from `storage/{simulation_name}/personas/{role_name}
"""
pass
async def observe(self):
# TODO observe info from maze_env
pass
async def plan(self):
# TODO make a plan
# TODO judge if start a conversation
# TODO update plan
# TODO re-add result into memory
pass
async def reflect(self):
# TODO reflection if meet reflect condition
# TODO re-add result to memory
pass
async def _react(self) -> Message:
maze_env = self._rc.env
# TODO observe
# get maze_env from self._rc.env, and observe env info
# TODO retrieve, use self._rc.memory 's retrieve functions
# TODO plan
# TODO reflect
# TODO execute(feed-back into maze_env)

View file

@ -7,15 +7,26 @@ import fire
from stanford_town import StanfordTown
from roles.st_role import STRole
from utils.mg_ga_transform import get_reverie_meta
from utils.const import STORAGE_PATH
async def startup(idea: str,
fork_sim_code: str,
sim_code: str,
investment: float = 30.0,
n_round: int = 500):
# get role names from `storage/{simulation_name}/reverie/meta.json` and then init roles
reverie_meta = get_reverie_meta(fork_sim_code)
roles = []
# TODO
for idx, role_name in enumerate(reverie_meta["persona_names"]):
role_stg_path = STORAGE_PATH.joinpath(fork_sim_code).joinpath(f"personas/{role_name}")
has_inner_voice = True if idx == 0 else False
role = STRole(name=role_name, has_inner_voice=has_inner_voice)
role.load_from(role_stg_path)
roles.append(role)
town = StanfordTown()
town.wakeup_roles(roles)
@ -27,13 +38,22 @@ async def startup(idea: str,
def main(idea: str,
fork_sim_code: str,
sim_code: str,
investment: float = 30.0,
n_round: int = 500):
"""
idea works as an `inner voice` to the first agent.
Args:
idea: idea works as an `inner voice` to the first agent.
fork_sim_code: old simulation name to start with
sim_code: new simulation name to save simulation result
investment: the investment of running agents
n_round: rounds to run agents
"""
asyncio.run(startup(idea=idea,
fork_sim_code=fork_sim_code,
sim_code=sim_code,
investment=investment,
n_round=n_round))

View file

@ -1,3 +1,12 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Desc : data transform of mg <-> ga under storage
from .const import STORAGE_PATH
from .utils import read_json_file, write_json_file
def get_reverie_meta(sim_code: str) -> dict:
meta_file_path = STORAGE_PATH.joinpath(sim_code).joinpath("reverie/meta.json")
reverie_meta = read_json_file(meta_file_path)
return reverie_meta

View file

@ -0,0 +1,24 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Desc : utils
from typing import Any
import json
from pathlib import Path
def read_json_file(json_file: str, encoding=None) -> list[Any]:
if not Path(json_file).exists():
raise FileNotFoundError(f"json_file: {json_file} not exist, return []")
with open(json_file, "r", encoding=encoding) as fin:
try:
data = json.load(fin)
except Exception as exp:
raise ValueError(f"read json file: {json_file} failed")
return data
def write_json_file(json_file: str, data: list, encoding=None):
with open(json_file, "w", encoding=encoding) as fout:
json.dump(data, fout, ensure_ascii=False, indent=4)