mirror of
https://github.com/FoundationAgents/MetaGPT.git
synced 2026-05-15 11:02:36 +02:00
Merge branch 'opt_speed_quality' into 'mgx_ops'
Faster & Better Engineer2, & some small updates See merge request pub/MetaGPT!359
This commit is contained in:
commit
bbbaf08563
4 changed files with 94 additions and 62 deletions
|
|
@ -1,14 +1,25 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from pydantic import Field
|
||||
|
||||
from metagpt.actions.write_code_review import ValidateAndRewriteCode
|
||||
from metagpt.prompts.di.engineer2 import ENGINEER2_INSTRUCTION
|
||||
# from metagpt.actions.write_code_review import ValidateAndRewriteCode
|
||||
from metagpt.prompts.di.engineer2 import (
|
||||
ENGINEER2_INSTRUCTION,
|
||||
WRITE_CODE_PROMPT,
|
||||
WRITE_CODE_SYSTEM_PROMPT,
|
||||
)
|
||||
from metagpt.roles.di.role_zero import RoleZero
|
||||
from metagpt.schema import UserMessage
|
||||
from metagpt.strategy.experience_retriever import ENGINEER_EXAMPLE
|
||||
from metagpt.tools.libs.terminal import Terminal
|
||||
from metagpt.tools.tool_registry import register_tool
|
||||
from metagpt.utils.common import CodeParser, awrite
|
||||
from metagpt.utils.report import EditorReporter
|
||||
|
||||
|
||||
@register_tool(include_functions=["write_new_code"])
|
||||
class Engineer2(RoleZero):
|
||||
name: str = "Alex"
|
||||
profile: str = "Engineer"
|
||||
|
|
@ -17,16 +28,16 @@ class Engineer2(RoleZero):
|
|||
|
||||
terminal: Terminal = Field(default_factory=Terminal, exclude=True)
|
||||
|
||||
tools: list[str] = ["Plan", "Editor:write,read", "RoleZero", "Terminal:run_command", "ValidateAndRewriteCode"]
|
||||
tools: list[str] = ["Plan", "Editor:read", "RoleZero", "Terminal:run_command", "Engineer2"]
|
||||
|
||||
def _update_tool_execution(self):
|
||||
validate = ValidateAndRewriteCode()
|
||||
|
||||
# validate = ValidateAndRewriteCode()
|
||||
self.tool_execution_map.update(
|
||||
{
|
||||
"Terminal.run_command": self.terminal.run_command,
|
||||
"ValidateAndRewriteCode.run": validate.run,
|
||||
"ValidateAndRewriteCode": validate.run,
|
||||
"Engineer2.write_new_code": self.write_new_code,
|
||||
# "ValidateAndRewriteCode.run": validate.run,
|
||||
# "ValidateAndRewriteCode": validate.run,
|
||||
}
|
||||
)
|
||||
|
||||
|
|
@ -42,3 +53,28 @@ class Engineer2(RoleZero):
|
|||
command_output += "All tasks are finished.\n"
|
||||
command_output += await super()._run_special_command(cmd)
|
||||
return command_output
|
||||
|
||||
async def write_new_code(self, path: str, instruction: str = "") -> str:
|
||||
"""Write a new code file.
|
||||
|
||||
Args:
|
||||
path (str): The absolute path of the file to be created.
|
||||
instruction (optional, str): Further hints or notice other than the current task instruction, must be very concise and can be empty. Defaults to "".
|
||||
"""
|
||||
plan_status, _ = self._get_plan_status()
|
||||
prompt = WRITE_CODE_PROMPT.format(
|
||||
user_requirement=self.planner.plan.goal,
|
||||
plan_status=plan_status,
|
||||
instruction=instruction,
|
||||
)
|
||||
context = self.llm.format_msg(self.rc.memory.get(self.memory_k) + [UserMessage(content=prompt)])
|
||||
|
||||
async with EditorReporter(enable_llm_stream=True) as reporter:
|
||||
await reporter.async_report({"type": "code", "filename": Path(path).name, "src_path": path}, "meta")
|
||||
rsp = await self.llm.aask(context, system_msgs=[WRITE_CODE_SYSTEM_PROMPT])
|
||||
code = CodeParser.parse_code(text=rsp)
|
||||
await awrite(path, code)
|
||||
await reporter.async_report(path, "path")
|
||||
|
||||
# TODO: Consider adding line no to be ready for editing.
|
||||
return f"The file {path} has been successfully created, with content:\n{code}"
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import inspect
|
|||
import json
|
||||
import re
|
||||
import traceback
|
||||
from datetime import datetime
|
||||
from typing import Annotated, Callable, Dict, List, Literal, Optional, Tuple
|
||||
|
||||
from pydantic import Field, model_validator
|
||||
|
|
@ -67,7 +68,7 @@ class RoleZero(Role):
|
|||
|
||||
# React Mode
|
||||
react_mode: Literal["react"] = "react"
|
||||
max_react_loop: int = 20 # used for react mode
|
||||
max_react_loop: int = 50 # used for react mode
|
||||
|
||||
# Tools
|
||||
tools: list[str] = [] # Use special symbol ["<all>"] to indicate use of all registered tools
|
||||
|
|
@ -233,6 +234,10 @@ class RoleZero(Role):
|
|||
msg.add_metadata(IMAGES, images)
|
||||
return memory
|
||||
|
||||
def _get_prefix(self) -> str:
|
||||
time_info = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
return super()._get_prefix() + f" The current time is {time_info}."
|
||||
|
||||
async def _act(self) -> Message:
|
||||
if self.use_fixed_sop:
|
||||
return await super()._act()
|
||||
|
|
@ -276,6 +281,14 @@ class RoleZero(Role):
|
|||
logger.debug(f"{self._setting}: {self.rc.state=}, will do {self.rc.todo}")
|
||||
rsp = await self._act()
|
||||
actions_taken += 1
|
||||
|
||||
# post-check
|
||||
if self.rc.max_react_loop >= 10 and actions_taken >= self.rc.max_react_loop:
|
||||
# If max_react_loop is a small value (e.g. < 10), it is intended to be reached and make the agent stop
|
||||
logger.warning(f"reached max_react_loop: {actions_taken}")
|
||||
rsp = await self.ask_human("I have reached my max action rounds, do you want me to continue? Yes or no")
|
||||
if "yes" in rsp.lower():
|
||||
actions_taken = 0
|
||||
return rsp # return output from the last action
|
||||
|
||||
def format_quick_system_prompt(self) -> str:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue