mirror of
https://github.com/FoundationAgents/MetaGPT.git
synced 2026-06-08 15:05:17 +02:00
remove useless code and format code
This commit is contained in:
parent
ebc4fe4b17
commit
57121ef395
14 changed files with 50 additions and 165 deletions
|
|
@ -71,22 +71,6 @@ class Action(BaseModel):
|
|||
def __repr__(self):
|
||||
return self.__str__()
|
||||
|
||||
@classmethod
|
||||
def ser_class(cls) -> dict:
|
||||
""" serialize class type"""
|
||||
return {
|
||||
"action_class": cls.__name__,
|
||||
"module_name": cls.__module__
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def deser_class(cls, action_dict: dict):
|
||||
""" deserialize class type """
|
||||
action_class_str = action_dict.pop("action_class")
|
||||
module_name = action_dict.pop("module_name")
|
||||
action_class = import_class(action_class_str, module_name)
|
||||
return action_class
|
||||
|
||||
async def _aask(self, prompt: str, system_msgs: Optional[list[str]] = None) -> str:
|
||||
"""Append default prefix"""
|
||||
if not system_msgs:
|
||||
|
|
|
|||
|
|
@ -12,17 +12,11 @@
|
|||
import json
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
from pydantic import Field
|
||||
|
||||
from metagpt.actions import Action, ActionOutput
|
||||
from metagpt.actions.design_api_an import DESIGN_API_NODE
|
||||
from typing import List, Optional, Any
|
||||
|
||||
from pydantic import Field
|
||||
|
||||
from metagpt.actions import Action, ActionOutput
|
||||
from metagpt.llm import LLM
|
||||
from metagpt.provider.base_gpt_api import BaseGPTAPI
|
||||
from metagpt.config import CONFIG
|
||||
from metagpt.const import (
|
||||
DATA_API_DESIGN_FILE_REPO,
|
||||
|
|
@ -31,12 +25,13 @@ from metagpt.const import (
|
|||
SYSTEM_DESIGN_FILE_REPO,
|
||||
SYSTEM_DESIGN_PDF_FILE_REPO,
|
||||
)
|
||||
from metagpt.llm import LLM
|
||||
from metagpt.logs import logger
|
||||
from metagpt.schema import Document, Documents
|
||||
from metagpt.provider.base_gpt_api import BaseGPTAPI
|
||||
from metagpt.schema import Document, Documents, Message
|
||||
from metagpt.utils.file_repository import FileRepository
|
||||
from metagpt.utils.mermaid import mermaid_to_file
|
||||
|
||||
|
||||
NEW_REQ_TEMPLATE = """
|
||||
### Legacy Content
|
||||
{old_design}
|
||||
|
|
@ -50,11 +45,11 @@ class WriteDesign(Action):
|
|||
name: str = ""
|
||||
context: Optional[str] = None
|
||||
llm: BaseGPTAPI = Field(default_factory=LLM)
|
||||
desc: str = "Based on the PRD, think about the system design, and design the corresponding APIs, "
|
||||
"data structures, library tables, processes, and paths. Please provide your design, feedback "
|
||||
"clearly and in detail."
|
||||
desc: str = "Based on the PRD, think about the system design, and design the corresponding APIs, " \
|
||||
"data structures, library tables, processes, and paths. Please provide your design, feedback " \
|
||||
"clearly and in detail."
|
||||
|
||||
async def run(self, with_messages, format=CONFIG.prompt_format):
|
||||
async def run(self, with_messages: Message, format: str = CONFIG.prompt_format):
|
||||
# Use `git diff` to identify which PRD documents have been modified in the `docs/prds` directory.
|
||||
prds_file_repo = CONFIG.git_repo.new_file_repository(PRDS_FILE_REPO)
|
||||
changed_prds = prds_file_repo.changed_files
|
||||
|
|
|
|||
|
|
@ -9,16 +9,24 @@
|
|||
"""
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
from pydantic import Field
|
||||
|
||||
from metagpt.actions import Action, ActionOutput
|
||||
from metagpt.config import CONFIG
|
||||
from metagpt.const import DEFAULT_WORKSPACE_ROOT, DOCS_FILE_REPO, REQUIREMENT_FILENAME
|
||||
from metagpt.llm import LLM
|
||||
from metagpt.provider.base_gpt_api import BaseGPTAPI
|
||||
from metagpt.schema import Document
|
||||
from metagpt.utils.file_repository import FileRepository
|
||||
from metagpt.utils.git_repository import GitRepository
|
||||
|
||||
|
||||
class PrepareDocuments(Action):
|
||||
name: str = "PrepareDocuments"
|
||||
context: Optional[str] = None
|
||||
llm: BaseGPTAPI = Field(default_factory=LLM)
|
||||
|
||||
async def run(self, with_messages, **kwargs):
|
||||
if not CONFIG.git_repo:
|
||||
|
|
|
|||
|
|
@ -11,14 +11,13 @@
|
|||
"""
|
||||
|
||||
import json
|
||||
from typing import List, Optional, Any
|
||||
from typing import Optional
|
||||
|
||||
from pydantic import Field
|
||||
|
||||
from metagpt.actions import ActionOutput
|
||||
from metagpt.actions.action import Action
|
||||
from metagpt.actions.project_management_an import PM_NODE
|
||||
from metagpt.llm import LLM
|
||||
from metagpt.provider.base_gpt_api import BaseGPTAPI
|
||||
from metagpt.config import CONFIG
|
||||
from metagpt.const import (
|
||||
PACKAGE_REQUIREMENTS_FILENAME,
|
||||
|
|
@ -26,11 +25,11 @@ from metagpt.const import (
|
|||
TASK_FILE_REPO,
|
||||
TASK_PDF_FILE_REPO,
|
||||
)
|
||||
from metagpt.llm import LLM
|
||||
from metagpt.logs import logger
|
||||
from metagpt.provider.base_gpt_api import BaseGPTAPI
|
||||
from metagpt.schema import Document, Documents
|
||||
from metagpt.utils.file_repository import FileRepository
|
||||
from metagpt.provider.base_gpt_api import BaseGPTAPI
|
||||
|
||||
|
||||
NEW_REQ_TEMPLATE = """
|
||||
### Legacy Content
|
||||
|
|
|
|||
|
|
@ -166,7 +166,7 @@ class WritePRD(Action):
|
|||
if not quadrant_chart:
|
||||
return
|
||||
pathname = (
|
||||
CONFIG.git_repo.workdir / Path(COMPETITIVE_ANALYSIS_FILE_REPO) / Path(prd_doc.filename).with_suffix("")
|
||||
CONFIG.git_repo.workdir / Path(COMPETITIVE_ANALYSIS_FILE_REPO) / Path(prd_doc.filename).with_suffix("")
|
||||
)
|
||||
if not pathname.parent.exists():
|
||||
pathname.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
|
|
|||
|
|
@ -5,20 +5,28 @@
|
|||
@Author : alexanderwu
|
||||
@File : write_prd_review.py
|
||||
"""
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from pydantic import Field
|
||||
|
||||
from metagpt.actions.action import Action
|
||||
from metagpt.llm import LLM
|
||||
from metagpt.provider.base_gpt_api import BaseGPTAPI
|
||||
|
||||
|
||||
class WritePRDReview(Action):
|
||||
def __init__(self, name, context=None, llm=None):
|
||||
super().__init__(name, context, llm)
|
||||
self.prd = None
|
||||
self.desc = "Based on the PRD, conduct a PRD Review, providing clear and detailed feedback"
|
||||
self.prd_review_prompt_template = """
|
||||
Given the following Product Requirement Document (PRD):
|
||||
{prd}
|
||||
name: str = ""
|
||||
context: Optional[str] = None
|
||||
llm: BaseGPTAPI = Field(default_factory=LLM)
|
||||
prd: Optional[str] = None
|
||||
desc: str = "Based on the PRD, conduct a PRD Review, providing clear and detailed feedback"
|
||||
prd_review_prompt_template: str = """
|
||||
Given the following Product Requirement Document (PRD):
|
||||
{prd}
|
||||
|
||||
As a project manager, please review it and provide your feedback and suggestions.
|
||||
"""
|
||||
As a project manager, please review it and provide your feedback and suggestions.
|
||||
"""
|
||||
|
||||
async def run(self, prd):
|
||||
self.prd = prd
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ class Environment(BaseModel):
|
|||
"role_class": role.__class__.__name__,
|
||||
"module_name": role.__module__,
|
||||
"role_name": role.name,
|
||||
"role_sub_tags": list(self.members.get(role))
|
||||
})
|
||||
role.serialize(stg_path=stg_path.joinpath(f"roles/{role.__class__.__name__}_{role.name}"))
|
||||
write_json_file(roles_path, roles_info)
|
||||
|
|
@ -70,14 +71,13 @@ class Environment(BaseModel):
|
|||
|
||||
@classmethod
|
||||
def deserialize(cls, stg_path: Path) -> "Environment":
|
||||
""" stg_path: ./storage/team/environment/ """
|
||||
""" stg_path: ./storage/team/environment/ """
|
||||
roles_path = stg_path.joinpath("roles.json")
|
||||
roles_info = read_json_file(roles_path)
|
||||
roles = []
|
||||
for role_info in roles_info:
|
||||
# role stored in ./environment/roles/{role_class}_{role_name}
|
||||
role_path = stg_path.joinpath(f'roles/{role_info.get("role_class")}_{role_info.get("role_name")}')
|
||||
role_path = stg_path.joinpath(f"roles/{role_info.get('role_class')}_{role_info.get('role_name')}")
|
||||
role = Role.deserialize(role_path)
|
||||
roles.append(role)
|
||||
|
||||
|
|
@ -96,7 +96,6 @@ class Environment(BaseModel):
|
|||
Add a role in the current environment
|
||||
"""
|
||||
role.set_env(self)
|
||||
# use alias
|
||||
self.roles[role.profile] = role
|
||||
|
||||
def add_roles(self, roles: Iterable[Role]):
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ from metagpt.utils.utils import read_json_file, write_json_file
|
|||
|
||||
class Memory(BaseModel):
|
||||
"""The most basic memory: super-memory"""
|
||||
|
||||
storage: list[Message] = Field(default=[])
|
||||
index: dict[str, list[Message]] = Field(default_factory=defaultdict(list))
|
||||
|
||||
|
|
@ -33,15 +32,6 @@ class Memory(BaseModel):
|
|||
super(Memory, self).__init__(**kwargs)
|
||||
self.index = new_index
|
||||
|
||||
def dict(self, *args, **kwargs) -> "DictStrAny":
|
||||
""" overwrite the `dict` to dump dynamic pydantic model"""
|
||||
obj_dict = super(Memory, self).dict(*args, **kwargs)
|
||||
new_obj_dict = copy.deepcopy(obj_dict)
|
||||
new_obj_dict["index"] = {}
|
||||
for action_str, value in obj_dict["index"].items():
|
||||
new_obj_dict["index"][action_str] = value
|
||||
return new_obj_dict
|
||||
|
||||
def serialize(self, stg_path: Path):
|
||||
""" stg_path = ./storage/team/environment/ or ./storage/team/environment/roles/{role_class}_{role_name}/ """
|
||||
memory_path = stg_path.joinpath("memory.json")
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ from metagpt.roles.role import Role
|
|||
|
||||
class ProductManager(Role):
|
||||
"""
|
||||
Represents a Project Manager role responsible for overseeing project execution and team efficiency.
|
||||
Represents a Product Manager role responsible for product development and management.
|
||||
|
||||
Attributes:
|
||||
name (str): Name of the project manager.
|
||||
|
|
@ -28,11 +28,7 @@ class ProductManager(Role):
|
|||
name: str = "Alice"
|
||||
profile: str = Field(default="Product Manager")
|
||||
goal: str = "efficiently create a successful product"
|
||||
constraints: str = "use same language as user requiremen"
|
||||
|
||||
"""
|
||||
Represents a Product Manager role responsible for product development and management.
|
||||
"""
|
||||
constraints: str = "use same language as user requirement"
|
||||
|
||||
def __init__(self, **kwargs) -> None:
|
||||
super().__init__(**kwargs)
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ class ProjectManager(Role):
|
|||
"""
|
||||
name: str = Field(default="Eve")
|
||||
profile: str = Field(default="Project Manager")
|
||||
goal: str = "reak down tasks according to PRD/technical design, generate a task list, and analyze task " \
|
||||
goal: str = "break down tasks according to PRD/technical design, generate a task list, and analyze task " \
|
||||
"dependencies to start with the prerequisite modules"
|
||||
constraints: str = "use same language as user requirement"
|
||||
|
||||
|
|
|
|||
|
|
@ -81,22 +81,6 @@ class RoleReactMode(str, Enum):
|
|||
return [item.value for item in cls]
|
||||
|
||||
|
||||
class RoleSetting(BaseModel):
|
||||
"""Role Settings"""
|
||||
name: str = ""
|
||||
profile: str = ""
|
||||
goal: str = ""
|
||||
constraints: str = ""
|
||||
desc: str = ""
|
||||
is_human: bool = False
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.name}({self.profile})"
|
||||
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
||||
|
||||
|
||||
class RoleContext(BaseModel):
|
||||
"""Role Runtime Context"""
|
||||
# # env exclude=True to avoid `RecursionError: maximum recursion depth exceeded in comparison`
|
||||
|
|
@ -160,7 +144,8 @@ class Role(BaseModel):
|
|||
"_role_id": _role_id,
|
||||
"_states": [],
|
||||
"_actions": [],
|
||||
"_rc": RoleContext()
|
||||
"_rc": RoleContext(),
|
||||
"_subscription": set()
|
||||
}
|
||||
|
||||
__hash__ = object.__hash__ # support Role as hashable type in `Environment.members`
|
||||
|
|
@ -186,7 +171,7 @@ class Role(BaseModel):
|
|||
# 关于私有变量的初始化 https://github.com/pydantic/pydantic/issues/655
|
||||
self._private_attributes["_llm"] = LLM() if not self.is_human else HumanProvider()
|
||||
self._private_attributes["_role_id"] = str(self._setting)
|
||||
self._subscription = {any_to_str(self), name} if name else {any_to_str(self)}
|
||||
self._private_attributes["_subscription"] = {any_to_str(self), self.name} if self.name else {any_to_str(self)}
|
||||
|
||||
for key in self._private_attributes.keys():
|
||||
if key in kwargs:
|
||||
|
|
@ -202,64 +187,7 @@ class Role(BaseModel):
|
|||
else:
|
||||
object.__setattr__(self, key, self._private_attributes[key])
|
||||
|
||||
if not self._rc.watch:
|
||||
self._watch([UserRequirement])
|
||||
|
||||
# deserialize child classes dynamically for inherited `role`
|
||||
object.__setattr__(self, "builtin_class_name", self.__class__.__name__)
|
||||
self.__fields__["builtin_class_name"].default = self.__class__.__name__
|
||||
|
||||
def __init_subclass__(cls, **kwargs: Any) -> None:
|
||||
super().__init_subclass__(**kwargs)
|
||||
role_subclass_registry[cls.__name__] = cls
|
||||
|
||||
# builtin variables
|
||||
recovered: bool = False # to tag if a recovered role
|
||||
builtin_class_name: str = ""
|
||||
|
||||
_private_attributes = {
|
||||
"_llm": LLM() if not is_human else HumanProvider(),
|
||||
"_role_id": _role_id,
|
||||
"_states": [],
|
||||
"_actions": [],
|
||||
"_rc": RoleContext()
|
||||
}
|
||||
|
||||
class Config:
|
||||
arbitrary_types_allowed = True
|
||||
exclude = ["_llm"]
|
||||
|
||||
def __init__(self, **kwargs: Any):
|
||||
for index in range(len(kwargs.get("_actions", []))):
|
||||
current_action = kwargs["_actions"][index]
|
||||
if isinstance(current_action, dict):
|
||||
item_class_name = current_action.get("builtin_class_name", None)
|
||||
for name, subclass in action_subclass_registry.items():
|
||||
registery_class_name = subclass.__fields__["builtin_class_name"].default
|
||||
if item_class_name == registery_class_name:
|
||||
current_action = subclass(**current_action)
|
||||
break
|
||||
kwargs["_actions"][index] = current_action
|
||||
|
||||
super().__init__(**kwargs)
|
||||
|
||||
# 关于私有变量的初始化 https://github.com/pydantic/pydantic/issues/655
|
||||
self._private_attributes["_llm"] = LLM() if not self.is_human else HumanProvider()
|
||||
self._private_attributes["_role_id"] = str(self._setting)
|
||||
|
||||
for key in self._private_attributes.keys():
|
||||
if key in kwargs:
|
||||
object.__setattr__(self, key, kwargs[key])
|
||||
if key == "_rc":
|
||||
_rc = RoleContext(**kwargs["_rc"])
|
||||
object.__setattr__(self, "_rc", _rc)
|
||||
else:
|
||||
if key == "_rc":
|
||||
# # Warning, if use self._private_attributes["_rc"],
|
||||
# # self._rc will be a shared object between roles, so init one or reset it inside `_reset`
|
||||
object.__setattr__(self, key, RoleContext())
|
||||
else:
|
||||
object.__setattr__(self, key, self._private_attributes[key])
|
||||
self._llm.system_prompt = self._get_prefix()
|
||||
|
||||
# deserialize child classes dynamically for inherited `role`
|
||||
object.__setattr__(self, "builtin_class_name", self.__class__.__name__)
|
||||
|
|
@ -341,9 +269,6 @@ class Role(BaseModel):
|
|||
self._actions.append(i)
|
||||
self._states.append(f"{idx}. {action}")
|
||||
|
||||
def set_react_mode(self, react_mode: RoleReactMode, max_react_loop: int = 1):
|
||||
self._set_react_mode(react_mode, max_react_loop)
|
||||
|
||||
def _set_react_mode(self, react_mode: str, max_react_loop: int = 1):
|
||||
"""Set strategy of the Role reacting to observed Message. Variation lies in how
|
||||
this Role elects action to perform during the _think stage, especially if it is capable of multiple Actions.
|
||||
|
|
@ -365,9 +290,6 @@ class Role(BaseModel):
|
|||
if react_mode == RoleReactMode.REACT:
|
||||
self._rc.max_react_loop = max_react_loop
|
||||
|
||||
def watch(self, actions: Iterable[Type[Action]]):
|
||||
self._watch(actions)
|
||||
|
||||
def _watch(self, actions: Iterable[Type[Action]]):
|
||||
"""Watch Actions of interest. Role will select Messages caused by these Actions from its personal message
|
||||
buffer during _observe.
|
||||
|
|
@ -386,9 +308,6 @@ class Role(BaseModel):
|
|||
if self._rc.env: # According to the routing feature plan in Chapter 2.2.3.2 of RFC 113
|
||||
self._rc.env.set_subscription(self, self._subscription)
|
||||
|
||||
def set_state(self, state: int):
|
||||
self._set_state(state)
|
||||
|
||||
def _set_state(self, state: int):
|
||||
"""Update the current state."""
|
||||
self._rc.state = state
|
||||
|
|
@ -436,7 +355,7 @@ class Role(BaseModel):
|
|||
n_states=len(self._states) - 1,
|
||||
previous_state=self._rc.state,
|
||||
)
|
||||
# print(prompt)
|
||||
|
||||
next_state = await self._llm.aask(prompt)
|
||||
next_state = extract_state_value_from_output(next_state)
|
||||
logger.debug(f"{prompt=}")
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ from typing import Dict, List, Set, TypedDict, Optional, Any
|
|||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from metagpt.actions import UserRequirement
|
||||
from metagpt.config import CONFIG
|
||||
from metagpt.const import (
|
||||
MESSAGE_ROUTE_CAUSE_BY,
|
||||
|
|
@ -118,7 +119,7 @@ class Message(BaseModel):
|
|||
kwargs["instruct_content"] = ic_new
|
||||
|
||||
kwargs["id"] = uuid.uuid4().hex
|
||||
kwargs["cause_by"] = any_to_str(kwargs.get("cause_by", ""))
|
||||
kwargs["cause_by"] = any_to_str(kwargs.get("cause_by", UserRequirement))
|
||||
kwargs["sent_from"] = any_to_str(kwargs.get("sent_from", ""))
|
||||
kwargs["send_to"] = any_to_str_set(kwargs.get("send_to", {MESSAGE_ROUTE_TO_ALL}))
|
||||
super(Message, self).__init__(**kwargs)
|
||||
|
|
|
|||
|
|
@ -68,9 +68,6 @@ def serialize_general_message(message: "Message") -> dict:
|
|||
mapping = actionoutput_mapping_to_str(mapping)
|
||||
|
||||
message_cp.instruct_content = {"class": schema["title"], "mapping": mapping, "value": ic.dict()}
|
||||
cb = message_cp.cause_by
|
||||
if cb:
|
||||
message_cp.cause_by = cb.ser_class()
|
||||
return message_cp.dict()
|
||||
|
||||
|
||||
|
|
@ -103,9 +100,6 @@ def deserialize_general_message(message_dict: dict) -> "Message":
|
|||
ic_obj = actionoutput_class.create_model_class(class_name=ic["class"], mapping=mapping)
|
||||
ic_new = ic_obj(**ic["value"])
|
||||
message.instruct_content = ic_new
|
||||
if cause_by:
|
||||
action_class = import_class("Action", "metagpt.actions.action")
|
||||
message.cause_by = action_class.deser_class(cause_by)
|
||||
|
||||
return message
|
||||
|
||||
|
|
|
|||
|
|
@ -25,11 +25,3 @@ async def test_action_deserialize():
|
|||
assert new_action.name == ""
|
||||
assert new_action.llm == LLM()
|
||||
assert len(await new_action._aask("who are you")) > 0
|
||||
|
||||
|
||||
def test_action_serdeser():
|
||||
action_info = WriteTest.ser_class()
|
||||
assert action_info["action_class"] == "WriteTest"
|
||||
|
||||
action_class = Action.deser_class(action_info)
|
||||
assert action_class == WriteTest
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue