diff --git a/metagpt/prompts/di/engineer2.py b/metagpt/prompts/di/engineer2.py index cef90ec3e..016884d2b 100644 --- a/metagpt/prompts/di/engineer2.py +++ b/metagpt/prompts/di/engineer2.py @@ -80,6 +80,7 @@ Note: 21. When using the editor, pay attention to the editor's current directory. When you use editor tools, the paths must be either absolute or relative to the editor's current directory. 22. The default programming languages are Native HTML. 23. When planning, consider whether images are needed. If you are developing a showcase website, start by using ImageGetter.get_image to obtain the necessary images. +24. If you finish all the tasks, use the command "end" to end. """ CURRENT_STATE = """ The current editor state is: diff --git a/metagpt/prompts/di/role_zero.py b/metagpt/prompts/di/role_zero.py index 820466b6f..2697ecef4 100644 --- a/metagpt/prompts/di/role_zero.py +++ b/metagpt/prompts/di/role_zero.py @@ -108,6 +108,17 @@ Describe if you should terminate using **end** command, or use **RoleZero.ask_hu You should use "end" to stop when all tasks have been completed and the requirements are satisfied. Your reflection, then the commands in a json array: """ +END_COMMAND = """ +```json +[ + { + "command_name": "end", + "args": {} + } +] +``` +""" + ASK_HUMAN_COMMAND = """ ```json [ diff --git a/metagpt/roles/di/role_zero.py b/metagpt/roles/di/role_zero.py index b4c7553ea..0e7e04969 100644 --- a/metagpt/roles/di/role_zero.py +++ b/metagpt/roles/di/role_zero.py @@ -21,6 +21,7 @@ from metagpt.prompts.di.role_zero import ( ASK_HUMAN_COMMAND, CMD_PROMPT, DETECT_LANGUAGE_PROMPT, + END_COMMAND, JSON_REPAIR_PROMPT, QUICK_RESPONSE_SYSTEM_PROMPT, QUICK_THINK_EXAMPLES, @@ -383,8 +384,8 @@ class RoleZero(Role): return rsp_msg, intent_result - async def _check_duplicates(self, req: list[dict], command_rsp: str): - past_rsp = [mem.content for mem in self.rc.memory.get(self.memory_k)] + async def _check_duplicates(self, req: list[dict], command_rsp: str, check_window: int = 10): + past_rsp = [mem.content for mem in self.rc.memory.get(check_window)] if command_rsp in past_rsp: # Normal response with thought contents are highly unlikely to reproduce # If an identical response is detected, it is a bad response, mostly due to LLM repeating generated content @@ -393,6 +394,10 @@ class RoleZero(Role): # Hard rule to ask human for help if past_rsp.count(command_rsp) >= 3: + if '"command_name": "Plan.finish_current_task",' in command_rsp: + # Detect the deplicate of "Plan.finish_current_task" command, use command "end" to finish the task + logger.warning(f"Duplicate response detected: {command_rsp}") + return END_COMMAND return ASK_HUMAN_COMMAND # Try correction by self logger.warning(f"Duplicate response detected: {command_rsp}") diff --git a/metagpt/tools/libs/editor.py b/metagpt/tools/libs/editor.py index 9d1dc9730..ca8cd9ccf 100644 --- a/metagpt/tools/libs/editor.py +++ b/metagpt/tools/libs/editor.py @@ -696,7 +696,7 @@ class Editor(BaseModel): new_content: str, ) -> str: """ - Line numbers start from 1. Replaces lines start_line through end_line (inclusive) with the given text in the open file. + Line numbers start from 1. Replace lines from start_line to end_line (inclusive) with the new_content in the open file. All of the new_content will be entered, so makesure your indentation is formatted properly. The new_content must be a complete block of code. @@ -712,14 +712,14 @@ class Editor(BaseModel): EDITING: If you want to replace line 2 and line 3 edit_file_by_replace( - '/workspace/example.txt', - first_replaced_line_number =2, + "/workspace/example.txt", + first_replaced_line_number=2, first_replaced_line_content="contain g", - last_replaced_line_number =3, + last_replaced_line_number=3, last_replaced_line_content="contain h", - new_content='new content', + new_content="new content", ) - This will replace only the second line 2 and line 3 with "new content". + This will replace the second line 2 and line 3 with "new content". The resulting file will be: ``` @@ -735,16 +735,16 @@ class Editor(BaseModel): 003|contain h 004|contain i ``` - EDITING: If you want to remove the line 2 and line 3 + EDITING: If you want to remove the line 2 and line 3. edit_file_by_replace( - '/workspace/example.txt', - first_replaced_line_number =2, + "/workspace/example.txt", + first_replaced_line_number=2, first_replaced_line_content="contain g", - last_replaced_line_number =3, + last_replaced_line_number=3, last_replaced_line_content="contain h", - new_content='', + new_content="", ) - This will remove line 2 and line 3 + This will remove line 2 and line 3. The resulting file will be: ``` 001|contain f @@ -752,12 +752,12 @@ class Editor(BaseModel): 003|contain i ``` Args: - file_name (str):The name of the file to edit. - first_replaced_line_number (int):The line number to start the edit at, starting from 1. - first_replaced_line_content (str):The content of the start replace line, according to the first_replaced_line_number . - last_replaced_line_number (int):The line number to end the edit at (inclusive), starting from 1. - last_replaced_line_content (str):The content of the end replace line, according to the last_replaced_line_number . - new_content (str): The text to replace the current selection with, must conform to PEP8 standards.The content in the start line and end line will also be replaced. + file_name (str): The name of the file to edit. + first_replaced_line_number (int): The line number to start the edit at, starting from 1. + first_replaced_line_content (str): The content of the start replace line, according to the first_replaced_line_number. + last_replaced_line_number (int): The line number to end the edit at (inclusive), starting from 1. + last_replaced_line_content (str): The content of the end replace line, according to the last_replaced_line_number. + new_content (str): The text to replace the current selection with, must conform to PEP8 standards. The content in the start line and end line will also be replaced. """ @@ -938,7 +938,7 @@ class Editor(BaseModel): Args: file_name: (str): The name of the file to edit. line_number (int): The line number (starting from 1) to insert the content after.the insert content will be add between the line of line_number-1 and line_number - insert_content (str): The content to insert betweed the previous_line_content and current_line_content.The insert_content must be a complete block of code at. + insert_content (str): The content to insert betweed the previous_line_content and current_line_content.The insert_content must be a complete block of code at. NOTE: This tool is exclusive. If you use this tool, you cannot use any other commands in the current response.