mirror of
https://github.com/FoundationAgents/MetaGPT.git
synced 2026-04-27 17:56:23 +02:00
Merge pull request #652 from better629/dev
Feat add extra role/actions' ser&desr unittest
This commit is contained in:
commit
5510df5f96
10 changed files with 238 additions and 9 deletions
|
|
@ -7,12 +7,11 @@
|
|||
"""
|
||||
from typing import Optional
|
||||
|
||||
from pydantic import Field
|
||||
|
||||
from metagpt.document_store.base_store import BaseStore
|
||||
from metagpt.roles import Sales
|
||||
|
||||
# from metagpt.actions import SearchAndSummarize
|
||||
# from metagpt.tools import SearchEngineType
|
||||
|
||||
|
||||
DESC = """
|
||||
## Principles (all things must not bypass the principles)
|
||||
|
||||
|
|
@ -29,4 +28,4 @@ class CustomerService(Sales):
|
|||
name: str = "Xiaomei"
|
||||
profile: str = "Human customer service"
|
||||
desc: str = DESC
|
||||
store: Optional[str] = None
|
||||
store: Optional[BaseStore] = Field(default=None, exclude=True)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
from typing import Optional
|
||||
|
||||
from pydantic import Field
|
||||
|
||||
from metagpt.actions import SearchAndSummarize, UserRequirement
|
||||
from metagpt.document_store.base_store import BaseStore
|
||||
from metagpt.roles import Role
|
||||
|
|
@ -25,7 +27,7 @@ class Sales(Role):
|
|||
"delivered with the professionalism and courtesy expected of a seasoned sales guide."
|
||||
)
|
||||
|
||||
store: Optional[BaseStore] = None
|
||||
store: Optional[BaseStore] = Field(default=None, exclude=True)
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
|
|
|||
|
|
@ -41,13 +41,13 @@ class SkAgent(Role):
|
|||
goal: str = "Execute task based on passed in task description"
|
||||
constraints: str = ""
|
||||
|
||||
plan: Plan = None
|
||||
plan: Plan = Field(default=None, exclude=True)
|
||||
planner_cls: Any = None
|
||||
planner: Union[BasicPlanner, SequentialPlanner, ActionPlanner] = None
|
||||
llm: BaseLLM = Field(default_factory=LLM)
|
||||
kernel: Kernel = Field(default_factory=Kernel)
|
||||
import_semantic_skill_from_directory: Callable = None
|
||||
import_skill: Callable = None
|
||||
import_semantic_skill_from_directory: Callable = Field(default=None, exclude=True)
|
||||
import_skill: Callable = Field(default=None, exclude=True)
|
||||
|
||||
def __init__(self, **data: Any) -> None:
|
||||
"""Initializes the Engineer role with given attributes."""
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# @Desc :
|
||||
|
||||
import pytest
|
||||
|
||||
from metagpt.actions.action_node import ActionNode
|
||||
from metagpt.actions.prepare_interview import PrepareInterview
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_action_deserialize():
|
||||
action = PrepareInterview()
|
||||
serialized_data = action.model_dump()
|
||||
assert serialized_data["name"] == "PrepareInterview"
|
||||
|
||||
new_action = PrepareInterview(**serialized_data)
|
||||
|
||||
assert new_action.name == "PrepareInterview"
|
||||
assert type(await new_action.run("python developer")) == ActionNode
|
||||
22
tests/metagpt/serialize_deserialize/test_reasearcher.py
Normal file
22
tests/metagpt/serialize_deserialize/test_reasearcher.py
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# @Desc :
|
||||
|
||||
import pytest
|
||||
|
||||
from metagpt.actions import CollectLinks
|
||||
from metagpt.roles.researcher import Researcher
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_tutorial_assistant_deserialize():
|
||||
role = Researcher()
|
||||
ser_role_dict = role.model_dump()
|
||||
assert "name" in ser_role_dict
|
||||
assert "language" in ser_role_dict
|
||||
|
||||
new_role = Researcher(**ser_role_dict)
|
||||
assert new_role.language == "en-us"
|
||||
assert len(new_role.actions) == 3
|
||||
assert isinstance(new_role.actions[0], CollectLinks)
|
||||
|
||||
# todo: 需要测试不同的action失败下,记忆是否正常保存
|
||||
24
tests/metagpt/serialize_deserialize/test_sk_agent.py
Normal file
24
tests/metagpt/serialize_deserialize/test_sk_agent.py
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# @Desc :
|
||||
import pytest
|
||||
|
||||
from metagpt.roles.sk_agent import SkAgent
|
||||
|
||||
|
||||
def test_sk_agent_serialize():
|
||||
role = SkAgent()
|
||||
ser_role_dict = role.model_dump(exclude={"import_semantic_skill_from_directory", "import_skill"})
|
||||
assert "name" in ser_role_dict
|
||||
assert "planner" in ser_role_dict
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_sk_agent_deserialize():
|
||||
role = SkAgent()
|
||||
ser_role_dict = role.model_dump(exclude={"import_semantic_skill_from_directory", "import_skill"})
|
||||
assert "name" in ser_role_dict
|
||||
assert "planner" in ser_role_dict
|
||||
|
||||
new_role = SkAgent(**ser_role_dict)
|
||||
assert new_role.name == "Sunshine"
|
||||
assert len(new_role.actions) == 1
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# @Desc :
|
||||
import pytest
|
||||
|
||||
from metagpt.actions.write_tutorial import WriteDirectory
|
||||
from metagpt.roles.tutorial_assistant import TutorialAssistant
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_tutorial_assistant_deserialize():
|
||||
role = TutorialAssistant()
|
||||
ser_role_dict = role.model_dump()
|
||||
assert "name" in ser_role_dict
|
||||
assert "language" in ser_role_dict
|
||||
assert "topic" in ser_role_dict
|
||||
|
||||
new_role = TutorialAssistant(**ser_role_dict)
|
||||
assert new_role.name == "Stitch"
|
||||
assert len(new_role.actions) == 1
|
||||
assert isinstance(new_role.actions[0], WriteDirectory)
|
||||
44
tests/metagpt/serialize_deserialize/test_write_docstring.py
Normal file
44
tests/metagpt/serialize_deserialize/test_write_docstring.py
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# @Desc :
|
||||
import pytest
|
||||
|
||||
from metagpt.actions.write_docstring import WriteDocstring
|
||||
|
||||
code = """
|
||||
def add_numbers(a: int, b: int):
|
||||
return a + b
|
||||
|
||||
|
||||
class Person:
|
||||
def __init__(self, name: str, age: int):
|
||||
self.name = name
|
||||
self.age = age
|
||||
|
||||
def greet(self):
|
||||
return f"Hello, my name is {self.name} and I am {self.age} years old."
|
||||
"""
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize(
|
||||
("style", "part"),
|
||||
[
|
||||
("google", "Args:"),
|
||||
("numpy", "Parameters"),
|
||||
("sphinx", ":param name:"),
|
||||
],
|
||||
ids=["google", "numpy", "sphinx"],
|
||||
)
|
||||
async def test_action_deserialize(style: str, part: str):
|
||||
action = WriteDocstring()
|
||||
serialized_data = action.model_dump()
|
||||
|
||||
assert "name" in serialized_data
|
||||
assert serialized_data["desc"] == "Write docstring for code."
|
||||
|
||||
new_action = WriteDocstring(**serialized_data)
|
||||
|
||||
assert not new_action.name
|
||||
assert new_action.desc == "Write docstring for code."
|
||||
ret = await new_action.run(code, style=style)
|
||||
assert part in ret
|
||||
56
tests/metagpt/serialize_deserialize/test_write_review.py
Normal file
56
tests/metagpt/serialize_deserialize/test_write_review.py
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# @Desc :
|
||||
import pytest
|
||||
|
||||
from metagpt.actions.action_node import ActionNode
|
||||
from metagpt.actions.write_review import WriteReview
|
||||
|
||||
CONTEXT = """
|
||||
{
|
||||
"Language": "zh_cn",
|
||||
"Programming Language": "Python",
|
||||
"Original Requirements": "写一个简单的2048",
|
||||
"Project Name": "game_2048",
|
||||
"Product Goals": [
|
||||
"创建一个引人入胜的用户体验",
|
||||
"确保高性能",
|
||||
"提供可定制的功能"
|
||||
],
|
||||
"User Stories": [
|
||||
"作为用户,我希望能够选择不同的难度级别",
|
||||
"作为玩家,我希望在每局游戏结束后能看到我的得分"
|
||||
],
|
||||
"Competitive Analysis": [
|
||||
"Python Snake Game: 界面简单,缺乏高级功能"
|
||||
],
|
||||
"Competitive Quadrant Chart": "quadrantChart\n title \"Reach and engagement of campaigns\"\n x-axis \"Low Reach\" --> \"High Reach\"\n y-axis \"Low Engagement\" --> \"High Engagement\"\n quadrant-1 \"我们应该扩展\"\n quadrant-2 \"需要推广\"\n quadrant-3 \"重新评估\"\n quadrant-4 \"可能需要改进\"\n \"Campaign A\": [0.3, 0.6]\n \"Campaign B\": [0.45, 0.23]\n \"Campaign C\": [0.57, 0.69]\n \"Campaign D\": [0.78, 0.34]\n \"Campaign E\": [0.40, 0.34]\n \"Campaign F\": [0.35, 0.78]\n \"Our Target Product\": [0.5, 0.6]",
|
||||
"Requirement Analysis": "产品应该用户友好。",
|
||||
"Requirement Pool": [
|
||||
[
|
||||
"P0",
|
||||
"主要代码..."
|
||||
],
|
||||
[
|
||||
"P0",
|
||||
"游戏算法..."
|
||||
]
|
||||
],
|
||||
"UI Design draft": "基本功能描述,简单的风格和布局。",
|
||||
"Anything UNCLEAR": "..."
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_action_deserialize():
|
||||
action = WriteReview()
|
||||
serialized_data = action.model_dump()
|
||||
assert serialized_data["name"] == "WriteReview"
|
||||
|
||||
new_action = WriteReview(**serialized_data)
|
||||
review = await new_action.run(CONTEXT)
|
||||
|
||||
assert new_action.name == "WriteReview"
|
||||
assert type(review) == ActionNode
|
||||
assert review.instruct_content
|
||||
assert review.get("LGTM") in ["LGTM", "LBTM"]
|
||||
43
tests/metagpt/serialize_deserialize/test_write_tutorial.py
Normal file
43
tests/metagpt/serialize_deserialize/test_write_tutorial.py
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# @Desc :
|
||||
from typing import Dict
|
||||
|
||||
import pytest
|
||||
|
||||
from metagpt.actions.write_tutorial import WriteContent, WriteDirectory
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize(("language", "topic"), [("English", "Write a tutorial about Python")])
|
||||
async def test_write_directory_deserialize(language: str, topic: str):
|
||||
action = WriteDirectory()
|
||||
serialized_data = action.model_dump()
|
||||
assert serialized_data["name"] == "WriteDirectory"
|
||||
assert serialized_data["language"] == "Chinese"
|
||||
|
||||
new_action = WriteDirectory(**serialized_data)
|
||||
ret = await new_action.run(topic=topic)
|
||||
assert isinstance(ret, dict)
|
||||
assert "title" in ret
|
||||
assert "directory" in ret
|
||||
assert isinstance(ret["directory"], list)
|
||||
assert len(ret["directory"])
|
||||
assert isinstance(ret["directory"][0], dict)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize(
|
||||
("language", "topic", "directory"),
|
||||
[("English", "Write a tutorial about Python", {"Introduction": ["What is Python?", "Why learn Python?"]})],
|
||||
)
|
||||
async def test_write_content_deserialize(language: str, topic: str, directory: Dict):
|
||||
action = WriteContent(language=language, directory=directory)
|
||||
serialized_data = action.model_dump()
|
||||
assert serialized_data["name"] == "WriteContent"
|
||||
|
||||
new_action = WriteContent(**serialized_data)
|
||||
ret = await new_action.run(topic=topic)
|
||||
assert isinstance(ret, str)
|
||||
assert list(directory.keys())[0] in ret
|
||||
for value in list(directory.values())[0]:
|
||||
assert value in ret
|
||||
Loading…
Add table
Add a link
Reference in a new issue