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 1/7] =?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" + } +] +``` """ From 94aada5e0db69e4b74b810e42c72d8fc5eadae52 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 14:20:26 +0800 Subject: [PATCH 2/7] =?UTF-8?q?=E4=BF=AE=E6=94=B9role=5Fzore=E6=8F=90?= =?UTF-8?q?=E7=A4=BA=E8=AF=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- metagpt/prompts/di/role_zero.py | 6 ++++-- metagpt/roles/di/role_zero.py | 9 +++++---- metagpt/tools/libs/editor.py | 2 +- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/metagpt/prompts/di/role_zero.py b/metagpt/prompts/di/role_zero.py index 243f33604..5561d0942 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 c945f4d3d..c33e398be 100644 --- a/metagpt/roles/di/role_zero.py +++ b/metagpt/roles/di/role_zero.py @@ -149,13 +149,12 @@ 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) memory = await self.parse_browser_actions(memory) + memory = await self.add_editor_root_directory(memory) context = self.llm.format_msg(memory + [UserMessage(content=prompt)]) # print(*context, sep="\n" + "*" * 5 + "\n") async with ThoughtReporter(enable_llm_stream=True) as reporter: @@ -173,7 +172,10 @@ class RoleZero(Role): print(self.command_rsp) self.rc.memory.add(AIMessage(content=self.command_rsp)) return True - + + async def add_editor_root_directory(self,memory) -> List[Message]: + memory.append(UserMessage(cause_by="editory", content=f'Root directory is {DEFAULT_WORKSPACE_ROOT}')) + return memory async def parse_browser_actions(self, memory: List[Message]) -> List[Message]: if not self.browser.is_empty_page: pattern = re.compile(r"Command Browser\.(\w+) executed") @@ -251,7 +253,6 @@ class RoleZero(Role): ) return rsp_msg - async def _parse_commands(self) -> Tuple[List[Dict], bool]: """Retrieves commands from the Large Language Model (LLM). diff --git a/metagpt/tools/libs/editor.py b/metagpt/tools/libs/editor.py index c9f02c4f1..edc228b12 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() From 56efc6d155a89b8407cdbd59181451bf2fa6abc0 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 14:43:59 +0800 Subject: [PATCH 3/7] =?UTF-8?q?=E4=BF=AE=E6=94=B9role=5Fzore=E9=87=8D?= =?UTF-8?q?=E5=A4=8D=E6=8C=87=E4=BB=A4=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- metagpt/roles/di/role_zero.py | 36 ++++++++++++------------ metagpt/strategy/experience_retriever.py | 4 +-- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/metagpt/roles/di/role_zero.py b/metagpt/roles/di/role_zero.py index d4bba89de..23755d3e8 100644 --- a/metagpt/roles/di/role_zero.py +++ b/metagpt/roles/di/role_zero.py @@ -10,9 +10,7 @@ from pydantic import model_validator from metagpt.actions import Action, UserRequirement from metagpt.actions.di.run_command import RunCommand -from metagpt.exp_pool import exp_cache -from metagpt.exp_pool.context_builders import RoleZeroContextBuilder -from metagpt.exp_pool.serializers import RoleZeroSerializer +from metagpt.const import DEFAULT_WORKSPACE_ROOT from metagpt.logs import logger from metagpt.prompts.di.role_zero import ( CMD_PROMPT, @@ -31,7 +29,6 @@ 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"]) @@ -164,22 +161,24 @@ 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) - try : + # check and repair + 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...') + 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```" + if commands.endswith("]") and not commands.startswith("["): + commands = "[" + commands + self.command_rsp = f"```json\n{self.command_rsp}\n```" print(self.command_rsp) - self.rc.memory.add(AIMessage(content=self.command_rsp)) + self.rc.memory.add(AIMessage(content=self.command_rsp)) return True - - async def add_editor_root_directory(self,memory) -> List[Message]: - memory.append(UserMessage(cause_by="editory", content=f'Root directory is {DEFAULT_WORKSPACE_ROOT}')) + + async def add_editor_root_directory(self, memory) -> List[Message]: + memory.append(UserMessage(cause_by="editory", content=f"Root directory is {DEFAULT_WORKSPACE_ROOT}")) return memory + async def parse_browser_actions(self, memory: List[Message]) -> List[Message]: if not self.browser.is_empty_page: pattern = re.compile(r"Command Browser\.(\w+) executed") @@ -257,6 +256,7 @@ class RoleZero(Role): ) return rsp_msg + async def _parse_commands(self) -> Tuple[List[Dict], bool]: """Retrieves commands from the Large Language Model (LLM). @@ -294,7 +294,7 @@ class RoleZero(Role): # handle special command first if self._is_special_command(cmd): special_command_output = await self._run_special_command(cmd) - outputs.append(output+':'+special_command_output) + outputs.append(output + ":" + special_command_output) continue # run command as specified by tool_execute_map if cmd["command_name"] in self.tool_execution_map: @@ -318,10 +318,10 @@ class RoleZero(Role): outputs = "\n\n".join(outputs) return outputs - def _is_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""" command_output = "" diff --git a/metagpt/strategy/experience_retriever.py b/metagpt/strategy/experience_retriever.py index ee034cb16..bb1565f66 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" } }, { @@ -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 ..." } }, { From 838892e17d2e0e1ceda11c890285f906c05dbd6d 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 15:18:18 +0800 Subject: [PATCH 4/7] =?UTF-8?q?=E4=BF=AE=E6=94=B9role=5Fzero=E6=8C=87?= =?UTF-8?q?=E4=BB=A4=E5=BE=AA=E7=8E=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 | 6 ------ metagpt/strategy/experience_retriever.py | 2 +- 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/metagpt/environment/mgx/mgx_env.py b/metagpt/environment/mgx/mgx_env.py index 1f74a16c8..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 "Message send successfully." + 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/roles/di/role_zero.py b/metagpt/roles/di/role_zero.py index 23755d3e8..4a23110d3 100644 --- a/metagpt/roles/di/role_zero.py +++ b/metagpt/roles/di/role_zero.py @@ -10,7 +10,6 @@ from pydantic import model_validator from metagpt.actions import Action, UserRequirement from metagpt.actions.di.run_command import RunCommand -from metagpt.const import DEFAULT_WORKSPACE_ROOT from metagpt.logs import logger from metagpt.prompts.di.role_zero import ( CMD_PROMPT, @@ -155,7 +154,6 @@ class RoleZero(Role): ) memory = self.rc.memory.get(self.memory_k) memory = await self.parse_browser_actions(memory) - memory = await self.add_editor_root_directory(memory) context = self.llm.format_msg(memory + [UserMessage(content=prompt)]) # print(*context, sep="\n" + "*" * 5 + "\n") async with ThoughtReporter(enable_llm_stream=True) as reporter: @@ -175,10 +173,6 @@ class RoleZero(Role): self.rc.memory.add(AIMessage(content=self.command_rsp)) return True - async def add_editor_root_directory(self, memory) -> List[Message]: - memory.append(UserMessage(cause_by="editory", content=f"Root directory is {DEFAULT_WORKSPACE_ROOT}")) - return memory - async def parse_browser_actions(self, memory: List[Message]) -> List[Message]: if not self.browser.is_empty_page: pattern = re.compile(r"Command Browser\.(\w+) executed") diff --git a/metagpt/strategy/experience_retriever.py b/metagpt/strategy/experience_retriever.py index bb1565f66..7a943fc7f 100644 --- a/metagpt/strategy/experience_retriever.py +++ b/metagpt/strategy/experience_retriever.py @@ -613,7 +613,7 @@ 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". +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 [ { From 8fec1d17758f4a5fdb5c743267de76461f1cb050 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 15:45:09 +0800 Subject: [PATCH 5/7] =?UTF-8?q?=E5=90=88=E5=B9=B6role=5Fzero?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- metagpt/roles/di/role_zero.py | 39 ++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/metagpt/roles/di/role_zero.py b/metagpt/roles/di/role_zero.py index 4a23110d3..40bc2e3c7 100644 --- a/metagpt/roles/di/role_zero.py +++ b/metagpt/roles/di/role_zero.py @@ -10,6 +10,9 @@ from pydantic import model_validator from metagpt.actions import Action, UserRequirement from metagpt.actions.di.run_command import RunCommand +from metagpt.exp_pool import exp_cache +from metagpt.exp_pool.context_builders import RoleZeroContextBuilder +from metagpt.exp_pool.serializers import RoleZeroSerializer from metagpt.logs import logger from metagpt.prompts.di.role_zero import ( CMD_PROMPT, @@ -154,25 +157,31 @@ class RoleZero(Role): ) memory = self.rc.memory.get(self.memory_k) memory = await self.parse_browser_actions(memory) - context = self.llm.format_msg(memory + [UserMessage(content=prompt)]) - # print(*context, sep="\n" + "*" * 5 + "\n") + + req = self.llm.format_msg(memory + [UserMessage(content=prompt)]) 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) - # check and repair - 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.command_rsp}\n```" - print(self.command_rsp) + state_data = dict( + plan_status=plan_status, + current_task=current_task, + instruction=instruction, + ) + self.command_rsp = await self.llm_cached_aask(req=req, system_msgs=self.system_msg, state_data=state_data) + self.rc.memory.add(AIMessage(content=self.command_rsp)) + return True + @exp_cache(context_builder=RoleZeroContextBuilder(), serializer=RoleZeroSerializer()) + async def llm_cached_aask(self, *, req: list[dict], system_msgs: list[str], **kwargs) -> str: + """Use `exp_cache` to automatically manage experiences. + + The `RoleZeroContextBuilder` attempts to add experiences to `req`. + The `RoleZeroSerializer` extracts essential parts of `req` for the experience pool, trimming lengthy entries to retain only necessary parts. + """ + + return await self.llm.aask(req, system_msgs=system_msgs) + async def parse_browser_actions(self, memory: List[Message]) -> List[Message]: if not self.browser.is_empty_page: pattern = re.compile(r"Command Browser\.(\w+) executed") @@ -264,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...") From 0181bd293f3e6489ef0e1f4a1a47da27c35e410c 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 18:09:03 +0800 Subject: [PATCH 6/7] formate --- metagpt/prompts/di/engineer2.py | 1 + 1 file changed, 1 insertion(+) 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. """ From f62e66ec586281dd5518874297c5184e56620527 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 18:54:54 +0800 Subject: [PATCH 7/7] format --- metagpt/tools/libs/editor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metagpt/tools/libs/editor.py b/metagpt/tools/libs/editor.py index edc228b12..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.It is strongly advised to utilize absolute paths""" + """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()