diff --git a/metagpt/context.py b/metagpt/context.py index e24e99afc..0556add8a 100644 --- a/metagpt/context.py +++ b/metagpt/context.py @@ -7,7 +7,7 @@ """ import os from pathlib import Path -from typing import Dict, Optional +from typing import Optional from metagpt.config2 import Config from metagpt.const import OPTIONS @@ -17,8 +17,27 @@ from metagpt.utils.cost_manager import CostManager from metagpt.utils.git_repository import GitRepository +class AttrDict: + def __init__(self, d=None): + if d is None: + d = {} + self.__dict__["_dict"] = d + + def __getattr__(self, key): + return self._dict.get(key, None) + + def __setattr__(self, key, value): + self._dict[key] = value + + def __delattr__(self, key): + if key in self._dict: + del self._dict[key] + else: + raise AttributeError(f"No such attribute: {key}") + + class Context: - kwargs: Dict = {} + kwargs: AttrDict = {} config: Config = Config.default() git_repo: Optional[GitRepository] = None src_workspace: Optional[Path] = None diff --git a/metagpt/roles/assistant.py b/metagpt/roles/assistant.py index d96d8a895..90a33ad6a 100644 --- a/metagpt/roles/assistant.py +++ b/metagpt/roles/assistant.py @@ -22,7 +22,7 @@ from pydantic import Field from metagpt.actions.skill_action import ArgumentsParingAction, SkillAction from metagpt.actions.talk_action import TalkAction -from metagpt.config import CONFIG +from metagpt.context import context from metagpt.learn.skill_loader import SkillsDeclaration from metagpt.logs import logger from metagpt.memory.brain_memory import BrainMemory @@ -48,7 +48,7 @@ class Assistant(Role): def __init__(self, **kwargs): super().__init__(**kwargs) - self.constraints = self.constraints.format(language=kwargs.get("language") or CONFIG.language or "Chinese") + self.constraints = self.constraints.format(language=kwargs.get("language") or context.kwargs.language) async def think(self) -> bool: """Everything will be done part by part.""" @@ -56,7 +56,7 @@ class Assistant(Role): if not last_talk: return False if not self.skills: - skill_path = Path(CONFIG.SKILL_PATH) if CONFIG.SKILL_PATH else None + skill_path = Path(context.kwargs.SKILL_PATH) if context.kwargs.SKILL_PATH else None self.skills = await SkillsDeclaration.load(skill_yaml_file_name=skill_path) prompt = "" diff --git a/tests/metagpt/roles/test_architect.py b/tests/metagpt/roles/test_architect.py index 06e4b2d11..69afbcfe1 100644 --- a/tests/metagpt/roles/test_architect.py +++ b/tests/metagpt/roles/test_architect.py @@ -12,8 +12,8 @@ import uuid import pytest from metagpt.actions import WriteDesign, WritePRD -from metagpt.config import CONFIG from metagpt.const import PRDS_FILE_REPO +from metagpt.context import context from metagpt.logs import logger from metagpt.roles import Architect from metagpt.schema import Message @@ -25,7 +25,7 @@ from tests.metagpt.roles.mock import MockMessages async def test_architect(): # Prerequisites filename = uuid.uuid4().hex + ".json" - await awrite(CONFIG.git_repo.workdir / PRDS_FILE_REPO / filename, data=MockMessages.prd.content) + await awrite(context.git_repo.workdir / PRDS_FILE_REPO / filename, data=MockMessages.prd.content) role = Architect() rsp = await role.run(with_message=Message(content="", cause_by=WritePRD)) diff --git a/tests/metagpt/roles/test_assistant.py b/tests/metagpt/roles/test_assistant.py index 24096b357..8797ba7f1 100644 --- a/tests/metagpt/roles/test_assistant.py +++ b/tests/metagpt/roles/test_assistant.py @@ -12,7 +12,7 @@ from pydantic import BaseModel from metagpt.actions.skill_action import SkillAction from metagpt.actions.talk_action import TalkAction -from metagpt.config import CONFIG +from metagpt.context import context from metagpt.memory.brain_memory import BrainMemory from metagpt.roles.assistant import Assistant from metagpt.schema import Message @@ -21,7 +21,7 @@ from metagpt.utils.common import any_to_str @pytest.mark.asyncio async def test_run(): - CONFIG.language = "Chinese" + context.kwargs.language = "Chinese" class Input(BaseModel): memory: BrainMemory @@ -65,7 +65,7 @@ async def test_run(): "cause_by": any_to_str(SkillAction), }, ] - CONFIG.agent_skills = [ + context.kwargs.agent_skills = [ {"id": 1, "name": "text_to_speech", "type": "builtin", "config": {}, "enabled": True}, {"id": 2, "name": "text_to_image", "type": "builtin", "config": {}, "enabled": True}, {"id": 3, "name": "ai_call", "type": "builtin", "config": {}, "enabled": True}, @@ -77,8 +77,8 @@ async def test_run(): for i in inputs: seed = Input(**i) - CONFIG.language = seed.language - CONFIG.agent_description = seed.agent_description + context.kwargs.language = seed.language + context.kwargs.agent_description = seed.agent_description role = Assistant(language="Chinese") role.memory = seed.memory # Restore historical conversation content. while True: @@ -118,13 +118,7 @@ async def test_memory(memory): assert val await role.talk("draw apple") - - agent_skills = CONFIG.agent_skills - CONFIG.agent_skills = [] - try: - await role.think() - finally: - CONFIG.agent_skills = agent_skills + await role.think() assert isinstance(role.rc.todo, TalkAction)