注:此文章内容均节选自充电了么创始人,CEO兼CTO陈敬雷老师的新书《GPT多模态大模型与AI Agent智能体》(跟我一起学人工智能)【陈敬雷编著】【清华大学出版社】

清华《GPT多模态大模型与AI Agent智能体》书籍配套视频课程【陈敬雷】

文章目录

GPT多模态大模型与AI Agent智能体系列一百七十八

从单智能体到人类介入!MetaGPT 完整教程:原理、代码实战、开源模型集成全攻略

7.2.2 MetaGPT
MetaGPT是由一位来自深圳的开发者所创建的项目,项目发布后在GitHub上引发了广泛的关注。MetaGPT是一种创新的多智能体框架,它巧妙地运用标准作业程序(Standard Operating Procedures,SOP)来协调基于大模型的多智能体系统,从而实现了元编程的技术。这个框架通过智能体的协作模拟了一个虚拟的软件团队,涵盖了产品经理、架构师、项目经理、工程师和质量工程师等关键角色。在这个框架中,SOP成为了虚拟软件团队开发流程的核心,确保了从需求分析到代码实现的全生命周期管理的高效和有序。MetaGPT专注于软件开发,其目标是提供一个端到端的解决方案,以自动化的方式满足软件开发过程中的所有需求。作为一个全新的基于AI Agent的大模型框架,MetaGPT区别于以往的项目,因为它专注于软件开发的全过程,实现了从需求分析到代码实现的全覆盖。这个框架能够基于用户提供的原始需求,提供一整套服务,包括需求分析、系统设计、代码实现及代码审查等流程环节:
(1)需求分析:负责接收和理解用户提出的原始需求,并进行初步的分析,明确需求的范围及其核心要素。
(2)需求评审:对需求进行分析,确保需求的清晰度和完整性,评估其可行性。
(3)系统需求分析:深入研究系统的功能和非功能要求,制定详尽的系统规格说明书。
(4)系统设计:依据系统需求,设计软件架构,选择合适技术,绘制系统设计图。
(5)代码实现:编写符合设计要求的代码,实现系统的各项功能。
(6)代码评审:检查代码质量,确保代码遵守编码规范且无重大缺陷。
(7)代码测试:进行单元测试、集成测试和系统测试,验证代码的正确性和稳定性。
在一个典型的软件开发团队中,上述流程虽然能够有效地保障代码开发的质量,但也可能导致开发周期较长,不够灵活。MetaGPT通过大模型实现这一流程,只需要输入一句话的老板需求,就能够借助GPT-4完成产品的全部开发工作,输出用户故事/竞品分析/需求/数据结构/ APIs /文件等形式,这无疑将对软件开发的效率和品质产生显著的积极影响。软件开发团队多角色示意如图7-2所示。
在这里插入图片描述

图译:SoftwareCompany(软件公司),Investment(投资),Idea(想法),Environment(环境)
Boss(老板),Boss Requirement(老板要求)
Product Manager(产品经理),Write PRD(写PRD文档),Revise PRD(改PRD文档)
Architect(架构师),Write Design(编写设计),Revise Design(修订设计),Review PRD(审核PRD),Review Code(审核代码)
Project Manager(项目经理),Write Tasks(编写任务),Assign Task(分配任务),Review PRD(审核PRD),Review Design(审核设计),Review Code(审核代码)
Engineer(工程师),Write Code(编写代码),Review Code(审核代码),Debug Code(调试代码)
QA(质量保证),Write Tests(编写用例),Run Tests(运行用例)。
图7-2 软件开发团队多角色示意图
1.MetaGPT实现原理
MetaGPT的实现原理相较于之前的AutoGPT更为复杂。在MetaGPT中,定义了多种角色,并为每个角色设定了目标和提示模板,以指导相关角色解决问题。以下是主要角色及其目标、可行动和观察输入的概述,见表7-1。
在这里插入图片描述

从以上表格可知,MetaGPT通过定义多种角色来完成初始需求的一系列实现过程。整个流程的起点是老板的需求,随后各个角色会基于这个原始需求按上述步骤进行处理。
MetaGPT的一个有趣设定是为每种角色定义了一个单独的“进程”运行。每个角色在运行过程中都在等待是否有相应的输入出现,一旦观察到相应的输入,便会立即根据自己的目标,使用大型模型来解决这个问题,并将结果返回至系统中。系统的其他角色一旦监测到有关于自己的任务输入,便可获取任务进行执行。这与当前的开发流程和组织架构非常相似。此外,为了赋予每个角色更强大的能力,MetaGPT还设置了额外的角色来帮助系统完成任务,如搜索角色、提示分解角色等。MetaGPT内置的任务和技能主要包括:
(1)分析代码库(analyze_dep_libs.py);
(2)Azure的语音合成(azure_tts.py);
(3)Debug(debug_error.py);
(4)设计API(design_api.py);
(5)API评审(design_api_review.py);
(6)设计文件名(design_filenames.py);
(7)项目管理(project_management.py);
(8)代码运行(run_code.py);
(9)搜索和摘要(search_and_summarize.py);
(10)编写代码(write_code.py);
(11)编写代码评审(write_code_review.py);
(12)编写需求说明书(write_prd.py);
(13)编写需求说明书评审(write_prd_review.py);
(14)编写测试用例(write_test.py)。
简而言之,上述每一项技能都对应一个Python文件,每个Python文件中定义的都是对应技能的提示模板。最终,各个角色都是通过自己所拥有的这些技能来处理输入和输出,完成任务。MetaGPT框架的这种全面角色定义使其能够创建高度专业化的基于大模型的智能体,每个智能体都针对特定的领域和目标进行了定制。角色定义不仅引入了基于预期功能的行为指导,而且有助于创建多样化和专业化的智能体,每个智能体都是其领域的专家。角色的行为主要由以下几个部分组成:
(1)思考与反思(Think & Reflect):角色可以检索角色描述来构建思考,然后通过_think()函数来反思需要做什么并决定下一步的行动。
(2)观察(Observe):角色可以观察环境,并根据观察结果使用_observe()函数进行思考和行动。它们会关注重要信息,并将其纳入记忆中,以丰富其上下文理解并为未来的决策提供信息。
(3)广播消息(Broadcast Messages):角色可以使用_publish_message()函数将消息广播到环境中。这些消息包含有关当前执行结果和相关行动记录的信息,用于发布和共享信息。
(4)知识沉淀与行动(Knowledge Precipitation & Act):角色不仅是广播者,也是环境信息的接收者。角色可以评估传入的消息的相关性和及时性,从共享环境中提取相关知识,并维护一个内部的知识库以支持决策。它们通过咨询大模型,并利用其具有丰富上下文信息和自我知识的来执行行动。执行结果被封装为消息,而规范性组件则由环境共享。
(5)状态管理(State Management):角色可以通过更新工作状态和监控待办事项列表来跟踪它们的行动。这使得角色能够按顺序处理多个行动而不中断。在执行每个行动时,角色首先锁定其状态。完成行动后,将状态标记为解锁。这样可以防止其他行动中断工作流程。
通过这些行为的组合,MetaGPT中的角色可有效地协作,共同实现复杂的任务和目标。
2.单智能体
根据MetaGPT的理念,只要一个智能体能够执行某些动作(无论这些动作是由大模型驱动还是其他方式实现的),它就具有一定的实用价值。MetaGPT提供了高度的灵活性,可以根据自己的需求定义所需的行为和智能体,其流程如下:
首先,需要明确目标。智能体能够完成的任务可能是一个简单的任务,比如查询天气,或者是一个复杂的任务。明确了目标之后,就可以开始定义智能体的行为。
接下来,需要确定智能体的核心行为。这些行为应该是实现目标所必需的。例如,如果目标是查询天气,那么智能体的核心行为可能包括:接收查询请求、访问天气数据源、解析数据、生成报告。对于更复杂的任务,可能需要更多的核心行为。
然后,需要为智能体配置必要的资源和能力。这包括选择合适的大模型、训练数据、以及其他任何需要的工具或服务。这一步骤的目标是让智能体具备足够的知识和能力来执行它的核心行为。
最后,需要对智能体进行测试和优化。在实际使用中,可能会发现智能体在某些方面表现不佳,或者在某些情况下无法正确地执行任务。这时需要对智能体进行调整和优化,以提高其性能和准确性。
通过以上步骤,就可以成功地开发出自己的人工智能助手。虽然这个过程可能需要一些时间和努力,但是一旦完成,就拥有了一个强大工具,可以更高效地完成各种任务。
1)具有单一动作的智能体
设想一下,如果能用自然语言编写代码,那将是多么便捷的事情!现在,就来实现这个想法,创建一个名为SimpleCoder的智能体,让它完成这项任务。要实现这个目标,需要分两步进行:第一步是定义一个编写代码的动作。这个动作应该包括接收自然语言的编程指令,将其转换为具体的代码,然后将生成的代码输出。为了实现这一点,需要详细描述这个动作的各个组成部分,包括输入、处理和输出。第二步是为智能体配备这个动作。这意味着需要为SimpleCoder提供必要的资源和工具,以便它能够理解和执行自然语言编程指令。这可能包括选择一个合适的语言模型,以及提供相关的训练数据,让模型学会如何将自然语言转换为代码。在这个过程中,还需要考虑到一些实际问题,比如如何处理语法错误、如何确保生成的代码符合编程规范等等。这些问题都需要在开发和测试过程中逐步解决。
在MetaGPT中,动作和角色的定义是实现智能体功能的关键。通过定义SimpleWriteCode子类Action,可以将自然语言编程指令的转换过程封装为一个可执行的动作。同时,Role类的引入使得智能体能够执行动作、存储记忆并制定策略,从而形成一个完整的智能体实体。
下面继续探索如何在MetaGPT框架下,通过定义动作和角色,来实现SimpleCoder智能体。
(1)定义动作:在MetaGPT中,类Action是动作的逻辑抽象。用户可以通过简单地调用self._aask函数令大模型赋予这个动作能力,即这个函数将在底层调用大模型api。在这个场景中,定义了一个SimpleWriteCode子类 Action。虽然它主要是一个围绕提示和大模型调用的包装器,但可认为这个Action抽象更直观。在下游和高级任务中,使用它作为一个整体感觉更自然,而不是分别制作提示和调用大模型,尤其是在智能体的框架内。
(2)定义角色:在MetaGPT中,Role类是智能体的逻辑抽象。一个Role能执行特定的Action,拥有记忆、思考并采用各种策略行动。基本上,它充当一个将所有这些组件联系在一起的凝聚实体。现只关注一个执行动作的智能体,并看看如何定义一个最简单的Role。
接下来就可以创建一个SimpleCoder,实现自然语言描述编写代码。首先为其指定一个名称和配置文件,然后使用self._init_action函数为其配备期望的动作SimpleWriteCode,最后覆盖_act函数,其中包含智能体具体行动逻辑。写入时,智能体将从最新的记忆中获取人类指令,运行配备的动作,MetaGPT将其作为待办事项(self.rc.todo)在幕后处理,最后返回一个完整的消息。
2)具有多个动作的智能体
一个智能体能够执行一个动作,但如果只有这些,实际上并不需要一个智能体。通过直接运行动作本身,可以得到相同的结果。智能体的力量,或者说Role抽象的惊人之处,在于动作的组合(以及其他组件,比如记忆,将把它们留到后面的部分)。通过连接动作,可以构建一个工作流程,使智能体能够完成更复杂的任务。假设现在不仅希望用自然语言编写代码,而且还希望生成的代码立即执行。一个拥有多个动作的智能体可以满足需求,称之为RunnableCoder,一个既写代码又立即运行的Role。需要两个Action:SimpleWriteCode和SimpleRunCode。
(1)定义动作:首先,定义SimpleWriteCode。将重用上面创建的那个。接下来,定义SimpleRunCode。如前所述,从概念上讲,一个动作可以利用大模型,也可以在没有大模型的情况下运行。在SimpleRunCode的情况下,大模型不涉及其中,只需启动一个子进程来运行代码并获取结果。对于动作逻辑的结构,没有设定任何限制,用户可以根据需要完全灵活地设计逻辑。
(2)定义角色:与定义单一动作的智能体没有太大不同!下面来映射一下:首先用self.set_actions初始化所有Action,然后指定每次Role会选择哪个Action,将react_mode设置为“by_order”,这意味着Role将按照self.set_actions中指定的顺序执行其能够执行的Action。在这种情况下,当Role执行_act 时,self.rc.todo将首先是SimpleWriteCode,然后是SimpleRunCode。
最后是覆盖_act 函数。Role从上一轮的人类输入或动作输出中检索消息,用适当的 Message内容提供当前的Action(self.rc.todo),最后返回由当前Action输出组成的Message。
3)运行单一动作和多个动作的智能体
现在可以让智能体开始工作,包括上面的具有单一动作的智能体和具有多个动作的智能体,都是只需初始化它并使用一个起始消息运行它。下面是定义动作、角色,并运行角色的完整示例,代码如下:
#第7章/build_customized_agent.py

导入所需库

import asyncio
import re
import subprocess
import fire
from metagpt.actions import Action
from metagpt.logs import logger
from metagpt.roles.role import Role, RoleReactMode
from metagpt.schema import Message

定义一个用于生成简单Python代码的Action类

class SimpleWriteCode(Action):
# 提示模板,用于向模型发送指令
PROMPT_TEMPLATE: str = “”"
Write a python function that can {instruction} and provide two runnable test cases.
Return python your_code_here with NO other texts,
your code:
“”"
# 设置Action名称
name: str = “SimpleWriteCode”
# 实现run方法,接收一个指令参数,返回生成的Python代码文本
async def run(self, instruction: str):
prompt = self.PROMPT_TEMPLATE.format(instruction=instruction)
# 向模型发送提示并获取响应
rsp = await self._aask(prompt)
# 从响应中提取出Python代码文本
code_text = SimpleWriteCode.parse_code(rsp)
return code_text
# 静态方法,从给定的响应中提取Python代码
@staticmethod
def parse_code(rsp):
pattern = r"python(.*)"
match = re.search(pattern, rsp, re.DOTALL)
code_text = match.group(1) if match else rsp
return code_text

定义一个用于执行Python代码的Action类

class SimpleRunCode(Action):
# 设置Action名称
name: str = “SimpleRunCode”
# 实现run方法,接收一个Python代码文本参数,返回执行结果
async def run(self, code_text: str):
# 使用子进程执行Python代码并捕获输出
result = subprocess.run([“python3”, “-c”, code_text], capture_output=True, text=True)
code_result = result.stdout
logger.info(f"{code_result=}")
return code_result

定义一个名为SimpleCoder的角色类,仅使用SimpleWriteCode动作

class SimpleCoder(Role):
# 设置角色名称和简介
name: str = “Alice”
profile: str = “SimpleCoder”
def init(self, **kwargs):
super().init(**kwargs)
# 为角色设置可用的动作(此处仅为SimpleWriteCode)
self.set_actions([SimpleWriteCode])

# 实现角色行为方法,根据待办任务(即Action)生成消息
async def _act(self) -> Message:
    logger.info(f"{self._setting}: to do {self.rc.todo}({self.rc.todo.name})")
    # 获取当前待办任务(SimpleWriteCode实例)
    todo = self.rc.todo  # todo will be SimpleWriteCode()
    # 从记忆中获取最近一条消息内容作为输入
    msg = self.get_memories(k=1)[0]  # find the most recent messages
    # 运行待办任务并获取生成的Python代码文本
    code_text = await todo.run(msg.content)
    # 构造并返回包含生成代码的Message对象
    msg = Message(content=code_text, role=self.profile, cause_by=type(todo))
    return msg

定义一个名为RunnableCoder的角色类,使用SimpleWriteCode和SimpleRunCode动作

class RunnableCoder(Role):
# 设置角色名称和简介
name: str = “Alice”
profile: str = “RunnableCoder”
def init(self, **kwargs):
super().init(**kwargs)
# 为角色设置可用的动作(SimpleWriteCode和SimpleRunCode)
self.set_actions([SimpleWriteCode, SimpleRunCode])
# 设置角色反应模式为按顺序执行动作
self._set_react_mode(react_mode=RoleReactMode.BY_ORDER.value)
# 实现角色行为方法,根据待办任务(按顺序执行SimpleWriteCode和SimpleRunCode)生成消息
async def _act(self) -> Message:
logger.info(f"{self._setting}: to do {self.rc.todo}({self.rc.todo.name})")
# 获取当前待办任务(按顺序为SimpleWriteCode或SimpleRunCode实例)
todo = self.rc.todo
# 从记忆中获取最近一条消息内容作为输入
msg = self.get_memories(k=1)[0]
# 执行待办任务并获取结果
result = await todo.run(msg.content)
# 构造并返回包含执行结果的Message对象,并将其添加至记忆中
msg = Message(content=result, role=self.profile, cause_by=type(todo))
self.rc.memory.add(msg)
return msg

主函数,接收一个指令参数,创建RunnableCoder角色并运行

def main(msg=“write a function that calculates the product of a list and run it”):
# role = SimpleCoder()
role = RunnableCoder()
logger.info(msg)
result = asyncio.run(role.run(msg))
logger.info(result)
if name == “main”:
fire.Fire(main)
通过以下命令运行上面代码:
python3 examples/build_customized_agent.py --msg “编写一个计算列表总和的函数”。
3.多智能体
上面探讨了单个智能体的创建过程。尽管在许多情况下,单一智能体已经足够应对挑战,但对于更为复杂的问题,往往需要多个智能体协同合作才能有效解决。这就是多智能体系统不可或缺的原因。MetaGPT的核心优势之一就是能够轻松且灵活地开发出一个智能体团队。在MetaGPT框架下,用户可以通过少量的代码实现智能体之间的有效交互。接下来讲解智能体之间如何进行交互,然后开发第一个智能体团队。
智能体之间的交互是实现多智能体协作的关键。这种交互可以是直接的,也可以是间接的,取决于任务的性质和智能体的设计。直接交互通常涉及到智能体之间的通信,例如发送消息、共享数据等。间接交互则可能涉及到智能体对环境的共同影响,例如在一个共享的工作空间中协作完成任务。开发一个智能体团队的过程可以分为几个步骤。首先,你需要定义各个智能体的角色和职责,确保它们各自的任务和责任清晰明了。其次,你需要设计智能体之间的交互机制,包括它们如何通信、如何协调行动等。然后,你需要为每个智能体配置必要的资源和工具,使它们具备完成任务的能力。最后,你需要对整个系统进行测试和优化,以确保所有智能体都能高效、准确地完成任务。下面以运行“软件公司”示例讲解多智能体。上面已经讲过单个智能体,接下来将继续在单个智能体的简单代码示例中添加更多角色,并引入智能体之间的交互协作。增加角色可雇佣一名测试人员和一名审阅人员携手与编码人员一起工作。这样看起来像一个开发团队了,总的来说,需要三个步骤来建立团队并使其运作:
(1)定义每个角色能够执行的预期动作;
(2)基于SOP确保每个角色遵守它。通过使每个角色观察上游的相应输出结果,并为下游发布自己的输出结果,可以实现这一点;
(3)初始化所有角色,创建一个带有环境的智能体团队,并使它们之间能够进行交互。
1)定义动作和角色
与单个智能体过程类似,可以定义三个具有各自动作的Role:
(1)SimpleCoder具有SimpleWriteCode动作,接收用户的指令并编写主要代码;
(2)SimpleTester具有SimpleWriteTest动作,从SimpleWriteCode的输出中获取主代码并为其提供测试套件;
(3)SimpleReviewer具有SimpleWriteReview动作,审查来自SimpleWriteTest输出的测试用例,并检查其覆盖范围和质量。
通过上述概述,使得SOP变得更加清晰明了。接下来,将详细讨论如何根据SOP来定义Role。在多智能体场景中,定义Role可能只需几行代码。对于SimpleCoder,做了两件事:
(1)使用set_actions为Role配备适当的Action,这与设置单智能体相同
(2)多智能体操作逻辑,使Role _watch来自用户或其他智能体的重要上游消息。回想SOP,SimpleCoder接收用户指令,这是由MetaGPT中的UserRequirement引起的Message。因此,添加了self._watch([UserRequirement])。
这就是用户需要做的全部。与上述相似,对于SimpleTester,做了如下几件事:
(1)使用set_actions为SimpleTester配备SimpleWriteTest动作;
(2)使Role _watch来自其他智能体的重要上游消息。回想SOP,SimpleTester从SimpleCoder中获取主代码,这是由SimpleWriteCode引起的 Message。因此添加了 self._watch([SimpleWriteCode])。一个扩展的问题:想一想如果使用 self._watch([SimpleWriteCode, SimpleWriteReview]) 会意味着什么,可以尝试这样做。此外,可以为智能体定义自己的操作逻辑。这适用于Action需要多个输入的情况,修改输入,使用特定记忆,或进行任何其他更改以反映特定逻辑的情况。
(3)重写_act函数,就像在单智能体设置中所做的那样。在这里,SimpleTester将所有记忆用作编写测试用例的上下文,并希望有5个测试用例。
按照相同的过程定义SimpleReviewer。
2)创建一个团队并添加角色
现在已经定义了三个Role,将它们放在一起初始化所有角色,然后设置一个Team,并hire它们。运行Team会看到它们之间的协作。下面是定义动作、角色,并运行角色的完整多智能体示例,代码如下:

第7章/build_customized_multi_agents.py

#导入相关库
import re
import fire
from metagpt.actions import Action, UserRequirement
from metagpt.logs import logger
from metagpt.roles import Role
from metagpt.schema import Message
from metagpt.team import Team

定义一个辅助函数,从响应中提取Python代码片段

def parse_code(rsp):
pattern = r"python(.*)"
match = re.search(pattern, rsp, re.DOTALL)
code_text = match.group(1) if match else rsp
return code_text

定义一个用于生成Python代码的Action类

class SimpleWriteCode(Action):
# 提示模板,用于向模型发送指令
PROMPT_TEMPLATE: str = “”"
Write a python function that can {instruction}.
Return python your_code_here with NO other texts,
your code:
“”"
# 设置Action名称
name: str = “SimpleWriteCode”
# 实现run方法,接收一个指令参数,返回生成的Python代码文本
async def run(self, instruction: str):
prompt = self.PROMPT_TEMPLATE.format(instruction=instruction)
# 向模型发送提示并获取响应
rsp = await self._aask(prompt)
# 从响应中提取出Python代码文本
code_text = parse_code(rsp)
return code_text

定义一个名为SimpleCoder的角色类,使用SimpleWriteCode动作

class SimpleCoder(Role):
# 设置角色名称和简介
name: str = “Alice”
profile: str = “SimpleCoder”

def __init__(self, **kwargs):
    super().__init__(**kwargs)
    # 观察UserRequirement事件
    self._watch([UserRequirement])
    # 为角色设置可用的动作(此处仅为SimpleWriteCode)
    self.set_actions([SimpleWriteCode])

定义一个用于生成Python单元测试代码的Action类

class SimpleWriteTest(Action):
# 提示模板,用于向模型发送指令
PROMPT_TEMPLATE: str = “”"
Context: {context}
Write {k} unit tests using pytest for the given function, assuming you have imported it.
Return python your_code_here with NO other texts,
your code:
“”"
# 设置Action名称
name: str = “SimpleWriteTest”
# 实现run方法,接收上下文字符串和测试数量参数,返回生成的单元测试代码文本
async def run(self, context: str, k: int = 3):
prompt = self.PROMPT_TEMPLATE.format(context=context, k=k)
# 向模型发送提示并获取响应
rsp = await self._aask(prompt)
# 从响应中提取出单元测试代码文本
code_text = parse_code(rsp)
return code_text

定义一个名为SimpleTester的角色类,使用SimpleWriteTest动作

class SimpleTester(Role):
# 设置角色名称和简介
name: str = “Bob”
profile: str = “SimpleTester”

def __init__(self, **kwargs):
    super().__init__(**kwargs)
    # 为角色设置可用的动作(此处仅为SimpleWriteTest)
    self.set_actions([SimpleWriteTest])
    # 观察SimpleWriteCode和SimpleWriteReview事件(可尝试开启/关闭观察SimpleWriteCode)
    self._watch([SimpleWriteCode, SimpleWriteReview])

# 实现角色行为方法,根据待办任务(即Action)生成消息
async def _act(self) -> Message:
    logger.info(f"{self._setting}: to do {self.rc.todo}({self.rc.todo.name})")
    # 获取当前待办任务(SimpleWriteTest实例)
    todo = self.rc.todo
    # 使用所有记忆作为上下文
    context = self.get_memories()
    # 运行待办任务并获取生成的单元测试代码文本
    code_text = await todo.run(context, k=5)  # specify arguments
    # 构造并返回包含生成代码的Message对象
    msg = Message(content=code_text, role=self.profile, cause_by=type(todo))
    return msg

定义一个用于生成代码审查意见的Action类

class SimpleWriteReview(Action):
# 提示模板,用于向模型发送指令
PROMPT_TEMPLATE: str = “”"
Context: {context}
Review the test cases and provide one critical comments:
“”"
# 设置Action名称
name: str = “SimpleWriteReview”
# 实现run方法,接收一个上下文字符串参数,返回生成的代码审查意见文本
async def run(self, context: str):
prompt = self.PROMPT_TEMPLATE.format(context=context)
# 向模型发送提示并获取响应
rsp = await self._aask(prompt)
# 直接返回响应作为审查意见文本
return rsp

定义一个名为SimpleReviewer的角色类,使用SimpleWriteReview动作

class SimpleReviewer(Role):
# 设置角色名称和简介
name: str = “Charlie”
profile: str = “SimpleReviewer”
def init(self, **kwargs):
super().init(**kwargs)
# 为角色设置可用的动作(此处仅为SimpleWriteReview)
self.set_actions([SimpleWriteReview])
# 观察SimpleWriteTest事件
self._watch([SimpleWriteTest])

主函数,定义团队协作流程

async def main(
idea: str = “write a function that calculates the product of a list”,
investment: float = 3.0,
n_round: int = 5,
add_human: bool = False,
):
logger.info(idea)
# 创建团队对象
team = Team()
# 聘请角色成员(可选择是否为SimpleReviewer角色添加人类身份)
team.hire(
[
SimpleCoder(),
SimpleTester(),
SimpleReviewer(is_human=add_human),
]
)
# 投资团队
team.invest(investment=investment)
# 开始项目
team.run_project(idea)
# 运行团队协作流程指定轮数
await team.run(n_round=n_round)
if name == “main”:
fire.Fire(main)
通过以下命令运行上面代码:
python3 examples/build_customized_multi_agents.py --idea “编写一个计算列表乘积的函数”。
5.使用短时记忆
记忆是智能体的核心组件之一。智能体需要记忆来获取做出决策或执行动作所需的基本上下文,还需要记忆来学习技能或积累经验。接下来将介绍短时记忆的基本使用方法。在MetaGPT中,Memory类是智能体的记忆的抽象。当初始化时,Role初始化一个Memory对象作为self.rc.memory属性,它将在之后的_observe中存储每个Message,以便后续的检索。简而言之,Role的记忆是一个含有Message的列表。
1)检索记忆
当需要获取记忆时(获取大模型输入的上下文),可以使用self.get_memories。函数定义代码如下:

第7章/getmemories.py

def get_memories(self, k=0) -> list[Message]:
“”"
封装方法,用于获取该角色最近的k条记忆。当k=0时,返回所有记忆。
“”"
return self.rc.memory.get(k=k)
这段代码定义了一个名为get_memories的方法,该方法在metagpt\roles\role.py代码文件里。方法接受一个可选参数k,默认值为0,其类型注解表明它返回一个list[Message],即一个包含Message对象的列表。注释对方法进行了简要说明:
(1)封装方法:表明这是一个为了简化操作或提供更清晰接口而设计的辅助方法。
(2)用于获取该角色最近的k条记忆:指明该方法的主要功能是从当前角色(self)的历史记录中获取最近的k条记忆。这里的“记忆”可能指的是角色在执行任务过程中产生的、具有重要意义的信息记录,如生成的代码片段、完成的任务状态等。
(3)当k=0时,返回所有记忆:说明了参数k的特殊处理情况。如果传入的k值为0,则方法不局限于返回最近的固定数量的记忆,而是返回角色的所有记忆。
方法实现非常直接:调用self.rc.memory.get(k=k)来获取所需的记忆,并返回得到的结果。这里的self.rc.memory表示角色实例(self)的某个内部属性(如一个内存管理器),通过.get(k=k)方法来根据参数k获取相应数量的记忆记录。在多智能体示例中,调用此函数为测试人员提供完整的历史记录。
2)添加记忆
可以使用self.rc.memory.add(msg)添加记忆,其中msg必须是Message的实例。请查看上述讲解单智能体build_customized_agent.py的代码片段以获取示例用法。建议在定义_act逻辑时将Message的动作输出添加到Role的记忆中。通常,Role需要记住它先前说过或做过什么,以便采取下一步的行动。短期记忆的容量有限,为了做到无限容量的长期记忆,可以使用外部存储的知识库。接下来讲解长期记忆。
6.使用长期记忆
在前面章节中,已经介绍了RAG技术,这是一种通过引用外部知识库来优化大模型输出的方法。RAG能够增强模型的生成响应能力,同时减少模型的幻觉现象。这种方法不需要对大型模型进行重新训练或微调,只需访问特定领域的知识库,就可以提高输出的相关性、准确性和实用性。接下来将详细介绍MetaGPT所提供的RAG功能。
首先,MetaGPT支持多种格式的数据输入,包括PDF、DOCX、MD、CSV、TXT、PPT等文档格式,以及Python对象。这可以方便地将各种类型的数据整合到知识库中。
其次,MetaGPT提供了强大的检索功能,支持FAISS、BM25、ChromaDB、Elasticsearch等多种检索方法,并支持混合检索。这意味着可以根据实际需求选择最适合的检索方法,以获得最佳的检索效果。
此外,MetaGPT还提供了检索后处理功能,支持大模型Rerank和ColbertRerank等方法。这些方法可以对检索到的内容进行重新排序,以得到更准确的结果。
为了方便数据的更新和管理,MetaGPT还提供了数据更新的功能,可以方便地增加新的文本和Python对象到知识库中。同时,MetaGPT还支持数据的保存和恢复,这样就不需要每次使用时都对数据进行向量化处理。
总的来说,MetaGPT提供的RAG功能强大且灵活,可以满足各种不同的需求。通过合理地使用这些功能,可以有效地提升大模型的性能和应用效果。
1)环境准备
安装RAG模块有两种方式,一种是用pip安装,使用pip install metagpt[rag]命令,另外一种可以使用源码安装,进入源码路径后,使用pip install -e .[rag]命令。向量数据库需要配置embedding,需要修改MetaGPT源码项目config文件夹下的config2.yaml文件的embedding配置部分。config2.yaml文件里的完整代码如下:
#第7章/config2.yaml

LLM 配置

llm:

API 类型:指定使用的 LLM 服务提供商,如 OpenAI、Azure、OLLAMA 等。参考 LLMType 获取更多选项。

api_type: “openai”

基础 URL:LLM 服务的 API 访问地址

base_url: “YOUR_BASE_URL”

API 密钥:用于认证访问 LLM 服务的密钥

api_key: “YOUR_API_KEY”

模型名称:指定要使用的 LLM 模型版本,如 gpt-4-turbo-preview、gpt-3.5-turbo-1106 等

model: “gpt-4-turbo-preview”

代理设置:为 LLM API 请求配置代理服务器

proxy: “YOUR_PROXY”

超时时间(可选):请求超时限制(单位:秒)。若设为 0,默认值为 300 秒。

timeout: 600

定价计划(可选):指定使用的付费方案。若填写无效,将自动填充与 model 对应的默认值。

Azure 独享的定价计划映射示例:

- gpt-3.5-turbo 4k: “gpt-3.5-turbo-1106”

- gpt-4-turbo: “gpt-4-turbo-preview”

- gpt-4-turbo-vision: “gpt-4-vision-preview”

- gpt-4 8k: “gpt-4”

嵌入向量配置

embedding:
# API 类型:指定嵌入向量服务提供商,如 OpenAI、Azure、Gemini、OLLAMA 等。参考 EmbeddingType 获取更多选项。
api_type: “”
# 基础 URL:嵌入向量服务的 API 访问地址
base_url: “”
# API 密钥:用于认证访问嵌入向量服务的密钥
api_key: “”
# 模型名称:指定要使用的嵌入模型版本
model: “”
# API 版本:嵌入服务对应的版本信息
api_version: “”
# 批量处理大小:一次请求中同时处理的嵌入项数量
embed_batch_size: 100

修复 LLM 输出:当输出结果不是有效的 JSON 格式时,尝试进行修复

repair_llm_output: true

全局代理设置:为诸如 requests、playwright、selenium 等工具配置代理服务器

proxy: “YOUR_PROXY”

搜索配置

search:

API 类型:指定搜索引擎类型,如 Google

api_type: “google”

API 密钥:用于认证访问搜索服务的密钥

api_key: “YOUR_API_KEY”

CSE ID:Google 自定义搜索引擎 ID

cse_id: “YOUR_CSE_ID”

浏览器配置

browser:

引擎类型:指定浏览器自动化工具,如 playwright 或 selenium

engine: “playwright”

浏览器类型:根据所选引擎指定具体的浏览器类型,如 playwright 下的 chromium、firefox、webkit;selenium 下的 chrome、firefox、edge、ie

browser_type: “chromium”

Mermaid 图表生成配置

mermaid:

引擎类型:指定用于渲染 Mermaid 图表的工具,此处为 pyppeteer

engine: “pyppeteer”

浏览器路径:指定用于渲染图表的浏览器应用程序路径

path: “/Applications/Google Chrome.app”

Redis 数据库连接配置

redis:

主机地址:Redis 服务器的主机名或 IP 地址

host: “YOUR_HOST”

端口:Redis 服务器监听的端口号

port: 32582

密码:访问 Redis 服务器所需的密码

password: “YOUR_PASSWORD”

数据库编号:选择要连接的 Redis 数据库(默认值为 0)

db: “0”

S3 存储服务配置

s3:

访问密钥:AWS S3 存储服务的访问密钥

access_key: “YOUR_ACCESS_KEY”

密钥密钥:AWS S3 存储服务的密钥密钥

secret_key: “YOUR_SECRET_KEY”

终端节点:S3 服务的自定义终端节点(如使用非 AWS S3 兼容服务)

endpoint: “YOUR_ENDPOINT”

使用安全连接(HTTPS):是否启用 SSL 加密传输(默认为 false)

secure: false

存储桶名称:要操作的目标 S3 存储桶名称

bucket: “test”

Azure 语音合成订阅密钥与区域配置

azure_tts_subscription_key: “YOUR_SUBSCRIPTION_KEY”
azure_tts_region: “eastus”

科大讯飞语音相关 API 配置

iflytek_api_id: “YOUR_APP_ID”
iflytek_api_key: “YOUR_API_KEY”
iflytek_api_secret: “YOUR_API_SECRET”

MetaGPT TTI 模型访问 URL

metagpt_tti_url: “YOUR_MODEL_URL”
如果使用openai的Embedding可以参考如下配置:
api_type: “openai”
base_url: “YOU_BASE_URL”
api_key: “YOU_API_KEY”
如果使用azure的Embedding可以参考如下配置:
api_type: “azure”
base_url: “YOU_BASE_URL”
api_key: “YOU_API_KEY”
api_version: “YOU_API_VERSION”
如果使用gemini的Embedding可以参考如下配置:
api_type: “gemini”
api_key: “YOU_API_KEY”
如果使用ollama的Embedding,需要在config2.yaml文件里llm配置部分里加上max_token配置节点,比如2048。Embedding部分可以参考如下配置:
api_type: “ollama”
base_url: “YOU_BASE_URL”
model: “YOU_MODEL”
2)数据输入
数据使用源码项目MetaGPT\examples\data\rag\travel.txt文件,下面使用最简配置,输入travel.txt文件,接收一个问题,查询并打印出返回结果,代码如下:
#第7章/MetaGPTSimpleQuery.py

导入所需模块

import asyncio

从metagpt库中导入相关类与常量

from metagpt.rag.engines import SimpleEngine
from metagpt.const import EXAMPLE_DATA_PATH

定义文档数据文件路径

DOC_PATH = EXAMPLE_DATA_PATH / “rag/travel.txt”

定义异步主函数

async def main():
# 创建一个基于简单引擎(SimpleEngine)的对象,该引擎从指定的文档文件中加载数据
engine = SimpleEngine.from_docs(input_files=[DOC_PATH])
# 使用创建的引擎实例执行异步查询(aquery),询问“Bob喜欢什么?”
answer = await engine.aquery(“What does Bob like?”)
# 输出查询结果
print(answer)

当脚本作为主程序运行时,启动异步事件循环并执行main()函数

if name == “main”:
asyncio.run(main())
另外可以自定义对象,下面代码示例中,使用最简配置,定义Player对象,其中最重要的是自定义对象需满足接口,具体可以查看metagpt/rag/interface.py源码的class RAGObject(Protocol)类信息,自定义对象代码如下:
#第7章/MetaGPTDefineRAGObject.py

导入所需模块

import asyncio

从pydantic库导入BaseModel类,用于构建数据验证和序列化模型

from pydantic import BaseModel

从metagpt库中的rag.engines模块导入SimpleEngine类

from metagpt.rag.engines import SimpleEngine

定义自定义对象类Player,继承自BaseModel

在此示例中,使用最简配置,定义一个表示玩家的Player对象,其包含姓名(name)和目标(goal)属性

class Player(BaseModel):
name: str # 玩家姓名
goal: str # 玩家目标
# 实现自定义方法,返回用于RAG引擎内部索引的键值字符串
def rag_key(self):
return f"{self.name}'s goal is {self.goal}."

定义异步主函数

async def main():
# 创建两个Player对象实例,分别代表两位玩家及其目标
objs = [Player(name=“Jeff”, goal=“Top One”),
Player(name=“Mike”, goal=“Top Three”)]
# 使用Player对象列表初始化一个SimpleEngine实例
engine = SimpleEngine.from_objs(objs=objs)
# 使用创建的引擎实例执行异步查询(aquery),询问“Jeff的目标是什么?”
answer = await engine.aquery(“What is Jeff’s goal?”)
# 输出查询结果
print(answer)

当脚本作为主程序运行时,启动异步事件循环并执行main()函数

if name == “main”:
asyncio.run(main())
3)检索功能
在这个示例中,使用Faiss进行检索,其中更多参数可查看FAISSRetrieverConfig,Faiss检索示例代码如下:
#第7章/MetaGPTFAISSRetriever.py

导入所需模块

import asyncio

从metagpt库导入相关类与常量

from metagpt.rag.engines import SimpleEngine
from metagpt.rag.schema import FAISSRetrieverConfig
from metagpt.const import EXAMPLE_DATA_PATH

定义文档数据文件路径

DOC_PATH = EXAMPLE_DATA_PATH / “rag/travel.txt”

定义异步主函数

async def main():
# 创建一个基于SimpleEngine的实例,用于处理输入文档。在初始化时,指定了使用FAISSRetrieverConfig进行检索,
# 其他可能的参数配置可查阅FAISSRetrieverConfig类。这里仅使用默认配置。
engine = SimpleEngine.from_docs(input_files=[DOC_PATH], retriever_configs=[FAISSRetrieverConfig()])
# 使用创建的引擎实例执行异步查询(aquery),询问“Bob喜欢什么?”
answer = await engine.aquery(“What does Bob like?”)
# 输出查询结果
print(answer)

当脚本作为主程序运行时,启动异步事件循环并执行main()函数

if name == “main”:
asyncio.run(main())
下面使用Faiss和BM25进行混合检索,把两种检索出来的结果去重结合,代码如下:
#第7章/MetaGPTFAISSBM25Retriever.py

导入所需模块

import asyncio

从metagpt库导入相关类与常量

from metagpt.rag.engines import SimpleEngine
from metagpt.rag.schema import FAISSRetrieverConfig, BM25RetrieverConfig
from metagpt.const import EXAMPLE_DATA_PATH

定义文档数据文件路径

DOC_PATH = EXAMPLE_DATA_PATH / “rag/travel.txt”

定义异步主函数

async def main():
# 创建一个基于SimpleEngine的实例,用于处理输入文档。在初始化时,指定了使用FAISSRetrieverConfig和BM25RetrieverConfig进行混合检索,
# 即同时利用FAISS和BM25两种检索算法,并将两者检索结果去重后合并。
engine = SimpleEngine.from_docs(input_files=[DOC_PATH], retriever_configs=[FAISSRetrieverConfig(), BM25RetrieverConfig()])
# 使用创建的引擎实例执行异步查询(aquery),询问“Bob喜欢什么?”
answer = await engine.aquery(“What does Bob like?”)
# 输出查询结果
print(answer)

当脚本作为主程序运行时,启动异步事件循环并执行main()函数

if name == “main”:
asyncio.run(main())
4)检索后处理
下面使用Faiss进行检索,然后对检索出来的结果再用LLMRanker进行重排,得到最后检索的结果,代码如下:
#第7章/MetaGPTLLMRanker.py

导入所需模块

import asyncio

从metagpt库导入相关类与常量

from metagpt.rag.engines import SimpleEngine
from metagpt.rag.schema import FAISSRetrieverConfig, LLMRankerConfig
from metagpt.const import EXAMPLE_DATA_PATH

定义文档数据文件路径

DOC_PATH = EXAMPLE_DATA_PATH / “rag/travel.txt”

定义异步主函数

async def main():
# 创建一个基于SimpleEngine的实例,用于处理输入文档。在初始化时,指定了使用FAISSRetrieverConfig进行初步检索,
# 同时使用LLMRankerConfig对检索结果进行重新排序。这样可以先利用FAISS进行高效检索,再通过LLM模型对结果进行语义层面的精细打分与排序。
engine = SimpleEngine.from_docs(input_files=[DOC_PATH], retriever_configs=[FAISSRetrieverConfig()], ranker_configs=[LLMRankerConfig()])
# 使用创建的引擎实例执行异步查询(aquery),询问“Bob喜欢什么?”
answer = await engine.aquery(“What does Bob like?”)
# 输出最终经过检索与重排后的查询结果
print(answer)

当脚本作为主程序运行时,启动异步事件循环并执行main()函数

if name == “main”:
asyncio.run(main())
5)数据更新
创建engine后,可以添加文档或者对象,最重要的是,如果自定义retriever需要实现接口ModifiableRAGRetriever,代码如下:
#第7章/MetaGPTAddDocs.py

导入所需模块

import asyncio

从pydantic库导入BaseModel类,用于构建数据验证和序列化模型

from pydantic import BaseModel

从metagpt库中的rag.engines模块导入SimpleEngine类

from metagpt.rag.engines import SimpleEngine

从metagpt库导入FAISSRetrieverConfig类,用于配置FAISS检索器

from metagpt.rag.schema import FAISSRetrieverConfig

从metagpt库导入常量EXAMPLE_DATA_PATH,指向示例数据目录

from metagpt.const import EXAMPLE_DATA_PATH

定义文档数据文件路径

DOC_PATH = EXAMPLE_DATA_PATH / “rag/travel.txt”

定义自定义对象类Player,继承自BaseModel

class Player(BaseModel):
name: str # 玩家姓名
goal: str # 玩家目标
# 实现自定义方法,返回用于RAG引擎内部索引的键值字符串
def rag_key(self):
return f"{self.name}'s goal is {self.goal}."

定义异步主函数

async def main():
# 创建一个基于SimpleEngine的实例,使用FAISSRetrieverConfig配置检索器
engine = SimpleEngine.from_objs(retriever_configs=[FAISSRetrieverConfig()])
# 向引擎中添加文档资源,即travel.txt文件
engine.add_docs([DOC_PATH])
# 使用创建的引擎实例执行异步查询(aquery),询问“Bob喜欢什么?”
answer = await engine.aquery(“What does Bob like?”)
print(answer)
# 向引擎中添加自定义对象资源,即一个名为Jeff的Player对象
engine.add_objs([Player(name=“Jeff”, goal=“Top One”)])
# 使用创建的引擎实例执行异步查询(aquery),询问“Jeff的目标是什么?”
answer = await engine.aquery(“What is Jeff’s goal?”)
print(answer)

当脚本作为主程序运行时,启动异步事件循环并执行main()函数

if name == “main”:
asyncio.run(main())
6)数据保存及恢复
下面示例先把向量化相关数据保存在persist_dir目录,然后从persist_dir目录进行恢复后查询,代码如下:
#第7章/MetaGPTFromIndexQuery.py

导入所需模块

import asyncio

从metagpt库导入相关类与常量

from metagpt.rag.engines import SimpleEngine
from metagpt.rag.schema import FAISSRetrieverConfig, FAISSIndexConfig
from metagpt.const import EXAMPLE_DATA_PATH

定义文档数据文件路径

DOC_PATH = EXAMPLE_DATA_PATH / “rag/travel.txt”

定义异步主函数

async def main():
# 定义持久化存储目录
persist_dir = “./tmp_storage”
# 定义检索器配置列表,只包含FAISSRetrieverConfig一个配置
retriever_configs = [FAISSRetrieverConfig()]
# 1. 将向量化数据保存至指定目录
SimpleEngine.from_docs(input_files=[DOC_PATH], retriever_configs=retriever_configs).persist(persist_dir)
# 2. 从持久化目录加载索引,重建引擎
engine = SimpleEngine.from_index(index_config=FAISSIndexConfig(persist_path=persist_dir), retriever_configs=retriever_configs)
# 3. 使用恢复后的引擎执行异步查询(aquery),询问“Bob喜欢什么?”
answer = await engine.aquery(“What does Bob like?”)
# 输出查询结果
print(answer)

当脚本作为主程序运行时,启动异步事件循环并执行main()函数

if name == “main”:
asyncio.run(main())
7.人类介入
当谈论智能体时,通常指的是由大模型驱动的。然而,在一些实际情境中,确实希望人类介入,无论是为了项目的质量保证,在关键决策中提供指导,还是在游戏中扮演角色。接下来将讨论如何将人类纳入SOP。在这个例子中展示了如何在一个多智能体系统中集成人类参与者,使得人类可以在智能体执行任务的过程中介入并提供反馈或做出决策。这种能力在需要人工审核、关键决策支持或增强人机协作的场景中非常有用。
首先,创建一个团队,其中包括三个角色:SimpleCoder、SimpleTester和SimpleReviewer。这些角色分别负责编写代码、编写测试用例以及审查测试用例。其中,SimpleReviewer角色原本是由大模型来执行的,但现在可以通过设置is_human=True参数来让人类直接扮演这个角色。
当人类扮演SimpleReviewer时,系统会暂停等待人类的输入。人类可以直接在命令行终端中输入评论或建议,这些输入将被发送到其他智能体。这种方式允许人类轻松地与其他智能体互动,并对它们的输出作出反应。需要注意的是,为了让人类介入机制正常工作,自定义角色的_act函数中调用的Action对象必须在角色初始化时通过self.set_actions方法设置。此外,由于目前人类交互是通过命令行完成的,因此人类输入的内容需要在格式和内容上符合提示的要求,以确保后续的流程能够正确处理这些信息。
代码上面内容讲过了,就是build_customized_multi_agents.py多智能体,通过加上is_human=True参数就可以人类介入了,可以用如下命令来启动这个脚本:
python3 examples/build_customized_multi_agents.py --add_human True
这样,就可以参与到智能体交互过程中,体验在多智能体系统中作为人类参与者的感觉。
8.集成开源大模型
MetaGPT也支持开源大模型的集成,下面讲解如何集成开源大模型以获得较为稳定的代码生成结果,尽管其效果可能不及OpenAI的GPT-3.5或GPT-4,但仍能提供相对满意的输出。随着开源模型的不断更新与优化,未来有望实现更优的性能。用户在实践时,表明已知悉开源模型可能存在效果局限性。集成开源大模型按照以下步骤进行:
(1)模型部署:通过使用LLaMA-Factory、FastChat、VLLM和OLLAMA等推理仓库部署所需的大模型模型。推荐采用OpenAI兼容接口进行部署,简化集成流程。显卡资源有助于提高推理速度,CPU推理则可能较慢。各仓库的部署流程包括克隆仓库、安装依赖、指定模型路径与模板(如适用),以及启动服务。其中,OLLAMA不支持OpenAI API接口,但可通过其自身接口方式进行访问。
(2)大模型配置:针对部署为API接口的模型,通过修改config/config2.yaml文件进行配置。对于OpenAI兼容接口(如LLaMA-Factory、FastChat、VLLM),设置api_type为open_llm,指定base_url和model参数;对于OLLAMA接口,设置api_type为ollama,同样配置base_url和model。配置文件中还包括修复大模型输出结果的选项。
(3)修复大模型输出结果:鉴于开源大模型对MetaGPT角色指令的输出可能存在结构不匹配、大小写不符、JSON格式错误等问题,教程提供了修复功能。启用该功能repair_llm_output: true后,系统会在执行过程中尝试解决这些问题。用户可关注日志中带有repair_关键词的信息,并积极参与改进工作。
(4)运行使用:完成部署与配置后,用户即可通过命令行如metagpt "编写一个贪吃蛇游戏"使用集成的开源大模型进行项目输出。此外,用户还可结合所集成模型在多智能体框架MetaGPT中构建适用于各自应用场景的智能体。
10.MetaGPT与AutoGPT优劣势比较
MetaGPT与AutoGPT作为两种先进的多智能体协作框架,在功能特点、适用场景及用户体验等方面呈现出各自的优劣特性。以下是它们各自的优势与劣势分析:
1)MetaGPT的优势
(1)多智能体框架与角色专业化:MetaGPT采用多智能体协作架构,通过角色专业化设计,确保各智能体专精于特定职责,如需求分析、竞品研究、技术设计等。这种分工模式有助于提升协作效率,并能有效防止单一模型在处理复杂任务时产生“幻觉”问题。
(2)工作流管理与消息机制:MetaGPT内置工作流管理系统,能够清晰定义和管理任务流程,确保智能体间协同工作的流畅性。灵活的消息机制,如消息池和订阅系统,促进智能体间的即时通讯与信息共享,增强了整体系统的响应速度和决策能力。
(3)全面的项目执行能力:MetaGPT特别强调其在项目执行全过程中的卓越表现,包括生成详细的产品需求规格和技术设计方案,甚至具备独特的API界面生成能力,这对于快速API设计原型阶段具有显著优势。尤其在低成本、低门槛的简易软件项目开发中,MetaGPT展现出强大的竞争力。
(4)类比人类团队的工作模式:MetaGPT借鉴人类软件开发团队的高效实践,通过明确角色分工、强化协作流程,显著提升了软件开发的效率、精确度与一致性,从而优化整个项目的生命周期管理。
2)MetaGPT的劣势
(1)实现原理复杂性:相较于AutoGPT,MetaGPT的内部机制更为复杂。它为智能体设定多种角色,并配备相应的目标和Prompt模板以指导行为。这种复杂性可能导致用户在学习和操作过程中面临更高的门槛。
(2)可能的使用难度:虽然MetaGPT在诸多方面表现出色,但其复杂的多智能体框架和对特定功能(如API界面生成)的专注,可能在通用性或灵活性上不及AutoGPT。用户在应对某些非典型或需要高度自定义的场景时,可能会觉得MetaGPT不够灵活易用。
以上分析了MetaGPT的优劣势,总体来说,MetaGPT通过角色专业化、工作流管理和灵活的消息机制,以及可能的元编程技术应用,显著增强了大模型在多智能体协作环境下的性能,形成了一个通用性强、可移植性好的协作框架。

更多技术内容

更多技术内容可参见
清华《GPT多模态大模型与AI Agent智能体》书籍配套视频【陈敬雷】
更多的技术交流和探讨也欢迎加我个人微信chenjinglei66。

总结

此文章有对应的配套新书教材和视频:

【配套新书教材】
《GPT多模态大模型与AI Agent智能体》(跟我一起学人工智能)【陈敬雷编著】【清华大学出版社】
新书特色:《GPT多模态大模型与AI Agent智能体》(跟我一起学人工智能)是一本2025年清华大学出版社出版的图书,作者是陈敬雷,本书深入探讨了GPT多模态大模型与AI Agent智能体的技术原理及其在企业中的应用落地。
全书共8章,从大模型技术原理切入,逐步深入大模型训练及微调,还介绍了众多国内外主流大模型。LangChain技术、RAG检索增强生成、多模态大模型等均有深入讲解。对AI Agent智能体,从定义、原理到主流框架也都进行了深入讲解。在企业应用落地方面,本书提供了丰富的案例分析,如基于大模型的对话式推荐系统、多模态搜索、NL2SQL数据即席查询、智能客服对话机器人、多模态数字人,以及多模态具身智能等。这些案例不仅展示了大模型技术的实际应用,也为读者提供了宝贵的实践经验。
本书适合对大模型、多模态技术及AI Agent感兴趣的读者阅读,也特别适合作为高等院校本科生和研究生的教材或参考书。书中内容丰富、系统,既有理论知识的深入讲解,也有大量的实践案例和代码示例,能够帮助学生在掌握理论知识的同时,培养实际操作能力和解决问题的能力。通过阅读本书,读者将能够更好地理解大模型技术的前沿发展,并将其应用于实际工作中,推动人工智能技术的进步和创新。

【配套视频】

清华《GPT多模态大模型与AI Agent智能体》书籍配套视频【陈敬雷】
视频特色: 前沿技术深度解析,把握行业脉搏

实战驱动,掌握大模型开发全流程

智能涌现与 AGI 前瞻,抢占技术高地

上一篇:《GPT多模态大模型与AI Agent智能体》系列一》大模型技术原理 - 大模型技术的起源、思想
下一篇:DeepSeek大模型技术系列五》DeepSeek大模型基础设施全解析:支撑万亿参数模型的幕后英雄

Logo

更多推荐