mirror of
https://github.com/FoundationAgents/MetaGPT.git
synced 2026-05-03 04:42:38 +02:00
Merge branch 'dev' of https://github.com/geekan/MetaGPT into geekan/dev
This commit is contained in:
commit
2ed7c50822
26 changed files with 282 additions and 117 deletions
|
|
@ -23,14 +23,12 @@ from metagpt.team import Team
|
|||
async def test_debate_two_roles():
|
||||
action1 = Action(name="AlexSay", instruction="Express your opinion with emotion and don't repeat it")
|
||||
action2 = Action(name="BobSay", instruction="Express your opinion with emotion and don't repeat it")
|
||||
biden = Role(
|
||||
alex = Role(
|
||||
name="Alex", profile="Democratic candidate", goal="Win the election", actions=[action1], watch=[action2]
|
||||
)
|
||||
trump = Role(
|
||||
name="Bob", profile="Republican candidate", goal="Win the election", actions=[action2], watch=[action1]
|
||||
)
|
||||
bob = Role(name="Bob", profile="Republican candidate", goal="Win the election", actions=[action2], watch=[action1])
|
||||
env = Environment(desc="US election live broadcast")
|
||||
team = Team(investment=10.0, env=env, roles=[biden, trump])
|
||||
team = Team(investment=10.0, env=env, roles=[alex, bob])
|
||||
|
||||
history = await team.run(idea="Topic: climate change. Under 80 words per message.", send_to="Alex", n_round=3)
|
||||
assert "Alex" in history
|
||||
|
|
@ -39,9 +37,9 @@ async def test_debate_two_roles():
|
|||
@pytest.mark.asyncio
|
||||
async def test_debate_one_role_in_env():
|
||||
action = Action(name="Debate", instruction="Express your opinion with emotion and don't repeat it")
|
||||
biden = Role(name="Alex", profile="Democratic candidate", goal="Win the election", actions=[action])
|
||||
alex = Role(name="Alex", profile="Democratic candidate", goal="Win the election", actions=[action])
|
||||
env = Environment(desc="US election live broadcast")
|
||||
team = Team(investment=10.0, env=env, roles=[biden])
|
||||
team = Team(investment=10.0, env=env, roles=[alex])
|
||||
history = await team.run(idea="Topic: climate change. Under 80 words per message.", send_to="Alex", n_round=3)
|
||||
assert "Alex" in history
|
||||
|
||||
|
|
@ -49,8 +47,8 @@ async def test_debate_one_role_in_env():
|
|||
@pytest.mark.asyncio
|
||||
async def test_debate_one_role():
|
||||
action = Action(name="Debate", instruction="Express your opinion with emotion and don't repeat it")
|
||||
biden = Role(name="Alex", profile="Democratic candidate", goal="Win the election", actions=[action])
|
||||
msg: Message = await biden.run("Topic: climate change. Under 80 words per message.")
|
||||
alex = Role(name="Alex", profile="Democratic candidate", goal="Win the election", actions=[action])
|
||||
msg: Message = await alex.run("Topic: climate change. Under 80 words per message.")
|
||||
|
||||
assert len(msg.content) > 10
|
||||
assert msg.sent_from == "metagpt.roles.role.Role"
|
||||
|
|
|
|||
|
|
@ -39,5 +39,6 @@ mock_llm_config_zhipu = LLMConfig(
|
|||
llm_type="zhipu",
|
||||
api_key="mock_api_key.zhipu",
|
||||
base_url="mock_base_url",
|
||||
model="mock_zhipu_model",
|
||||
proxy="http://localhost:8080",
|
||||
)
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
import pytest
|
||||
|
||||
from metagpt.config2 import Config
|
||||
from metagpt.provider.spark_api import GetMessageFromWeb, SparkLLM
|
||||
from tests.metagpt.provider.mock_llm_config import mock_llm_config
|
||||
|
||||
|
|
@ -33,6 +34,14 @@ def mock_spark_get_msg_from_web_run(self) -> str:
|
|||
return resp_content
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_spark_aask():
|
||||
llm = SparkLLM(Config.from_home("spark.yaml").llm)
|
||||
|
||||
resp = await llm.aask("Hello!")
|
||||
print(resp)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_spark_acompletion(mocker):
|
||||
mocker.patch("metagpt.provider.spark_api.GetMessageFromWeb.run", mock_spark_get_msg_from_web_run)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
# @Desc : unittest of Role
|
||||
import pytest
|
||||
|
||||
from metagpt.llm import HumanProvider
|
||||
from metagpt.roles.role import Role
|
||||
|
||||
|
||||
|
|
@ -12,5 +13,10 @@ def test_role_desc():
|
|||
assert role.desc == "Best Seller"
|
||||
|
||||
|
||||
def test_role_human():
|
||||
role = Role(is_human=True)
|
||||
assert isinstance(role.llm, HumanProvider)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pytest.main([__file__, "-s"])
|
||||
|
|
|
|||
|
|
@ -5,15 +5,10 @@
|
|||
@Author : alexanderwu
|
||||
@File : test_config.py
|
||||
"""
|
||||
from pydantic import BaseModel
|
||||
|
||||
from metagpt.config2 import Config
|
||||
from metagpt.configs.llm_config import LLMType
|
||||
from metagpt.context_mixin import ContextMixin
|
||||
from tests.metagpt.provider.mock_llm_config import (
|
||||
mock_llm_config,
|
||||
mock_llm_config_proxy,
|
||||
)
|
||||
from tests.metagpt.provider.mock_llm_config import mock_llm_config
|
||||
|
||||
|
||||
def test_config_1():
|
||||
|
|
@ -27,57 +22,3 @@ def test_config_from_dict():
|
|||
cfg = Config(llm=mock_llm_config)
|
||||
assert cfg
|
||||
assert cfg.llm.api_key == "mock_api_key"
|
||||
|
||||
|
||||
class ModelX(ContextMixin, BaseModel):
|
||||
a: str = "a"
|
||||
b: str = "b"
|
||||
|
||||
|
||||
class WTFMixin(BaseModel):
|
||||
c: str = "c"
|
||||
d: str = "d"
|
||||
|
||||
|
||||
class ModelY(WTFMixin, ModelX):
|
||||
pass
|
||||
|
||||
|
||||
def test_config_mixin_1():
|
||||
new_model = ModelX()
|
||||
assert new_model.a == "a"
|
||||
assert new_model.b == "b"
|
||||
|
||||
|
||||
def test_config_mixin_2():
|
||||
i = Config(llm=mock_llm_config)
|
||||
j = Config(llm=mock_llm_config_proxy)
|
||||
obj = ModelX(config=i)
|
||||
assert obj.config == i
|
||||
assert obj.config.llm == mock_llm_config
|
||||
|
||||
obj.set_config(j)
|
||||
# obj already has a config, so it will not be set
|
||||
assert obj.config == i
|
||||
|
||||
|
||||
def test_config_mixin_3():
|
||||
"""Test config mixin with multiple inheritance"""
|
||||
i = Config(llm=mock_llm_config)
|
||||
j = Config(llm=mock_llm_config_proxy)
|
||||
obj = ModelY(config=i)
|
||||
assert obj.private_config == i
|
||||
assert obj.private_config.llm == mock_llm_config
|
||||
|
||||
obj.set_config(j)
|
||||
# obj already has a config, so it will not be set
|
||||
assert obj.private_config == i
|
||||
assert obj.private_config.llm == mock_llm_config
|
||||
|
||||
assert obj.a == "a"
|
||||
assert obj.b == "b"
|
||||
assert obj.c == "c"
|
||||
assert obj.d == "d"
|
||||
|
||||
print(obj.__dict__.keys())
|
||||
assert "_config" in obj.__dict__.keys()
|
||||
|
|
|
|||
128
tests/metagpt/test_context_mixin.py
Normal file
128
tests/metagpt/test_context_mixin.py
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@Time : 2024/1/11 19:24
|
||||
@Author : alexanderwu
|
||||
@File : test_context_mixin.py
|
||||
"""
|
||||
import pytest
|
||||
from pydantic import BaseModel
|
||||
|
||||
from metagpt.actions import Action
|
||||
from metagpt.config2 import Config
|
||||
from metagpt.context_mixin import ContextMixin
|
||||
from metagpt.environment import Environment
|
||||
from metagpt.roles import Role
|
||||
from metagpt.team import Team
|
||||
from tests.metagpt.provider.mock_llm_config import (
|
||||
mock_llm_config,
|
||||
mock_llm_config_proxy,
|
||||
mock_llm_config_zhipu,
|
||||
)
|
||||
|
||||
|
||||
class ModelX(ContextMixin, BaseModel):
|
||||
a: str = "a"
|
||||
b: str = "b"
|
||||
|
||||
|
||||
class WTFMixin(BaseModel):
|
||||
c: str = "c"
|
||||
d: str = "d"
|
||||
|
||||
|
||||
class ModelY(WTFMixin, ModelX):
|
||||
pass
|
||||
|
||||
|
||||
def test_config_mixin_1():
|
||||
new_model = ModelX()
|
||||
assert new_model.a == "a"
|
||||
assert new_model.b == "b"
|
||||
|
||||
|
||||
def test_config_mixin_2():
|
||||
i = Config(llm=mock_llm_config)
|
||||
j = Config(llm=mock_llm_config_proxy)
|
||||
obj = ModelX(config=i)
|
||||
assert obj.config == i
|
||||
assert obj.config.llm == mock_llm_config
|
||||
|
||||
obj.set_config(j)
|
||||
# obj already has a config, so it will not be set
|
||||
assert obj.config == i
|
||||
|
||||
|
||||
def test_config_mixin_3_multi_inheritance_not_override_config():
|
||||
"""Test config mixin with multiple inheritance"""
|
||||
i = Config(llm=mock_llm_config)
|
||||
j = Config(llm=mock_llm_config_proxy)
|
||||
obj = ModelY(config=i)
|
||||
assert obj.config == i
|
||||
assert obj.config.llm == mock_llm_config
|
||||
|
||||
obj.set_config(j)
|
||||
# obj already has a config, so it will not be set
|
||||
assert obj.config == i
|
||||
assert obj.config.llm == mock_llm_config
|
||||
|
||||
assert obj.a == "a"
|
||||
assert obj.b == "b"
|
||||
assert obj.c == "c"
|
||||
assert obj.d == "d"
|
||||
|
||||
print(obj.__dict__.keys())
|
||||
assert "private_config" in obj.__dict__.keys()
|
||||
|
||||
|
||||
def test_config_mixin_4_multi_inheritance_override_config():
|
||||
"""Test config mixin with multiple inheritance"""
|
||||
i = Config(llm=mock_llm_config)
|
||||
j = Config(llm=mock_llm_config_zhipu)
|
||||
obj = ModelY(config=i)
|
||||
assert obj.config == i
|
||||
assert obj.config.llm == mock_llm_config
|
||||
|
||||
obj.set_config(j, override=True)
|
||||
# override obj.config
|
||||
assert obj.config == j
|
||||
assert obj.config.llm == mock_llm_config_zhipu
|
||||
|
||||
assert obj.a == "a"
|
||||
assert obj.b == "b"
|
||||
assert obj.c == "c"
|
||||
assert obj.d == "d"
|
||||
|
||||
print(obj.__dict__.keys())
|
||||
assert "private_config" in obj.__dict__.keys()
|
||||
assert obj.llm.model == "mock_zhipu_model"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_config_priority():
|
||||
"""If action's config is set, then its llm will be set, otherwise, it will use the role's llm"""
|
||||
gpt4t = Config.from_home("gpt-4-1106-preview.yaml")
|
||||
gpt35 = Config.default()
|
||||
gpt4 = Config.default()
|
||||
gpt4.llm.model = "gpt-4-0613"
|
||||
|
||||
a1 = Action(config=gpt4t, name="Say", instruction="Say your opinion with emotion and don't repeat it")
|
||||
a2 = Action(name="Say", instruction="Say your opinion with emotion and don't repeat it")
|
||||
a3 = Action(name="Vote", instruction="Vote for the candidate, and say why you vote for him/her")
|
||||
|
||||
# it will not work for a1 because the config is already set
|
||||
A = Role(name="A", profile="Democratic candidate", goal="Win the election", actions=[a1], watch=[a2], config=gpt4)
|
||||
# it will work for a2 because the config is not set
|
||||
B = Role(name="B", profile="Republican candidate", goal="Win the election", actions=[a2], watch=[a1], config=gpt4)
|
||||
# ditto
|
||||
C = Role(name="C", profile="Voter", goal="Vote for the candidate", actions=[a3], watch=[a1, a2], config=gpt35)
|
||||
|
||||
env = Environment(desc="US election live broadcast")
|
||||
Team(investment=10.0, env=env, roles=[A, B, C])
|
||||
|
||||
assert a1.llm.model == "gpt-4-1106-preview"
|
||||
assert a2.llm.model == "gpt-4-0613"
|
||||
assert a3.llm.model == "gpt-3.5-turbo-1106"
|
||||
|
||||
# history = await team.run(idea="Topic: climate change. Under 80 words per message.", send_to="a1", n_round=3)
|
||||
# assert "Alex" in history
|
||||
|
|
@ -5,25 +5,26 @@
|
|||
@Author : mashenquan
|
||||
@File : test_redis.py
|
||||
"""
|
||||
from unittest.mock import AsyncMock
|
||||
|
||||
import mock
|
||||
import pytest
|
||||
from pytest_mock import mocker
|
||||
|
||||
from metagpt.config2 import Config
|
||||
from metagpt.utils.redis import Redis
|
||||
|
||||
|
||||
async def async_mock_from_url(*args, **kwargs):
|
||||
mock_client = mock.AsyncMock()
|
||||
mock_client = AsyncMock()
|
||||
mock_client.set.return_value = None
|
||||
mock_client.get.side_effect = [b"test", b""]
|
||||
return mock_client
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@mock.patch("aioredis.from_url", return_value=async_mock_from_url())
|
||||
async def test_redis(i):
|
||||
redis = Config.default().redis
|
||||
mocker.patch("aioredis.from_url", return_value=async_mock_from_url())
|
||||
|
||||
conn = Redis(redis)
|
||||
await conn.set("test", "test", timeout_sec=0)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue