From ad2530aff98b9f8c7a78ac332e414538a754a4c4 Mon Sep 17 00:00:00 2001 From: zhanglei Date: Thu, 13 Jun 2024 11:17:16 +0800 Subject: [PATCH 1/6] update: git tool --- metagpt/tools/libs/git.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/metagpt/tools/libs/git.py b/metagpt/tools/libs/git.py index b4d759bf4..740cb81f9 100644 --- a/metagpt/tools/libs/git.py +++ b/metagpt/tools/libs/git.py @@ -141,6 +141,8 @@ async def git_create_pull( Returns: PullRequest: The created pull request. """ + from metagpt.utils.git_repository import GitRepository + return await GitRepository.create_pull( base=base, head=head, @@ -187,4 +189,6 @@ async def git_create_issue( Returns: Issue: The created issue. """ + from metagpt.utils.git_repository import GitRepository + return await GitRepository.create_issue(repo_name=repo_name, title=title, body=body, access_token=access_token) From f0df3144d68ed288f5ccce0c34d3939f8462ba98 Mon Sep 17 00:00:00 2001 From: garylin2099 Date: Thu, 13 Jun 2024 15:14:34 +0800 Subject: [PATCH 2/6] fix ask human problem --- metagpt/roles/di/role_zero.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/metagpt/roles/di/role_zero.py b/metagpt/roles/di/role_zero.py index dc28e53a6..6244a39a8 100644 --- a/metagpt/roles/di/role_zero.py +++ b/metagpt/roles/di/role_zero.py @@ -3,7 +3,7 @@ from __future__ import annotations import inspect import json import traceback -from typing import Literal, Tuple +from typing import Callable, Literal, Tuple from pydantic import model_validator @@ -42,7 +42,7 @@ class RoleZero(Role): # Tools tools: list[str] = [] # Use special symbol [""] to indicate use of all registered tools tool_recommender: ToolRecommender = None - tool_execution_map: dict[str, callable] = {} + tool_execution_map: dict[str, Callable] = {} special_tool_commands: list[str] = ["Plan.finish_current_task", "end"] # Equipped with three basic tools by default for optional use editor: Editor = Editor() @@ -247,7 +247,7 @@ class RoleZero(Role): if not isinstance(self.rc.env, MGXEnv): return "Not in MGXEnv, command will not be executed." - return await self.rc.env.get_human_input(question, sent_from=self) + return await self.rc.env.ask_human(question, sent_from=self) async def reply_to_human(self, content: str) -> str: """Reply to human user with the content provided. Use this when you have a clear answer or solution to the user's question.""" From 25ca3381101c94ed6dc249357aa03862b99169f3 Mon Sep 17 00:00:00 2001 From: garylin2099 Date: Thu, 13 Jun 2024 19:46:36 +0800 Subject: [PATCH 3/6] add back content display for Browser._view --- metagpt/tools/libs/browser.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/metagpt/tools/libs/browser.py b/metagpt/tools/libs/browser.py index 955058ea0..1b1b3d82d 100644 --- a/metagpt/tools/libs/browser.py +++ b/metagpt/tools/libs/browser.py @@ -189,8 +189,8 @@ class Browser: async def _view(self, keep_len: int = 5000) -> str: """simulate human viewing the current page, return the visible text with links""" - # visible_text_with_links = await self.current_page.evaluate(VIEW_CONTENT_JS) - # print("The visible text and their links (if any): ", visible_text_with_links[:keep_len]) + visible_text_with_links = await self.current_page.evaluate(VIEW_CONTENT_JS) + print("The visible text and their links (if any): ", visible_text_with_links[:keep_len]) # html_content = await self._view_page_html(keep_len=keep_len) # print("The html content: ", html_content) From 207f3f3b6ac271668d6f459857cb9576c5447bd1 Mon Sep 17 00:00:00 2001 From: garylin2099 Date: Thu, 13 Jun 2024 20:13:32 +0800 Subject: [PATCH 4/6] team leader common-sense qa, ask for clarification, increase max_react_loop, issue end command --- metagpt/prompts/di/team_leader.py | 4 +++- metagpt/roles/di/role_zero.py | 2 +- metagpt/roles/di/team_leader.py | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/metagpt/prompts/di/team_leader.py b/metagpt/prompts/di/team_leader.py index 2e4a17932..7af5a6e07 100644 --- a/metagpt/prompts/di/team_leader.py +++ b/metagpt/prompts/di/team_leader.py @@ -18,7 +18,9 @@ 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 -> (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. -4. It it helpful for Engineer to have both the system design and the project schedule for writing the code, so include paths of both files (if available) when publishing message to Engineer. +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. +6. It is helpful for Engineer to have both the system design and the project schedule for writing the code, so include paths of both files (if available) when publishing message to Engineer. """ FINISH_CURRENT_TASK_CMD = """ diff --git a/metagpt/roles/di/role_zero.py b/metagpt/roles/di/role_zero.py index 6244a39a8..44e658ed4 100644 --- a/metagpt/roles/di/role_zero.py +++ b/metagpt/roles/di/role_zero.py @@ -175,7 +175,7 @@ class RoleZero(Role): actions_taken += 1 return rsp # return output from the last action - async def _run_commands(self, commands) -> list: + async def _run_commands(self, commands) -> str: outputs = [] for cmd in commands: # handle special command first diff --git a/metagpt/roles/di/team_leader.py b/metagpt/roles/di/team_leader.py index 92ddcab04..2932dd7f0 100644 --- a/metagpt/roles/di/team_leader.py +++ b/metagpt/roles/di/team_leader.py @@ -18,7 +18,8 @@ class TeamLeader(RoleZero): profile: str = "Team Leader" system_msg: list[str] = [SYSTEM_PROMPT] - max_react_loop: int = 1 # TeamLeader only reacts once each time + # TeamLeader only reacts once each time, but may encounter errors or need to ask human, thus allowing 2 more turns + max_react_loop: int = 3 tools: list[str] = ["Plan", "RoleZero", "TeamLeader"] From d57d4f3c01bb8550424c17490bec805e381beedf Mon Sep 17 00:00:00 2001 From: garylin2099 Date: Thu, 13 Jun 2024 20:51:03 +0800 Subject: [PATCH 5/6] fix one line content (\\n issue) for editor --- metagpt/tools/libs/editor.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/metagpt/tools/libs/editor.py b/metagpt/tools/libs/editor.py index 23df02edd..eba1a1eac 100644 --- a/metagpt/tools/libs/editor.py +++ b/metagpt/tools/libs/editor.py @@ -1,4 +1,5 @@ import os +import re import shutil import subprocess @@ -26,6 +27,9 @@ class Editor: def write(self, path: str, content: str): """Write the whole content to a file. When used, make sure content arg contains the full content of the file.""" + if len(re.findall(r"\\n", content)) >= 5: + # A very raw rule to correct the content: Many \\n suggests all new line characters are mistaken as \\n whereas the correct one should be \n + content = content.replace("\\n", "\n") directory = os.path.dirname(path) if directory and not os.path.exists(directory): os.makedirs(directory) From aa0f8107262e73dbe41f17dd7956027901f4e2ae Mon Sep 17 00:00:00 2001 From: garylin2099 Date: Fri, 14 Jun 2024 13:58:27 +0800 Subject: [PATCH 6/6] add end command to experience --- metagpt/strategy/experience_retriever.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/metagpt/strategy/experience_retriever.py b/metagpt/strategy/experience_retriever.py index c122affb5..e268e9460 100644 --- a/metagpt/strategy/experience_retriever.py +++ b/metagpt/strategy/experience_retriever.py @@ -83,6 +83,9 @@ class SimpleExpRetriever(ExpRetriever): "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", } + }, + { + "command_name": "end" } ] ``` @@ -113,6 +116,9 @@ class SimpleExpRetriever(ExpRetriever): "args": { "content": "I have assigned the task to David. He will break down the task further by himself and starts solving it.", } + }, + { + "command_name": "end" } ] ``` @@ -142,6 +148,9 @@ class SimpleExpRetriever(ExpRetriever): "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.", } + }, + { + "command_name": "end" } ] ``` @@ -156,6 +165,9 @@ class SimpleExpRetriever(ExpRetriever): "args": { "content": "The team is currently working on ... We have completed ...", } + }, + { + "command_name": "end" } ] ``` @@ -213,6 +225,7 @@ Explanation: Launching a service requires Terminal tool with daemon mode, write "assignee": "David" } }, +] """