mirror of
https://github.com/FoundationAgents/MetaGPT.git
synced 2026-06-11 15:15:18 +02:00
feat: merge teacher
This commit is contained in:
commit
01c487fb6a
32 changed files with 1578 additions and 38 deletions
51
tests/metagpt/actions/test_meta_action.py
Normal file
51
tests/metagpt/actions/test_meta_action.py
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@Time : 2023/8/8
|
||||
@Author : mashenquan
|
||||
@File : test_meta_action.py
|
||||
"""
|
||||
from typing import Dict
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
from metagpt.actions.meta_action import MetaAction
|
||||
from metagpt.roles.uml_meta_role_options import MetaActionOptions
|
||||
|
||||
|
||||
def test_meta_action_create():
|
||||
class Inputs(BaseModel):
|
||||
options: Dict
|
||||
kwargs: Dict
|
||||
expect_class_name: str
|
||||
expect_prompt: str
|
||||
|
||||
inputs = [
|
||||
{
|
||||
"options": {
|
||||
"topic": "TOPIC_A",
|
||||
"name": "A",
|
||||
"language": "XX",
|
||||
"template_ix": 0,
|
||||
"statements": ["Statement A", "Statement B"],
|
||||
"template": "{statements}",
|
||||
"rsp_begin_tag": "",
|
||||
"rsp_end_tag": ""
|
||||
},
|
||||
"kwargs": {},
|
||||
"expect_class_name": "TOPIC_A",
|
||||
"expect_prompt": "\n".join(["Statement A", "Statement B"]),
|
||||
}
|
||||
]
|
||||
|
||||
for i in inputs:
|
||||
seed = Inputs(**i)
|
||||
opt = MetaActionOptions(**seed.options)
|
||||
act = MetaAction(opt, **seed.kwargs)
|
||||
assert seed.expect_prompt == act.prompt
|
||||
t = MetaAction.get_action_type(seed.expect_class_name)
|
||||
assert t.__name__ == seed.expect_class_name
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_meta_action_create()
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
#
|
||||
from tests.metagpt.roles.ui_role import UIDesign
|
||||
|
||||
llm_resp= '''
|
||||
llm_resp = '''
|
||||
# UI Design Description
|
||||
```The user interface for the snake game will be designed in a way that is simple, clean, and intuitive. The main elements of the game such as the game grid, snake, food, score, and game over message will be clearly defined and easy to understand. The game grid will be centered on the screen with the score displayed at the top. The game controls will be intuitive and easy to use. The design will be modern and minimalist with a pleasing color scheme.```
|
||||
|
||||
|
|
@ -100,6 +100,7 @@ body {
|
|||
font-size: 3em;
|
||||
'''
|
||||
|
||||
|
||||
def test_ui_design_parse_css():
|
||||
ui_design_work = UIDesign(name="UI design action")
|
||||
|
||||
|
|
@ -161,7 +162,7 @@ def test_ui_design_parse_css():
|
|||
transform: translate(-50%, -50%);
|
||||
font-size: 3em;
|
||||
'''
|
||||
assert ui_design_work.parse_css_code(context=llm_resp)==css
|
||||
assert ui_design_work.parse_css_code(context=llm_resp) == css
|
||||
|
||||
|
||||
def test_ui_design_parse_html():
|
||||
|
|
@ -185,7 +186,4 @@ def test_ui_design_parse_html():
|
|||
</body>
|
||||
</html>
|
||||
'''
|
||||
assert ui_design_work.parse_css_code(context=llm_resp)==html
|
||||
|
||||
|
||||
|
||||
assert ui_design_work.parse_css_code(context=llm_resp) == html
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
@Time : 2023/5/11 17:45
|
||||
@Author : alexanderwu
|
||||
@File : test_write_code.py
|
||||
@Modified By: mashenquan, 2023-8-1, fix-bug: `filename` of `write_code.run()` is missing.
|
||||
@Modified By: mashenquan, 2023/8/20. Remove global configuration `CONFIG`, enable configuration support for business isolation.
|
||||
"""
|
||||
import pytest
|
||||
|
|
@ -22,8 +23,7 @@ async def test_write_code():
|
|||
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, "filename")
|
||||
code = await write_code.run(context=api_design, filename="test")
|
||||
logger.info(code)
|
||||
|
||||
# 我们不能精确地预测生成的代码,但我们可以检查某些关键字
|
||||
|
|
|
|||
67
tests/metagpt/actions/test_write_teaching_plan.py
Normal file
67
tests/metagpt/actions/test_write_teaching_plan.py
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@Time : 2023/7/28 17:25
|
||||
@Author : mashenquan
|
||||
@File : test_write_teaching_plan.py
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
from typing import Optional
|
||||
from pydantic import BaseModel
|
||||
from langchain.llms.base import LLM
|
||||
|
||||
from metagpt.actions.write_teaching_plan import WriteTeachingPlanPart
|
||||
from metagpt.config import Config
|
||||
from metagpt.schema import Message
|
||||
|
||||
|
||||
class MockWriteTeachingPlanPart(WriteTeachingPlanPart):
|
||||
def __init__(self, options, name: str = '', context=None, llm: LLM = None, topic="", language="Chinese"):
|
||||
super().__init__(options, name, context, llm, topic, language)
|
||||
|
||||
async def _aask(self, prompt: str, system_msgs: Optional[list[str]] = None) -> str:
|
||||
return f"{WriteTeachingPlanPart.DATA_BEGIN_TAG}\nprompt\n{WriteTeachingPlanPart.DATA_END_TAG}"
|
||||
|
||||
|
||||
async def mock_write_teaching_plan_part():
|
||||
class Inputs(BaseModel):
|
||||
input: str
|
||||
name: str
|
||||
topic: str
|
||||
language: str
|
||||
|
||||
inputs = [
|
||||
{
|
||||
"input": "AABBCC",
|
||||
"name": "A",
|
||||
"topic": WriteTeachingPlanPart.COURSE_TITLE,
|
||||
"language": "C"
|
||||
},
|
||||
{
|
||||
"input": "DDEEFFF",
|
||||
"name": "A1",
|
||||
"topic": "B1",
|
||||
"language": "C1"
|
||||
}
|
||||
]
|
||||
|
||||
for i in inputs:
|
||||
seed = Inputs(**i)
|
||||
options = Config().runtime_options
|
||||
act = MockWriteTeachingPlanPart(options=options, name=seed.name, topic=seed.topic, language=seed.language)
|
||||
await act.run([Message(content="")])
|
||||
assert act.topic == seed.topic
|
||||
assert str(act) == seed.topic
|
||||
assert act.name == seed.name
|
||||
assert act.rsp == "# prompt" if seed.topic == WriteTeachingPlanPart.COURSE_TITLE else "prompt"
|
||||
|
||||
|
||||
def test_suite():
|
||||
loop = asyncio.get_event_loop()
|
||||
task = loop.create_task(mock_write_teaching_plan_part())
|
||||
loop.run_until_complete(task)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_suite()
|
||||
94
tests/metagpt/roles/test_fork_meta_role.py
Normal file
94
tests/metagpt/roles/test_fork_meta_role.py
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@Time : 2023/8/8
|
||||
@Author : mashenquan
|
||||
@File : test_fork_meta_role.py
|
||||
"""
|
||||
from typing import Dict
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
from metagpt.config import Config
|
||||
from metagpt.provider.openai_api import CostManager
|
||||
from metagpt.roles.fork_meta_role import ForkMetaRole
|
||||
|
||||
|
||||
def test_creat_role():
|
||||
class Inputs(BaseModel):
|
||||
role: Dict
|
||||
action_count: int
|
||||
|
||||
inputs = [
|
||||
{
|
||||
"role": {
|
||||
"role_type": "fork",
|
||||
"name": "Lily",
|
||||
"profile": "{teaching_language} Teacher",
|
||||
"goal": "writing a {language} teaching plan part by part",
|
||||
"constraints": "writing in {language}",
|
||||
"role": "You are a {teaching_language} Teacher, named Lily, your goal is writing a {"
|
||||
"teaching_language} teaching plan part by part, and the constraint is writing in {language}.",
|
||||
"desc": "",
|
||||
"output_filename": "teaching_plan_demo.md",
|
||||
"requirement": ["TeachingPlanRequirement"],
|
||||
"templates": [
|
||||
"Do not refer to the context of the previous conversation records, start the conversation "
|
||||
"anew.\n\nFormation: \"Capacity and role\" defines the role you are currently playing;\n\t\"["
|
||||
"LESSON_BEGIN]\" and \"[LESSON_END]\" tags enclose the content of textbook;\n\t\"Statement\" "
|
||||
"defines the work detail you need to complete at this stage;\n\t\"Answer options\" defines the "
|
||||
"format requirements for your responses;\n\t\"Constraint\" defines the conditions that your "
|
||||
"responses must comply with.\n\n{statements}\nConstraint: Writing in {language}.\nAnswer options: "
|
||||
"Encloses the lesson title with \"[TEACHING_PLAN_BEGIN]\" and \"[TEACHING_PLAN_END]\" tags.\n["
|
||||
"LESSON_BEGIN]\n{lesson}\n[LESSON_END]",
|
||||
"Do not refer to the context of the previous conversation records, start the conversation "
|
||||
"anew.\n\nFormation: \"Capacity and role\" defines the role you are currently playing;\n\t\"["
|
||||
"LESSON_BEGIN]\" and \"[LESSON_END]\" tags enclose the content of textbook;\n\t\"Statement\" "
|
||||
"defines the work detail you need to complete at this stage;\n\t\"Answer options\" defines the "
|
||||
"format requirements for your responses;\n\t\"Constraint\" defines the conditions that your "
|
||||
"responses must comply with.\n\nCapacity and role: {role}\nStatement: Write the \"{topic}\" part "
|
||||
"of teaching plan, WITHOUT ANY content unrelated to \"{topic}\"!!\n{statements}\nAnswer options: "
|
||||
"Enclose the teaching plan content with \"[TEACHING_PLAN_BEGIN]\" and \"[TEACHING_PLAN_END]\" "
|
||||
"tags.\nAnswer options: Using proper markdown format from second-level header "
|
||||
"format.\nConstraint: Writing in {language}.\n[LESSON_BEGIN]\n{lesson}\n[LESSON_END] "
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"name": "",
|
||||
"topic": "Title",
|
||||
"language": "Chinese",
|
||||
"statements": [
|
||||
"Statement: Find and return the title of the lesson only with \"# \" prefixed, without "
|
||||
"anything else."],
|
||||
"template_ix": 0},
|
||||
{
|
||||
"name": "",
|
||||
"topic": "Teaching Hours",
|
||||
"language": "Chinese",
|
||||
"statements": [],
|
||||
"template_ix": 1,
|
||||
"rsp_begin_tag": "[TEACHING_PLAN_BEGIN]",
|
||||
"rsp_end_tag": "[TEACHING_PLAN_END]"}
|
||||
]
|
||||
},
|
||||
"action_count": 2
|
||||
}
|
||||
]
|
||||
|
||||
for i in inputs:
|
||||
seed = Inputs(**i)
|
||||
kwargs = {
|
||||
"teaching_language": "AA",
|
||||
"language": "BB"
|
||||
}
|
||||
runtime_options = Config().runtime_options
|
||||
cost_manager = CostManager(options=runtime_options)
|
||||
role = ForkMetaRole(runtime_options=runtime_options, cost_manager=cost_manager, role_options=seed.role, **kwargs)
|
||||
assert role.action_count == 2
|
||||
assert "{" not in role.profile
|
||||
assert "{" not in role.goal
|
||||
assert "{" not in role.constraints
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_creat_role()
|
||||
101
tests/metagpt/roles/test_teacher.py
Normal file
101
tests/metagpt/roles/test_teacher.py
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@Time : 2023/7/27 13:25
|
||||
@Author : mashenquan
|
||||
@File : test_teacher.py
|
||||
"""
|
||||
|
||||
from typing import Dict, Optional
|
||||
from pydantic import BaseModel
|
||||
|
||||
from metagpt.config import Config
|
||||
from metagpt.provider.openai_api import CostManager
|
||||
from metagpt.roles.teacher import Teacher
|
||||
|
||||
|
||||
def test_init():
|
||||
class Inputs(BaseModel):
|
||||
name: str
|
||||
profile: str
|
||||
goal: str
|
||||
constraints: str
|
||||
desc: str
|
||||
kwargs: Optional[Dict] = None
|
||||
expect_name: str
|
||||
expect_profile: str
|
||||
expect_goal: str
|
||||
expect_constraints: str
|
||||
expect_desc: str
|
||||
|
||||
inputs = [
|
||||
{
|
||||
"name": "Lily{language}",
|
||||
"expect_name": "LilyCN",
|
||||
"profile": "X {teaching_language}",
|
||||
"expect_profile": "X EN",
|
||||
"goal": "Do {something_big}, {language}",
|
||||
"expect_goal": "Do sleep, CN",
|
||||
"constraints": "Do in {key1}, {language}",
|
||||
"expect_constraints": "Do in HaHa, CN",
|
||||
"kwargs": {"language": "CN", "key1": "HaHa", "something_big": "sleep", "teaching_language": "EN"},
|
||||
"desc": "aaa{language}",
|
||||
"expect_desc": "aaaCN"
|
||||
},
|
||||
{
|
||||
"name": "Lily{language}",
|
||||
"expect_name": "Lily{language}",
|
||||
"profile": "X {teaching_language}",
|
||||
"expect_profile": "X {teaching_language}",
|
||||
"goal": "Do {something_big}, {language}",
|
||||
"expect_goal": "Do {something_big}, {language}",
|
||||
"constraints": "Do in {key1}, {language}",
|
||||
"expect_constraints": "Do in {key1}, {language}",
|
||||
"kwargs": {},
|
||||
"desc": "aaa{language}",
|
||||
"expect_desc": "aaa{language}"
|
||||
},
|
||||
]
|
||||
|
||||
for i in inputs:
|
||||
seed = Inputs(**i)
|
||||
options = Config().runtime_options
|
||||
cost_manager = CostManager(options=options)
|
||||
teacher = Teacher(options=options, cost_manager=cost_manager, name=seed.name, profile=seed.profile,
|
||||
goal=seed.goal, constraints=seed.constraints,
|
||||
desc=seed.desc, **seed.kwargs)
|
||||
assert teacher.name == seed.expect_name
|
||||
assert teacher.desc == seed.expect_desc
|
||||
assert teacher.profile == seed.expect_profile
|
||||
assert teacher.goal == seed.expect_goal
|
||||
assert teacher.constraints == seed.expect_constraints
|
||||
assert teacher.course_title == "teaching_plan"
|
||||
|
||||
|
||||
def test_new_file_name():
|
||||
class Inputs(BaseModel):
|
||||
lesson_title: str
|
||||
ext: str
|
||||
expect: str
|
||||
|
||||
inputs = [
|
||||
{
|
||||
"lesson_title": "# @344\n12",
|
||||
"ext": ".md",
|
||||
"expect": "_344_12.md"
|
||||
},
|
||||
{
|
||||
"lesson_title": "1#@$%!*&\\/:*?\"<>|\n\t \'1",
|
||||
"ext": ".cc",
|
||||
"expect": "1_1.cc"
|
||||
}
|
||||
]
|
||||
for i in inputs:
|
||||
seed = Inputs(**i)
|
||||
result = Teacher.new_file_name(seed.lesson_title, seed.ext)
|
||||
assert result == seed.expect
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_init()
|
||||
test_new_file_name()
|
||||
61
tests/metagpt/roles/test_uml_meta_role_factory.py
Normal file
61
tests/metagpt/roles/test_uml_meta_role_factory.py
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@Time : 2023/8/8
|
||||
@Author : mashenquan
|
||||
@File : test_uml_meta_role_factory.py
|
||||
"""
|
||||
from typing import List, Dict
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
from metagpt.roles.uml_meta_role_factory import UMLMetaRoleFactory
|
||||
|
||||
|
||||
def test_create_roles():
|
||||
class Inputs(BaseModel):
|
||||
roles: List
|
||||
kwargs: Dict
|
||||
|
||||
inputs = [
|
||||
{
|
||||
"roles": [
|
||||
{
|
||||
"role_type": "fork",
|
||||
"name": "Lily",
|
||||
"profile": "{teaching_language} Teacher",
|
||||
"goal": "writing a {language} teaching plan part by part",
|
||||
"constraints": "writing in {language}",
|
||||
"role": "You are a {teaching_language} Teacher, named Lily.",
|
||||
"desc": "",
|
||||
"output_filename": "teaching_plan_demo.md",
|
||||
"requirement": ["TeachingPlanRequirement"],
|
||||
"templates": ["Do 1 {statements}", "Do 2 {statements}"],
|
||||
"actions": [
|
||||
{
|
||||
"name": "",
|
||||
"topic": "Title",
|
||||
"language": "Chinese",
|
||||
"statements": ["statement 1", "statement 2"]}
|
||||
],
|
||||
"template_ix": 0
|
||||
}
|
||||
],
|
||||
"kwargs": {
|
||||
"teaching_language": "AA",
|
||||
"language": "BB",
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
for i in inputs:
|
||||
seed = Inputs(**i)
|
||||
roles = UMLMetaRoleFactory.create_roles(seed.roles, **seed.kwargs)
|
||||
assert len(roles) == 1
|
||||
assert "{" not in roles[0].profile
|
||||
assert "{" not in roles[0].goal
|
||||
assert roles[0].action_count == 1
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_create_roles()
|
||||
40
tests/metagpt/roles/test_uml_meta_role_options.py
Normal file
40
tests/metagpt/roles/test_uml_meta_role_options.py
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@Time : 2023/8/8
|
||||
@Author : mashenquan
|
||||
@File : test_uml_meta_role_options.py
|
||||
"""
|
||||
from typing import List
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
from metagpt.roles.uml_meta_role_options import MetaActionOptions
|
||||
|
||||
|
||||
def test_set_default_template():
|
||||
class Inputs(BaseModel):
|
||||
statements: List
|
||||
template: str
|
||||
expect_prompt: str
|
||||
|
||||
inputs = [
|
||||
{
|
||||
"statements": ["Statement: 1", "Statement: 2"],
|
||||
"template": "{statements}",
|
||||
"expect_prompt": "Statement: 1\nStatement: 2"
|
||||
}
|
||||
]
|
||||
|
||||
for i in inputs:
|
||||
seed = Inputs(**i)
|
||||
opt = MetaActionOptions(topic="", statements=seed.statements)
|
||||
assert opt.template == ""
|
||||
opt.set_default_template(seed.template)
|
||||
assert opt.template == seed.template
|
||||
kwargs = {}
|
||||
assert opt.format_prompt(**kwargs) == seed.expect_prompt
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_set_default_template()
|
||||
|
|
@ -4,23 +4,46 @@
|
|||
@Time : 2023/7/1 22:50
|
||||
@Author : alexanderwu
|
||||
@File : test_azure_tts.py
|
||||
@Modified By: mashenquan, 2023-8-9, add more text formatting options
|
||||
@Modified By: mashenquan, 2023-8-17, move to `tools` folder.
|
||||
"""
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
sys.path.append(str(Path(__file__).resolve().parent.parent.parent.parent)) # fix-bug: No module named 'metagpt'
|
||||
from metagpt.const import WORKSPACE_ROOT
|
||||
from metagpt.tools.azure_tts import AzureTTS
|
||||
from metagpt.utils.common import initialize_environment
|
||||
|
||||
|
||||
def test_azure_tts():
|
||||
azure_tts = AzureTTS("azure_tts")
|
||||
azure_tts.synthesize_speech(
|
||||
"zh-CN",
|
||||
"zh-CN-YunxiNeural",
|
||||
"Boy",
|
||||
"你好,我是卡卡",
|
||||
"output.wav")
|
||||
initialize_environment()
|
||||
|
||||
azure_tts = AzureTTS()
|
||||
text = """
|
||||
女儿看见父亲走了进来,问道:
|
||||
<mstts:express-as role="YoungAdultFemale" style="calm">
|
||||
“您来的挺快的,怎么过来的?”
|
||||
</mstts:express-as>
|
||||
父亲放下手提包,说:
|
||||
<mstts:express-as role="OlderAdultMale" style="calm">
|
||||
“Writing a binary file in Python is similar to writing a regular text file, but you'll work with bytes instead of strings.”
|
||||
</mstts:express-as>
|
||||
"""
|
||||
path = WORKSPACE_ROOT / "tts"
|
||||
path.mkdir(exist_ok=True, parents=True)
|
||||
filename = path / "girl.wav"
|
||||
result = azure_tts.synthesize_speech(
|
||||
lang="zh-CN",
|
||||
voice="zh-CN-XiaomoNeural",
|
||||
text=text,
|
||||
output_file=str(filename))
|
||||
|
||||
print(result)
|
||||
|
||||
# 运行需要先配置 SUBSCRIPTION_KEY
|
||||
# TODO: 这里如果要检验,还要额外加上对应的asr,才能确保前后生成是接近一致的,但现在还没有
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_azure_tts()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue