feat: 删掉meta role相关代码

This commit is contained in:
莘权 马 2023-08-26 22:08:45 +08:00
parent cc89f3b726
commit 2574ecaecf
9 changed files with 0 additions and 623 deletions

View file

@ -1,126 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@Time : 2023/8/7
@Author : mashenquan
@File : fork_meta_role.py
@Desc : I am attempting to incorporate certain symbol concepts from UML into MetaGPT, enabling it to possess the
ability to construct flows freely by concatenating symbols. Simultaneously, I am also striving to make
these symbols configurable and standardized, making the process of building flow structures more
convenient. This is a fork meta-role demo that implements the functionality of
`examples/write_teaching_plan.py`.
"""
import asyncio
from pathlib import Path
import sys
sys.path.append(str(Path(__file__).resolve().parent.parent))
import aiofiles
import fire
import yaml
from metagpt.actions.meta_action import MetaAction
from metagpt.logs import logger
from metagpt.roles.uml_meta_role_factory import UMLMetaRoleFactory
from metagpt.roles.uml_meta_role_options import ProjectConfig
from metagpt.software_company import SoftwareCompany
async def startup(lesson_file: str, investment: float = 3.0, n_round: int = 1, *args, **kwargs):
"""Run a startup. Be a teacher in education industry."""
demo_lesson = """
UNIT 1 Making New Friends
TOPIC 1 Welcome to China!
Section A
1a Listen and number the following names.
Jane Mari Kangkang Michael
Look, listen and understand. Then practice the conversation.
Work in groups. Introduce yourself using
I m ... Then practice 1a
with your own hometown or the following places.
1b Listen and number the following names
Jane Michael Maria Kangkang
1c Work in groups. Introduce yourself using I m ... Then practice 1a with your own hometown or the following places.
China the USA the UK Hong Kong Beijing
2a Look, listen and understand. Then practice the conversation
Hello!
Hello!
Hello!
Hello! Are you Maria?
No, Im not. Im Jane.
Oh, nice to meet you, Jane
Nice to meet you, too.
Hi, Maria!
Hi, Kangkang!
Welcome to China!
Thanks.
2b Work in groups. Make up a conversation with your own name and the
following structures.
A: Hello! / Good morning! / Hi! Im ... Are you ... ?
B: ...
3a Listen, say and trace
Aa Bb Cc Dd Ee Ff Gg
3b Listen and number the following letters. Then circle the letters with the same sound as Bb.
Aa Bb Cc Dd Ee Ff Gg
3c Match the big letters with the small ones. Then write them on the lines.
"""
lesson = ""
if lesson_file and Path(lesson_file).exists():
async with aiofiles.open(lesson_file, mode="r", encoding="utf-8") as reader:
lesson = await reader.read()
logger.info(f"Course content: {lesson}")
if not lesson:
logger.info("No course content provided, using the demo course.")
lesson = demo_lesson
yaml_filename = kwargs["config"]
kwargs["lesson"] = lesson
with open(yaml_filename, "r") as reader:
configs = yaml.safe_load(reader)
startup_config = ProjectConfig(**configs)
company = SoftwareCompany()
roles = UMLMetaRoleFactory.create_roles(role_configs=startup_config.roles,
options=company.options,
cost_manager=company.cost_manager,
**kwargs)
company.hire(roles)
company.invest(startup_config.startup.investment)
company.start_project(lesson, role=startup_config.startup.role,
cause_by=MetaAction.get_action_type(startup_config.startup.requirement))
await company.run(n_round=startup_config.startup.n_round)
def main(idea: str, investment: float = 3.0, n_round: int = 5, *args, **kwargs):
"""
We are a software startup comprised of AI. By investing in us, you are empowering a future filled with limitless possibilities.
:param idea: lesson filename.
:param investment: As an investor, you have the opportunity to contribute a certain dollar amount to this AI company.
:param n_round: Reserved.
:param args: Parameters passed in format: `python your_script.py arg1 arg2 arg3`
:param kwargs: Parameters passed in format: `python your_script.py --param1=value1 --param2=value2`
:return:
"""
asyncio.run(startup(idea, investment, n_round, *args, **kwargs))
if __name__ == '__main__':
"""
Formats:
```
python write_teaching_plan.py lesson_filename --teaching_language=<the language you are teaching> --language=<your native language>
```
If `lesson_filename` is not available, a demo lesson content will be used.
"""
fire.Fire(main)

View file

@ -396,9 +396,6 @@ class OpenAIGPTAPI(BaseGPTAPI, RateLimiter):
logger.warning(f"Exception:{e}, sleeping for {rounded_time} seconds")
await asyncio.sleep(rounded_time)
continue
except openai.error.APIConnectionError as e:
logger.warning(f"Exception:{e}")
continue
except Exception as e:
error_str = traceback.format_exc()
logger.error(f"Exception:{e}, stack:{error_str}")
@ -414,9 +411,6 @@ class OpenAIGPTAPI(BaseGPTAPI, RateLimiter):
except openai.error.RateLimitError as e:
logger.warning(f"Exception:{e}")
continue
except openai.error.APIConnectionError as e:
logger.warning(f"Exception:{e}")
continue
except Exception as e:
error_str = traceback.format_exc()
logger.error(f"Exception:{e}, stack:{error_str}")

View file

@ -1,133 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@Time : 2023/8/7
@Author : mashenquan
@File : fork_meta_role.py
@Desc : I am attempting to incorporate certain symbol concepts from UML into MetaGPT, enabling it to have the
ability to freely construct flows through symbol concatenation. Simultaneously, I am also striving to
make these symbols configurable and standardized, making the process of building flows more convenient.
For more about `fork` node in activity diagrams, see: `https://www.uml-diagrams.org/activity-diagrams.html`
This file defines a `fork` style meta role capable of generating arbitrary roles at runtime based on a
configuration file.
@Modified By: mashenquan, 2023/8/22. A definition has been provided for the return value of _think: returning false indicates that further reasoning cannot continue.
"""
import re
import aiofiles
from metagpt.actions.meta_action import MetaAction
from metagpt.const import WORKSPACE_ROOT
from metagpt.logs import logger
from metagpt.roles import Role
from metagpt.roles.uml_meta_role_options import MetaActionOptions, UMLMetaRoleOptions
from metagpt.schema import Message
class ForkMetaRole(Role):
"""A `fork` style meta role capable of generating arbitrary roles at runtime based on a configuration file"""
def __init__(self, options, cost_manager, role_options, **kwargs):
"""Initialize a `fork` style meta role
:param options: System configuration
:param cost_manager: Cost manager
:param role_options: pattern yaml file data
:param args: Parameters passed in format: `python your_script.py arg1 arg2 arg3`
:param kwargs: Parameters passed in format: `python your_script.py --param1=value1 --param2=value2`
"""
opts = UMLMetaRoleOptions(**role_options)
global_variables = {
"name": Role.format_value(opts.name, kwargs),
"profile": Role.format_value(opts.profile, kwargs),
"goal": Role.format_value(opts.goal, kwargs),
"constraints": Role.format_value(opts.constraints, kwargs),
"desc": Role.format_value(opts.desc, kwargs),
"role": Role.format_value(opts.role, kwargs)
}
for k, v in kwargs.items():
if k not in global_variables:
global_variables[k] = v
super(ForkMetaRole, self).__init__(
options=options,
cost_manager=cost_manager,
name=global_variables["name"],
profile=global_variables["profile"],
goal=global_variables["goal"],
constraints=global_variables["constraints"],
desc=global_variables["desc"],
**kwargs
)
actions = []
for m in opts.actions:
for k, v in m.items():
v = Role.format_value(v, kwargs)
m[k] = v
for k, v in global_variables.items():
if k not in m:
m[k] = v
o = MetaActionOptions(**m)
o.set_default_template(opts.templates[o.template_ix])
act = MetaAction(options=options, action_options=o, llm=self._llm, **m)
actions.append(act)
self._init_actions(actions)
requirement_types = set()
for v in opts.requirement:
requirement_types.add(MetaAction.get_action_type(v))
self._watch(requirement_types)
async def _think(self) -> None:
"""Everything will be done part by part."""
if self._rc.todo is None:
self._set_state(0)
return True
if self._rc.state + 1 < len(self._states):
self._set_state(self._rc.state + 1)
else:
self._rc.todo = None
return False
async def _react(self) -> Message:
ret = Message(content="")
while True:
await self._think()
if self._rc.todo is None:
break
logger.debug(f"{self._setting}: {self._rc.state=}, will do {self._rc.todo}")
msg = await self._act()
if ret.content != '':
ret.content += "\n\n\n"
ret.content += msg.content
logger.info(ret.content)
await self.save(ret.content)
return ret
async def save(self, content):
"""Save teaching plan"""
output_filename = self.options.get("output_filename")
if not output_filename:
return
filename = ForkMetaRole.new_file_name(output_filename)
pathname = WORKSPACE_ROOT / "teaching_plan"
pathname.mkdir(exist_ok=True)
pathname = pathname / filename
try:
async with aiofiles.open(str(pathname), mode='w', encoding='utf-8') as writer:
await writer.write(content)
except Exception as e:
logger.error(f'Save failed{e}')
logger.info(f"Save to:{pathname}")
@staticmethod
def new_file_name(lesson_title, ext=".md"):
"""Create a related file name based on `lesson_title` and `ext`."""
# Define the special characters that need to be replaced.
illegal_chars = r'[#@$%!*&\\/:*?"<>|\n\t \']'
# Replace the special characters with underscores.
filename = re.sub(illegal_chars, '_', lesson_title) + ext
return re.sub(r'_+', '_', filename)

View file

@ -1,43 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@Time : 2023/8/7
@Author : mashenquan
@File : uml_meta_role_factory.py
@Desc : I am attempting to incorporate certain symbol concepts from UML into MetaGPT, enabling it to have the
ability to freely construct flows through symbol concatenation. Simultaneously, I am also striving to
make these symbols configurable and standardized, making the process of building flows more convenient.
For more about `fork` node in activity diagrams, see: `https://www.uml-diagrams.org/activity-diagrams.html`
"""
from metagpt.roles.fork_meta_role import ForkMetaRole
from metagpt.roles.uml_meta_role_options import UMLMetaRoleOptions
class UMLMetaRoleFactory:
"""Factory of UML activity role classes"""
@classmethod
def create_roles(cls, role_configs, **kwargs):
"""Generate the flow of the project based on the configuration in the format of config/pattern/template.yaml.
:param role_configs: `roles` field of template.yaml
:param kwargs: Parameters passed in format: `python your_script.py --param1=value1 --param2=value2`
"""
roles = []
for m in role_configs:
opt = UMLMetaRoleOptions(**m)
constructor = cls.CONSTRUCTORS.get(opt.role_type)
if constructor is None:
raise NotImplementedError(
f"{opt.role_type} is not implemented"
)
r = constructor(role_options=m, **kwargs)
roles.append(r)
return roles
CONSTRUCTORS = {
"fork": ForkMetaRole,
# TODO: add more activity node constructor here..
}

View file

@ -1,69 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@Time : 2023/8/7
@Author : mashenquan
@File : uml_meta_role_options.py
@Desc : I am attempting to incorporate certain symbol concepts from UML into MetaGPT, enabling it to have the
ability to freely construct flows through symbol concatenation. Simultaneously, I am also striving to
make these symbols configurable and standardized, making the process of building flows more convenient.
For more about `fork` node in activity diagrams, see: `https://www.uml-diagrams.org/activity-diagrams.html`
"""
from typing import List, Dict
from pydantic import BaseModel
# `startup` field of config/pattern/template.yaml
class StartupConfig(BaseModel):
requirement: str
role: str
investment: float = 3.0
n_round: int = 3
# config/pattern/template.yaml
class ProjectConfig(BaseModel):
startup: StartupConfig
roles: List[Dict]
# element of `actions` field of config/pattern/template.yaml
class MetaActionOptions(BaseModel):
topic: str
name: str = ""
language: str = "Chinese"
template_ix: int = 0
statements: List[str] = []
template: str = ""
rsp_begin_tag: str = ""
rsp_end_tag: str = ""
def set_default_template(self, v):
if not self.template:
self.template = v
def format_prompt(self, **kwargs):
statements = "\n".join(self.statements)
opts = kwargs.copy()
opts["statements"] = statements
from metagpt.roles import Role
prompt = Role.format_value(self.template, opts)
return prompt
# element of `roles` field of config/pattern/template.yaml
class UMLMetaRoleOptions(BaseModel):
role_type: str
name: str = ""
profile: str = ""
goal: str = ""
role: str = ""
constraints: str = ""
desc: str = ""
templates: List[str] = []
output_filename: str = ""
actions: List
requirement: List

View file

@ -1,51 +0,0 @@
#!/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()

View file

@ -1,94 +0,0 @@
#!/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()

View file

@ -1,61 +0,0 @@
#!/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()

View file

@ -1,40 +0,0 @@
#!/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()