mirror of
https://github.com/FoundationAgents/MetaGPT.git
synced 2026-06-05 14:55:18 +02:00
commit
119bc0d89a
78 changed files with 4740 additions and 31 deletions
|
|
@ -5,6 +5,7 @@
|
|||
@Author : alexanderwu
|
||||
@File : test_action_node.py
|
||||
"""
|
||||
from pathlib import Path
|
||||
from typing import List, Tuple
|
||||
|
||||
import pytest
|
||||
|
|
@ -17,6 +18,7 @@ from metagpt.llm import LLM
|
|||
from metagpt.roles import Role
|
||||
from metagpt.schema import Message
|
||||
from metagpt.team import Team
|
||||
from metagpt.utils.common import encode_image
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
|
@ -241,6 +243,18 @@ def test_create_model_class_with_mapping():
|
|||
assert value == ["game.py", "app.py", "static/css/styles.css", "static/js/script.js", "templates/index.html"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_action_node_with_image():
|
||||
invoice = ActionNode(
|
||||
key="invoice", expected_type=bool, instruction="if it's a invoice file, return True else False", example="False"
|
||||
)
|
||||
|
||||
invoice_path = Path(__file__).parent.joinpath("..", "..", "data", "invoices", "invoice-2.png")
|
||||
img_base64 = encode_image(invoice_path)
|
||||
node = await invoice.fill(context="", llm=LLM(), images=[img_base64])
|
||||
assert node.instruct_content.invoice
|
||||
|
||||
|
||||
class ToolDef(BaseModel):
|
||||
tool_name: str = Field(default="a", description="tool name", examples=[])
|
||||
description: str = Field(default="b", description="tool description", examples=[])
|
||||
|
|
|
|||
3
tests/metagpt/environment/android_env/__init__.py
Normal file
3
tests/metagpt/environment/android_env/__init__.py
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Desc :
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Desc : the unittest of AndroidExtEnv
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from metagpt.environment.android_env.android_ext_env import AndroidExtEnv
|
||||
from metagpt.environment.android_env.const import ADB_EXEC_FAIL
|
||||
|
||||
|
||||
def mock_device_shape(self, adb_cmd: str) -> str:
|
||||
return "shape: 720x1080"
|
||||
|
||||
|
||||
def mock_device_shape_invalid(self, adb_cmd: str) -> str:
|
||||
return ADB_EXEC_FAIL
|
||||
|
||||
|
||||
def mock_list_devices(self, adb_cmd: str) -> str:
|
||||
return "devices\nemulator-5554"
|
||||
|
||||
|
||||
def mock_get_screenshot(self, adb_cmd: str) -> str:
|
||||
return "screenshot_xxxx-xx-xx"
|
||||
|
||||
|
||||
def mock_get_xml(self, adb_cmd: str) -> str:
|
||||
return "xml_xxxx-xx-xx"
|
||||
|
||||
|
||||
def mock_write_read_operation(self, adb_cmd: str) -> str:
|
||||
return "OK"
|
||||
|
||||
|
||||
def test_android_ext_env(mocker):
|
||||
device_id = "emulator-5554"
|
||||
mocker.patch(
|
||||
"metagpt.environment.android_env.android_ext_env.AndroidExtEnv.execute_adb_with_cmd", mock_device_shape
|
||||
)
|
||||
|
||||
ext_env = AndroidExtEnv(device_id=device_id, screenshot_dir="/data2/", xml_dir="/data2/")
|
||||
assert ext_env.adb_prefix == f"adb -s {device_id} "
|
||||
assert ext_env.adb_prefix_shell == f"adb -s {device_id} shell "
|
||||
assert ext_env.adb_prefix_si == f"adb -s {device_id} shell input "
|
||||
|
||||
assert ext_env.device_shape == (720, 1080)
|
||||
|
||||
mocker.patch(
|
||||
"metagpt.environment.android_env.android_ext_env.AndroidExtEnv.execute_adb_with_cmd", mock_device_shape_invalid
|
||||
)
|
||||
assert ext_env.device_shape == (0, 0)
|
||||
|
||||
mocker.patch(
|
||||
"metagpt.environment.android_env.android_ext_env.AndroidExtEnv.execute_adb_with_cmd", mock_list_devices
|
||||
)
|
||||
assert ext_env.list_devices() == [device_id]
|
||||
|
||||
mocker.patch(
|
||||
"metagpt.environment.android_env.android_ext_env.AndroidExtEnv.execute_adb_with_cmd", mock_get_screenshot
|
||||
)
|
||||
assert ext_env.get_screenshot("screenshot_xxxx-xx-xx", "/data/") == Path("/data/screenshot_xxxx-xx-xx.png")
|
||||
|
||||
mocker.patch("metagpt.environment.android_env.android_ext_env.AndroidExtEnv.execute_adb_with_cmd", mock_get_xml)
|
||||
assert ext_env.get_xml("xml_xxxx-xx-xx", "/data/") == Path("/data/xml_xxxx-xx-xx.xml")
|
||||
|
||||
mocker.patch(
|
||||
"metagpt.environment.android_env.android_ext_env.AndroidExtEnv.execute_adb_with_cmd", mock_write_read_operation
|
||||
)
|
||||
res = "OK"
|
||||
assert ext_env.system_back() == res
|
||||
assert ext_env.system_tap(10, 10) == res
|
||||
assert ext_env.user_input("test_input") == res
|
||||
assert ext_env.user_longpress(10, 10) == res
|
||||
assert ext_env.user_swipe(10, 10) == res
|
||||
assert ext_env.user_swipe_to((10, 10), (20, 20)) == res
|
||||
3
tests/metagpt/environment/api/__init__.py
Normal file
3
tests/metagpt/environment/api/__init__.py
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Desc :
|
||||
15
tests/metagpt/environment/api/test_env_api.py
Normal file
15
tests/metagpt/environment/api/test_env_api.py
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Desc :
|
||||
|
||||
from metagpt.environment.api.env_api import EnvAPIRegistry
|
||||
|
||||
|
||||
def test_env_api_registry():
|
||||
def test_func():
|
||||
pass
|
||||
|
||||
env_api_registry = EnvAPIRegistry()
|
||||
env_api_registry["test"] = test_func
|
||||
|
||||
env_api_registry.get("test") == test_func
|
||||
3
tests/metagpt/environment/mincraft_env/__init__.py
Normal file
3
tests/metagpt/environment/mincraft_env/__init__.py
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Desc :
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Desc : the unittest of MincraftExtEnv
|
||||
|
||||
|
||||
from metagpt.environment.mincraft_env.const import MC_CKPT_DIR
|
||||
from metagpt.environment.mincraft_env.mincraft_ext_env import MincraftExtEnv
|
||||
|
||||
|
||||
def test_mincraft_ext_env():
|
||||
ext_env = MincraftExtEnv()
|
||||
assert ext_env.server, f"{ext_env.server_host}:{ext_env.server_port}"
|
||||
assert MC_CKPT_DIR.joinpath("skill/code").exists()
|
||||
assert ext_env.warm_up.get("optional_inventory_items") == 7
|
||||
3
tests/metagpt/environment/stanford_town_env/__init__.py
Normal file
3
tests/metagpt/environment/stanford_town_env/__init__.py
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Desc :
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Desc : the unittest of StanfordTownExtEnv
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from metagpt.environment.stanford_town_env.stanford_town_ext_env import (
|
||||
StanfordTownExtEnv,
|
||||
)
|
||||
|
||||
maze_asset_path = (
|
||||
Path(__file__).absolute().parent.joinpath("..", "..", "..", "data", "environment", "stanford_town", "the_ville")
|
||||
)
|
||||
|
||||
|
||||
def test_stanford_town_ext_env():
|
||||
ext_env = StanfordTownExtEnv(maze_asset_path=maze_asset_path)
|
||||
|
||||
tile_coord = ext_env.turn_coordinate_to_tile((64, 64))
|
||||
assert tile_coord == (2, 2)
|
||||
|
||||
tile = (58, 9)
|
||||
assert len(ext_env.get_collision_maze()) == 100
|
||||
assert len(ext_env.get_address_tiles()) == 306
|
||||
assert ext_env.access_tile(tile=tile)["world"] == "the Ville"
|
||||
assert ext_env.get_tile_path(tile=tile, level="world") == "the Ville"
|
||||
assert len(ext_env.get_nearby_tiles(tile=tile, vision_r=5)) == 121
|
||||
|
||||
event = ("double studio:double studio:bedroom 2:bed", None, None, None)
|
||||
ext_env.add_tiles_event(tile[1], tile[0], event=event)
|
||||
ext_env.add_event_from_tile(event, tile)
|
||||
assert len(ext_env.tiles[tile[1]][tile[0]]["events"]) == 1
|
||||
|
||||
ext_env.turn_event_from_tile_idle(event, tile)
|
||||
|
||||
ext_env.remove_event_from_tile(event, tile)
|
||||
assert len(ext_env.tiles[tile[1]][tile[0]]["events"]) == 0
|
||||
|
||||
ext_env.remove_subject_events_from_tile(subject=event[0], tile=tile)
|
||||
assert len(ext_env.tiles[tile[1]][tile[0]]["events"]) == 0
|
||||
54
tests/metagpt/environment/test_base_env.py
Normal file
54
tests/metagpt/environment/test_base_env.py
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Desc : the unittest of ExtEnv&Env
|
||||
|
||||
import pytest
|
||||
|
||||
from metagpt.environment.api.env_api import EnvAPIAbstract
|
||||
from metagpt.environment.base_env import (
|
||||
Environment,
|
||||
env_read_api_registry,
|
||||
env_write_api_registry,
|
||||
mark_as_readable,
|
||||
mark_as_writeable,
|
||||
)
|
||||
|
||||
|
||||
class ForTestEnv(Environment):
|
||||
value: int = 0
|
||||
|
||||
@mark_as_readable
|
||||
def read_api_no_param(self):
|
||||
return self.value
|
||||
|
||||
@mark_as_readable
|
||||
def read_api(self, a: int, b: int):
|
||||
return a + b
|
||||
|
||||
@mark_as_writeable
|
||||
def write_api(self, a: int, b: int):
|
||||
self.value = a + b
|
||||
|
||||
@mark_as_writeable
|
||||
async def async_read_api(self, a: int, b: int):
|
||||
return a + b
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_ext_env():
|
||||
env = ForTestEnv()
|
||||
assert len(env_read_api_registry) > 0
|
||||
assert len(env_write_api_registry) > 0
|
||||
|
||||
apis = env.get_all_available_apis(mode="read")
|
||||
assert len(apis) > 0
|
||||
assert len(apis["read_api"]) == 3
|
||||
|
||||
_ = await env.step(EnvAPIAbstract(api_name="write_api", kwargs={"a": 5, "b": 10}))
|
||||
assert env.value == 15
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
await env.observe("not_exist_api")
|
||||
|
||||
assert await env.observe("read_api_no_param") == 15
|
||||
assert await env.observe(EnvAPIAbstract(api_name="read_api", kwargs={"a": 5, "b": 5})) == 10
|
||||
3
tests/metagpt/environment/werewolf_env/__init__.py
Normal file
3
tests/metagpt/environment/werewolf_env/__init__.py
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Desc :
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Desc : the unittest of WerewolfExtEnv
|
||||
|
||||
from metagpt.environment.werewolf_env.werewolf_ext_env import RoleState, WerewolfExtEnv
|
||||
from metagpt.roles.role import Role
|
||||
|
||||
|
||||
class Werewolf(Role):
|
||||
profile: str = "Werewolf"
|
||||
|
||||
|
||||
class Villager(Role):
|
||||
profile: str = "Villager"
|
||||
|
||||
|
||||
class Witch(Role):
|
||||
profile: str = "Witch"
|
||||
|
||||
|
||||
class Guard(Role):
|
||||
profile: str = "Guard"
|
||||
|
||||
|
||||
def test_werewolf_ext_env():
|
||||
players_state = {
|
||||
"Player0": ("Werewolf", RoleState.ALIVE),
|
||||
"Player1": ("Werewolf", RoleState.ALIVE),
|
||||
"Player2": ("Villager", RoleState.ALIVE),
|
||||
"Player3": ("Witch", RoleState.ALIVE),
|
||||
"Player4": ("Guard", RoleState.ALIVE),
|
||||
}
|
||||
ext_env = WerewolfExtEnv(players_state=players_state, step_idx=4, special_role_players=["Player3", "Player4"])
|
||||
|
||||
assert len(ext_env.living_players) == 5
|
||||
assert len(ext_env.special_role_players) == 2
|
||||
assert len(ext_env.werewolf_players) == 2
|
||||
|
||||
curr_instr = ext_env.curr_step_instruction()
|
||||
assert ext_env.step_idx == 5
|
||||
assert "Werewolves, please open your eyes" in curr_instr["content"]
|
||||
|
||||
# current step_idx = 5
|
||||
ext_env.wolf_kill_someone(wolf=Role(name="Player10"), player_name="Player4")
|
||||
ext_env.wolf_kill_someone(wolf=Werewolf(name="Player0"), player_name="Player4")
|
||||
ext_env.wolf_kill_someone(wolf=Werewolf(name="Player1"), player_name="Player4")
|
||||
assert ext_env.player_hunted == "Player4"
|
||||
assert len(ext_env.living_players) == 5 # hunted but can be saved by witch
|
||||
|
||||
for idx in range(13):
|
||||
_ = ext_env.curr_step_instruction()
|
||||
|
||||
# current step_idx = 18
|
||||
assert ext_env.step_idx == 18
|
||||
ext_env.vote_kill_someone(voteer=Werewolf(name="Player0"), player_name="Player2")
|
||||
ext_env.vote_kill_someone(voteer=Werewolf(name="Player1"), player_name="Player3")
|
||||
ext_env.vote_kill_someone(voteer=Villager(name="Player2"), player_name="Player3")
|
||||
ext_env.vote_kill_someone(voteer=Witch(name="Player3"), player_name="Player4")
|
||||
ext_env.vote_kill_someone(voteer=Guard(name="Player4"), player_name="Player2")
|
||||
assert ext_env.player_current_dead == "Player2"
|
||||
assert len(ext_env.living_players) == 4
|
||||
|
||||
player_names = ["Player0", "Player2"]
|
||||
assert ext_env.get_players_state(player_names) == dict(zip(player_names, [RoleState.ALIVE, RoleState.KILLED]))
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
import pytest
|
||||
from PIL import Image
|
||||
|
||||
from metagpt.const import TEST_DATA_PATH
|
||||
from metagpt.llm import LLM
|
||||
|
|
@ -62,6 +63,18 @@ async def test_speech_to_text():
|
|||
assert "你好" == resp.text
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_gen_image():
|
||||
llm = LLM()
|
||||
model = "dall-e-3"
|
||||
prompt = 'a logo with word "MetaGPT"'
|
||||
images: list[Image] = await llm.gen_image(model=model, prompt=prompt)
|
||||
assert images[0].size == (1024, 1024)
|
||||
|
||||
images: list[Image] = await llm.gen_image(model=model, prompt=prompt, resp_format="b64_json")
|
||||
assert images[0].size == (1024, 1024)
|
||||
|
||||
|
||||
class TestOpenAI:
|
||||
def test_make_client_kwargs_without_proxy(self):
|
||||
instance = OpenAILLM(mock_llm_config)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue