Merge branch 'Format-RoleZero-prompt-to-fit-into-exp_pool' into 'mgx_ops'

修改RoleZero的提示词,以适配经验池

See merge request pub/MetaGPT!319
This commit is contained in:
林义章 2024-08-16 07:55:26 +00:00
commit 94ec668c3d
5 changed files with 28 additions and 38 deletions

View file

@ -83,6 +83,7 @@ MESSAGE_ROUTE_TO_ALL = "<all>"
MESSAGE_ROUTE_TO_NONE = "<none>"
MESSAGE_ROUTE_TO_SELF = "<self>" # Add this tag to replace `ActionOutput`
REQUIREMENT_FILENAME = "requirement.txt"
BUGFIX_FILENAME = "bugfix.txt"
PACKAGE_REQUIREMENTS_FILENAME = "requirements.txt"
@ -153,3 +154,6 @@ IMAGES = "images"
# SWE agent
SWE_SETUP_PATH = get_metagpt_package_root() / "metagpt/tools/swe_agent_commands/setup_default.sh"
# experience pool
EXPERIENCE_MASK = "<experience>"

View file

@ -1,9 +1,9 @@
"""RoleZero context builder."""
import copy
import re
from typing import Any
from metagpt.const import EXPERIENCE_MASK
from metagpt.exp_pool.context_builders.base import BaseContextBuilder
@ -31,26 +31,9 @@ class RoleZeroContextBuilder(BaseContextBuilder):
return req_copy
def replace_example_content(self, text: str, new_example_content: str) -> str:
return self.replace_content_between_markers(text, "# Example", "# Instruction", new_example_content)
return self.fill_experience(text, new_example_content)
@staticmethod
def replace_content_between_markers(text: str, start_marker: str, end_marker: str, new_content: str) -> str:
"""Replace the content between `start_marker` and `end_marker` in the text with `new_content`.
Args:
text (str): The original text.
new_content (str): The new content to replace the old content.
start_marker (str): The marker indicating the start of the content to be replaced, such as '# Example'.
end_marker (str): The marker indicating the end of the content to be replaced, such as '# Instruction'.
Returns:
str: The text with the content replaced.
"""
pattern = re.compile(f"({start_marker}\n)(.*?)(\n{end_marker})", re.DOTALL)
def replacement(match):
return f"{match.group(1)}{new_content}\n{match.group(3)}"
replaced_text = pattern.sub(replacement, text)
def fill_experience(text: str, new_example_content: str) -> str:
replaced_text = text.replace(EXPERIENCE_MASK, new_example_content)
return replaced_text

View file

@ -1,3 +1,5 @@
from metagpt.const import EXPERIENCE_MASK
ROLE_INSTRUCTION = """
Based on the context, write a plan or modify an existing plan to achieve the goal. A plan consists of one to 3 tasks.
If plan is created, you should track the progress and update the plan accordingly, such as Plan.finish_current_task, Plan.append_task, Plan.reset_task, Plan.replace_task, etc.
@ -10,7 +12,6 @@ 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".
########################## ignore guidance
@ -47,7 +48,14 @@ Special Command: Use {{"command_name": "end"}} to do nothing or indicate complet
{instruction}
"""
CMD_PROMPT = """
CMD_EXPERIENCE_MASK = f"""
# Past Experience
{EXPERIENCE_MASK}
"""
CMD_PROMPT = (
CMD_EXPERIENCE_MASK
+ """
{current_state}
# Current Plan
@ -79,6 +87,7 @@ Output should adhere to the following format.
```
Notice: your output JSON data section must start with **```json [**
"""
)
THOUGHT_GUIDANCE = """
First, describe the actions you have taken recently.

View file

@ -436,11 +436,6 @@ class RoleZero(Role):
def _get_plan_status(self) -> Tuple[str, str]:
plan_status = self.planner.plan.model_dump(include=["goal", "tasks"])
for task in plan_status["tasks"]:
task.pop("code")
task.pop("result")
task.pop("is_success")
# print(plan_status)
current_task = (
self.planner.plan.current_task.model_dump(exclude=["code", "result", "is_success"])
if self.planner.plan.current_task

View file

@ -1,5 +1,6 @@
import pytest
from metagpt.const import EXPERIENCE_MASK
from metagpt.exp_pool.context_builders.base import BaseContextBuilder
from metagpt.exp_pool.context_builders.role_zero import RoleZeroContextBuilder
@ -30,22 +31,20 @@ class TestRoleZeroContextBuilder:
assert result == [{"content": "Updated content"}]
def test_replace_example_content(self, context_builder, mocker):
mocker.patch.object(RoleZeroContextBuilder, "replace_content_between_markers", return_value="Replaced content")
mocker.patch.object(RoleZeroContextBuilder, "fill_experience", return_value="Replaced content")
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"
)
context_builder.fill_experience.assert_called_once_with("Original text", "New example content")
def test_replace_content_between_markers(self):
text = "Start\n# Example\nOld content\n# Instruction\nEnd"
def test_fill_experience(self):
text = f"Start\n# Past Experience\n{EXPERIENCE_MASK}\n\n# Instruction\nEnd"
new_content = "New content"
result = RoleZeroContextBuilder.replace_content_between_markers(text, "# Example", "# Instruction", new_content)
expected = "Start\n# Example\nNew content\n\n# Instruction\nEnd"
result = RoleZeroContextBuilder.fill_experience(text, new_content)
expected = "Start\n# Past Experience\nNew content\n\n# Instruction\nEnd"
assert result == expected
def test_replace_content_between_markers_no_match(self):
def test_fill_experience_no_match(self):
text = "Start\nNo markers\nEnd"
new_content = "New content"
result = RoleZeroContextBuilder.replace_content_between_markers(text, "# Example", "# Instruction", new_content)
result = RoleZeroContextBuilder.fill_experience(text, new_content)
assert result == text