feat: Remove global configuration , enable configuration support for business isolation.

This commit is contained in:
莘权 马 2023-08-20 17:33:13 +08:00
parent d764b8e6fa
commit f45a8e5284
50 changed files with 437 additions and 278 deletions

View file

@ -4,6 +4,8 @@
@Time : 2023/5/11 14:43
@Author : alexanderwu
@File : architect.py
@Modified By: mashenquan, 2023/8/20. Remove global configuration `CONFIG`, enable configuration support for business isolation;
Change cost control from global to company level.
"""
from metagpt.actions import WriteDesign, WritePRD
@ -12,8 +14,8 @@ 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",
def __init__(self, options, cost_manager, name="Bob", profile="Architect", goal="Design a concise, usable, complete python system",
constraints="Try to specify good open source tools as much as possible"):
super().__init__(name, profile, goal, constraints)
super().__init__(name=name, profile=profile, goal=goal, constraints=constraints, options=options, cost_manager=cost_manager)
self._init_actions([WriteDesign])
self._watch({WritePRD})

View file

@ -47,10 +47,10 @@ 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",
def __init__(self, options, cost_manager, 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):
super().__init__(name, profile, goal, constraints)
super().__init__(name=name, profile=profile, goal=goal, constraints=constraints, options=options, cost_manager=cost_manager)
self._init_actions([WriteCode])
self.use_code_review = use_code_review
if self.use_code_review:
@ -131,7 +131,7 @@ class Engineer(Role):
async def _act_sp(self) -> Message:
code_msg_all = [] # gather all code info, will pass to qa_engineer for tests later
for todo in self.todos:
code = await WriteCode().run(
code = await WriteCode(options=self.options, llm=self._llm).run(
context=self._rc.history,
filename=todo
)

View file

@ -4,14 +4,16 @@
@Time : 2023/5/11 14:43
@Author : alexanderwu
@File : product_manager.py
@Modified By: mashenquan, 2023/8/20. Remove global configuration `CONFIG`, enable configuration support for business isolation;
Change cost control from global to company level.
"""
from metagpt.actions import BossRequirement, WritePRD
from metagpt.roles import Role
class ProductManager(Role):
def __init__(self, name="Alice", profile="Product Manager", goal="Efficiently create a successful product",
def __init__(self, options, cost_manager, name="Alice", profile="Product Manager", goal="Efficiently create a successful product",
constraints=""):
super().__init__(name, profile, goal, constraints)
super().__init__(name=name, profile=profile, goal=goal, constraints=constraints, options=options, cost_manager=cost_manager)
self._init_actions([WritePRD])
self._watch([BossRequirement])

View file

@ -4,14 +4,16 @@
@Time : 2023/5/11 15:04
@Author : alexanderwu
@File : project_manager.py
@Modified By: mashenquan, 2023/8/20. Remove global configuration `CONFIG`, enable configuration support for business isolation;
Change cost control from global to company level.
"""
from metagpt.actions import WriteDesign, WriteTasks
from metagpt.roles import Role
class ProjectManager(Role):
def __init__(self, name="Eve", profile="Project Manager",
def __init__(self, options, cost_manager, name="Eve", profile="Project Manager",
goal="Improve team efficiency and deliver with quality and quantity", constraints=""):
super().__init__(name, profile, goal, constraints)
super().__init__(name=name, profile=profile, goal=goal, constraints=constraints, options=options, cost_manager=cost_manager)
self._init_actions([WriteTasks])
self._watch([WriteDesign])

View file

@ -20,13 +20,15 @@ from metagpt.utils.special_tokens import FILENAME_CODE_SEP, MSG_SEP
class QaEngineer(Role):
def __init__(
self,
options,
cost_manager,
name="Edward",
profile="QaEngineer",
goal="Write comprehensive and robust tests to ensure codes will work as expected without bugs",
constraints="The test code you write should conform to code standard like PEP8, be modular, easy to read and maintain",
test_round_allowed=5,
):
super().__init__(name, profile, goal, constraints)
super().__init__(name=name, profile=profile, goal=goal, constraints=constraints, options=options, cost_manager=cost_manager)
self._init_actions(
[WriteTest]
) # FIXME: a bit hack here, only init one action to circumvent _think() logic, will overwrite _think() in future updates

View file

@ -4,17 +4,16 @@
@Time : 2023/5/11 14:42
@Author : alexanderwu
@File : role.py
@Modified By: mashenquan, 2023/8/20. Remove global configuration `CONFIG`, enable configuration support for business isolation;
Change cost control from global to company level.
"""
from __future__ import annotations
from typing import Iterable, Type
from typing import Iterable, Type, Dict
from pydantic import BaseModel, Field
# from metagpt.environment import Environment
from metagpt.config import CONFIG
from metagpt.provider.openai_api import OpenAIGPTAPI as LLM
from metagpt.actions import Action, ActionOutput
from metagpt.llm import LLM
from metagpt.logs import logger
from metagpt.memory import Memory, LongTermMemory
from metagpt.schema import Message
@ -71,12 +70,13 @@ class RoleContext(BaseModel):
todo: Action = Field(default=None)
watch: set[Type[Action]] = Field(default_factory=set)
news: list[Type[Message]] = Field(default=[])
options: Dict
class Config:
arbitrary_types_allowed = True
def check(self, role_id: str):
if hasattr(CONFIG, "long_term_memory") and CONFIG.long_term_memory:
if self.options.get("long_term_memory"):
self.long_term_memory.recover_memory(role_id, self)
self.memory = self.long_term_memory # use memory to act as long_term_memory for unify operation
@ -93,13 +93,15 @@ class RoleContext(BaseModel):
class Role:
"""角色/代理"""
def __init__(self, name="", profile="", goal="", constraints="", desc=""):
self._llm = LLM()
def __init__(self, options, cost_manager, name="", profile="", goal="", constraints="", desc=""):
self._options = options if options else {}
self._cost_manager = cost_manager
self._llm = LLM(options=self._options, cost_manager=cost_manager)
self._setting = RoleSetting(name=name, profile=profile, goal=goal, constraints=constraints, desc=desc)
self._states = []
self._actions = []
self._role_id = str(self._setting)
self._rc = RoleContext()
self._rc = RoleContext(options=options)
def _reset(self):
self._states = []
@ -109,7 +111,7 @@ class Role:
self._reset()
for idx, action in enumerate(actions):
if not isinstance(action, Action):
i = action("")
i = action(options=self._options, name="", llm=self._llm)
else:
i = action
i.set_prefix(self._get_prefix(), self.profile)
@ -137,6 +139,14 @@ class Role:
"""获取角色描述(职位)"""
return self._setting.profile
@property
def options(self):
return self._options
@options.setter
def options(self, opts):
self._options.update(opts)
def _get_prefix(self):
"""获取角色前缀"""
if self._setting.desc: