From 819c00a55a90697cb817e71cb0aa02957195e67a Mon Sep 17 00:00:00 2001 From: garylin2099 Date: Mon, 13 May 2024 22:20:34 +0800 Subject: [PATCH] allow immediate deploy after software sop; fix TL to PM msg info loss --- metagpt/environment/mgx/mgx_env.py | 24 ++++++++++-------------- metagpt/prompts/di/team_leader.py | 2 +- metagpt/roles/engineer.py | 4 ++-- metagpt/strategy/experience_retriever.py | 8 ++++---- metagpt/strategy/thinking_command.py | 2 +- 5 files changed, 18 insertions(+), 22 deletions(-) diff --git a/metagpt/environment/mgx/mgx_env.py b/metagpt/environment/mgx/mgx_env.py index 107f449a6..3bd41fd1e 100644 --- a/metagpt/environment/mgx/mgx_env.py +++ b/metagpt/environment/mgx/mgx_env.py @@ -9,14 +9,7 @@ from metagpt.actions.summarize_code import SummarizeCode from metagpt.const import AGENT from metagpt.environment.base_env import Environment from metagpt.logs import get_human_input -from metagpt.roles import ( - Architect, - Engineer, - ProductManager, - ProjectManager, - QaEngineer, - Role, -) +from metagpt.roles import Architect, ProductManager, ProjectManager, Role from metagpt.schema import Message from metagpt.utils.common import any_to_str, any_to_str_set @@ -88,7 +81,9 @@ class MGXEnv(Environment): return content def message_within_software_sop(self, message: Message) -> bool: - return message.sent_from in any_to_str_set([ProductManager, Architect, ProjectManager, Engineer, QaEngineer]) + # Engineer, QaEngineer can be end of the SOP. Their msg requires routing outside. + members_concerned = [ProductManager, Architect, ProjectManager] + return message.sent_from in any_to_str_set(members_concerned) def has_user_requirement(self, k=1) -> bool: """A heuristics to check if there is a recent user intervention""" @@ -105,8 +100,9 @@ class MGXEnv(Environment): 1. Convert role, since role field must be reserved for LLM API, and is limited to, for example, one of ["user", "assistant", "system"] 2. Add sender and recipient info to content, making TL aware, since LLM API only takes content as input """ - if message.role not in ["system", "user", "assistant"]: - message.role = "assistant" - sent_from = message.metadata[AGENT] if AGENT in message.metadata else message.sent_from - message.content = f"from {sent_from} to {message.send_to}: {message.content}" - return message + converted_msg = message.model_copy(deep=True) + if converted_msg.role not in ["system", "user", "assistant"]: + converted_msg.role = "assistant" + sent_from = converted_msg.metadata[AGENT] if AGENT in converted_msg.metadata else converted_msg.sent_from + converted_msg.content = f"from {sent_from} to {converted_msg.send_to}: {converted_msg.content}" + return converted_msg diff --git a/metagpt/prompts/di/team_leader.py b/metagpt/prompts/di/team_leader.py index c5f6a79aa..dacd3d876 100644 --- a/metagpt/prompts/di/team_leader.py +++ b/metagpt/prompts/di/team_leader.py @@ -35,7 +35,7 @@ Pay close attention to new user message, review the conversation history, use re Note: 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, usually the sequence of Product Manager -> Architect -> Project Manager -> Engineer -> QaEngine, each assigned ONE task. +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. 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. Pay close attention to the Example provided diff --git a/metagpt/roles/engineer.py b/metagpt/roles/engineer.py index a76db09b1..d9e375a9a 100644 --- a/metagpt/roles/engineer.py +++ b/metagpt/roles/engineer.py @@ -208,8 +208,8 @@ class Engineer(Role): if not tasks or self.config.max_auto_summarize_code == 0: self.n_summarize = 0 return AIMessage( - content="Coding is complete. " - "\n".join( + content=f"Coding is complete. The source code is at {self.project_repo.workdir.name}/{self.project_repo.srcs.root_path}, containing: " + + "\n".join( list(self.project_repo.resources.code_summary.changed_files.keys()) + list(self.project_repo.srcs.changed_files.keys()) ), diff --git a/metagpt/strategy/experience_retriever.py b/metagpt/strategy/experience_retriever.py index 614a26d16..a57abe72f 100644 --- a/metagpt/strategy/experience_retriever.py +++ b/metagpt/strategy/experience_retriever.py @@ -15,8 +15,8 @@ class SimpleExpRetriever(ExpRetriever): EXAMPLE: str = """ ## example 1 - User Requirement: Create a cli snake game - Explanation: The requirement is about software development. Assign each tasks to a different team member based on their expertise. + User Requirement: Create a cli snake game using Python. + Explanation: The requirement is about software development. Assign each tasks to a different team member based on their expertise. When publishing message to Product Manager, we copy original user requirement directly to ensure no information loss. ```json [ { @@ -24,7 +24,7 @@ class SimpleExpRetriever(ExpRetriever): "args": { "task_id": "1", "dependent_task_ids": [], - "instruction": "Create a product requirement document (PRD) outlining the features, user interface, and user experience of the CLI snake game.", + "instruction": "Create a product requirement document (PRD) outlining the features, user interface, and user experience of the CLI python snake game.", "assignee": "Alice" } }, @@ -67,7 +67,7 @@ class SimpleExpRetriever(ExpRetriever): { "command_name": "publish_message", "args": { - "content": "User request to create a cli snake game. Please create a product requirement document (PRD) outlining the features, user interface, and user experience of the snake game.", + "content": "Create a cli snake game using Python", "send_to": "Alice" } }, diff --git a/metagpt/strategy/thinking_command.py b/metagpt/strategy/thinking_command.py index ae689eb1f..2910af5cb 100644 --- a/metagpt/strategy/thinking_command.py +++ b/metagpt/strategy/thinking_command.py @@ -43,7 +43,7 @@ class Command(Enum): PUBLISH_MESSAGE = CommandDef( name="publish_message", signature="publish_message(content: str, send_to: str)", - desc="Publish a message to a team member, use member name to fill send_to args. You may copy the full original content or add additional information from upstream. This will make team members start their work. DONT omit any necessary info such as path, link, environment from original content to team members because you are their sole info source.", + desc="Publish a message to a team member, use member name to fill send_to args. You may copy the full original content or add additional information from upstream. This will make team members start their work. DONT omit any necessary info such as path, link, environment, programming language, framework, requirement, constraint from original content to team members because you are their sole info source.", ) REPLY_TO_HUMAN = CommandDef( name="reply_to_human",