#!/usr/bin/env python # -*- coding: utf-8 -*- """ @Time : 2024/1/4 16:32 @Author : alexanderwu @File : context.py """ import os from pathlib import Path from typing import Optional from pydantic import BaseModel, ConfigDict from metagpt.config2 import Config from metagpt.configs.llm_config import LLMType from metagpt.const import OPTIONS from metagpt.provider.base_llm import BaseLLM from metagpt.provider.llm_provider_registry import get_llm from metagpt.utils.cost_manager import CostManager from metagpt.utils.git_repository import GitRepository class AttrDict(BaseModel): """A dict-like object that allows access to keys as attributes, compatible with Pydantic.""" model_config = ConfigDict(extra="allow") def __init__(self, **kwargs): super().__init__(**kwargs) self.__dict__.update(kwargs) 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(BaseModel): """Env context for MetaGPT""" model_config = ConfigDict(arbitrary_types_allowed=True) kwargs: AttrDict = AttrDict() config: Config = Config.default() git_repo: Optional[GitRepository] = None src_workspace: Optional[Path] = None cost_manager: CostManager = CostManager() @property def file_repo(self): return self.git_repo.new_file_repository() @property def options(self): """Return all key-values""" return OPTIONS.get() def new_environ(self): """Return a new os.environ object""" env = os.environ.copy() i = self.options env.update({k: v for k, v in i.items() if isinstance(v, str)}) return env def llm(self, name: Optional[str] = None, provider: LLMType = LLMType.OPENAI) -> BaseLLM: """Return a LLM instance""" if provider: llm_configs = self.config.get_llm_configs_by_type(provider) if name: llm_configs = [c for c in llm_configs if c.name == name] if len(llm_configs) == 0: raise ValueError(f"Cannot find llm config with name {name} and provider {provider}") # return the first one if name is None, or return the only one llm_config = llm_configs[0] else: llm_config = self.config.get_llm_config(name) llm = get_llm(llm_config) if llm.cost_manager is None: llm.cost_manager = self.cost_manager return llm # Global context, not in Env context = Context()