mirror of
https://github.com/FoundationAgents/MetaGPT.git
synced 2026-05-27 14:25:20 +02:00
roles update. More comments and docstrings
This commit is contained in:
parent
5a466d577f
commit
5170ee720a
6 changed files with 193 additions and 63 deletions
|
|
@ -11,10 +11,28 @@ from metagpt.roles import Role
|
|||
|
||||
|
||||
class Architect(Role):
|
||||
"""Architect: Listen to PRD, responsible for designing API, designing code files"""
|
||||
def __init__(self, name="Bob", profile="Architect", goal="Design a concise, usable, complete python system",
|
||||
constraints="Try to specify good open source tools as much as possible"):
|
||||
"""
|
||||
Represents an Architect role in a software development process.
|
||||
|
||||
Attributes:
|
||||
name (str): Name of the architect.
|
||||
profile (str): Role profile, default is 'Architect'.
|
||||
goal (str): Primary goal or responsibility of the architect.
|
||||
constraints (str): Constraints or guidelines for the architect.
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
name: str = "Bob",
|
||||
profile: str = "Architect",
|
||||
goal: str = "Design a concise, usable, complete python system",
|
||||
constraints: str = "Try to specify good open source tools as much as possible") -> None:
|
||||
"""Initializes the Architect with given attributes."""
|
||||
super().__init__(name, profile, goal, constraints)
|
||||
|
||||
# Initialize actions specific to the Architect role
|
||||
self._init_actions([WriteDesign])
|
||||
|
||||
# Set events or actions the Architect should watch or be aware of
|
||||
self._watch({WritePRD})
|
||||
|
||||
|
||||
|
|
@ -46,9 +46,27 @@ async def gather_ordered_k(coros, k) -> list:
|
|||
|
||||
|
||||
class Engineer(Role):
|
||||
def __init__(self, name="Alex", profile="Engineer", goal="Write elegant, readable, extensible, efficient code",
|
||||
constraints="The code you write should conform to code standard like PEP8, be modular, easy to read and maintain",
|
||||
n_borg=1, use_code_review=False):
|
||||
"""
|
||||
Represents an Engineer role responsible for writing and possibly reviewing code.
|
||||
|
||||
Attributes:
|
||||
name (str): Name of the engineer.
|
||||
profile (str): Role profile, default is 'Engineer'.
|
||||
goal (str): Goal of the engineer.
|
||||
constraints (str): Constraints for the engineer.
|
||||
n_borg (int): Number of borgs.
|
||||
use_code_review (bool): Whether to use code review.
|
||||
todos (list): List of tasks.
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
name: str = "Alex",
|
||||
profile: str = "Engineer",
|
||||
goal: str = "Write elegant, readable, extensible, efficient code",
|
||||
constraints: str = "The code should conform to standards like PEP8 and be modular and maintainable",
|
||||
n_borg: int = 1,
|
||||
use_code_review: bool = False) -> None:
|
||||
"""Initializes the Engineer role with given attributes."""
|
||||
super().__init__(name, profile, goal, constraints)
|
||||
self._init_actions([WriteCode])
|
||||
self.use_code_review = use_code_review
|
||||
|
|
@ -142,47 +160,47 @@ class Engineer(Role):
|
|||
msg = Message(content="all done.", role=self.profile, cause_by=type(self._rc.todo))
|
||||
return msg
|
||||
|
||||
async def _act_sp_precision(self) -> Message:
|
||||
for todo in self.todos:
|
||||
"""
|
||||
# Select essential information from the historical data to reduce the length of the prompt (summarized from human experience):
|
||||
1. All from Architect
|
||||
2. All from ProjectManager
|
||||
3. Do we need other codes (currently needed)?
|
||||
TODO: The goal is not to need it. After clear task decomposition, based on the design idea, you should be able to write a single file without needing other codes. If you can't, it means you need a clearer definition. This is the key to writing longer code.
|
||||
"""
|
||||
context = []
|
||||
msg = self._rc.memory.get_by_actions([WriteDesign, WriteTasks, WriteCode])
|
||||
for m in msg:
|
||||
context.append(m.content)
|
||||
context_str = "\n".join(context)
|
||||
# Write code
|
||||
code = await WriteCode().run(
|
||||
context=context_str,
|
||||
filename=todo
|
||||
)
|
||||
# Code review
|
||||
async def _act_sp_precision(self) -> Message:
|
||||
for todo in self.todos:
|
||||
"""
|
||||
# Select essential information from the historical data to reduce the length of the prompt (summarized from human experience):
|
||||
1. All from Architect
|
||||
2. All from ProjectManager
|
||||
3. Do we need other codes (currently needed)?
|
||||
TODO: The goal is not to need it. After clear task decomposition, based on the design idea, you should be able to write a single file without needing other codes. If you can't, it means you need a clearer definition. This is the key to writing longer code.
|
||||
"""
|
||||
context = []
|
||||
msg = self._rc.memory.get_by_actions([WriteDesign, WriteTasks, WriteCode])
|
||||
for m in msg:
|
||||
context.append(m.content)
|
||||
context_str = "\n".join(context)
|
||||
# Write code
|
||||
code = await WriteCode().run(
|
||||
context=context_str,
|
||||
filename=todo
|
||||
)
|
||||
# Code review
|
||||
if self.use_code_review:
|
||||
try:
|
||||
rewrite_code = await WriteCodeReview().run(
|
||||
context=context_str,
|
||||
code=code,
|
||||
filename=todo
|
||||
)
|
||||
code = rewrite_code
|
||||
except Exception as e:
|
||||
logger.error("code review failed!", e)
|
||||
pass
|
||||
self.write_file(todo, code)
|
||||
msg = Message(content=code, role=self.profile, cause_by=WriteCode)
|
||||
self._rc.memory.add(msg)
|
||||
|
||||
logger.info(f'Done {self.get_workspace()} generating.')
|
||||
msg = Message(content="all done.", role=self.profile, cause_by=WriteCode)
|
||||
return msg
|
||||
|
||||
async def _act(self) -> Message:
|
||||
"""Determines the mode of action based on whether code review is used."""
|
||||
if self.use_code_review:
|
||||
try:
|
||||
rewrite_code = await WriteCodeReview().run(
|
||||
context=context_str,
|
||||
code=code,
|
||||
filename=todo
|
||||
)
|
||||
code = rewrite_code
|
||||
except Exception as e:
|
||||
logger.error("code review failed!", e)
|
||||
pass
|
||||
self.write_file(todo, code)
|
||||
msg = Message(content=code, role=self.profile, cause_by=WriteCode)
|
||||
self._rc.memory.add(msg)
|
||||
|
||||
logger.info(f'Done {self.get_workspace()} generating.')
|
||||
msg = Message(content="all done.", role=self.profile, cause_by=WriteCode)
|
||||
return msg
|
||||
|
||||
async def _act(self) -> Message:
|
||||
if self.use_code_review:
|
||||
return await self._act_sp_precision()
|
||||
return await self._act_sp()
|
||||
|
||||
return await self._act_sp_precision()
|
||||
return await self._act_sp()
|
||||
|
|
@ -10,9 +10,30 @@ from metagpt.roles import Role
|
|||
|
||||
|
||||
class ProductManager(Role):
|
||||
def __init__(self, name="Alice", profile="Product Manager", goal="Efficiently create a successful product",
|
||||
constraints=""):
|
||||
"""
|
||||
Represents a Product Manager role responsible for product development and management.
|
||||
|
||||
Attributes:
|
||||
name (str): Name of the product manager.
|
||||
profile (str): Role profile, default is 'Product Manager'.
|
||||
goal (str): Goal of the product manager.
|
||||
constraints (str): Constraints or limitations for the product manager.
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
name: str = "Alice",
|
||||
profile: str = "Product Manager",
|
||||
goal: str = "Efficiently create a successful product",
|
||||
constraints: str = "") -> None:
|
||||
"""
|
||||
Initializes the ProductManager role with given attributes.
|
||||
|
||||
Args:
|
||||
name (str): Name of the product manager.
|
||||
profile (str): Role profile.
|
||||
goal (str): Goal of the product manager.
|
||||
constraints (str): Constraints or limitations for the product manager.
|
||||
"""
|
||||
super().__init__(name, profile, goal, constraints)
|
||||
self._init_actions([WritePRD])
|
||||
self._watch([BossRequirement])
|
||||
|
||||
self._watch([BossRequirement])
|
||||
|
|
@ -10,9 +10,30 @@ from metagpt.roles import Role
|
|||
|
||||
|
||||
class ProjectManager(Role):
|
||||
def __init__(self, name="Eve", profile="Project Manager",
|
||||
goal="Improve team efficiency and deliver with quality and quantity", constraints=""):
|
||||
"""
|
||||
Represents a Project Manager role responsible for overseeing project execution and team efficiency.
|
||||
|
||||
Attributes:
|
||||
name (str): Name of the project manager.
|
||||
profile (str): Role profile, default is 'Project Manager'.
|
||||
goal (str): Goal of the project manager.
|
||||
constraints (str): Constraints or limitations for the project manager.
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
name: str = "Eve",
|
||||
profile: str = "Project Manager",
|
||||
goal: str = "Improve team efficiency and deliver with quality and quantity",
|
||||
constraints: str = "") -> None:
|
||||
"""
|
||||
Initializes the ProjectManager role with given attributes.
|
||||
|
||||
Args:
|
||||
name (str): Name of the project manager.
|
||||
profile (str): Role profile.
|
||||
goal (str): Goal of the project manager.
|
||||
constraints (str): Constraints or limitations for the project manager.
|
||||
"""
|
||||
super().__init__(name, profile, goal, constraints)
|
||||
self._init_actions([WriteTasks])
|
||||
self._watch([WriteDesign])
|
||||
|
||||
self._watch([WriteDesign])
|
||||
|
|
@ -10,6 +10,29 @@ from metagpt.roles import Role
|
|||
|
||||
|
||||
class QaEngineer(Role):
|
||||
def __init__(self, name, profile, goal, constraints):
|
||||
"""
|
||||
Represents a Quality Assurance (QA) Engineer role responsible for writing tests to ensure software quality.
|
||||
|
||||
Attributes:
|
||||
name (str): Name of the QA engineer.
|
||||
profile (str): Role profile.
|
||||
goal (str): Goal of the QA engineer.
|
||||
constraints (str): Constraints or limitations for the QA engineer.
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
name: str,
|
||||
profile: str,
|
||||
goal: str,
|
||||
constraints: str) -> None:
|
||||
"""
|
||||
Initializes the QaEngineer role with given attributes.
|
||||
|
||||
Args:
|
||||
name (str): Name of the QA engineer.
|
||||
profile (str): Role profile.
|
||||
goal (str): Goal of the QA engineer.
|
||||
constraints (str): Constraints or limitations for the QA engineer.
|
||||
"""
|
||||
super().__init__(name, profile, goal, constraints)
|
||||
self._init_actions([WriteTest])
|
||||
|
|
@ -13,26 +13,55 @@ from metagpt.tools import SearchEngineType
|
|||
|
||||
|
||||
class Searcher(Role):
|
||||
def __init__(self, name='Alice', profile='Smart Assistant', goal='Provide search services for users',
|
||||
constraints='Answer is rich and complete', engine=SearchEngineType.SERPAPI_GOOGLE, **kwargs):
|
||||
"""
|
||||
Represents a Searcher role responsible for providing search services to users.
|
||||
|
||||
Attributes:
|
||||
name (str): Name of the searcher.
|
||||
profile (str): Role profile.
|
||||
goal (str): Goal of the searcher.
|
||||
constraints (str): Constraints or limitations for the searcher.
|
||||
engine (SearchEngineType): The type of search engine to use.
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
name: str = 'Alice',
|
||||
profile: str = 'Smart Assistant',
|
||||
goal: str = 'Provide search services for users',
|
||||
constraints: str = 'Answer is rich and complete',
|
||||
engine=SearchEngineType.SERPAPI_GOOGLE,
|
||||
**kwargs) -> None:
|
||||
"""
|
||||
Initializes the Searcher role with given attributes.
|
||||
|
||||
Args:
|
||||
name (str): Name of the searcher.
|
||||
profile (str): Role profile.
|
||||
goal (str): Goal of the searcher.
|
||||
constraints (str): Constraints or limitations for the searcher.
|
||||
engine (SearchEngineType): The type of search engine to use.
|
||||
"""
|
||||
super().__init__(name, profile, goal, constraints, **kwargs)
|
||||
self._init_actions([SearchAndSummarize(engine=engine)])
|
||||
|
||||
def set_search_func(self, search_func):
|
||||
"""Sets a custom search function for the searcher."""
|
||||
action = SearchAndSummarize("", engine=SearchEngineType.CUSTOM_ENGINE, search_func=search_func)
|
||||
self._init_actions([action])
|
||||
|
||||
async def _act_sp(self) -> Message:
|
||||
"""Performs the search action in a single process."""
|
||||
logger.info(f"{self._setting}: ready to {self._rc.todo}")
|
||||
response = await self._rc.todo.run(self._rc.memory.get(k=0))
|
||||
# logger.info(response)
|
||||
|
||||
if isinstance(response, ActionOutput):
|
||||
msg = Message(content=response.content, instruct_content=response.instruct_content,
|
||||
role=self.profile, cause_by=type(self._rc.todo))
|
||||
role=self.profile, cause_by=type(self._rc.todo))
|
||||
else:
|
||||
msg = Message(content=response, role=self.profile, cause_by=type(self._rc.todo))
|
||||
self._rc.memory.add(msg)
|
||||
return msg
|
||||
|
||||
async def _act(self) -> Message:
|
||||
"""Determines the mode of action for the searcher."""
|
||||
return await self._act_sp()
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue