feat: + uml fork style role demo

This commit is contained in:
莘权 马 2023-08-07 21:12:27 +08:00
parent 80a189ad4a
commit 5702aaa5ad
11 changed files with 543 additions and 128 deletions

View file

@ -0,0 +1,40 @@
# Pattern Configuration Template
# Created By: mashenquan, 2023-8-7
# File Name: template.yaml
# This template defines a set of structural standards for generating roles and action flows based on configurations.
# For more about UML 2.0 activity diagrams, see: `https://www.uml-diagrams.org/activity-diagrams.html`
# project settings
startup:
requirement: "TeachingPlanRequirement" # Defines project initial requirement action
role: "Teacher" # Defines project role
investment: 3.0 # Defines the max project investment
n_round: 1 # Defines the max project round count
# roles settings
roles: # A project can involve multiple roles.
- role_type: "fork" # `fork` type role corresponds to the functional positioning of the `fork` node in UML 2.0 activity diagrams.
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 ..."
desc: ""
output_filename: "teaching_plan_demo.md"
requirement: ["TeachingPlanRequirement"]
templates: # The template provides a convenient way to generate prompts. After each action selects its respective template, you only need to provide the corresponding variable values. Variable replacement is automatically handled by the framework.
- "Do ..."
- "Do ..."
# role's action settings
actions: # A role can have multiple actions.
- name: ""
topic: "Title"
language: "Chinese"
statements: # When replacing template variables, multiple statements will be joined into a single string using line breaks.
- "Statement: Find and return ..."
template_ix: 0
rsp_begin_tag: "[..._BEGIN]" # When asking, request the LLM to include the tag in the response. It's optional.
rsp_end_tag: "[..._END]" # When asking, request the LLM to include the tag in the response. It's optional.

View file

@ -1,51 +1,124 @@
# `fork` role demo
- role_type: "fork"
# The `fork` role demo implements the flow of the code in `examples/write_teaching_plan.py`.
# project settings
startup:
requirement: "TeachingPlanRequirement" # Defines project initial requirement action
role: "Teacher"
investment: 3.0
n_round: 1
# roles settings
roles: # A project can involve multiple roles.
- role_type: "fork" # `fork` type role corresponds to the functional positioning of the `fork` node in UML 2.0 activity diagrams.
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: ""
actions:
output_filename: "teaching_plan_demo.md"
requirement: ["TeachingPlanRequirement"]
templates: # The template provides a convenient way to generate prompts. After each action selects its respective template, you only need to provide the corresponding variable values. Variable replacement is automatically handled by the framework.
- "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: # 一个role可以有多个action
- name: ""
topic: "Title"
language: "Chinese"
statements:
- "Statement: Find and return the title of the lesson only in markdown first-level header format, without anything else."
statements: # When replacing template variables, multiple statements will be joined into a single string using line breaks.
- "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]" # When asking, request the LLM to include the tag in the response. It's optional.
rsp_end_tag: "[TEACHING_PLAN_END]" # When asking, request the LLM to include the tag in the response. It's optional.
- name: ""
topic: "Teaching Objectives"
language: "Chinese"
statements: []
template_ix: 1
rsp_begin_tag: "[TEACHING_PLAN_BEGIN]"
rsp_end_tag: "[TEACHING_PLAN_END]"
- name: ""
topic: "Teaching Content"
language: "Chinese"
statements:
- "Statement: \"Teaching Content\" must include vocabulary, analysis, and examples of various grammar structures that appear in the textbook, as well as the listening materials and key points."
- "Statement: \"Teaching Content\" must include more examples."
- name: ""
topic: "Teaching Time Allocation"
language: "Chinese"
statements:
- "Statement: \"Teaching Time Allocation\" must include how much time is allocated to each part of the textbook content."
template_ix: 1
rsp_begin_tag: "[TEACHING_PLAN_BEGIN]"
rsp_end_tag: "[TEACHING_PLAN_END]"
- name: ""
topic: "Teaching Methods and Strategies"
language: "Chinese"
statements:
- "Statement: \"Teaching Methods and Strategies\" must include teaching focus, difficulties, materials, procedures, in detail."
template_ix: 1
rsp_begin_tag: "[TEACHING_PLAN_BEGIN]"
rsp_end_tag: "[TEACHING_PLAN_END]"
- name: ""
topic: "Learning Activities"
language: "Chinese"
statements: []
template_ix: 1
rsp_begin_tag: "[TEACHING_PLAN_BEGIN]"
rsp_end_tag: "[TEACHING_PLAN_END]"
- name: ""
topic: "Teaching Time Allocation"
language: "Chinese"
statements:
- "Statement: \"Teaching Time Allocation\" must include how much time is allocated to each part of the textbook content."
template_ix: 1
rsp_begin_tag: "[TEACHING_PLAN_BEGIN]"
rsp_end_tag: "[TEACHING_PLAN_END]"
- name: ""
topic: "Assessment and Feedback"
language: "Chinese"
statements: []
template_ix: 1
rsp_begin_tag: "[TEACHING_PLAN_BEGIN]"
rsp_end_tag: "[TEACHING_PLAN_END]"
- name: ""
topic: "Teaching Summary and Improvement"
language: "Chinese"
statements: []
template_ix: 1
rsp_begin_tag: "[TEACHING_PLAN_BEGIN]"
rsp_end_tag: "[TEACHING_PLAN_END]"
- name: ""
topic: "Vocabulary Cloze"
language: "Chinese"
statements:
- "Statement: Based on the content of the textbook enclosed by \"[LESSON_BEGIN]\" and \"[LESSON_END]\", create vocabulary cloze. The cloze should include 10 {language} questions with {teaching_language} answers, and it should also include 10 {teaching_language} questions with {language} answers. The key-related vocabulary and phrases in the textbook content must all be included in the exercises."
- name: ""
topic: "Grammar Questions"
language: "Chinese"
statements:
- "Statement: Based on the content of the textbook enclosed by \"[LESSON_BEGIN]\" and \"[LESSON_END]\", create grammar questions. 10 questions."
template_ix: 1
rsp_begin_tag: "[TEACHING_PLAN_BEGIN]"
rsp_end_tag: "[TEACHING_PLAN_END]"
- name: ""
topic: "Choice Questions"
language: "Chinese"
statements:
- "Statement: Based on the content of the textbook enclosed by \"[LESSON_BEGIN]\" and \"[LESSON_END]\", create choice questions. 10 questions."
template_ix: 1
rsp_begin_tag: "[TEACHING_PLAN_BEGIN]"
rsp_end_tag: "[TEACHING_PLAN_END]"
- name: ""
topic: "Grammar Questions"
language: "Chinese"
statements:
- "Statement: Based on the content of the textbook enclosed by \"[LESSON_BEGIN]\" and \"[LESSON_END]\", create grammar questions. 10 questions."
template_ix: 1
rsp_begin_tag: "[TEACHING_PLAN_BEGIN]"
rsp_end_tag: "[TEACHING_PLAN_END]"
- name: ""
topic: "Translation Questions"
language: "Chinese"
statements:
- "Statement: Based on the content of the textbook enclosed by \"[LESSON_BEGIN]\" and \"[LESSON_END]\", create translation questions. The translation should include 10 {language} questions with {teaching_language} answers, and it should also include 10 {teaching_language} questions with {language} answers."
template_ix: 1
rsp_begin_tag: "[TEACHING_PLAN_BEGIN]"
rsp_end_tag: "[TEACHING_PLAN_END]"

121
examples/fork_meta_role.py Normal file
View file

@ -0,0 +1,121 @@
#!/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 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 is not None 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)
roles = UMLMetaRoleFactory.create_roles(startup_config.roles, **kwargs)
company = SoftwareCompany()
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

@ -0,0 +1,61 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@Time : 2023/8/7
@Author : mashenquan
@File : meta_action.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 meta action capable of generating arbitrary actions at runtime based on a
configuration file.
"""
from typing import Type
from metagpt.actions import Action
from metagpt.logs import logger
from metagpt.roles.uml_meta_role_options import MetaActionOptions
from metagpt.schema import Message
class MetaAction(Action):
def __init__(self, options: MetaActionOptions, llm=None, **kwargs):
super(MetaAction, self).__init__(options.name, kwargs.get("context"), llm=llm)
self.prompt = options.format_prompt(**kwargs)
self.options = options
self.kwargs = kwargs
def __str__(self):
"""Return `topic` value when str()"""
return self.options.topic
def __repr__(self):
"""Show `topic` value when debug"""
return self.options.topic
async def run(self, messages, *args, **kwargs):
if len(messages) < 1 or not isinstance(messages[0], Message):
raise ValueError("Invalid args, a tuple of List[Message] is expected")
logger.debug(self.prompt)
rsp = await self._aask(prompt=self.prompt)
logger.debug(rsp)
self._set_result(rsp)
return self.rsp
def _set_result(self, rsp):
if self.options.rsp_begin_tag and self.options.rsp_begin_tag in rsp:
ix = rsp.index(self.options.rsp_begin_tag)
rsp = rsp[ix + len(self.options.rsp_begin_tag):]
if self.options.rsp_end_tag and self.options.rsp_end_tag in rsp:
ix = rsp.index(self.options.rsp_end_tag)
rsp = rsp[0:ix]
self.rsp = rsp.strip()
@staticmethod
def get_action_type(topic: str):
"""Create a runtime :class:`Action` subclass"""
action_type: Type["Action"] = type(topic, (Action,), {"name": topic})
return action_type

View file

@ -4,6 +4,8 @@
@Time : 2023/5/20 12:15
@Author : alexanderwu
@File : memory.py
@Modified By: mashenquan, 2023-8-7. Modified get_by_actions() to support for dynamically generated Action classes
at runtime.
"""
from collections import defaultdict
from typing import Iterable, Type
@ -80,8 +82,12 @@ class Memory:
def get_by_actions(self, actions: Iterable[Type[Action]]) -> list[Message]:
"""Return all messages triggered by specified Actions"""
rsp = []
# Using the `type(obj).__name__` approach to support the runtime creation of requirement classes.
# See `MetaAction.get_action_type()` for more.
class_names = {type(k).__name__: k for k in self.index.keys()}
for action in actions:
if action not in self.index:
if type(action).__name__ not in class_names:
continue
rsp += self.index[action]
key = class_names[type(action).__name__]
rsp += self.index[key]
return rsp

View file

@ -4,95 +4,124 @@
@Time : 2023/8/7
@Author : mashenquan
@File : fork_meta_role.py
@Desc : 我试图将UML的一些符号概念引入到MetaGPT使其具备通过符号拼接自由搭建flow的能力同时我也尝试将这些符号做得配置化和标准化让flow搭建流程更便捷这是一个`fork` meta-role demo实现的是write_teaching_plan功能
@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.
"""
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
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."""
class ForkMetaRole(Role):
"""A `fork` style meta role capable of generating arbitrary roles at runtime based on a configuration file"""
def __init__(self, options, **kwargs):
"""Initialize a `fork` style meta role
demo_lesson = """
UNIT 1 Making New Friends
TOPIC 1 Welcome to China!
Section A
:param 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(**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
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.
super(ForkMetaRole, self).__init__(
name=global_variables["name"],
profile=global_variables["profile"],
goal=global_variables["goal"],
constraints=global_variables["constraints"],
desc=global_variables["desc"],
**kwargs
)
self.options = options
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
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
o = MetaActionOptions(**m)
o.set_default_template(opts.templates[o.template_ix])
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.
act = MetaAction(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)
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: ...
async def _think(self) -> None:
"""Everything will be done part by part."""
if self._rc.todo is None:
self._set_state(0)
return
3a Listen, say and trace
Aa Bb Cc Dd Ee Ff Gg
if self._rc.state + 1 < len(self._states):
self._set_state(self._rc.state + 1)
else:
self._rc.todo = None
3b Listen and number the following letters. Then circle the letters with the same sound as Bb.
Aa Bb Cc Dd Ee Ff Gg
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
3c Match the big letters with the small ones. Then write them on the lines.
"""
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}")
lesson = ""
if lesson_file is not None 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
company = SoftwareCompany()
company.hire([(*args, **kwargs)])
company.invest(investment)
company.start_project(lesson, role="Teacher", cause_by=TeachingPlanRequirement)
await company.run(n_round=1)
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)
@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,29 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@Time : 2023/8/7
@Author : mashenquan
@File : meta_role.py
@Desc : 我试图将UML的一些符号概念引入到MetaGPT使其具备通过符号拼接自由搭建flow的能力同时我也尝试将这些符号做得配置化和标准化让flow搭建流程更便捷
分工参照UML 2.0 activity diagrams: `https://www.uml-diagrams.org/activity-diagrams.html`
"""
from typing import Dict, List
from metagpt.roles import Role
from pydantic import BaseModel
class UMLMetaRoleArgs(BaseModel):
role_type: str
name: str = ""
profile: str = ""
goal: str = ""
constraints: str = ""
desc: str = ""
actions: List
class UMLMetaRole(Role):
"""UML activity roles抽象父类"""
def __init__(self, role_args: Dict):
""""""
self.role_args

View file

@ -4,7 +4,7 @@
@Time : 2023/5/11 14:42
@Author : alexanderwu
@File : role.py
@Modified By: mashenquan, 2023-07-27, :class:`Role` + properties.
@Modified By: mashenquan, 2023-8-7, :class:`Role` + properties.
"""
from __future__ import annotations
@ -286,6 +286,8 @@ class Role:
@staticmethod
def format_value(value, options):
"""Fill parameters inside `value` with `options`."""
if not isinstance(value, str):
return value
if "{" not in value:
return value
@ -295,7 +297,7 @@ class Role:
except KeyError as e:
logger.warning(f"Parameter is missing:{e}")
for k, v in options.items():
value = value.replace("{" + f"{k}" + "}", v)
value = value.replace("{" + f"{k}" + "}", str(v))
return value
__DEFAULT_OPTIONS__ = {

View file

@ -5,7 +5,7 @@
@Author : mashenquan
@File : teacher.py
"""
from pathlib import Path
import aiofiles

View file

@ -0,0 +1,43 @@
#!/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(m, **kwargs)
roles.append(r)
return roles
CONSTRUCTORS = {
"fork": ForkMetaRole,
# TODO: add more activity node constructor here..
}

View file

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