diff --git a/metagpt/environment/mgx/mgx_env.py b/metagpt/environment/mgx/mgx_env.py index 69f80c2ff..3a492b3ac 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 "The monitor has verified the message, confirmation acknowledged. Refrain from resending duplicate messages." 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/prompts/di/engineer2.py b/metagpt/prompts/di/engineer2.py index f3f2155b6..c4dec8d5e 100644 --- a/metagpt/prompts/di/engineer2.py +++ b/metagpt/prompts/di/engineer2.py @@ -11,6 +11,7 @@ EXTRA_INSTRUCTION = """ 11. Write out EVERY CODE DETAIL, DON'T LEAVE TODO. 12. To modify code in a file, read the entire file, make changes, and update the file with the complete code, ensuring that no line numbers are included in the final write. 13. When a system design or project schedule is provided, at the end of the plan, add a CodeRview Task for each file; for example, if there are three files, add three CodeRview Tasks. For each CodeRview Task, just call ReviewAndRewriteCode.run. +14. When you are making plan.it is hightly recommand to plan all the coding plan and reviews plan in first response. """ diff --git a/metagpt/prompts/di/role_zero.py b/metagpt/prompts/di/role_zero.py index 890c1d562..5bf1e15fc 100644 --- a/metagpt/prompts/di/role_zero.py +++ b/metagpt/prompts/di/role_zero.py @@ -40,6 +40,7 @@ Special Command: Use {{"command_name": "end"}} to do nothing or indicate complet Pay close attention to the Example provided, you can reuse the example for your current situation if it fits. You may use any of the available commands to create a plan or update the plan. You may output mutiple commands, they will be executed sequentially. If you finish current task, you will automatically take the next task in the existing plan, use Plan.finish_task, DON'T append a new task. +Pay close attention to what you have done. Be different with your previous action. # Your commands in a json array, in the following output format with correct command_name and args. If there is nothing to do, use the pass or end command: Some text indicating your thoughts, such as how you should update the plan status, respond to inquiry, or seek for help. Then a json array of commands. You must output ONE and ONLY ONE json array. DON'T output multiple json arrays with thoughts between them. @@ -52,6 +53,7 @@ Some text indicating your thoughts, such as how you should update the plan statu ... ] ``` +Notice: your output JSON data must be a command list. Notice: your output JSON data section must start with **```json [** """ @@ -61,9 +63,9 @@ JSON_REPAIR_PROMPT = """ ## Output Format ```json -Formatted JSON data + ``` -Help check if there are any formatting issues with the JSON data? If so, please help format it +Help check if there are any formatting issues with the JSON data? If so, please help format it. """ QUICK_THINK_PROMPT = """ diff --git a/metagpt/roles/di/role_zero.py b/metagpt/roles/di/role_zero.py index ce305707e..40bc2e3c7 100644 --- a/metagpt/roles/di/role_zero.py +++ b/metagpt/roles/di/role_zero.py @@ -273,6 +273,8 @@ class RoleZero(Role): """ try: commands = CodeParser.parse_code(block=None, lang="json", text=self.command_rsp) + if commands.endswith("]") and not commands.startswith("["): + commands = "[" + commands commands = json.loads(repair_llm_raw_output(output=commands, req_keys=[None], repair_type=RepairType.JSON)) except json.JSONDecodeError: logger.warning(f"Failed to parse JSON for: {self.command_rsp}. Trying to repair...") @@ -295,8 +297,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: @@ -321,19 +324,24 @@ class RoleZero(Role): 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 ce5a8480e..7a943fc7f 100644 --- a/metagpt/strategy/experience_retriever.py +++ b/metagpt/strategy/experience_retriever.py @@ -520,7 +520,7 @@ Explanation: The requirement is about software development. Assign each tasks to { "command_name": "RoleZero.reply_to_human", "args": { - "content": "I have assigned the tasks to the team members. Alice will create the PRD, Bob will design the software architecture, Eve will break down the architecture into tasks, Alex will implement the core game logic, and Edward will write comprehensive tests. The team will work on the project accordingly", + "content": "I have assigned the tasks to the team members. Alice will create the PRD, Bob will design the software architecture, Eve will break down the architecture into tasks, Alex will implement the core game logic, and Edward will write comprehensive tests. The team will work on the project accordingly" } }, { @@ -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." } }, { @@ -602,7 +602,7 @@ Explanation: The user is asking for a general update on the project status. Give { "command_name": "RoleZero.reply_to_human", "args": { - "content": "The team is currently working on ... We have completed ...", + "content": "The team is currently working on ... We have completed ..." } }, { @@ -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" or 'RoleZero.reply_to_human' and now the current task is none, it means everything is done.Just coutput command "end". +```json +[ + { + "command_name": "end" + } +] +``` """ diff --git a/metagpt/tools/libs/editor.py b/metagpt/tools/libs/editor.py index c9f02c4f1..24eca65fc 100644 --- a/metagpt/tools/libs/editor.py +++ b/metagpt/tools/libs/editor.py @@ -38,7 +38,7 @@ class Editor: # self.resource.report(path, "path") def read(self, path: str) -> FileBlock: - """Read the whole content of a file.""" + """Read the whole content of a file. It is strongly advised to utilize absolute paths""" with open(path, "r") as f: self.resource.report(path, "path") lines = f.readlines()