From 775a327fbdb7e1e4a9c01b2798b80ffb7c263979 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E4=BC=9F=E9=9F=AC?= Date: Thu, 18 Jul 2024 11:49:44 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9Editor.read=20=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E8=B7=AF=E5=BE=84=E9=94=99=E8=AF=AF=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- metagpt/environment/mgx/mgx_env.py | 2 +- metagpt/roles/di/role_zero.py | 34 ++++++++++++++++++------ metagpt/strategy/experience_retriever.py | 13 ++++++++- 3 files changed, 39 insertions(+), 10 deletions(-) diff --git a/metagpt/environment/mgx/mgx_env.py b/metagpt/environment/mgx/mgx_env.py index 69f80c2ff..1f74a16c8 100644 --- a/metagpt/environment/mgx/mgx_env.py +++ b/metagpt/environment/mgx/mgx_env.py @@ -91,7 +91,7 @@ class MGXEnv(Environment): async def reply_to_human(self, content: str, sent_from: Role = None) -> str: # NOTE: Can be overwritten in remote setting - return content + return "Message send successfully." def message_within_software_sop(self, message: Message) -> bool: # Engineer, QaEngineer can be end of the SOP. Their msg requires routing outside. diff --git a/metagpt/roles/di/role_zero.py b/metagpt/roles/di/role_zero.py index 5f27c79ef..c945f4d3d 100644 --- a/metagpt/roles/di/role_zero.py +++ b/metagpt/roles/di/role_zero.py @@ -28,6 +28,7 @@ from metagpt.tools.tool_registry import register_tool from metagpt.utils.common import CodeParser, any_to_str from metagpt.utils.repair_llm_raw_output import RepairType, repair_llm_raw_output from metagpt.utils.report import ThoughtReporter +from metagpt.const import DEFAULT_WORKSPACE_ROOT @register_tool(include_functions=["ask_human", "reply_to_human"]) @@ -148,7 +149,9 @@ class RoleZero(Role): current_task=current_task, example=example, available_commands=tool_info, + pre_task = await self._parse_commands(), instruction=self.instruction.strip(), + root_direction = DEFAULT_WORKSPACE_ROOT, task_type_desc=self.task_type_desc, ) memory = self.rc.memory.get(self.memory_k) @@ -158,8 +161,17 @@ class RoleZero(Role): async with ThoughtReporter(enable_llm_stream=True) as reporter: await reporter.async_report({"type": "react"}) self.command_rsp = await self.llm.aask(context, system_msgs=self.system_msg) - self.rc.memory.add(AIMessage(content=self.command_rsp)) - + try : + commands = CodeParser.parse_code(block=None, lang="json", text=self.command_rsp) + commands = json.loads(repair_llm_raw_output(output=commands, req_keys=[None], repair_type=RepairType.JSON)) + except : + logger.warning('Trying to repair json string with repair tool...') + commands = CodeParser.parse_code(block=None, lang="json", text=self.command_rsp).strip() + if commands.endswith(']') and not commands.startswith('['): + commands = '['+ commands + self.command_rsp = f"```json\n{self.commands}\n```" + print(self.command_rsp) + self.rc.memory.add(AIMessage(content=self.command_rsp)) return True async def parse_browser_actions(self, memory: List[Message]) -> List[Message]: @@ -275,8 +287,9 @@ class RoleZero(Role): for cmd in commands: output = f"Command {cmd['command_name']} executed" # handle special command first - if await self._run_special_command(cmd): - outputs.append(output) + if self._is_special_command(cmd): + special_command_output = await self._run_special_command(cmd) + outputs.append(output+':'+special_command_output) continue # run command as specified by tool_execute_map if cmd["command_name"] in self.tool_execution_map: @@ -300,20 +313,25 @@ class RoleZero(Role): outputs = "\n\n".join(outputs) return outputs - - async def _run_special_command(self, cmd) -> bool: + def _is_special_command(self,cmd) -> bool: + + return cmd["command_name"] in self.special_tool_commands + + async def _run_special_command(self, cmd) -> str: """command requiring special check or parsing""" - is_special_cmd = cmd["command_name"] in self.special_tool_commands + command_output = "" if cmd["command_name"] == "Plan.finish_current_task" and not self.planner.plan.is_plan_finished(): # task_result = TaskResult(code=str(commands), result=outputs, is_success=is_success) # self.planner.plan.current_task.update_task_result(task_result=task_result) self.planner.plan.finish_current_task() + command_output = "Current task is finished. " elif cmd["command_name"] == "end": self._set_state(-1) + command_output = "Everything Done" - return is_special_cmd + return command_output def _get_plan_status(self) -> Tuple[str, str]: plan_status = self.planner.plan.model_dump(include=["goal", "tasks"]) diff --git a/metagpt/strategy/experience_retriever.py b/metagpt/strategy/experience_retriever.py index 668b44c40..4e9817f2c 100644 --- a/metagpt/strategy/experience_retriever.py +++ b/metagpt/strategy/experience_retriever.py @@ -585,7 +585,7 @@ Explanation: You received a message from Alice, the Product Manager, that she ha { "command_name": "RoleZero.reply_to_human", "args": { - "content": "Alice has completed the PRD. I have marked her task as finished and sent the PRD to Bob. Bob will work on the software architecture.", + "content": "Alice has completed the PRD. I have marked her task as finished and sent the PRD to Bob. Bob will work on the software architecture." } }, { @@ -610,6 +610,17 @@ Explanation: The user is asking for a general update on the project status. Give } ] ``` + +## example 4 +OBSERVATION : current task is none and all task is finished. +Explanation: Last task is "Plan.finish_current_task" and now the current task is none, it means everything is done.Just coutput command "end". +```json +[ + { + "command_name": "end" + } +] +``` """