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,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)

View file

@ -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()

View file

@ -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)

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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