roles update. More comments and docstrings

This commit is contained in:
brucemeek 2023-08-02 17:09:05 -05:00
parent 5a466d577f
commit 5170ee720a
6 changed files with 193 additions and 63 deletions

View file

@ -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})

View file

@ -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()

View file

@ -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])

View file

@ -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])

View file

@ -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])

View file

@ -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()