MetaGPT 教学助手:一键生成技术教程 2024-06-19 作者 C3P00 在学习新技术时,一份好的教程可以事半功倍。MetaGPT 的教学助手角色,可以帮助你根据简单的描述,自动生成技术教程文档。 教学助手的功能 教学助手可以根据用户提供的单句描述,生成一份技术教程文档,并支持自定义语言。 设计理念 教学助手的设计思路是: 使用大型语言模型 (LLM) 生成教程的大纲。 根据二级标题将大纲分解成多个部分。 针对每个部分,根据标题生成详细内容。 最后将标题和内容拼接起来。 使用分段的方式,可以解决 LLM 模型处理长文本的限制。 代码实现 角色定义 定义教学助手角色类,继承自 Role 基类,并重写 __init__ 初始化方法。__init__ 方法必须包含 name、profile、goal 和 constraints 参数。第一行代码使用 super().__init__(name, profile, goal, constraints) 调用父类的构造函数,初始化 Role。使用 self.set_actions([WriteDirectory(language=language)]) 添加初始动作和状态。这里,最初添加了写目录动作。此外,还可以定义自定义参数;这里添加了 language 参数,用于支持自定义语言。使用 self._set_react_mode(react_mode="by_order") 将 set_actions 中的动作执行顺序设置为顺序执行。 class TutorialAssistant(Role): """教学助手,输入一句话生成一份标记格式的教程文档。 Args: name: 角色名称。 profile: 角色简介。 goal: 角色目标。 constraints: 角色的约束或要求。 language: 生成教程文档的语言。 """ def __init__( self, name: str = "Stitch", profile: str = "教学助手", goal: str = "生成教程文档", constraints: str = "严格遵循 Markdown 语法,布局整洁规范", language: str = "Chinese", ): super().__init__(name, profile, goal, constraints) self.set_actions([WriteDirectory(language=language)]) self.topic = "" self.main_title = "" self.total_content = "" self.language = language self._set_react_mode(react_mode="by_order") 重写 react 方法 重写 react 方法。使用 await super().react() 调用 Role 基类的 react 方法。根据 __init__ 方法中设置的 react_mode="by_order",按顺序执行 states 中的每个动作。这里重写的目的是在完成所有动作后执行最终操作,即:将拼接后的教程内容写入 markdown 文件。 async def react(self) -> Message: msg = await super().react() root_path = TUTORIAL_PATH / datetime.now().strftime("%Y-%m-%d_%H-%M-%S") await File.write(root_path, f"{self.main_title}.md", self.total_content.encode('utf-8')) return msg 重写 _act 方法 _act 方法负责执行动作。使用 todo = self.rc.todo 从上下文中获取下一个要执行的动作,然后执行动作的 run 方法。这里,它首先通过 WriteDirectory 获取教程目录结构,然后对目录进行分块,为每个块生成一个 WriteContent 动作,并初始化新添加的动作。这里再次调用 await super().react() 是为了从头开始执行所有新添加的 WriteContent 动作。每个动作的结果用于生成一个 Message(content=resp, role=self.profile) 消息,该消息可以放置在上下文记忆 self.rc.memory 中。该角色不需要存储。 async def _act(self) -> Message: todo = self.rc.todo if type(todo) is WriteDirectory: msg = self.rc.memory.get(k=1)[0] self.topic = msg.content resp = await todo.run(topic=self.topic) logger.info(resp) await self._handle_directory(resp) return await super().react() resp = await todo.run(topic=self.topic) logger.info(resp) if self.total_content != "": self.total_content += "\n\n\n" self.total_content += resp return Message(content=resp, role=self.profile) async def _handle_directory(self, titles: Dict) -> Message: """处理教程文档的目录。 Args: titles: 包含标题和目录结构的字典, 例如 {"title": "xxx", "directory": [{"dir 1": ["sub dir 1", "sub dir 2"]}]} Returns: 包含目录信息的 Message。 """ self.main_title = titles.get("title") directory = f"{self.main_title}\n" self.total_content += f"# {self.main_title}" actions = list() for first_dir in titles.get("directory"): actions.append(WriteContent(language=self.language, directory=first_dir)) key = list(first_dir.keys())[0] directory += f"- {key}\n" for second_dir in first_dir[key]: directory += f" - {second_dir}\n" self.set_actions(actions) 动作定义 定义动作,每个动作对应一个类对象。继承自 Action 基类,并重写 __init__ 初始化方法。__init__ 方法包含 name 参数。第一行代码使用 super().__init__(name, *args, **kwargs) 调用父类的构造函数,初始化动作。这里,使用 args 和 kwargs 将其他参数传递给父类构造函数,例如 context 和 llm。 #!/usr/bin/env python3 # _*_ coding: utf-8 _*_ """ @Time : 2023/9/4 15:40:40 @Author : Stitch-z @File : tutorial_assistant.py @Describe : Actions of the tutorial assistant, including writing directories and document content. """ from typing import Dict from metagpt.actions import Action from metagpt.prompts.tutorial_assistant import DIRECTORY_PROMPT, CONTENT_PROMPT from metagpt.utils.common import OutputParser class WriteDirectory(Action): """写教程目录的动作类。 Args: name: 动作名称。 language: 输出语言,默认值为 "Chinese"。 """ def __init__(self, name: str = "", language: str = "Chinese", *args, **kwargs): super().__init__(name, *args, **kwargs) self.language = language 重写 run 方法 run 方法是动作执行的主要函数,使用 self._aask(prompt=prompt) 方法查询 LLM 模型。 async def run(self, topic: str, *args, **kwargs) -> Dict: """执行动作,根据主题生成教程目录。 Args: topic: 教程主题。 Returns: 教程目录信息,包括 {"title": "xxx", "directory": [{"dir 1": ["sub dir 1", "sub dir 2"]}]}。 """ prompt = DIRECTORY_PROMPT.format(topic=topic, language=self.language) resp = await self._aask(prompt=prompt) return OutputParser.extract_struct(resp, dict) 其他动作的编写类似: class WriteContent(Action): """写教程内容的动作类。 Args: name: 动作名称。 directory: 要写入的内容。 language: 输出语言,默认值为 "Chinese"。 """ def __init__(self, name: str = "", directory: str = "", language: str = "Chinese", *args, **kwargs): super().__init__(name, *args, **kwargs) self.language = language self.directory = directory async def run(self, topic: str, *args, **kwargs) -> str: """执行动作,根据目录和主题写入文档内容。 Args: topic: 教程主题。 Returns: 写入的教程内容。 """ prompt = CONTENT_PROMPT.format(topic=topic, language=self.language, directory=self.directory) return await self._aask(prompt=prompt) 角色执行结果 输入示例 MySQL 教程 Redis 教程 Hive 教程 执行命令示例 提供相应的执行命令示例。 执行结果 生成的教程文档位于项目的 /data/tutorial_docx 目录中。 注意: 该角色目前不支持互联网搜索功能。内容生成依赖于 LLM 大模型训练的数据。 总结 MetaGPT 的教学助手角色可以帮助你快速生成技术教程文档,并支持自定义语言。它可以节省你大量时间和精力,让你专注于更重要的工作。 更多学习资源 MetaGPT 文档:了解更多关于 MetaGPT 的信息。 MetaGPT Github:查看 MetaGPT 的源代码和示例。 MetaGPT 论文:深入了解 MetaGPT 的技术细节。
在学习新技术时,一份好的教程可以事半功倍。MetaGPT 的教学助手角色,可以帮助你根据简单的描述,自动生成技术教程文档。
教学助手的功能
教学助手可以根据用户提供的单句描述,生成一份技术教程文档,并支持自定义语言。
设计理念
教学助手的设计思路是:
使用分段的方式,可以解决 LLM 模型处理长文本的限制。
代码实现
角色定义
定义教学助手角色类,继承自
Role
基类,并重写__init__
初始化方法。__init__
方法必须包含name
、profile
、goal
和constraints
参数。第一行代码使用super().__init__(name, profile, goal, constraints)
调用父类的构造函数,初始化Role
。使用self.set_actions([WriteDirectory(language=language)])
添加初始动作和状态。这里,最初添加了写目录动作。此外,还可以定义自定义参数;这里添加了language
参数,用于支持自定义语言。使用self._set_react_mode(react_mode="by_order")
将set_actions
中的动作执行顺序设置为顺序执行。重写
react
方法重写
react
方法。使用await super().react()
调用Role
基类的react
方法。根据__init__
方法中设置的react_mode="by_order"
,按顺序执行states
中的每个动作。这里重写的目的是在完成所有动作后执行最终操作,即:将拼接后的教程内容写入 markdown 文件。重写
_act
方法_act
方法负责执行动作。使用todo = self.rc.todo
从上下文中获取下一个要执行的动作,然后执行动作的run
方法。这里,它首先通过WriteDirectory
获取教程目录结构,然后对目录进行分块,为每个块生成一个WriteContent
动作,并初始化新添加的动作。这里再次调用await super().react()
是为了从头开始执行所有新添加的WriteContent
动作。每个动作的结果用于生成一个Message(content=resp, role=self.profile)
消息,该消息可以放置在上下文记忆self.rc.memory
中。该角色不需要存储。动作定义
定义动作,每个动作对应一个类对象。继承自
Action
基类,并重写__init__
初始化方法。__init__
方法包含name
参数。第一行代码使用super().__init__(name, *args, **kwargs)
调用父类的构造函数,初始化动作。这里,使用args
和kwargs
将其他参数传递给父类构造函数,例如context
和llm
。重写
run
方法run
方法是动作执行的主要函数,使用self._aask(prompt=prompt)
方法查询 LLM 模型。其他动作的编写类似:
角色执行结果
输入示例
执行命令示例
提供相应的执行命令示例。
执行结果
生成的教程文档位于项目的
/data/tutorial_docx
目录中。注意:
该角色目前不支持互联网搜索功能。内容生成依赖于 LLM 大模型训练的数据。
总结
MetaGPT 的教学助手角色可以帮助你快速生成技术教程文档,并支持自定义语言。它可以节省你大量时间和精力,让你专注于更重要的工作。
更多学习资源