mirror of
https://github.com/FoundationAgents/MetaGPT.git
synced 2026-04-30 19:36:24 +02:00
feat: Remove global configuration , enable configuration support for business isolation.
This commit is contained in:
parent
d764b8e6fa
commit
f45a8e5284
50 changed files with 437 additions and 278 deletions
|
|
@ -4,11 +4,13 @@
|
|||
@Time : 2023/5/11 17:45
|
||||
@Author : alexanderwu
|
||||
@File : test_write_code.py
|
||||
@Modified By: mashenquan, 2023/8/20. Remove global configuration `CONFIG`, enable configuration support for business isolation.
|
||||
"""
|
||||
import pytest
|
||||
|
||||
from metagpt.config import Config
|
||||
from metagpt.provider.openai_api import OpenAIGPTAPI as LLM, CostManager
|
||||
from metagpt.actions.write_code import WriteCode
|
||||
from metagpt.llm import LLM
|
||||
from metagpt.logs import logger
|
||||
from tests.metagpt.actions.mock import TASKS_2, WRITE_CODE_PROMPT_SAMPLE
|
||||
|
||||
|
|
@ -16,9 +18,12 @@ from tests.metagpt.actions.mock import TASKS_2, WRITE_CODE_PROMPT_SAMPLE
|
|||
@pytest.mark.asyncio
|
||||
async def test_write_code():
|
||||
api_design = "设计一个名为'add'的函数,该函数接受两个整数作为输入,并返回它们的和。"
|
||||
write_code = WriteCode("write_code")
|
||||
conf = Config()
|
||||
cost_manager = CostManager(conf.runtime_options)
|
||||
llm = LLM(options=conf.runtime_options, cost_manager=cost_manager)
|
||||
write_code = WriteCode(options=conf.runtime_options, name="write_code", llm=llm)
|
||||
|
||||
code = await write_code.run(api_design)
|
||||
code = await write_code.run(api_design, "filename")
|
||||
logger.info(code)
|
||||
|
||||
# 我们不能精确地预测生成的代码,但我们可以检查某些关键字
|
||||
|
|
@ -29,6 +34,7 @@ async def test_write_code():
|
|||
@pytest.mark.asyncio
|
||||
async def test_write_code_directly():
|
||||
prompt = WRITE_CODE_PROMPT_SAMPLE + '\n' + TASKS_2[0]
|
||||
llm = LLM()
|
||||
options = Config().runtime_options
|
||||
llm = LLM(options=options, cost_manager=CostManager(options=options))
|
||||
rsp = await llm.aask(prompt)
|
||||
logger.info(rsp)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Desc : unittest of `metagpt/memory/longterm_memory.py`
|
||||
|
||||
from metagpt.config import CONFIG
|
||||
"""
|
||||
@Desc : unittest of `metagpt/memory/longterm_memory.py`
|
||||
@Modified By: mashenquan, 2023/8/20. Remove global configuration `CONFIG`, enable configuration support for business isolation.
|
||||
"""
|
||||
from metagpt.config import Config
|
||||
from metagpt.schema import Message
|
||||
from metagpt.actions import BossRequirement
|
||||
from metagpt.roles.role import RoleContext
|
||||
|
|
@ -10,12 +12,13 @@ from metagpt.memory import LongTermMemory
|
|||
|
||||
|
||||
def test_ltm_search():
|
||||
assert hasattr(CONFIG, "long_term_memory") is True
|
||||
openai_api_key = CONFIG.openai_api_key
|
||||
conf = Config()
|
||||
assert hasattr(conf, "long_term_memory") is True
|
||||
openai_api_key = conf.openai_api_key
|
||||
assert len(openai_api_key) > 20
|
||||
|
||||
role_id = 'UTUserLtm(Product Manager)'
|
||||
rc = RoleContext(watch=[BossRequirement])
|
||||
rc = RoleContext(options=conf.runtime_options, watch=[BossRequirement])
|
||||
ltm = LongTermMemory()
|
||||
ltm.recover_memory(role_id, rc)
|
||||
|
||||
|
|
@ -23,19 +26,19 @@ def test_ltm_search():
|
|||
message = Message(role='BOSS', content=idea, cause_by=BossRequirement)
|
||||
news = ltm.remember([message])
|
||||
assert len(news) == 1
|
||||
ltm.add(message)
|
||||
ltm.add(message, **conf.runtime_options)
|
||||
|
||||
sim_idea = 'Write a game of cli snake'
|
||||
sim_message = Message(role='BOSS', content=sim_idea, cause_by=BossRequirement)
|
||||
news = ltm.remember([sim_message])
|
||||
assert len(news) == 0
|
||||
ltm.add(sim_message)
|
||||
ltm.add(sim_message, **conf.runtime_options)
|
||||
|
||||
new_idea = 'Write a 2048 web game'
|
||||
new_message = Message(role='BOSS', content=new_idea, cause_by=BossRequirement)
|
||||
news = ltm.remember([new_message])
|
||||
assert len(news) == 1
|
||||
ltm.add(new_message)
|
||||
ltm.add(new_message, **conf.runtime_options)
|
||||
|
||||
# restore from local index
|
||||
ltm_new = LongTermMemory()
|
||||
|
|
|
|||
|
|
@ -4,14 +4,17 @@
|
|||
@Time : 2023/5/12 00:47
|
||||
@Author : alexanderwu
|
||||
@File : test_environment.py
|
||||
@Modified By: mashenquan, 2023/8/20. Remove global configuration `CONFIG`, enable configuration support for business isolation.
|
||||
|
||||
"""
|
||||
|
||||
import pytest
|
||||
|
||||
from metagpt.actions import BossRequirement
|
||||
from metagpt.config import Config
|
||||
from metagpt.environment import Environment
|
||||
from metagpt.logs import logger
|
||||
from metagpt.manager import Manager
|
||||
from metagpt.provider.openai_api import CostManager
|
||||
from metagpt.roles import Architect, ProductManager, Role
|
||||
from metagpt.schema import Message
|
||||
|
||||
|
|
@ -22,33 +25,45 @@ def env():
|
|||
|
||||
|
||||
def test_add_role(env: Environment):
|
||||
role = ProductManager("Alice", "product manager", "create a new product", "limited resources")
|
||||
conf = Config()
|
||||
cost_manager = CostManager(options=conf.runtime_options)
|
||||
role = ProductManager(options=conf.runtime_options,
|
||||
cost_manager=cost_manager,
|
||||
name="Alice",
|
||||
profile="product manager",
|
||||
goal="create a new product",
|
||||
constraints="limited resources")
|
||||
env.add_role(role)
|
||||
assert env.get_role(role.profile) == role
|
||||
|
||||
|
||||
def test_get_roles(env: Environment):
|
||||
role1 = Role("Alice", "product manager", "create a new product", "limited resources")
|
||||
role2 = Role("Bob", "engineer", "develop the new product", "short deadline")
|
||||
conf = Config()
|
||||
cost_manager = CostManager(options=conf.runtime_options)
|
||||
role1 = Role(options=conf.runtime_options, cost_manager=cost_manager, name="Alice", profile="product manager",
|
||||
goal="create a new product", constraints="limited resources")
|
||||
role2 = Role(options=conf.runtime_options, cost_manager=cost_manager, name="Bob", profile="engineer",
|
||||
goal="develop the new product", constraints="short deadline")
|
||||
env.add_role(role1)
|
||||
env.add_role(role2)
|
||||
roles = env.get_roles()
|
||||
assert roles == {role1.profile: role1, role2.profile: role2}
|
||||
|
||||
|
||||
def test_set_manager(env: Environment):
|
||||
manager = Manager()
|
||||
env.set_manager(manager)
|
||||
assert env.manager == manager
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_publish_and_process_message(env: Environment):
|
||||
product_manager = ProductManager("Alice", "Product Manager", "做AI Native产品", "资源有限")
|
||||
architect = Architect("Bob", "Architect", "设计一个可用、高效、较低成本的系统,包括数据结构与接口", "资源有限,需要节省成本")
|
||||
conf = Config()
|
||||
cost_manager = CostManager(options=conf.runtime_options)
|
||||
product_manager = ProductManager(options=conf.runtime_options,
|
||||
cost_manager=cost_manager,
|
||||
name="Alice", profile="Product Manager",
|
||||
goal="做AI Native产品", constraints="资源有限")
|
||||
architect = Architect(options=conf.runtime_options,
|
||||
cost_manager=cost_manager,
|
||||
name="Bob", profile="Architect", goal="设计一个可用、高效、较低成本的系统,包括数据结构与接口",
|
||||
constraints="资源有限,需要节省成本")
|
||||
|
||||
env.add_roles([product_manager, architect])
|
||||
env.set_manager(Manager())
|
||||
env.publish_message(Message(role="BOSS", content="需要一个基于LLM做总结的搜索引擎", cause_by=BossRequirement))
|
||||
|
||||
await env.run(k=2)
|
||||
|
|
|
|||
|
|
@ -4,16 +4,19 @@
|
|||
@Time : 2023/5/11 14:45
|
||||
@Author : alexanderwu
|
||||
@File : test_llm.py
|
||||
@Modified By: mashenquan, 2023/8/20. Remove global configuration `CONFIG`, enable configuration support for business isolation.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
|
||||
from metagpt.llm import LLM
|
||||
from metagpt.config import Config
|
||||
from metagpt.provider.openai_api import OpenAIGPTAPI as LLM, CostManager
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def llm():
|
||||
return LLM()
|
||||
options = Config().runtime_options
|
||||
return LLM(options=options, cost_manager=CostManager(options))
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
|
|
|||
|
|
@ -4,11 +4,13 @@
|
|||
@Time : 2023/5/2 17:46
|
||||
@Author : alexanderwu
|
||||
@File : test_search_engine.py
|
||||
@Modified By: mashenquan, 2023/8/20. Remove global configuration `CONFIG`, enable configuration support for business isolation.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
from metagpt.config import Config
|
||||
from metagpt.logs import logger
|
||||
from metagpt.tools import SearchEngineType
|
||||
from metagpt.tools.search_engine import SearchEngine
|
||||
|
|
@ -37,9 +39,10 @@ class MockSearchEnine:
|
|||
|
||||
],
|
||||
)
|
||||
async def test_search_engine(search_engine_typpe, run_func, max_results, as_string, ):
|
||||
search_engine = SearchEngine(search_engine_typpe, run_func)
|
||||
rsp = await search_engine.run("metagpt", max_results=max_results, as_string=as_string)
|
||||
async def test_search_engine(search_engine_typpe, run_func, max_results, as_string):
|
||||
conf = Config()
|
||||
search_engine = SearchEngine(options=conf.runtime_options, engine=search_engine_typpe, run_func=run_func)
|
||||
rsp = await search_engine.run(query="metagpt", max_results=max_results, as_string=as_string)
|
||||
logger.info(rsp)
|
||||
if as_string:
|
||||
assert isinstance(rsp, str)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,10 @@
|
|||
"""
|
||||
@Modified By: mashenquan, 2023/8/20. Remove global configuration `CONFIG`, enable configuration support for business isolation.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
|
||||
from metagpt.config import Config
|
||||
from metagpt.tools import WebBrowserEngineType, web_browser_engine
|
||||
|
||||
|
||||
|
|
@ -13,7 +18,8 @@ from metagpt.tools import WebBrowserEngineType, web_browser_engine
|
|||
ids=["playwright", "selenium"],
|
||||
)
|
||||
async def test_scrape_web_page(browser_type, url, urls):
|
||||
browser = web_browser_engine.WebBrowserEngine(browser_type)
|
||||
conf = Config()
|
||||
browser = web_browser_engine.WebBrowserEngine(options=conf.runtime_options, engine=browser_type)
|
||||
result = await browser.run(url)
|
||||
assert isinstance(result, str)
|
||||
assert "深度赋智" in result
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
"""
|
||||
@Modified By: mashenquan, 2023/8/20. Remove global configuration `CONFIG`, enable configuration support for business isolation.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
|
||||
from metagpt.config import CONFIG
|
||||
from metagpt.config import Config
|
||||
from metagpt.tools import web_browser_engine_playwright
|
||||
|
||||
|
||||
|
|
@ -15,22 +19,24 @@ from metagpt.tools import web_browser_engine_playwright
|
|||
ids=["chromium-normal", "firefox-normal", "webkit-normal"],
|
||||
)
|
||||
async def test_scrape_web_page(browser_type, use_proxy, kwagrs, url, urls, proxy, capfd):
|
||||
conf = Config()
|
||||
global_proxy = conf.global_proxy
|
||||
try:
|
||||
global_proxy = CONFIG.global_proxy
|
||||
if use_proxy:
|
||||
CONFIG.global_proxy = proxy
|
||||
browser = web_browser_engine_playwright.PlaywrightWrapper(browser_type, **kwagrs)
|
||||
conf.global_proxy = proxy
|
||||
browser = web_browser_engine_playwright.PlaywrightWrapper(options=conf.runtime_options,
|
||||
browser_type=browser_type, **kwagrs)
|
||||
result = await browser.run(url)
|
||||
result = result.inner_text
|
||||
assert isinstance(result, str)
|
||||
assert "Deepwisdom" in result
|
||||
assert "DeepWisdom" in result
|
||||
|
||||
if urls:
|
||||
results = await browser.run(url, *urls)
|
||||
assert isinstance(results, list)
|
||||
assert len(results) == len(urls) + 1
|
||||
assert all(("Deepwisdom" in i) for i in results)
|
||||
assert all(("DeepWisdom" in i) for i in results)
|
||||
if use_proxy:
|
||||
assert "Proxy:" in capfd.readouterr().out
|
||||
finally:
|
||||
CONFIG.global_proxy = global_proxy
|
||||
conf.global_proxy = global_proxy
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
"""
|
||||
@Modified By: mashenquan, 2023/8/20. Remove global configuration `CONFIG`, enable configuration support for business isolation.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
|
||||
from metagpt.config import CONFIG
|
||||
from metagpt.config import Config
|
||||
from metagpt.tools import web_browser_engine_selenium
|
||||
|
||||
|
||||
|
|
@ -15,11 +19,12 @@ from metagpt.tools import web_browser_engine_selenium
|
|||
ids=["chrome-normal", "firefox-normal", "edge-normal"],
|
||||
)
|
||||
async def test_scrape_web_page(browser_type, use_proxy, url, urls, proxy, capfd):
|
||||
conf = Config()
|
||||
global_proxy = conf.global_proxy
|
||||
try:
|
||||
global_proxy = CONFIG.global_proxy
|
||||
if use_proxy:
|
||||
CONFIG.global_proxy = proxy
|
||||
browser = web_browser_engine_selenium.SeleniumWrapper(browser_type)
|
||||
conf.global_proxy = proxy
|
||||
browser = web_browser_engine_selenium.SeleniumWrapper(options=conf.runtime_options, browser_type=browser_type)
|
||||
result = await browser.run(url)
|
||||
result = result.inner_text
|
||||
assert isinstance(result, str)
|
||||
|
|
@ -33,4 +38,4 @@ async def test_scrape_web_page(browser_type, use_proxy, url, urls, proxy, capfd)
|
|||
if use_proxy:
|
||||
assert "Proxy:" in capfd.readouterr().out
|
||||
finally:
|
||||
CONFIG.global_proxy = global_proxy
|
||||
conf.global_proxy = global_proxy
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
@Time : 2023/5/1 11:19
|
||||
@Author : alexanderwu
|
||||
@File : test_config.py
|
||||
@Modified By: mashenquan, 2013/8/20, add `test_options`
|
||||
@Modified By: mashenquan, 2013/8/20, Add `test_options`; remove global configuration `CONFIG`, enable configuration support for business isolation.
|
||||
"""
|
||||
from pathlib import Path
|
||||
|
||||
|
|
@ -13,12 +13,6 @@ import pytest
|
|||
from metagpt.config import Config
|
||||
|
||||
|
||||
def test_config_class_is_singleton():
|
||||
config_1 = Config()
|
||||
config_2 = Config()
|
||||
assert config_1 == config_2
|
||||
|
||||
|
||||
def test_config_class_get_key_exception():
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
config = Config()
|
||||
|
|
@ -27,16 +21,15 @@ def test_config_class_get_key_exception():
|
|||
|
||||
|
||||
def test_config_yaml_file_not_exists():
|
||||
config = Config('wtf.yaml')
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
config.get('OPENAI_BASE_URL')
|
||||
assert str(exc_info.value) == "Key 'OPENAI_BASE_URL' not found in environment variables or in the YAML file"
|
||||
Config(Path('wtf.yaml'))
|
||||
assert str(exc_info.value) == "Set OPENAI_API_KEY or Anthropic_API_KEY first"
|
||||
|
||||
|
||||
def test_options():
|
||||
filename = Path(__file__).resolve().parent.parent.parent.parent / "config/config.yaml"
|
||||
config = Config(filename)
|
||||
opts = config.options
|
||||
opts = config.runtime_options
|
||||
assert opts
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue