diff --git a/metagpt/environment/mgx/mgx_env.py b/metagpt/environment/mgx/mgx_env.py index 3a492b3ac..8347e4f44 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 "The monitor has verified the message, confirmation acknowledged. Refrain from resending duplicate messages." + return "Human has received and confirmed the message. Refrain from resending duplicate messages. Jsut move the plan to the next task." 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/role_zero.py b/metagpt/prompts/di/role_zero.py index d3f978c15..375e7f256 100644 --- a/metagpt/prompts/di/role_zero.py +++ b/metagpt/prompts/di/role_zero.py @@ -10,7 +10,7 @@ Note: 4. Don't forget to append task first when all existing tasks are finished and new tasks are required. 5. Avoid repeating tasks you have already completed. And end loop when all requirements are met. """ -# To ensure compatibility with hard-coded experience, do not add any other content between "# Example" and "# Instruction". +# To ensure compatibility with hard-coded experience, do not add any other content between "# Example" and "# User Requirements". CMD_PROMPT = """ # Latest Observation {latest_observation} @@ -39,6 +39,9 @@ Special Command: Use {{"command_name": "end"}} to do nothing or indicate complet # Example {example} +# User Requirements +{user_requirements} + # Instruction {instruction} @@ -50,10 +53,9 @@ In your response, include at least one command. # 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 before JSON is required, such as what tasks have been completed, what tasks are next, 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. -Output should adhere to the following format. -Firstly, describe the actions you have taken recently. -Secondly, describe the messages you have received recently, with a particular emphasis on messages from users. -Thirdly, describe your current task . Review the histroy, if you find that the current task is identical to a previously completed one, it indicates that the current task has already been accomplished. If all tasks are finished and current task is empty, use the end command to terminate. +Firstly, pay attention to User Requirements and it's constraints. Provide a complete description of the User Requirements and the current task. +Secondly, pay attention to the Latest Observation, describing what the latest observation is and any relevant messages. +Thirdly, if you find that the current task is identical to a previously completed one, it indicates that the current task has already been accomplished. Then, articulate your thoughts and list the commands, adhering closely to the instructions provided. ```json [ @@ -64,8 +66,9 @@ Then, articulate your thoughts and list the commands, adhering closely to the in ... ] ``` -Notice: your output JSON data must be a command list. Notice: your output JSON data section must start with **```json [** +Notice: Your answer must start with an ordinal number. +Notice: The response and arguments must be in the language specified in the User Requirements. """ JSON_REPAIR_PROMPT = """ @@ -78,10 +81,11 @@ JSON_REPAIR_PROMPT = """ ``` Do not use escape characters in json data, particularly within file paths. Help check if there are any formatting issues with the JSON data? If so, please help format it. -If no issues are detected, the original json data should be returned unchanged. +If no issues are detected, the original json data should be returned unchanged. Do not omit any information. Output the JSON data in a format that can be loaded by the json.loads() function. """ + QUICK_THINK_PROMPT = """ Decide if the latest user message previously is a quick question. Quick questions include common-sense, logical, math, multiple-choice questions, greetings, or casual chat that you can answer directly. diff --git a/metagpt/prompts/di/team_leader.py b/metagpt/prompts/di/team_leader.py index acd44d56c..f3d677d45 100644 --- a/metagpt/prompts/di/team_leader.py +++ b/metagpt/prompts/di/team_leader.py @@ -15,8 +15,8 @@ You should use TeamLeader.publish_team_message to team members, asking them to s Pay close attention to new user message, review the conversation history, use RoleZero.reply_to_human to respond to the user directly, DON'T ask your team members. Pay close attention to messages from team members. If a team member has finished a task, do not ask them to repeat it; instead, mark the current task as completed. Note: -1. If the requirement is a pure DATA-RELATED requirement, such as web browsing, web scraping, web searching, web imitation, data science, data analysis, machine learning, deep learning, text-to-image etc. DON'T decompose it, assign a single task with the original user requirement as instruction directly to Data Analyst. -2. If the requirement is developing a software, game, app, or website, excluding the above data-related tasks, you should decompose the requirement into multiple tasks and assign them to different team members based on their expertise, usually the sequence of Product Manager -> Architect -> Project Manager -> Engineer -> (optional: QaEngine if present) -> (optional: DataAnalyst if user requests deployment), each assigned ONE task. When publishing message to Product Manager, you should directly copy the full original user requirement. +1. If the requirement is a pure DATA-RELATED requirement, such as bug fixes, issue reporting, environment setup, terminal operations, pip install, web browsing, web scraping, web searching, web imitation, data science, data analysis, machine learning, deep learning, text-to-image etc. DON'T decompose it, assign a single task with the original user requirement as instruction directly to Data Analyst. +2. If the requirement is developing a software, game, app, or website, excluding the above data-related tasks, you should decompose the requirement into multiple tasks and assign them to different team members based on their expertise. The software default development process has four steps: creating a Product Requirement Document (PRD) by the Product Manager, writing a System Design by the Architect, creating tasks by the Project Manager, and coding by the Engineer. You may choose to execute any of these steps. When publishing message to Product Manager, you should directly copy the full original user requirement. 3. If the requirement contains both DATA-RELATED part mentioned in 1 and software development part mentioned in 2, you should decompose the software development part and assign them to different team members based on their expertise, and assign the DATA-RELATED part to Data Analyst David directly. 4. If the requirement is a common-sense, logical, or math problem, you should respond directly without assigning any task to team members. 5. If you think the requirement is not clear or ambiguous, you should ask the user for clarification immediately. Assign tasks only after all info is clear. @@ -24,8 +24,8 @@ Note: 7. If the requirement is writing a TRD and software framework, you should assign it to Architect. When publishing message to Architect, you should directly copy the full original user requirement. 8. If the receiver message reads 'from {{team member}} to {{\'\'}}, it indicates that someone has completed the current task. Note this in your thoughts. 9. Do not use the 'end' command when the current task remains unfinished; instead, use the 'finish_current_task' command to indicate completion before switching to the next task. -10. If you have made a plan, simply follow it without creating a new one. -11. Do not use escape characters in json data, particularly within file paths. +10. Do not use escape characters in json data, particularly within file paths. +11. Analyze the capabilities of team members and assign tasks to them based on user Requirements. If the requirements ask to ignore certain tasks, follow the requirements. """ QUICK_THINK_SYSTEM_PROMPT = """ diff --git a/metagpt/roles/architect.py b/metagpt/roles/architect.py index f640d4a87..c14a424da 100644 --- a/metagpt/roles/architect.py +++ b/metagpt/roles/architect.py @@ -11,6 +11,14 @@ from metagpt.roles.di.role_zero import RoleZero from metagpt.tools.libs.software_development import write_trd_and_framework from metagpt.utils.common import tool2name +ARCHITECT_INSTRUCTION = """ +Use WriteDesign tool to write a system design document if a system design is required;Use `write_trd_and_framework` tool to write a software framework if a software framework is required; + +Note: +1. When you think, just analyze which tool you should use, and then provide your answer. And your output should contain firstly, secondly, ... +2. The automated tools at your disposal will generate a document that perfectly meets your requirements. There is no need to do it manually. +""" + class Architect(RoleZero): """ @@ -25,13 +33,13 @@ class Architect(RoleZero): name: str = "Bob" profile: str = "Architect" - goal: str = "design a concise, usable, complete software system" + goal: str = "design a concise, usable, complete software system. Create a System Design Document." constraints: str = ( "make sure the architecture is simple enough and use appropriate open source " "libraries. Use same language as user requirement" ) - instruction: str = """Use WriteDesign tool to write a system design document if a system design is required; Use `write_trd_and_framework` tool to write a software framework if a software framework is required;""" + instruction: str = ARCHITECT_INSTRUCTION max_react_loop: int = 1 # FIXME: Read and edit files requires more steps, consider later tools: list[str] = [ "Editor:write,read,write_content", diff --git a/metagpt/roles/di/role_zero.py b/metagpt/roles/di/role_zero.py index 40c03ccad..27bbb76b9 100644 --- a/metagpt/roles/di/role_zero.py +++ b/metagpt/roles/di/role_zero.py @@ -156,6 +156,7 @@ class RoleZero(Role): current_task=current_task, instruction=instruction, latest_observation=memory[-1].content, + user_requirements=self.planner.plan, ) memory = await self.parse_browser_actions(memory) req = self.llm.format_msg(memory + [UserMessage(content=prompt)]) diff --git a/metagpt/roles/product_manager.py b/metagpt/roles/product_manager.py index 7933e74b8..4a86e39f1 100644 --- a/metagpt/roles/product_manager.py +++ b/metagpt/roles/product_manager.py @@ -15,6 +15,14 @@ from metagpt.roles.role import RoleReactMode from metagpt.utils.common import any_to_name, any_to_str, tool2name from metagpt.utils.git_repository import GitRepository +PRODUCTMANAGER_INSTRUCTION = """ +Use WritePRD tool to write PRD if a PRD is required; +Use `Pic2Txt` tool to write out an intact textual user requirements if an intact textual user requiremnt is required given some images alongside the contextual textual descriptions; + +Note: +1. Consider which tools you need in your thoughts. +""" + class ProductManager(RoleZero): """ @@ -29,13 +37,13 @@ class ProductManager(RoleZero): name: str = "Alice" profile: str = "Product Manager" - goal: str = "efficiently create a successful product that meets market demands and user expectations" + goal: str = "efficiently create a successful product that meets market demands and user expectations. Create a Product Requirement Document.." constraints: str = "utilize the same language as the user requirements for seamless communication" todo_action: str = any_to_name(WritePRD) - instruction: str = """Use WritePRD tool to write PRD if a PRD is required, users may asks for a software without mentioning PRD, but you should output the PRD of that software; Use `Pic2Txt` tool to write out an intact textual user requirements if an intact textual user requiremnt is required given some images alongside the contextual textual descriptions""" + instruction: str = """Use WritePRD tool to write PRD if a PRD is required; Use `Pic2Txt` tool to write out an intact textual user requirements if an intact textual user requiremnt is required given some images alongside the contextual textual descriptions;""" max_react_loop: int = 1 # FIXME: Read and edit files requires more steps, consider later - tools: list[str] = ["RoleZero", "WritePRD", Pic2Txt.__name__] + tools: list[str] = ["Editor:write,read,write_content", "RoleZero", "WritePRD", Pic2Txt.__name__] def __init__(self, **kwargs) -> None: super().__init__(**kwargs) diff --git a/metagpt/tools/libs/editor.py b/metagpt/tools/libs/editor.py index 4c6d2b1dc..ca0fbbae5 100644 --- a/metagpt/tools/libs/editor.py +++ b/metagpt/tools/libs/editor.py @@ -36,7 +36,7 @@ class Editor: with open(path, "w", encoding="utf-8") as f: f.write(content) # self.resource.report(path, "path") - return f"The writing/coding the of the file {os.path.basename(path)}' is now completed. The file '{os.path.basename(path)}' has been successfully created." + return f"Writing/coding the of the file {os.path.basename(path)}' has been completed. The file '{os.path.basename(path)}' has been successfully created." def read(self, path: str) -> FileBlock: """Read the whole content of a file. Using absolute paths as the argument for specifying the file location.""" diff --git a/tests/metagpt/exp_pool/test_context_builders/test_rolezero_context_builder.py b/tests/metagpt/exp_pool/test_context_builders/test_rolezero_context_builder.py index b7182602d..9e7e628d5 100644 --- a/tests/metagpt/exp_pool/test_context_builders/test_rolezero_context_builder.py +++ b/tests/metagpt/exp_pool/test_context_builders/test_rolezero_context_builder.py @@ -34,7 +34,7 @@ class TestRoleZeroContextBuilder: result = context_builder.replace_example_content("Original text", "New example content") assert result == "Replaced content" context_builder.replace_content_between_markers.assert_called_once_with( - "Original text", "# Example", "# Instruction", "New example content" + "Original text", "# Example", "# User Requirements", "New example content" ) def test_replace_content_between_markers(self):