From 4dfe6ef26f8c0ae642542b85bc18af65e8211ab8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8E=98=E6=9D=83=20=E9=A9=AC?= Date: Tue, 18 Jun 2024 10:33:15 +0800 Subject: [PATCH] feat: rfc243 --- examples/mgx_write_project_framework.py | 5 +- .../framework/write_framework.py | 9 ++- metagpt/roles/architect.py | 10 +-- metagpt/strategy/experience_retriever.py | 73 ++++++++++++------- metagpt/tools/libs/software_development.py | 22 +++++- 5 files changed, 77 insertions(+), 42 deletions(-) diff --git a/examples/mgx_write_project_framework.py b/examples/mgx_write_project_framework.py index f82666e04..109ce877d 100644 --- a/examples/mgx_write_project_framework.py +++ b/examples/mgx_write_project_framework.py @@ -90,10 +90,7 @@ Given the user requirement of "User Requirements", write out the software framew ## User Requirements {user_requirements} """ - env.publish_message( - UserMessage(content=msg.format(user_requirements="\n".join(user_requirements)), send_to="Bob"), - user_defined_recipient="Bob", - ) + env.publish_message(UserMessage(content=msg.format(user_requirements="\n".join(user_requirements)))) while not env.is_idle: await env.run() diff --git a/metagpt/actions/requirement_analysis/framework/write_framework.py b/metagpt/actions/requirement_analysis/framework/write_framework.py index ec9ac9b62..8bb66e948 100644 --- a/metagpt/actions/requirement_analysis/framework/write_framework.py +++ b/metagpt/actions/requirement_analysis/framework/write_framework.py @@ -119,7 +119,7 @@ The content of "Actor, System, External System" provides an explanation of actor The descriptions of the interfaces of the external system used in the "TRD" can be found in the "Acknowledge" section; Do not implement the interface of the external system in "Acknowledge" section until it is used in "TRD"; "Legacy Outputs" contains the software framework code generated by you last time, which you can improve by addressing the issues raised in "Evaluation Conclusion"; "Additional Technical Requirements" specifies the additional technical requirements that the generated software framework code must meet; -Develop source code based on the content of the "TRD"; +Develop the software framework based on the "TRD", the output files should include: - The `README.md` file should include: - The folder structure diagram of the entire project; - Correspondence between classes, interfaces, and functions with the content in the "TRD" section; @@ -127,9 +127,10 @@ Develop source code based on the content of the "TRD"; - Installation if necessary; - Configuration if necessary; - Usage if necessary; -- The `CLASS.md` file should include the class diagram in PlantUML format; -- The `SEQUENCE.md` file should include the sequence diagram in PlantUML format; -- Do not add comments to source code; +- The `CLASS.md` file should include the class diagram in PlantUML format based on the "TRD"; +- The `SEQUENCE.md` file should include the sequence diagram in PlantUML format based on the "TRD"; +- The source code files that implement the "TRD" and "Additional Technical Requirements"; do not add comments to source code files; +- The configuration files that required by the source code files, "TRD" and "Additional Technical Requirements"; Return a markdown JSON object list, each object containing: - a "path" key with a value specifying its path; diff --git a/metagpt/roles/architect.py b/metagpt/roles/architect.py index 404291e1e..553a4ed7a 100644 --- a/metagpt/roles/architect.py +++ b/metagpt/roles/architect.py @@ -8,7 +8,7 @@ from metagpt.actions import WritePRD from metagpt.actions.design_api import WriteDesign from metagpt.roles.di.role_zero import RoleZero -from metagpt.tools.libs.software_development import write_framework, write_trd +from metagpt.tools.libs.software_development import write_trd_and_framework from metagpt.utils.common import tool2name @@ -31,14 +31,13 @@ class Architect(RoleZero): "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 WriteTRD tool to write a TRD if a TRD is required;""" + 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;""" max_react_loop: int = 1 # FIXME: Read and edit files requires more steps, consider later tools: list[str] = [ "Editor:write,read,write_content", "RoleZero", "WriteDesign", - write_trd.__name__, - write_framework.__name__, + write_trd_and_framework.__name__, ] def __init__(self, **kwargs) -> None: @@ -57,7 +56,6 @@ class Architect(RoleZero): self.tool_execution_map.update(tool2name(WriteDesign, ["run"], write_design.run)) self.tool_execution_map.update( { - write_trd.__name__: write_trd, - write_framework.__name__: write_framework, + write_trd_and_framework.__name__: write_trd_and_framework, } ) diff --git a/metagpt/strategy/experience_retriever.py b/metagpt/strategy/experience_retriever.py index 75139fdc7..6caf83810 100644 --- a/metagpt/strategy/experience_retriever.py +++ b/metagpt/strategy/experience_retriever.py @@ -26,35 +26,54 @@ class TRDToolExpRetriever(ExpRetriever): return self.EXAMPLE EXAMPLE: str = """ - ## example 1 - User Requirement: Given some user requirements, write a software framework. - Explanation: Given a complete user requirement, to write a software framework, you must follow all of the following steps to complete the TRD output required by the user: 1. Call 'write_trd' to generate TRD; 2. Call 'write_framework' to implement TRD into the software framework. - ```json - [ - { - "command_name": "write_trd", - "args": { - "task_id": "1", - "dependent_task_ids": [], - "instruction": "Execute `write_trd` to write the TRD based on user requirements", - "user_requirements": "This is user requirement balabala...", - "use_case_actors": "These are actors involved in the use case, balabala...", - } - }, - { - "command_name": "write_framework", - "args": { - "task_id": "2", - "dependent_task_ids": ["1"], - "instruction": "Execute `write_framework` to write the framework based on the TRD", - "use_case_actors": "These are actors involved in the use case, balabala...", - "trd": " returned by `write_trd`", - "additional_technical_requirements": "These are additional technical requirements, balabala..." - } +## example 1 +User Requirement: Given some user requirements, write a software framework. +Explanation: Given a complete user requirement, to write a software framework, you must follow all of the following steps to complete the TRD output required by the user: 1. Call 'write_trd' to generate TRD; 2. Call 'write_framework' to implement TRD into the software framework. +```json +[ + { + "command_name": "write_trd_and_framework", + "task_id": "1", + "dependent_task_ids": [], + "instruction": "Execute `write_trd` to write the TRD based on user requirements", + "args": { + "user_requirements": "This is user requirement balabala...", + "use_case_actors": "These are actors involved in the use case, balabala...", + "additional_technical_requirements": "These are additional technical requirements, balabala..." } - ] - ``` + } +] """ + # EXAMPLE: str = """ + # ## example 1 + # User Requirement: Given some user requirements, write a software framework. + # Explanation: Given a complete user requirement, to write a software framework, you must follow all of the following steps to complete the TRD output required by the user: 1. Call 'write_trd' to generate TRD; 2. Call 'write_framework' to implement TRD into the software framework. + # ```json + # [ + # { + # "command_name": "write_trd", + # "task_id": "1", + # "dependent_task_ids": [], + # "instruction": "Execute `write_trd` to write the TRD based on user requirements", + # "args": { + # "user_requirements": "This is user requirement balabala...", + # "use_case_actors": "These are actors involved in the use case, balabala...", + # } + # }, + # { + # "command_name": "write_framework", + # "task_id": "2", + # "dependent_task_ids": ["1"], + # "instruction": "Execute `write_framework` to write the framework based on the TRD", + # "args": { + # "use_case_actors": "These are actors involved in the use case, balabala...", + # "trd": " returned by `write_trd`", + # "additional_technical_requirements": "These are additional technical requirements, balabala..." + # } + # } + # ] + # ``` + # """ class TRDExpRetriever(ExpRetriever): diff --git a/metagpt/tools/libs/software_development.py b/metagpt/tools/libs/software_development.py index 16ab74621..e10ddab4a 100644 --- a/metagpt/tools/libs/software_development.py +++ b/metagpt/tools/libs/software_development.py @@ -264,7 +264,7 @@ async def write_trd( user_requirements: str, investment: float = 10, context: Optional[Context] = None, -) -> (str, str): +) -> str: """ Handles the writing of a Technical Requirements Document (TRD) based on user requirements. @@ -397,3 +397,23 @@ async def write_framework( file_list = await save_framework(dir_data=framework, output_dir=output_dir) logger.info(f"Output:\n{file_list}") return "## Software Framework" + "".join([f"\n- {i}" for i in file_list]) + + +@register_tool(tags=["system design", "write trd and framework", "Write a TRD and the framework"]) +async def write_trd_and_framework( + use_case_actors: str, + user_requirements: str, + additional_technical_requirements: str, + investment: float = 15.0, + output_dir: Optional[str] = "", + context: Optional[Context] = None, +) -> str: + context = context or Context(cost_manager=CostManager(max_budget=investment)) + trd = await write_trd(use_case_actors=use_case_actors, user_requirements=user_requirements, context=context) + return await write_framework( + use_case_actors=use_case_actors, + trd=trd, + additional_technical_requirements=additional_technical_requirements, + output_dir=output_dir, + context=context, + )