mirror of
https://github.com/FoundationAgents/MetaGPT.git
synced 2026-04-26 01:06:27 +02:00
1. SummarizeCode动作:用于基于代码进行总结,思考bug、逻辑、todo
2. CodeReview动作优化:目前强制要求回答问题,有更高的成功率了
2. 数据结构
1. Document的标准化:Env->Repo->Document,其中Document/Asset/Code都只用Document
1. 原用于检索的Document改为IndexableDocument
2. Repo结构引入:用于Document装载与元数据装载
3. RepoParser引入:写了一个简单的AST parser(后续可能要换tree-sitter),给出了整库symbol
3. 配置优化
1. 默认更换为gpt-4-1106-preview,以获得最好的效果与成本
2. 提供~/.metagpt作为配置最高优先级目录,从中读取config.yaml
3. workspace可以灵活指定了,在config中配置
4. metagpt作为默认命令行,而非python startup.py
1. 使用新的METAGPT_ROOT生成方式,而非寻找git,以便cli安装
2. 命令行由fire换为了typer,它会带来相对更好的体验
3. project_name可以灵活指定了,在metagpt命令行输入中配置
5. 其他
1. BossRequirement -> UserRequirement
2. 大量错误文本的修正,增加了可读性
3. 中量提示词优化,稍微提升了一些准确率
4. 暂时屏蔽了LongtermMemory相关逻辑,这个逻辑底层调用了langchain的FAISS,会带来~5秒加载耗时
5. 修复了安装包中的部分描述错误
134 lines
5.6 KiB
Python
134 lines
5.6 KiB
Python
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
"""
|
|
Provide configuration, singleton
|
|
"""
|
|
import os
|
|
|
|
import openai
|
|
import yaml
|
|
|
|
from pathlib import Path
|
|
|
|
from metagpt.const import METAGPT_ROOT, DEFAULT_WORKSPACE_ROOT
|
|
from metagpt.logs import logger
|
|
from metagpt.tools import SearchEngineType, WebBrowserEngineType
|
|
from metagpt.utils.singleton import Singleton
|
|
|
|
|
|
class NotConfiguredException(Exception):
|
|
"""Exception raised for errors in the configuration.
|
|
|
|
Attributes:
|
|
message -- explanation of the error
|
|
"""
|
|
|
|
def __init__(self, message="The required configuration is not set"):
|
|
self.message = message
|
|
super().__init__(self.message)
|
|
|
|
|
|
class Config(metaclass=Singleton):
|
|
"""
|
|
Regular usage method:
|
|
config = Config("config.yaml")
|
|
secret_key = config.get_key("MY_SECRET_KEY")
|
|
print("Secret key:", secret_key)
|
|
"""
|
|
|
|
_instance = None
|
|
home_yaml_file = Path.home() / ".metagpt/config.yaml"
|
|
key_yaml_file = METAGPT_ROOT / "config/key.yaml"
|
|
default_yaml_file = METAGPT_ROOT / "config/config.yaml"
|
|
|
|
def __init__(self, yaml_file=default_yaml_file):
|
|
self._configs = {}
|
|
self._init_with_config_files_and_env(self._configs, yaml_file)
|
|
# logger.info("Config loading done.")
|
|
self.global_proxy = self._get("GLOBAL_PROXY")
|
|
self.openai_api_key = self._get("OPENAI_API_KEY")
|
|
self.anthropic_api_key = self._get("Anthropic_API_KEY")
|
|
self.zhipuai_api_key = self._get("ZHIPUAI_API_KEY")
|
|
if (not self.openai_api_key or "YOUR_API_KEY" == self.openai_api_key) and \
|
|
(not self.anthropic_api_key or "YOUR_API_KEY" == self.anthropic_api_key) and \
|
|
(not self.zhipuai_api_key or "YOUR_API_KEY" == self.zhipuai_api_key):
|
|
raise NotConfiguredException("Set OPENAI_API_KEY or Anthropic_API_KEY or ZHIPUAI_API_KEY first")
|
|
self.openai_api_base = self._get("OPENAI_API_BASE")
|
|
openai_proxy = self._get("OPENAI_PROXY") or self.global_proxy
|
|
if openai_proxy:
|
|
openai.proxy = openai_proxy
|
|
openai.api_base = self.openai_api_base
|
|
self.openai_api_type = self._get("OPENAI_API_TYPE")
|
|
self.openai_api_version = self._get("OPENAI_API_VERSION")
|
|
self.openai_api_rpm = self._get("RPM", 3)
|
|
self.openai_api_model = self._get("OPENAI_API_MODEL", "gpt-4")
|
|
self.max_tokens_rsp = self._get("MAX_TOKENS", 2048)
|
|
self.deployment_name = self._get("DEPLOYMENT_NAME")
|
|
self.deployment_id = self._get("DEPLOYMENT_ID")
|
|
|
|
self.spark_appid = self._get("SPARK_APPID")
|
|
self.spark_api_secret = self._get("SPARK_API_SECRET")
|
|
self.spark_api_key = self._get("SPARK_API_KEY")
|
|
self.domain = self._get("DOMAIN")
|
|
self.spark_url = self._get("SPARK_URL")
|
|
|
|
self.claude_api_key = self._get("Anthropic_API_KEY")
|
|
self.serpapi_api_key = self._get("SERPAPI_API_KEY")
|
|
self.serper_api_key = self._get("SERPER_API_KEY")
|
|
self.google_api_key = self._get("GOOGLE_API_KEY")
|
|
self.google_cse_id = self._get("GOOGLE_CSE_ID")
|
|
self.search_engine = SearchEngineType(self._get("SEARCH_ENGINE", SearchEngineType.SERPAPI_GOOGLE))
|
|
self.web_browser_engine = WebBrowserEngineType(self._get("WEB_BROWSER_ENGINE", WebBrowserEngineType.PLAYWRIGHT))
|
|
self.playwright_browser_type = self._get("PLAYWRIGHT_BROWSER_TYPE", "chromium")
|
|
self.selenium_browser_type = self._get("SELENIUM_BROWSER_TYPE", "chrome")
|
|
|
|
self.long_term_memory = self._get("LONG_TERM_MEMORY", False)
|
|
if self.long_term_memory:
|
|
logger.warning("LONG_TERM_MEMORY is True")
|
|
self.max_budget = self._get("MAX_BUDGET", 10.0)
|
|
self.total_cost = 0.0
|
|
|
|
self.puppeteer_config = self._get("PUPPETEER_CONFIG", "")
|
|
self.mmdc = self._get("MMDC", "mmdc")
|
|
self.calc_usage = self._get("CALC_USAGE", True)
|
|
self.model_for_researcher_summary = self._get("MODEL_FOR_RESEARCHER_SUMMARY")
|
|
self.model_for_researcher_report = self._get("MODEL_FOR_RESEARCHER_REPORT")
|
|
self.mermaid_engine = self._get("MERMAID_ENGINE", "nodejs")
|
|
self.pyppeteer_executable_path = self._get("PYPPETEER_EXECUTABLE_PATH", "")
|
|
|
|
self.prompt_format = self._get("PROMPT_FORMAT", "markdown")
|
|
self.workspace_path = Path(self._get("WORKSPACE_PATH", DEFAULT_WORKSPACE_ROOT))
|
|
self._ensure_workspace_exists()
|
|
|
|
def _ensure_workspace_exists(self):
|
|
self.workspace_path.mkdir(parents=True, exist_ok=True)
|
|
logger.info(f"WORKSPACE_PATH set to {self.workspace_path}")
|
|
|
|
def _init_with_config_files_and_env(self, configs: dict, yaml_file):
|
|
"""Load from config/key.yaml, config/config.yaml, and env in decreasing order of priority"""
|
|
configs.update(os.environ)
|
|
|
|
for _yaml_file in [yaml_file, self.key_yaml_file, self.home_yaml_file]:
|
|
if not _yaml_file.exists():
|
|
continue
|
|
|
|
# Load local YAML file
|
|
with open(_yaml_file, "r", encoding="utf-8") as file:
|
|
yaml_data = yaml.safe_load(file)
|
|
if not yaml_data:
|
|
continue
|
|
os.environ.update({k: v for k, v in yaml_data.items() if isinstance(v, str)})
|
|
configs.update(yaml_data)
|
|
|
|
def _get(self, *args, **kwargs):
|
|
return self._configs.get(*args, **kwargs)
|
|
|
|
def get(self, key, *args, **kwargs):
|
|
"""Search for a value in config/key.yaml, config/config.yaml, and env; raise an error if not found"""
|
|
value = self._get(key, *args, **kwargs)
|
|
if value is None:
|
|
raise ValueError(f"Key '{key}' not found in environment variables or in the YAML file")
|
|
return value
|
|
|
|
|
|
CONFIG = Config()
|