diff --git a/src/public/image/rfcs/rfc135/img.png b/src/public/image/rfcs/rfc135/img.png new file mode 100644 index 00000000..40cf8ba2 Binary files /dev/null and b/src/public/image/rfcs/rfc135/img.png differ diff --git a/src/public/image/rfcs/rfc135/img_1.png b/src/public/image/rfcs/rfc135/img_1.png new file mode 100644 index 00000000..db7862e5 Binary files /dev/null and b/src/public/image/rfcs/rfc135/img_1.png differ diff --git a/src/public/image/rfcs/rfc135/img_10.png b/src/public/image/rfcs/rfc135/img_10.png new file mode 100644 index 00000000..2025e33d Binary files /dev/null and b/src/public/image/rfcs/rfc135/img_10.png differ diff --git a/src/public/image/rfcs/rfc135/img_11.png b/src/public/image/rfcs/rfc135/img_11.png new file mode 100644 index 00000000..2d9fb7b3 Binary files /dev/null and b/src/public/image/rfcs/rfc135/img_11.png differ diff --git a/src/public/image/rfcs/rfc135/img_12.png b/src/public/image/rfcs/rfc135/img_12.png new file mode 100644 index 00000000..57950cbd Binary files /dev/null and b/src/public/image/rfcs/rfc135/img_12.png differ diff --git a/src/public/image/rfcs/rfc135/img_13.png b/src/public/image/rfcs/rfc135/img_13.png new file mode 100644 index 00000000..ac8edb05 Binary files /dev/null and b/src/public/image/rfcs/rfc135/img_13.png differ diff --git a/src/public/image/rfcs/rfc135/img_14.png b/src/public/image/rfcs/rfc135/img_14.png new file mode 100644 index 00000000..deb0ce28 Binary files /dev/null and b/src/public/image/rfcs/rfc135/img_14.png differ diff --git a/src/public/image/rfcs/rfc135/img_15.png b/src/public/image/rfcs/rfc135/img_15.png new file mode 100644 index 00000000..3f77ed48 Binary files /dev/null and b/src/public/image/rfcs/rfc135/img_15.png differ diff --git a/src/public/image/rfcs/rfc135/img_16.png b/src/public/image/rfcs/rfc135/img_16.png new file mode 100644 index 00000000..ed7cd987 Binary files /dev/null and b/src/public/image/rfcs/rfc135/img_16.png differ diff --git a/src/public/image/rfcs/rfc135/img_17.png b/src/public/image/rfcs/rfc135/img_17.png new file mode 100644 index 00000000..4f1f61c9 Binary files /dev/null and b/src/public/image/rfcs/rfc135/img_17.png differ diff --git a/src/public/image/rfcs/rfc135/img_18.png b/src/public/image/rfcs/rfc135/img_18.png new file mode 100644 index 00000000..a52ae16d Binary files /dev/null and b/src/public/image/rfcs/rfc135/img_18.png differ diff --git a/src/public/image/rfcs/rfc135/img_19.png b/src/public/image/rfcs/rfc135/img_19.png new file mode 100644 index 00000000..d7ca9678 Binary files /dev/null and b/src/public/image/rfcs/rfc135/img_19.png differ diff --git a/src/public/image/rfcs/rfc135/img_2.png b/src/public/image/rfcs/rfc135/img_2.png new file mode 100644 index 00000000..dbe441c9 Binary files /dev/null and b/src/public/image/rfcs/rfc135/img_2.png differ diff --git a/src/public/image/rfcs/rfc135/img_20.png b/src/public/image/rfcs/rfc135/img_20.png new file mode 100644 index 00000000..e927dccb Binary files /dev/null and b/src/public/image/rfcs/rfc135/img_20.png differ diff --git a/src/public/image/rfcs/rfc135/img_21.png b/src/public/image/rfcs/rfc135/img_21.png new file mode 100644 index 00000000..9adf73e7 Binary files /dev/null and b/src/public/image/rfcs/rfc135/img_21.png differ diff --git a/src/public/image/rfcs/rfc135/img_22.png b/src/public/image/rfcs/rfc135/img_22.png new file mode 100644 index 00000000..e2deec22 Binary files /dev/null and b/src/public/image/rfcs/rfc135/img_22.png differ diff --git a/src/public/image/rfcs/rfc135/img_3.png b/src/public/image/rfcs/rfc135/img_3.png new file mode 100644 index 00000000..796b5167 Binary files /dev/null and b/src/public/image/rfcs/rfc135/img_3.png differ diff --git a/src/public/image/rfcs/rfc135/img_4.png b/src/public/image/rfcs/rfc135/img_4.png new file mode 100644 index 00000000..ef31e390 Binary files /dev/null and b/src/public/image/rfcs/rfc135/img_4.png differ diff --git a/src/public/image/rfcs/rfc135/img_5.png b/src/public/image/rfcs/rfc135/img_5.png new file mode 100644 index 00000000..1b4e9d71 Binary files /dev/null and b/src/public/image/rfcs/rfc135/img_5.png differ diff --git a/src/public/image/rfcs/rfc135/img_6.png b/src/public/image/rfcs/rfc135/img_6.png new file mode 100644 index 00000000..2442a6ad Binary files /dev/null and b/src/public/image/rfcs/rfc135/img_6.png differ diff --git a/src/public/image/rfcs/rfc135/img_7.png b/src/public/image/rfcs/rfc135/img_7.png new file mode 100644 index 00000000..53d3d263 Binary files /dev/null and b/src/public/image/rfcs/rfc135/img_7.png differ diff --git a/src/public/image/rfcs/rfc135/img_8.png b/src/public/image/rfcs/rfc135/img_8.png new file mode 100644 index 00000000..b9c3435f Binary files /dev/null and b/src/public/image/rfcs/rfc135/img_8.png differ diff --git a/src/public/image/rfcs/rfc135/img_9.png b/src/public/image/rfcs/rfc135/img_9.png new file mode 100644 index 00000000..4cdb5b9b Binary files /dev/null and b/src/public/image/rfcs/rfc135/img_9.png differ diff --git "a/src/rfcs/RFC-116-MetaGPT\344\274\230\345\214\226\346\226\271\346\241\210.md" "b/src/rfcs/RFC-116-MetaGPT\344\274\230\345\214\226\346\226\271\346\241\210.md" index 904a4a98..45c728e8 100644 --- "a/src/rfcs/RFC-116-MetaGPT\344\274\230\345\214\226\346\226\271\346\241\210.md" +++ "b/src/rfcs/RFC-116-MetaGPT\344\274\230\345\214\226\346\226\271\346\241\210.md" @@ -1,289 +1,301 @@ -# [T]RFC-116-MetaGPT优化方案 - -**文档负责人** :马莘权 - -1. 文档修改记录 - -| **日期** | **版本** | **作者** | **修改内容** | -| ---------- | -------- | -------- | -------------- | -| 2023-10-25 | v1 | 马莘权 | 创建 | -| 2023-11-3 | v2 | 马莘权 | 删掉无用的设计 | - - - -2. 文档审核状态 - -| **审核人** | **邀请日期** | **审核日期** | **评论** | -| ---------- | ------------ | ------------ | -------- | -| @洪思睿 | 2023-10-26 | 2023-10-30 | LGTM | -| @林义章 | 2023-10-30 | 2023-10-30 | | -| @王金淋 | 2023-10-30 | 2023-10-30 | | -| @吴承霖 | 2023-10-30 | 2023-10-30 | | -| @沈楚城 | 2023-10-26 | 2023-10-30 | LGTM | - - -## 1. 引言 -### 1.1 背景 - -鉴于MetaGPT框架已经在软件公司、狼人杀等场景得到应用,希望通过总结现有落地过程中发现的问题,来优化MetaGPT框架设计,以简化后续算法同学、第三方同学的开发工作,简化MetaGPT向Agent的迁移工作。 - - -### 1.2 目标 - -明确下一步的MetaGPT框架优化方向,以: - -1. 简化后续算法同学的开发工作 -2. 简化第三方的开发工作 -3. 简化MetaGPT向Agent的迁移工作 - -## 2. 系统设计 - -### 2.1 系统架构 - -#### 2.1.1 MetaGPT内部的消息处理 - -##### 2.1.1.1 现状 - -![img](/image/rfcs/rfc116/8d9c341f-2bd4-4ab3-942f-2a8981f8eabd.png) - -现有设计适合简单、轻量的智能体应用。 - -在处理持续交互、跨网交互方面存在如下问题: - -1. 对于多轮场景,超参“n_round”的值难统一、难推荐。比如挖矿场景、软件开发场景。 -2. 共享式的消息存放不支持跨网的消息消费; -3. 共享式的消息存放不支持个性化role对象的记忆压缩和信息隔离,如下图所示: - -![img](/image/rfcs/rfc116/12423f9c-1f3c-48dc-b91f-ee23f4e95efd.png) - -##### 2.1.1.2 新的架构方案 - -###### 2.1.1.2.1 自适配event loop - -新架构中,Env对象的event loop终止的方式为: - -1. Env对外提供`is_idle`状态; -2. 外部可通过调Env的stop函数来终止event loop; -3. 外部通过调start函数来启动event loop。start参数中可指定event loop是否在空闲时自动终止。 - -![img](/image/rfcs/rfc116/4d85b0bd-ec56-4c8a-9820-f678cd989089.png) - -新架构中: - -1. 所有消息均通过`Environment`对象提供的路由功能,将消息存放到各个`Role`对象私有的消息buffer中; -2. 所有状态数据都存放到一个支持序列化和反序列化的`StateContext`对象中; -3. Env对象通过检查内部各个role是否都空闲来判断是否需要结束event loop; -4. 跨role对象的消息转发统一由`Environment`对象负责。 - -#### 2.1.2 状态数据管理 - -现状中,并未规范状态数据的存放原则。 - -新方案中,`Role`对象私用的状态数据统一存放在Role对象自己的`StateContext`对象中;跨`Role`对象的状态数据统一存放在`Environment`对象的`StateContext`对象中。 - -`Environment`提供`save`和`load`函数,用于对`Environment`对象内部的状态数据存档和恢复。 - -#### 2.1.3 消息结构 - -##### 2.1.3.1 现状 - -现存的消息结构如图所示: - -![img](/image/rfcs/rfc116/19970c7b-dcb9-4c0a-be4f-5f7af1b29261.png) - -其中: - -1. `content`用来存放消息内容; -2. `instruct_content`功能与`content`相同,区别是存放的是结构化的数据。 -3. `role`是OPENAI规范中定义的`role`的值,是调LLM的参数的一部分。本质是meta信息的一部分。 -4. `cause_by`被同时用作分类(一种meta信息)标签和路由标签: - ```Python - async def _observe(self) -> int: - await super()._observe() - # accept the very first human instruction (the debate topic) or messages sent (from opponent) to self, - # disregard own messages from the last round - self._rc.news = [msg for msg in self._rc.news if msg.cause_by == UserRequirement or msg.send_to == self.name] - return len(self._rc.news) - ``` -5. `sent_from`被用作展示时显示的发言者信息。本质是meta信息的一部分。 -6. `send_to`被用作路由参数,用来在从共享消息队列中筛选发给自己的消息: - ```Python - async def _observe(self) -> int: - await super()._observe() - self._rc.news = [ - msg for msg in self._rc.news if msg.send_to == self.profile - ] # only relevant msgs count as observed news - return len(self._rc.news) - ``` -7. `restricted_to`被用作群发(一发多)的路由参数,用来从共享消息队列中筛选发给自己的消息: - ```Python - async def _think(self): - news = self._rc.news[0] - assert news.cause_by == InstructSpeak # 消息为来自Moderator的指令时,才去做动作 - if not news.restricted_to: - # 消息接收范围为全体角色的,做公开发言(发表投票观点也算发言) - self._rc.todo = Speak() - elif self.profile in news.restricted_to.split(","): - # FIXME: hard code to split, restricted为"Moderator"或"Moderator,角色profile" - # Moderator加密发给自己的,意味着要执行角色的特殊动作 - self._rc.todo = self.special_actions[0]() - ``` - -##### 2.1.3.2 新的消息结构 -新的消息结构如图所示: - -![img](/image/rfcs/rfc116/4edb8a4c-245b-4d02-a065-8e39937e732e.png) - - -其中: - -1. 为了支持`Message`类的JSON化,将`cause_by`的类型替换成str,并封装了自动类型转换的功能; -2. 将原来`send_to`的str类型改为`Set`,以支持多标签“或关系”的消息订阅功能。如果`Message`对象在创建时未设置`send_to`的值,则默认是全员可接收(与现有公共memory的效果相同)。 -3. 本次修改,MetaGPT的消息处理参照了消息队列的定义,明确了消息的生产和消费关系。 - - a. 新框架中,所有`Role`类及其子类都是消费者,它们默认订阅了发送给全员、自己对象的类名字、自己对象的`name`属性值的消息,见缺省的消息订阅标签章。 - - b. 所有`Message`对象的创建者都是消息生产者,它们可以通过设置`Message`对象的`send_to`的值来调整让谁来消费这条消息。 - - - -下面是一些新Message类的使用示例: -1. 设置`cause_by`属性: -```Python -m = Message("a", cause_by=Action) -assert m.cause_by == get_class_name(Action) -assert m.cause_by == any_to_str(Action) -``` - -2. 设置`sent_from`属性: -```Python -m = Message("a", sent_from=Action) -assert m.sent_from == get_class_name(Action) -assert m.sent_from == any_to_str(Action) -``` -3. 设置`sent_to`属性: -```Python -m = Message("a", sent_to={"b", Action}) -assert m.send_to == {"b", get_class_name(Action)} -assert m.send_to == any_to_str_set({"b", Action}) -``` - -###### 2.1.3.2.1 缺省的消息订阅标签 -为了简化业务开发工作,框架默认提供了3种消息订阅标签。 -所有`Role`及其子类都已经订阅了这3种标签,开发者可在发消息时直接使用: -1. `Role`对象的`name`属性:对应`Role`类及其子类对象的`name`属性的值。 -2. `Role`类的类名:对应任何`Role`类及其子类对象的类名。比如"Architect"类的类名为"metagpt.roles.architect.Architect"。 -3. 全员:值为"<all>"。本地所有消费者,都能收到这个消息。 - -示例如下: -
-假设有如下几个`Role类`的子类对象:
-
-1. `Moderator`类对象 `r1`, `r1`.`name`为`a`;
-2. `Werewolf`类对象 `r2`, `r2`.`name`为`b`;
-3. `Werewolf`类对象 `r3`, `r3`.`name`为`c`;
-4. `Villager`类对象 `r4`, `r4`.`name`为`d`;
-5. `Villager`类对象 `r5`, `r5`.`name`为`e`;
-6. `Seer`类对象 `r6`, `r6`.`name`为`f`;
-
-已知`Environment`类对象`env`:
-
-1. `r1`发消息给所有`Werewolf`类对象:
-```Python
-env.publish_message(Message(content="...", send_to=Werewolf))
-```
- 这里的`Werewolf`用的就是`Role`类的类名做标签。这个消息的接收者是所有的`Werewolf`类对象。
-
-2. `r1`发消息给`c`和所有`Villager`类对象:
-```Python
-env.publish_message(Message(content="...", send_to={Villager, "c"}))
-```
-这里的`Villager`是`Role`类的类名标签,`c`是`Role`对象`r3`的`name`属性。这个消息的接收者是所有`Villager`类对象,以及`name`属性为`c`的`Role`对象`r3`。
-
-3. `r1`发消息给所有对象:
-```Python
-env.publish_message(Message(content="...", send_to=" |
+假设有如下几个`Role类`的子类对象:
+
+1. `Moderator`类对象 `r1`, `r1`.`name`为`a`;
+2. `Werewolf`类对象 `r2`, `r2`.`name`为`b`;
+3. `Werewolf`类对象 `r3`, `r3`.`name`为`c`;
+4. `Villager`类对象 `r4`, `r4`.`name`为`d`;
+5. `Villager`类对象 `r5`, `r5`.`name`为`e`;
+6. `Seer`类对象 `r6`, `r6`.`name`为`f`;
+
+已知`Environment`类对象`env`:
+
+1. `r1`发消息给所有`Werewolf`类对象:
+
+```Python
+env.publish_message(Message(content="...", send_to=Werewolf))
+```
+
+这里的`Werewolf`用的就是`Role`类的类名做标签。这个消息的接收者是所有的`Werewolf`类对象。
+
+2. `r1`发消息给`c`和所有`Villager`类对象:
+
+```Python
+env.publish_message(Message(content="...", send_to={Villager, "c"}))
+```
+
+这里的`Villager`是`Role`类的类名标签,`c`是`Role`对象`r3`的`name`属性。这个消息的接收者是所有`Villager`类对象,以及`name`属性为`c`的`Role`对象`r3`。
+
+3. `r1`发消息给所有对象:
+
+```Python
+env.publish_message(Message(content="...", send_to=" |
字段名 | +是否可增量修改 | +字段值示例 | +
Original Requirements | +否 | +"Create a snake game" | +
Search Information | +否 | +"" | +
Project Name | +否 | +如果想修改,请通过CLI命令参数 --project-name进行 | +
Requirements | +否 | +"" | +
Product Goals | +是 | +
+[ + "Provide an enjoyable gaming experience", + "Ensure smooth and responsive controls", + "Include engaging visuals and sound effects" +] |
+
User Stories | +是 | +
+[ + "As a player, I want to control the snake using arrow keys to navigate +through the game board", + "As a player, I want the snake to grow longer and increase in speed as +it consumes food", + "As a player, I want to see my high score and be able to compare it with +other players", + "As a player, I want to have different levels of difficulty to challenge +myself", + "As a player, I want to be able to pause and resume the game at any +time" +] |
+
Competitive Analysis | +否 | +
+[ + "Snake Game X has a simple and intuitive user interface", + "Snake Game Y offers multiple game modes and power-ups", + "Snake Game Z has a leaderboard feature to compare scores with +friends", + "Snake Game A has smooth and responsive controls", + "Snake Game B has visually appealing graphics and animations", + "Snake Game C offers customizable snake skins", + "Snake Game D has challenging obstacles and mazes" +] |
+
Competitive Quadrant Chart | +否 | ++"quadrantChart\n title Reach and engagement of snake games\n x-axis Low Reach --> High Reach\n y-axis Low Engagement --> High Engagement\n quadrant-1 Snake Game X: [0.3, 0.6]\n quadrant-2 Snake Game Y: [0.45, 0.23]\n quadrant-3 Snake Game Z: [0.57, 0.69]\n quadrant-4 Snake Game A: [0.78, 0.34]\n Snake Game B: [0.40, 0.34]\n Snake Game C: [0.35, 0.78]\n Snake Game D: [0.5, 0.6]" + | +
Requirement Analysis | +否 | +"" | +
Requirement Pool | +是 | +
+[ + [ + "P0", + "The snake should move smoothly and responsively when controlled by the +player." + ], + [ + "P1", + "The game should have different levels of difficulty to cater to players +of different skill levels." + ] +] |
+
UI Design draft | +是 | ++"The game will have a simple and clean user interface. It will consist +of a game board where the snake moves and food appears. The score and +high score will be displayed at the top of the screen. There will be +buttons to pause and resume the game. The snake and food will have +visually appealing graphics." | +
Anything UNCLEAR | +否 | +"" | +