From ff79389d9bdd3301886cb8780f1ed0dc4caaec59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E4=BC=9F=E9=9F=AC?= Date: Thu, 17 Oct 2024 18:49:26 +0800 Subject: [PATCH 1/7] refactor_the_architect --- metagpt/actions/project_management.py | 2 +- metagpt/actions/project_management_an.py | 3 +- metagpt/actions/write_prd_an.py | 4 +- metagpt/prompts/di/architect.py | 83 ++++++++++++++++++++++++ metagpt/prompts/di/engineer2.py | 2 +- metagpt/roles/architect.py | 35 +++------- metagpt/roles/di/role_zero.py | 2 +- metagpt/roles/project_manager.py | 2 +- metagpt/strategy/experience_retriever.py | 8 +-- metagpt/tools/libs/terminal.py | 10 ++- 10 files changed, 111 insertions(+), 40 deletions(-) create mode 100644 metagpt/prompts/di/architect.py diff --git a/metagpt/actions/project_management.py b/metagpt/actions/project_management.py index abfea7f10..1ce94cd99 100644 --- a/metagpt/actions/project_management.py +++ b/metagpt/actions/project_management.py @@ -180,7 +180,7 @@ class WriteTasks(Action): ) -> str: context = to_markdown_code_block(user_requirement) if design_filename: - design_filename = rectify_pathname(path=design_filename, default_filename="system_design.json") + design_filename = rectify_pathname(path=design_filename, default_filename="system_design.md") content = await aread(filename=design_filename) context += to_markdown_code_block(content) diff --git a/metagpt/actions/project_management_an.py b/metagpt/actions/project_management_an.py index 78f17653b..cca51a94b 100644 --- a/metagpt/actions/project_management_an.py +++ b/metagpt/actions/project_management_an.py @@ -28,7 +28,8 @@ LOGIC_ANALYSIS = ActionNode( expected_type=List[List[str]], instruction="Provide a list of files with the classes/methods/functions to be implemented, " "including dependency analysis and imports." - "Ensure consistency between System Design and Logic Analysis; the files must match exactly.", + "Ensure consistency between System Design and Logic Analysis; the files must match exactly. " + "If the file is written in Vue or React, use Tailwind CSS for styling.", example=[ ["game.py", "Contains Game class and ... functions"], ["main.py", "Contains main function, from game import Game"], diff --git a/metagpt/actions/write_prd_an.py b/metagpt/actions/write_prd_an.py index 574dcef89..81e16bcfa 100644 --- a/metagpt/actions/write_prd_an.py +++ b/metagpt/actions/write_prd_an.py @@ -19,8 +19,8 @@ LANGUAGE = ActionNode( PROGRAMMING_LANGUAGE = ActionNode( key="Programming Language", expected_type=str, - instruction="Mainstream programming language. If not specified in the requirements, use native HTML", - example="native HTML", + instruction="Mainstream programming language. If not specified in the requirements, use Vite, React, MUI, Tailwind CSS.", + example="Vite, React, MUI, Tailwind CSS", ) ORIGINAL_REQUIREMENTS = ActionNode( diff --git a/metagpt/prompts/di/architect.py b/metagpt/prompts/di/architect.py new file mode 100644 index 000000000..ed0c2b7d1 --- /dev/null +++ b/metagpt/prompts/di/architect.py @@ -0,0 +1,83 @@ +from metagpt.const import REACT_TEMPLATE_PATH, VUE_TEMPLATE_PATH + +SYSTEM_DESIGN_EXAMPLE = """ +```markdown +## Implementation approach": + +We will ... + +## File list + +- a.js +- b.py +- c.css +- d.html + +## Data structures and interfaces: + + +classDiagram + class Main { + <> + +main() str + } + class SearchEngine { + +search(query: str) str + } + class Index { + +create_index(data: dict) + +query_index(query: str) list + } + class Ranking { + +rank_results(results: list) list +} + +## Program call flow: + + +sequenceDiagram + participant M as Main + participant SE as SearchEngine + participant I as Index + participant R as Ranking + participant S as Summary + participant KB as KnowledgeBase + M->>SE: search(query) + SE->>I: query_index(query) + I->>KB: fetch_data(query) + KB-->>I: return data + + +## Anything UNCLEAR + +Clarification needed on third-party API integration, ... + +``` +""" + +ARCHITECT_INSTRUCTION = """ +You are an architect. Your task is to design a software system that meets the requirements. + +Note: +1. If Product Requirement Document is provided, read the document and use it as the requirement. +2. When the requirement use Vite, React/Vue, MUI, and Tailwind CSS to build a web application, list the files in the template before writing system design. Use "cd /{{template_path}} && tree -f". This must be a single response without other commands. +3. React template is in {react_template_path} and Vue template is in {vue_template_path}. +4. The system design must adhere to the following rules: +4.1 Chapter in the system design should include: +Required Python packages: Provide required Python packages in requirements.txt format. The response language should correspond to the context and requirements. +Required Other language third-party packages: List down the required packages for languages other than Python. +Logic Analysis: Provide a list of files with the classes/methods/functions to be implemented, including dependency analysis and imports.Ensure consistency between System Design and Logic Analysis; the files must match exactly. +Task list: Break down the tasks into a list of filenames, prioritized by dependency order. +Full API spec : escribe all APIs using OpenAPI 3.0 spec that may be used by both frontend and backend. If front-end and back-end communication is not required, leave it blank. +Shared Knowledge: Detail any shared knowledge, like common utility functions or configuration variables. +Anything UNCLEA: Mention any unclear aspects in the project management context and try to clarify them. + +4.2 System Design Format example: +{system_design_example} + +5. Use Editor.write to write the system design in markdown format. The path must be "/absolute/path/to/{{project_name}}/docs/system_design.md". Use command_name "end" when the system design is finished. +""".format( + system_design_example=SYSTEM_DESIGN_EXAMPLE, + vue_template_path=VUE_TEMPLATE_PATH.absolute(), + react_template_path=REACT_TEMPLATE_PATH.absolute(), +) diff --git a/metagpt/prompts/di/engineer2.py b/metagpt/prompts/di/engineer2.py index 1c39444de..74b41b750 100644 --- a/metagpt/prompts/di/engineer2.py +++ b/metagpt/prompts/di/engineer2.py @@ -46,7 +46,7 @@ Note: 23. When create unit tests for a code file, use Editor.read() to read the code file before planing. And create one plan to writing the unit test for the whole file. 24. the priority to select technical stack: Describe in Sytem Design and Project Schedule > Vite, React, MUI and Tailwind CSS > native HTML 24.1. The React template is in the "{react_template_path}" and Vue template is in the "{vue_template_path}". -25. If no programmming language is specified, use Vue/React project. Do the following steps: +25. If no programming language is specified or specifies use Vite, Vue/React, MUI, and Tailwind CSS, follow these steps: 25.1. Create the project folder first. Use cmd " mkdir -p {{project_name}} " 25.2. Copy a Vue/React template to your project folder, move into it and list the file in it. Use cmd "cp -r {{template_folder}}/* {{workspace}}/{{project_name}}/ && cd {{workspace}}/{{project_name}} && pwd && tree -f". This must be a single response without other commands. 25.3. User Editor.read to read the content of files in the src and read the index.html in the project root before making a plan. diff --git a/metagpt/roles/architect.py b/metagpt/roles/architect.py index b990808b3..4b54f2c26 100644 --- a/metagpt/roles/architect.py +++ b/metagpt/roles/architect.py @@ -5,18 +5,11 @@ @Author : alexanderwu @File : architect.py """ -from metagpt.actions import WritePRD -from metagpt.actions.design_api import WriteDesign +from pydantic import Field + +from metagpt.prompts.di.architect import ARCHITECT_INSTRUCTION from metagpt.roles.di.role_zero import RoleZero -from metagpt.utils.common import tool2name - -ARCHITECT_INSTRUCTION = """ -Use WriteDesign tool to write a system design document if a system design 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. -""" +from metagpt.tools.libs.terminal import Terminal class Architect(RoleZero): @@ -37,13 +30,12 @@ class Architect(RoleZero): "make sure the architecture is simple enough and use appropriate open source " "libraries. Use same language as user requirement" ) - + terminal: Terminal = Field(default_factory=Terminal, exclude=True) 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,similarity_search", + "Editor:write,read,similarity_search", "RoleZero", - "WriteDesign", + "Terminal:run_command", ] def __init__(self, **kwargs) -> None: @@ -51,17 +43,6 @@ class Architect(RoleZero): # NOTE: The following init setting will only be effective when self.use_fixed_sop is changed to True self.enable_memory = False - # Initialize actions specific to the Architect role - self.set_actions([WriteDesign]) - - # Set events or actions the Architect should watch or be aware of - self._watch({WritePRD}) def _update_tool_execution(self): - write_design = WriteDesign() - self.tool_execution_map.update(tool2name(WriteDesign, ["run"], write_design.run)) - self.tool_execution_map.update( - { - "run": write_design.run, # alias - } - ) + self.tool_execution_map.update({"Terminal.run_command": self.terminal.run_command}) diff --git a/metagpt/roles/di/role_zero.py b/metagpt/roles/di/role_zero.py index 4614de0f3..551034f2c 100644 --- a/metagpt/roles/di/role_zero.py +++ b/metagpt/roles/di/role_zero.py @@ -537,7 +537,7 @@ class RoleZero(Role): command_output = await self._end() elif cmd["command_name"] == "RoleZero.ask_human": human_response = await self.ask_human(**cmd["args"]) - if "stop" in human_response.lower(): + if human_response.strip().lower() in ["", "stop"]: human_response += "The user has asked me to stop because I have encountered a problem." self.rc.memory.add(UserMessage(content=human_response, cause_by=RunCommand)) end_output = "\nCommand end executed:" diff --git a/metagpt/roles/project_manager.py b/metagpt/roles/project_manager.py index d64fb90a1..cb0ead9de 100644 --- a/metagpt/roles/project_manager.py +++ b/metagpt/roles/project_manager.py @@ -31,7 +31,7 @@ class ProjectManager(RoleZero): instruction: str = """Use WriteTasks tool to write a project task list""" max_react_loop: int = 1 # FIXME: Read and edit files requires more steps, consider later - tools: list[str] = ["Editor:write,read,write_content,similarity_search", "RoleZero", "WriteTasks"] + tools: list[str] = ["Editor:write,read,similarity_search", "RoleZero", "WriteTasks"] def __init__(self, **kwargs) -> None: super().__init__(**kwargs) diff --git a/metagpt/strategy/experience_retriever.py b/metagpt/strategy/experience_retriever.py index 003bcd90c..aa094effb 100644 --- a/metagpt/strategy/experience_retriever.py +++ b/metagpt/strategy/experience_retriever.py @@ -479,7 +479,7 @@ Explanation: The requirement is about software development. Assign each tasks to "args": { "task_id": "1", "dependent_task_ids": [], - "instruction": "Use native HTML for the program. And create a product requirement document (PRD) outlining the features, user interface. ", + "instruction": "Use Vite, React, MUI, Tailwind CSS for the program. And create a product requirement document (PRD) outlining the features, user interface. ", "assignee": "Alice" } }, @@ -488,7 +488,7 @@ Explanation: The requirement is about software development. Assign each tasks to "args": { "task_id": "2", "dependent_task_ids": ["1"], - "instruction": "Use native HTML for the program. Design the software architecture for the CLI snake game, including the data flow.", + "instruction": "Use Vite, React, MUI, Tailwind CSS for the program. Design the software architecture for the CLI snake game, including the data flow.", "assignee": "Bob" } }, @@ -506,14 +506,14 @@ Explanation: The requirement is about software development. Assign each tasks to "args": { "task_id": "4", "dependent_task_ids": ["3"], - "instruction": "Use native HTML for the program. Implement the core game logic for the CLI snake game, including snake movement, food generation, and score tracking.", + "instruction": "Use Vite, React, MUI, Tailwind CSS for the program. Implement the core game logic for the CLI snake game, including snake movement, food generation, and score tracking.", "assignee": "Alex" } }, { "command_name": "TeamLeader.publish_message", "args": { - "content": "Use native HTML for the program. Create a cli snake game.", + "content": "Use Vite, React, MUI, Tailwind CSS for the program. Create a cli snake game.", "send_to": "Alice" } }, diff --git a/metagpt/tools/libs/terminal.py b/metagpt/tools/libs/terminal.py index 48f012e9f..9f3545052 100644 --- a/metagpt/tools/libs/terminal.py +++ b/metagpt/tools/libs/terminal.py @@ -6,7 +6,7 @@ from asyncio.subprocess import PIPE, STDOUT from typing import Optional from metagpt.config2 import Config -from metagpt.const import SWE_SETUP_PATH +from metagpt.const import DEFAULT_WORKSPACE_ROOT, SWE_SETUP_PATH from metagpt.logs import logger from metagpt.tools.tool_registry import register_tool from metagpt.utils.report import END_MARKER_VALUE, TerminalReporter @@ -37,7 +37,13 @@ class Terminal: async def _start_process(self): # Start a persistent shell process self.process = await asyncio.create_subprocess_exec( - *self.shell_command, stdin=PIPE, stdout=PIPE, stderr=STDOUT, executable="bash", env=os.environ.copy() + *self.shell_command, + stdin=PIPE, + stdout=PIPE, + stderr=STDOUT, + executable="bash", + env=os.environ.copy(), + cwd=DEFAULT_WORKSPACE_ROOT.absolute(), ) await self._check_state() From 2a53e30eba44926c1322d87f65055eb0dfb3fe2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E4=BC=9F=E9=9F=AC?= Date: Fri, 18 Oct 2024 16:04:55 +0800 Subject: [PATCH 2/7] update architect prompt --- metagpt/actions/project_management_an.py | 4 +- metagpt/prompts/di/architect.py | 62 ++++++++++++++++++------ metagpt/prompts/di/engineer2.py | 9 ++-- metagpt/prompts/di/team_leader.py | 2 +- metagpt/roles/architect.py | 5 +- metagpt/roles/di/engineer2.py | 2 +- metagpt/strategy/experience_retriever.py | 22 +++++++-- 7 files changed, 75 insertions(+), 31 deletions(-) diff --git a/metagpt/actions/project_management_an.py b/metagpt/actions/project_management_an.py index cca51a94b..7131a6c99 100644 --- a/metagpt/actions/project_management_an.py +++ b/metagpt/actions/project_management_an.py @@ -10,9 +10,9 @@ from typing import List from metagpt.actions.action_node import ActionNode REQUIRED_PYTHON_PACKAGES = ActionNode( - key="Required Python packages", + key="Required packages", expected_type=List[str], - instruction="Provide required Python packages in requirements.txt format. The response language should correspond to the context and requirements.", + instruction="Provide required packages The response language should correspond to the context and requirements.", example=["flask==1.1.2", "bcrypt==3.2.0"], ) diff --git a/metagpt/prompts/di/architect.py b/metagpt/prompts/di/architect.py index ed0c2b7d1..e6ea77e2b 100644 --- a/metagpt/prompts/di/architect.py +++ b/metagpt/prompts/di/architect.py @@ -8,10 +8,11 @@ We will ... ## File list -- a.js -- b.py -- c.css -- d.html +- a.jsx +- b.jx +- c.py +- d.css +- e.html ## Data structures and interfaces: @@ -60,24 +61,53 @@ You are an architect. Your task is to design a software system that meets the re Note: 1. If Product Requirement Document is provided, read the document and use it as the requirement. -2. When the requirement use Vite, React/Vue, MUI, and Tailwind CSS to build a web application, list the files in the template before writing system design. Use "cd /{{template_path}} && tree -f". This must be a single response without other commands. -3. React template is in {react_template_path} and Vue template is in {vue_template_path}. +2. If no programming language is specified, use Vite, React, MUI and Tailwind CSS as the programming language. +3. When use Vite, React, MUI and Tailwind CSS, view the default project structure before start to design. Execute "mkdir -p {{project_name}} && tree /path/of/the/template". This must be a single response WITHOUT other commands. React template is in {react_template_path} and Vue template is in {vue_template_path}. 4. The system design must adhere to the following rules: 4.1 Chapter in the system design should include: -Required Python packages: Provide required Python packages in requirements.txt format. The response language should correspond to the context and requirements. -Required Other language third-party packages: List down the required packages for languages other than Python. -Logic Analysis: Provide a list of files with the classes/methods/functions to be implemented, including dependency analysis and imports.Ensure consistency between System Design and Logic Analysis; the files must match exactly. -Task list: Break down the tasks into a list of filenames, prioritized by dependency order. -Full API spec : escribe all APIs using OpenAPI 3.0 spec that may be used by both frontend and backend. If front-end and back-end communication is not required, leave it blank. -Shared Knowledge: Detail any shared knowledge, like common utility functions or configuration variables. -Anything UNCLEA: Mention any unclear aspects in the project management context and try to clarify them. - +Implementation approach: Analyze the difficult points of the requirements, select the appropriate open-source framework. +File list: Only need relative paths. If using template, index.html and the file in src folder must be included. +Data structures and interfaces: Use mermaid classDiagram code syntax, including classes, method(__init__ etc.) and functions with type annotations, CLEARLY MARK the RELATIONSHIPS between classes, and comply with PEP8 standards. The data structures SHOULD BE VERY DETAILED and the API should be comprehensive with a complete design. +Program call flow: Use sequenceDiagram code syntax, COMPLETE and VERY DETAILED, using CLASSES AND API DEFINED ABOVE accurately, covering the CRUD AND INIT of each object, SYNTAX MUST BE CORRECT. +Anything UNCLEAR: Mention unclear project aspects, then try to clarify it. 4.2 System Design Format example: {system_design_example} - -5. Use Editor.write to write the system design in markdown format. The path must be "/absolute/path/to/{{project_name}}/docs/system_design.md". Use command_name "end" when the system design is finished. +5. Use Editor.write to write the system design in markdown format. The file path must be "{{project}}/docs/system_design.md". Use command_name "end" when the system design is finished. """.format( system_design_example=SYSTEM_DESIGN_EXAMPLE, vue_template_path=VUE_TEMPLATE_PATH.absolute(), react_template_path=REACT_TEMPLATE_PATH.absolute(), ) + +ARCHITECT_EXAMPLE = """ +## example 1 +Requirement: Create a system design for 2048 game. +Explanation: User requires create a system design. I have read the product requirement document and no programming language is specified. I will use Vite, React, MUI and Tailwind CSS. +I will use Terminal to execute "mkdir -p {{project_name}} && tree /path/of/the/template" to get the default project structure before I start to design. I will execute the command and wait for the result before writing the system design. +```json +[ + { + "command_name": "Terminal.run_command", + "args": { + "cmd": "mkdir -p {{project_name}} && tree /path/of/the/template" + } + } +] +``` +I will wait for the result. + +## example 2 +Requirement: Create a system design for a chatbot. +Explanation: User requires create a system design. And I have viewed the default project structure, now I will use Editor.write to finish the system design. +```json +[ + { + "command_name": "Editor.write"", + "args": { + "path": "/absolute/path/to/{{project}}/docs/system_design.md", + "content": "(The system design content)" + } + } +] +``` +""".strip() diff --git a/metagpt/prompts/di/engineer2.py b/metagpt/prompts/di/engineer2.py index 74b41b750..76cb87a63 100644 --- a/metagpt/prompts/di/engineer2.py +++ b/metagpt/prompts/di/engineer2.py @@ -35,7 +35,6 @@ Note: 12. If you choose Editor.insert_content_at_line, you must ensure that there is no duplication between the inserted content and the original code. If there is overlap between the new code and the original code, use Editor.edit_file_by_replace instead. 13. If you choose Editor.edit_file_by_replace, the original code that needs to be replaced must start at the beginning of the line and end at the end of the line 14. When not specified, you should write files in a folder named "{{project_name}}". The project name is the name of the project which meets the user's requirements. -15. When provided system design or project schedule, you MUST read them first before making a plan, then adhere to them in your implementation, especially in the programming language, package, or framework. You MUST implement all code files prescribed in the system design or project schedule. 16. When planning, initially list the files for coding, then outline all coding tasks based on the file organization in your first response. 17. If you plan to read a file, do not include other plans in the same response. 18. Write only one code file each time and provide its full implementation. @@ -44,11 +43,11 @@ Note: 21. 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. 22. When planning, merge multiple tasks that operate on the same file into a single task. For example, create one task for writing unit tests for all functions in a class. Also in using the editor, merge multiple tasks that operate on the same file into a single task. 23. When create unit tests for a code file, use Editor.read() to read the code file before planing. And create one plan to writing the unit test for the whole file. -24. the priority to select technical stack: Describe in Sytem Design and Project Schedule > Vite, React, MUI and Tailwind CSS > native HTML +24. the priority to select technology stacks: Describe in Sytem Design and Project Schedule > Vite, React, MUI and Tailwind CSS > native HTML 24.1. The React template is in the "{react_template_path}" and Vue template is in the "{vue_template_path}". -25. If no programming language is specified or specifies use Vite, Vue/React, MUI, and Tailwind CSS, follow these steps: -25.1. Create the project folder first. Use cmd " mkdir -p {{project_name}} " -25.2. Copy a Vue/React template to your project folder, move into it and list the file in it. Use cmd "cp -r {{template_folder}}/* {{workspace}}/{{project_name}}/ && cd {{workspace}}/{{project_name}} && pwd && tree -f". This must be a single response without other commands. +25. If use Vite, Vue/React, MUI, and Tailwind CSS as the programming language or no programming language is specified in document or user requirement, follow these steps: +25.1. Create the project folder if no exists. Use cmd " mkdir -p {{project_name}} " +25.2. Copy a Vue/React template to your project folder, move into it and list the file in it. Use cmd "cp -r {{template_folder}}/* {{workspace}}/{{project_name}}/ && cd {{workspace}}/{{project_name}} && pwd && tree ". This must be a single response without other commands. 25.3. User Editor.read to read the content of files in the src and read the index.html in the project root before making a plan. 25.4. List the files that you need to rewrite and create when making a plan. Indicate clearly what file to rewrite or create in each task. "index.html" and all files in the src folder always must be rewritten. Use Tailwind CSS for styling. Notice that you are in {{project_name}}. 25.5. After finish the project. use "pnpm install && pnpm run build" to build the project and then deploy the project to the public using the dist folder which contains the built project. diff --git a/metagpt/prompts/di/team_leader.py b/metagpt/prompts/di/team_leader.py index 9b0163710..64e85473e 100644 --- a/metagpt/prompts/di/team_leader.py +++ b/metagpt/prompts/di/team_leader.py @@ -34,7 +34,7 @@ Note: 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. 12. If the the user message is a question, use 'reply to human' to respond to the question, and then end. 13. Instructions and reply must be in the same language. -14. Default technology stack is HTML (.html), CSS (.css), and Pure JavaScript (.js). Web app is the default option when developing software. +14. Default technology stack is Vite, React, MUI, Tailwind CSS. Web app is the default option when developing software. If use these technology stacks, ask the engineer to delopy the web app after project completion. 15. You are the only one who decides the programming language for the software, so the instruction must contain the programming language. 16. Data collection and web/software development are two separate tasks. You must assign these tasks to data analysts and engineers, respectively. Wait for the data collection to be completed before starting the coding. """ diff --git a/metagpt/roles/architect.py b/metagpt/roles/architect.py index 4b54f2c26..f23d4d4d0 100644 --- a/metagpt/roles/architect.py +++ b/metagpt/roles/architect.py @@ -7,7 +7,7 @@ """ from pydantic import Field -from metagpt.prompts.di.architect import ARCHITECT_INSTRUCTION +from metagpt.prompts.di.architect import ARCHITECT_EXAMPLE, ARCHITECT_INSTRUCTION from metagpt.roles.di.role_zero import RoleZero from metagpt.tools.libs.terminal import Terminal @@ -44,5 +44,8 @@ class Architect(RoleZero): # NOTE: The following init setting will only be effective when self.use_fixed_sop is changed to True self.enable_memory = False + def _retrieve_experience(self) -> str: + return ARCHITECT_EXAMPLE + def _update_tool_execution(self): self.tool_execution_map.update({"Terminal.run_command": self.terminal.run_command}) diff --git a/metagpt/roles/di/engineer2.py b/metagpt/roles/di/engineer2.py index 22b3554bc..683b5f4a9 100644 --- a/metagpt/roles/di/engineer2.py +++ b/metagpt/roles/di/engineer2.py @@ -31,7 +31,7 @@ from metagpt.utils.report import EditorReporter class Engineer2(RoleZero): name: str = "Alex" profile: str = "Engineer" - goal: str = "Take on game, app, and web development." + goal: str = "Take on game, app, web development and deployment." instruction: str = ENGINEER2_INSTRUCTION terminal: Terminal = Field(default_factory=Terminal, exclude=True) deployer: Deployer = Field(default_factory=Deployer, exclude=True) diff --git a/metagpt/strategy/experience_retriever.py b/metagpt/strategy/experience_retriever.py index aa094effb..a467b1d47 100644 --- a/metagpt/strategy/experience_retriever.py +++ b/metagpt/strategy/experience_retriever.py @@ -479,7 +479,7 @@ Explanation: The requirement is about software development. Assign each tasks to "args": { "task_id": "1", "dependent_task_ids": [], - "instruction": "Use Vite, React, MUI, Tailwind CSS for the program. And create a product requirement document (PRD) outlining the features, user interface. ", + "instruction": "Use Vite, React, MUI, Tailwind CSS for the program. And create a product requirement document (PRD). ", "assignee": "Alice" } }, @@ -488,7 +488,7 @@ Explanation: The requirement is about software development. Assign each tasks to "args": { "task_id": "2", "dependent_task_ids": ["1"], - "instruction": "Use Vite, React, MUI, Tailwind CSS for the program. Design the software architecture for the CLI snake game, including the data flow.", + "instruction": "Use Vite, React, MUI, Tailwind CSS for the program. Design the software architecture for the CLI snake game.", "assignee": "Bob" } }, @@ -579,7 +579,7 @@ Explanation: You received a message from Alice, the Product Manager, that she ha { "command_name": "TeamLeader.publish_message", "args": { - "content": "Please design the software architecture for the snake game based on the PRD created by Alice. The PRD is at '/tmp/workspace/snake_game/docs/prd.json'. Include the choice of programming language, libraries, and data flow, etc.", + "content": "Please design the software architecture for the snake game based on the PRD created by Alice. The PRD is at '/tmp/workspace/snake_game/docs/prd.json'.", "send_to": "Bob" } }, @@ -840,8 +840,18 @@ Explanation: I will first need to read the system design document and the projec ] ``` ## example 2 -User Requirement: Implement the core game project in Vue/React framework. -Explanation: This is a project that needs to be implemented using Vue.js. Therefore, I need to copy the Vue/React template to the project folder first. +User Requirement: Implement the core game project in Vue/React framework. Document has been read. +Explanation: This is a project that needs to be implemented using Vue.js according to the system design document and user requirements. Therefore, I need to copy the Vue/React template to the project folder first. +```json +[ + { + "command_name": "Terminal.run_command", + "args": { + "cmd": "cp -r {{template_folder}}/* {{workspace}}/{{project_name}}/ && cd {{workspace}}/{{project_name}} && pwd && tree " + } + } +] +``` ## example 3 User Requirement: Writing code. @@ -948,6 +958,8 @@ Explanation: The project have been completed. This project is Vue/React Project, } } ] +``` + ## example 6 Explanation: After install and build the project, static dist is created in the current project folder. I will deploy the project to the public. ```json From 4067127525bd9100582881f1b88c88c762748fab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E4=BC=9F=E9=9F=AC?= Date: Mon, 21 Oct 2024 14:25:08 +0800 Subject: [PATCH 3/7] Generate mermaid files after completing the system design. --- metagpt/prompts/di/architect.py | 7 ++++--- metagpt/roles/di/role_zero.py | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/metagpt/prompts/di/architect.py b/metagpt/prompts/di/architect.py index e6ea77e2b..6b87d1f93 100644 --- a/metagpt/prompts/di/architect.py +++ b/metagpt/prompts/di/architect.py @@ -60,9 +60,9 @@ ARCHITECT_INSTRUCTION = """ You are an architect. Your task is to design a software system that meets the requirements. Note: -1. If Product Requirement Document is provided, read the document and use it as the requirement. -2. If no programming language is specified, use Vite, React, MUI and Tailwind CSS as the programming language. -3. When use Vite, React, MUI and Tailwind CSS, view the default project structure before start to design. Execute "mkdir -p {{project_name}} && tree /path/of/the/template". This must be a single response WITHOUT other commands. React template is in {react_template_path} and Vue template is in {vue_template_path}. +1. If Product Requirement Document is provided, read the document and use it as the requirement. If the Programming Language in PRD is Vite, React, MUI and Tailwind CSS, use the template. +2. Default programming language is Vite, React, MUI and Tailwind CSS. React template is in {react_template_path} and Vue template is in {vue_template_path}. +3. Execute "mkdir -p {{project_name}} && tree /path/of/the/template" to clear template structure if you want to use template. This must be a single response WITHOUT other commands. 4. The system design must adhere to the following rules: 4.1 Chapter in the system design should include: Implementation approach: Analyze the difficult points of the requirements, select the appropriate open-source framework. @@ -73,6 +73,7 @@ Anything UNCLEAR: Mention unclear project aspects, then try to clarify it. 4.2 System Design Format example: {system_design_example} 5. Use Editor.write to write the system design in markdown format. The file path must be "{{project}}/docs/system_design.md". Use command_name "end" when the system design is finished. +6. If no memtion, always use Editor.write to write "Program call flow" in a new file name "{{project}}/docs/system_design-sequence-diagram.mermaid" and write "Data structures and interfaces" in a new file "{{project}}/docs/system_design-sequence-diagram.mermaid-class-diagram" """.format( system_design_example=SYSTEM_DESIGN_EXAMPLE, vue_template_path=VUE_TEMPLATE_PATH.absolute(), diff --git a/metagpt/roles/di/role_zero.py b/metagpt/roles/di/role_zero.py index 551034f2c..9baafb9b2 100644 --- a/metagpt/roles/di/role_zero.py +++ b/metagpt/roles/di/role_zero.py @@ -537,7 +537,7 @@ class RoleZero(Role): command_output = await self._end() elif cmd["command_name"] == "RoleZero.ask_human": human_response = await self.ask_human(**cmd["args"]) - if human_response.strip().lower() in ["", "stop"]: + if human_response[len("Human response:") :].strip().lower() in ["", "stop"]: human_response += "The user has asked me to stop because I have encountered a problem." self.rc.memory.add(UserMessage(content=human_response, cause_by=RunCommand)) end_output = "\nCommand end executed:" From e531dd97c86b6462d761fe75f05db462d4146e62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E4=BC=9F=E9=9F=AC?= Date: Mon, 21 Oct 2024 14:31:15 +0800 Subject: [PATCH 4/7] fix engineer2 prompt --- metagpt/prompts/di/engineer2.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/metagpt/prompts/di/engineer2.py b/metagpt/prompts/di/engineer2.py index 76cb87a63..38b8ecc3c 100644 --- a/metagpt/prompts/di/engineer2.py +++ b/metagpt/prompts/di/engineer2.py @@ -35,6 +35,7 @@ Note: 12. If you choose Editor.insert_content_at_line, you must ensure that there is no duplication between the inserted content and the original code. If there is overlap between the new code and the original code, use Editor.edit_file_by_replace instead. 13. If you choose Editor.edit_file_by_replace, the original code that needs to be replaced must start at the beginning of the line and end at the end of the line 14. When not specified, you should write files in a folder named "{{project_name}}". The project name is the name of the project which meets the user's requirements. +15. When provided system design or project schedule, you MUST read them first before making a plan, then adhere to them in your implementation, especially in the programming language, package, or framework. You MUST implement all code files prescribed in the system design or project schedule. 16. When planning, initially list the files for coding, then outline all coding tasks based on the file organization in your first response. 17. If you plan to read a file, do not include other plans in the same response. 18. Write only one code file each time and provide its full implementation. @@ -43,7 +44,7 @@ Note: 21. 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. 22. When planning, merge multiple tasks that operate on the same file into a single task. For example, create one task for writing unit tests for all functions in a class. Also in using the editor, merge multiple tasks that operate on the same file into a single task. 23. When create unit tests for a code file, use Editor.read() to read the code file before planing. And create one plan to writing the unit test for the whole file. -24. the priority to select technology stacks: Describe in Sytem Design and Project Schedule > Vite, React, MUI and Tailwind CSS > native HTML +24. The priority to select technology stacks: Describe in Sytem Design and Project Schedule > Vite, React, MUI and Tailwind CSS > native HTML 24.1. The React template is in the "{react_template_path}" and Vue template is in the "{vue_template_path}". 25. If use Vite, Vue/React, MUI, and Tailwind CSS as the programming language or no programming language is specified in document or user requirement, follow these steps: 25.1. Create the project folder if no exists. Use cmd " mkdir -p {{project_name}} " From 1ac1da0299a50d4f103d408f8d934614e0b7e706 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E4=BC=9F=E9=9F=AC?= Date: Mon, 21 Oct 2024 14:57:14 +0800 Subject: [PATCH 5/7] Fix: "```mermaid```" exists in the Mermaid file --- metagpt/prompts/di/architect.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metagpt/prompts/di/architect.py b/metagpt/prompts/di/architect.py index 6b87d1f93..566835dac 100644 --- a/metagpt/prompts/di/architect.py +++ b/metagpt/prompts/di/architect.py @@ -73,7 +73,7 @@ Anything UNCLEAR: Mention unclear project aspects, then try to clarify it. 4.2 System Design Format example: {system_design_example} 5. Use Editor.write to write the system design in markdown format. The file path must be "{{project}}/docs/system_design.md". Use command_name "end" when the system design is finished. -6. If no memtion, always use Editor.write to write "Program call flow" in a new file name "{{project}}/docs/system_design-sequence-diagram.mermaid" and write "Data structures and interfaces" in a new file "{{project}}/docs/system_design-sequence-diagram.mermaid-class-diagram" +6. If no memtion, always use Editor.write to write "Program call flow" in a new file name "{{project}}/docs/system_design-sequence-diagram.mermaid" and write "Data structures and interfaces" in a new file "{{project}}/docs/system_design-sequence-diagram.mermaid-class-diagram". Mermaid code only. Do not add "```mermaid". """.format( system_design_example=SYSTEM_DESIGN_EXAMPLE, vue_template_path=VUE_TEMPLATE_PATH.absolute(), From b80f8c4f9ab5055779a2986c0c67856dccbea3de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E4=BC=9F=E9=9F=AC?= Date: Mon, 21 Oct 2024 15:37:54 +0800 Subject: [PATCH 6/7] fix typo --- metagpt/prompts/di/architect.py | 2 +- metagpt/roles/architect.py | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/metagpt/prompts/di/architect.py b/metagpt/prompts/di/architect.py index 566835dac..112f040c5 100644 --- a/metagpt/prompts/di/architect.py +++ b/metagpt/prompts/di/architect.py @@ -73,7 +73,7 @@ Anything UNCLEAR: Mention unclear project aspects, then try to clarify it. 4.2 System Design Format example: {system_design_example} 5. Use Editor.write to write the system design in markdown format. The file path must be "{{project}}/docs/system_design.md". Use command_name "end" when the system design is finished. -6. If no memtion, always use Editor.write to write "Program call flow" in a new file name "{{project}}/docs/system_design-sequence-diagram.mermaid" and write "Data structures and interfaces" in a new file "{{project}}/docs/system_design-sequence-diagram.mermaid-class-diagram". Mermaid code only. Do not add "```mermaid". +6. If not memtioned, always use Editor.write to write "Program call flow" in a new file name "{{project}}/docs/system_design-sequence-diagram.mermaid" and write "Data structures and interfaces" in a new file "{{project}}/docs/system_design-sequence-diagram.mermaid-class-diagram". Mermaid code only. Do not add "```mermaid". """.format( system_design_example=SYSTEM_DESIGN_EXAMPLE, vue_template_path=VUE_TEMPLATE_PATH.absolute(), diff --git a/metagpt/roles/architect.py b/metagpt/roles/architect.py index f23d4d4d0..7ec937675 100644 --- a/metagpt/roles/architect.py +++ b/metagpt/roles/architect.py @@ -7,6 +7,8 @@ """ from pydantic import Field +from metagpt.actions.design_api import WriteDesign +from metagpt.actions.write_prd import WritePRD from metagpt.prompts.di.architect import ARCHITECT_EXAMPLE, ARCHITECT_INSTRUCTION from metagpt.roles.di.role_zero import RoleZero from metagpt.tools.libs.terminal import Terminal @@ -43,6 +45,11 @@ class Architect(RoleZero): # NOTE: The following init setting will only be effective when self.use_fixed_sop is changed to True self.enable_memory = False + # Initialize actions specific to the Architect role + self.set_actions([WriteDesign]) + + # Set events or actions the Architect should watch or be aware of + self._watch({WritePRD}) def _retrieve_experience(self) -> str: return ARCHITECT_EXAMPLE From d16bafe428daa4827a937a215dcf343a2c8d7243 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E4=BC=9F=E9=9F=AC?= Date: Mon, 21 Oct 2024 15:52:15 +0800 Subject: [PATCH 7/7] improve fault tolerance when try to stop in ask_human action --- metagpt/roles/di/role_zero.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metagpt/roles/di/role_zero.py b/metagpt/roles/di/role_zero.py index 9baafb9b2..ca854fa60 100644 --- a/metagpt/roles/di/role_zero.py +++ b/metagpt/roles/di/role_zero.py @@ -537,7 +537,7 @@ class RoleZero(Role): command_output = await self._end() elif cmd["command_name"] == "RoleZero.ask_human": human_response = await self.ask_human(**cmd["args"]) - if human_response[len("Human response:") :].strip().lower() in ["", "stop"]: + if human_response.strip().lower().endswith(("stop", "")): human_response += "The user has asked me to stop because I have encountered a problem." self.rc.memory.add(UserMessage(content=human_response, cause_by=RunCommand)) end_output = "\nCommand end executed:"