update:更新基础版本,支持多轮,每轮使用每个角色的任务完成情况判断

This commit is contained in:
洪思睿 2023-10-02 03:09:20 +08:00
parent cbd071a10e
commit 493225f636
10 changed files with 93 additions and 37 deletions

View file

@ -10,31 +10,32 @@ from enum import Enum
from metagpt.actions.action import Action
from metagpt.actions.action_output import ActionOutput
from metagpt.actions.add_requirement import BossRequirement
'''
from metagpt.actions.debug_error import DebugError
from metagpt.actions.design_api import WriteDesign
from metagpt.actions.project_management import AssignTasks, WriteTasks
from metagpt.actions.run_code import RunCode
from metagpt.actions.search_and_summarize import SearchAndSummarize
#from metagpt.actions.search_and_summarize import SearchAndSummarize
from metagpt.actions.write_code import WriteCode
from metagpt.actions.write_code_review import WriteCodeReview
from metagpt.actions.write_prd import WritePRD
from metagpt.actions.write_test import WriteTest
'''
class ActionType(Enum):
"""All types of Actions, used for indexing."""
ADD_REQUIREMENT = BossRequirement
WRITE_PRD = WritePRD
WRITE_DESIGN = WriteDesign
WRTIE_CODE = WriteCode
WRITE_CODE_REVIEW = WriteCodeReview
WRITE_TEST = WriteTest
RUN_CODE = RunCode
DEBUG_ERROR = DebugError
WRITE_TASKS = WriteTasks
ASSIGN_TASKS = AssignTasks
SEARCH_AND_SUMMARIZE = SearchAndSummarize
#WRITE_PRD = WritePRD
#WRITE_DESIGN = WriteDesign
#WRTIE_CODE = WriteCode
#WRITE_CODE_REVIEW = WriteCodeReview
#WRITE_TEST = WriteTest
#RUN_CODE = RunCode
#DEBUG_ERROR = DebugError
#WRITE_TASKS = WriteTasks
#ASSIGN_TASKS = AssignTasks
# SEARCH_AND_SUMMARIZE = SearchAndSummarize
__all__ = [

View file

@ -219,24 +219,37 @@ class MinecraftPlayer(SoftwareCompany):
self.environment.add_roles(roles)
self.game_memory.register_roles(roles)
def start(self, task):
def start(self, task, round=0):
"""Start a project from publishing boss requirement."""
self.task = task
self.environment.publish_message(
Message(role="Player", content=task, cause_by=PlayerActions)
Message(role="Player", content=task, cause_by=PlayerActions, round_id=round)
)
logger.info(self.game_info)
def _save(self):
logger.info(self.json())
def _reset(self):
for role_profile, role in self.environment.roles.items():
role.reset_state()
async def run(self, n_round=3):
"""Run company until target round or no money"""
round_id=0
while n_round > 0:
# self._save()
n_round -= 1
logger.debug(f"{n_round=}")
if self.check_complete_round():
n_round -= 1
self.update_round()
round_id+=1
# add new task into env and continue
#fixme: update self.task
self.start(task=self.task, round=round_id)
logger.info(f"{n_round=}")
self._check_balance()
await self.environment.run()
#self.environment.memory.clear()
#self._reset()
return self.environment.history

View file

@ -7,19 +7,20 @@
"""
from metagpt.roles.role import Role
'''
from metagpt.roles.architect import Architect
from metagpt.roles.project_manager import ProjectManager
from metagpt.roles.product_manager import ProductManager
from metagpt.roles.engineer import Engineer
from metagpt.roles.qa_engineer import QaEngineer
'''
__all__ = [
"Role",
"Architect",
"ProjectManager",
"ProductManager",
"Engineer",
"QaEngineer",
#"Architect",
#"ProjectManager",
#"ProductManager",
#"Engineer",
#"QaEngineer",
]

View file

@ -197,7 +197,7 @@ class ActionDeveloper(Base):
async def _act(self) -> Message:
todo = self._rc.todo
logger.debug(f"Todo is {todo}")
self.maintain_actions(todo)
# 获取最新的游戏周边信息
events = await self._obtain_events()
self.perform_game_info_callback(events, self.game_memory.update_event)
@ -225,6 +225,7 @@ class ActionDeveloper(Base):
if handler:
msg = await handler(**message)
msg.cause_by = type(todo)
msg.round_id = self.round_id
logger.info(msg.send_to)
self._publish_message(msg)
return msg

View file

@ -116,7 +116,7 @@ class CriticReviewer(Base):
async def _act(self) -> Message:
todo = self._rc.todo
logger.debug(f"Todo is {todo}")
self.maintain_actions(todo)
# 获取最新的游戏周边信息
events = await self._obtain_events()
context = self.game_memory.context
@ -136,6 +136,7 @@ class CriticReviewer(Base):
if handler:
msg = await handler(**message)
msg.cause_by = type(todo)
msg.round_id = self.round_id
logger.info(msg.send_to)
self._publish_message(msg)
return msg

View file

@ -357,7 +357,7 @@ class CurriculumDesigner(Base):
async def _act(self) -> Message:
todo = self._rc.todo
logger.debug(f"Todo is {todo}")
self.maintain_actions(todo)
# 获取最新的游戏周边环境信息
events = await self._obtain_events()
self.perform_game_info_callback(events, self.game_memory.update_event)
@ -386,6 +386,7 @@ class CurriculumDesigner(Base):
else:
msg = await handler(**design_curriculum_message)
msg.cause_by = type(todo)
msg.round_id = self.round_id
self._publish_message(msg)
return msg

View file

@ -11,7 +11,7 @@ from metagpt.schema import HumanMessage, SystemMessage
from typing import Dict
from pydantic import BaseModel
from metagpt.roles.role import RoleContext
class Registry(BaseModel):
"""Registry for storing and building classes."""
@ -47,18 +47,47 @@ class Minecraft(Role):
super().__init__(name, profile, goal, constraints)
self.game_memory = None
self.event = {}
self.round_id = 0
self.finish_state = len(self._actions)
self.finish_step = False
def maintain_actions(self, todo):
if todo in self._actions:
self.finish_state-=1
if self.finish_state<=0:
self.finish_step = True
async def _observe(self) -> int:
await super()._observe()
for msg in self._rc.news:
logger.info(f"check msg round :{msg.round_id}")
logger.info(msg.round_id == self.round_id)
self._rc.news = [
msg for msg in self._rc.news if msg.round_id == self.round_id
] # only relevant msgs count as observed news
logger.info(len(self._rc.news))
return len(self._rc.news)
async def _think(self) -> None:
logger.info(self._actions)
logger.info(self._rc.state)
if len(self._actions) == 1:
# If there is only one action, then only this one can be performed
self._set_state(0)
return True
if self._rc.todo is None:
logger.info("0")
self._set_state(0)
return True
'''
if self._rc.state+1==len(self._states):
logger.info("new run")
self._set_state(0)
return True
'''
if self._rc.state + 1 < len(self._states):
self._set_state(self._rc.state + 1)
logger.info("1")
@ -66,9 +95,13 @@ class Minecraft(Role):
else:
self._rc.todo = None
logger.info("2")
self._set_state(self._rc.state)
logger.info(f"self.finish_step: {self.finish_step}")
return False
def reset_state(self):
self._rc.todo = None
async def _obtain_events(self):
return await self.game_memory.on_event()
@ -83,7 +116,7 @@ class Minecraft(Role):
@staticmethod
def perform_game_info_callback(info: object, callback: object) -> object:
logger.debug(info)
logger.info(info)
callback(info)
def encapsule_message(self, msg, *args, **kwargs):

View file

@ -23,7 +23,7 @@ class SkillManager(Base):
) -> None:
super().__init__(name, profile, goal, constraints)
# Initialize actions specific to the SkillManager role
self._init_actions([RetrieveSkills, GenerateSkillDescription, AddNewSkills])
self._init_actions([RetrieveSkills, GenerateSkillDescription]) #AddNewSkills])#先去掉add
# Set events or actions the SkillManager should watch or be aware of
self._watch([DesignCurriculum, VerifyTask, RetrieveSkills, GenerateSkillDescription])
@ -47,7 +47,7 @@ class SkillManager(Base):
async def _act(self) -> Message:
todo = self._rc.todo
logger.debug(f"Todo is {todo}")
self.maintain_actions(todo)
# 获取最新的游戏周边信息
context = self.game_memory.context
@ -65,6 +65,7 @@ class SkillManager(Base):
if handler:
msg = await handler(**message)
msg.cause_by = type(todo)
msg.round_id = self.round_id
self._publish_message(msg)
return msg

View file

@ -127,6 +127,7 @@ class Role:
self._rc.state = state
logger.debug(self._actions)
self._rc.todo = self._actions[self._rc.state]
logger.info(self._rc.todo)
def set_env(self, env: 'Environment'):
"""Set the environment in which the role works. The role can talk to the environment and can also receive messages by observing."""
@ -184,9 +185,11 @@ class Role:
env_msgs = self._rc.env.memory.get()
observed = self._rc.env.memory.get_by_actions(self._rc.watch)
logger.info(observed)
#logger.info(observed)
#self._rc.news = observed
self._rc.news = self._rc.memory.remember(observed) # remember recent exact or similar memories
logger.info(self._rc.news)
if len(self._rc.news)>0:
logger.info(self._rc.news)
for i in env_msgs:
self.recv(i)
@ -205,7 +208,7 @@ class Role:
async def _react(self) -> Message:
"""Think first, then act"""
await self._think()
logger.debug(f"{self._setting}: {self._rc.state=}, will do {self._rc.todo}")
logger.info(f"{self._setting}: {self._rc.state=}, will do {self._rc.todo}")
return await self._act()
def recv(self, message: Message) -> None:

View file

@ -29,6 +29,7 @@ class Message:
cause_by: Type["Action"] = field(default="")
sent_from: str = field(default="")
send_to: str = field(default="")
round_id: int=0
def __str__(self):
# prefix = '-'.join([self.role, str(self.cause_by)])