【AI Agent系列】【MetaGPT】总结这段时间学习MetaGPT的一些学习方法和感悟

简介: 【AI Agent系列】【MetaGPT】总结这段时间学习MetaGPT的一些学习方法和感悟

跟着《MetaGPT智能体开发入门》课程学习了近两周,原本是抱着试试看的心态,没想到自己竟然全程跟了下来。期间踩坑颇多,但也收获颇多,特写个总结回顾一下课程内容和沉淀下自己的收获,同时把我的学习方法记下来,希望后来学习的人能从中获得一点点的灵感或方向。

0. 个人背景

通过标题序号也可能猜出来,下标从0开始,我是一个程序员,不过是C++程序员。

  • Python:能写hello world,零零碎碎的知识,不系统,可以在代码上缝缝补补,但干不了大事。
  • 大模型:刚入门,知道里面的概念(Prompt、Function Calling、Agent等),基本没实操,只会调用OpenAI的一个对话接口(问:OpenAI一共有几个接口😀?)。
  • 爬虫:小白

所以对于本课程,我可能比小白好那么一丢丢,但不多。

1. 我的学习方法

下面说下我的学习方法,这可能不适合所有人,但是希望能对大家有点启发或帮助。

1.1 先跑通demo

教程有示例代码,可以不理解代码的意思,先试着跑通demo。作用有二:

  • 一是心里有底,路通了。既然路通了,结果好坏是有很多方法去调试的(断点也好、日志也罢),就算一行一行运行,也终究能调出大差不差的结果,毕竟demo一般也就不超过百行有效代码。
  • 二是有了成就感。无论懂不懂,我都能看到结果了,这样才有兴趣去深究。

可能有的同学会问demo不通怎么办?

这就考验你的debug问题的能力和运气了。说实话,我也没有很好的办法,只能一点点去debug、搜索、各种试…看过我系列文章的同学都能看出来,我踩得坑真的不少,基本是一步一坑…但是也一步一坑地走了下来。

但无论如何,想尽各种办法跑通示例demo一定是第一步。

1.2 搞清数据流

以我的经验来讲,快速入门了解某段程序最有效的方法,是抓住一个输出,或输入,去捋数据流。你可以看不懂架构的设计,但是一定得知道数据通路

在看数据流的过程,你就会自然而然的知道整个过程涉及哪些模块,每个模块的作用、依赖是什么,从而对整个程序有个宏观的认知。

可以看下我学习过程中绘制的各种图,很丑,但能凑合看出一些东西。

找到自己的画图风格,即使你画的不标准,不适合给别人看,但你能画出来,对程序的理解也是有帮助的。

1.3 有选择地看源码

源码太多,肯定看不过来,也不知道从哪开始看。根据数据流,或者过程中踩得坑,带着问题去看源码最有效

例如:

再比如,下面我要与大家探讨的智能体运行机制,其实就是带着问题去看的。

2. 从一个坑开始,看智能体运行机制

我看这部分的源码的起因,源自第三章作业,打印数字的一个坑。智能体run的时候,必须传入一个字符串,否则不运行,这是当时调试时浪费了我很久时间的一个坑。当时留了个TODO。后面详细了解了下智能体的运行机制,可以看下这篇文章,在这里也简单与大家交流下。

这是官方的智能体运行周期图,从_observe开始,经过思考、行动,最后将结果发送出去。

这是我根据Role的run函数画出来的一个智能体的运行的数据流(欢迎批评指正)。

跟着图,看下源码:

@role_raise_decorator
async def run(self, with_message=None) -> Message | None:
    """Observe, and think and act based on the results of the observation"""
    if with_message:
        msg = None
        if isinstance(with_message, str):
            msg = Message(content=with_message)
        elif isinstance(with_message, Message):
            msg = with_message
        elif isinstance(with_message, list):
            msg = Message(content="\n".join(with_message))
        if not msg.cause_by:
            msg.cause_by = UserRequirement
        self.put_message(msg)
    if not await self._observe():
        # If there is no new information, suspend and wait
        logger.info(f"{self._setting}: no news. waiting.")
        return
    rsp = await self.react()
    # Reset the next action to be taken.
    self.rc.todo = None
    # Send the response message to the Environment object to have it relay the message to the subscribers.
    self.publish_message(rsp)
    return rsp

(1) 首先是对 with_message参数的处理,如果with_message参数不是None,会执行下面指令:

self.put_message(msg)
  • self.put_message(msg)干了什么?
  • 将msg放到自身的msg_buffer中
def put_message(self, message):
        """Place the message into the Role object's private message buffer."""
        if not message:
            return
        self.rc.msg_buffer.push(message)

(2)执行 self._observe()函数,如果返回0或false,会进入if not await self._observe()的条件内,直接return,不触发后续动作的执行。

源码如下:

async def _observe(self, ignore_memory=False) -> int:
        """Prepare new messages for processing from the message buffer and other sources."""
        # Read unprocessed messages from the msg buffer.
        news = []
        if self.recovered: 
            news = [self.latest_observed_msg] if self.latest_observed_msg else []
        if not news:
            news = self.rc.msg_buffer.pop_all()
        # Store the read messages in your own memory to prevent duplicate processing.
        old_messages = [] if ignore_memory else self.rc.memory.get()
        self.rc.memory.add_batch(news)
        # Filter out messages of interest.
        self.rc.news = [
            n for n in news if (n.cause_by in self.rc.watch or self.name in n.send_to) and n not in old_messages
        ]
        self.latest_observed_msg = self.rc.news[-1] if self.rc.news else None  # record the latest observed msg
        # Design Rules:
        # If you need to further categorize Message objects, you can do so using the Message.set_meta function.
        # msg_buffer is a receiving buffer, avoid adding message data and operations to msg_buffer.
        news_text = [f"{i.role}: {i.content[:20]}..." for i in self.rc.news]
        if news_text:
            logger.debug(f"{self._setting} observed: {news_text}")
        return len(self.rc.news)
  • news = self.rc.msg_buffer.pop_all()取出msg_buffer中的所有消息。
  • 重点在这一句代码,从news中筛选出本role关注的消息
self.rc.news = [
         n for n in news if (n.cause_by in self.rc.watch or self.name in n.send_to) and n not in old_messages
     ]
  • 关注的消息:self.rc.watch或者n.send_to
  • watch的内容,可以通过_watch函数设置
def _watch(self, actions: Iterable[Type[Action]] | Iterable[Action]):
        """Watch Actions of interest. Role will select Messages caused by these Actions from its personal message
        buffer during _observe.
        """
        self.rc.watch = {any_to_str(t) for t in actions}

看到这,是不是对刚开始那个必须设置一个msg才能run的坑有了点想法?

  • 没有msg输入,就没有publish_message,_observe函数观察不到信息,就直接return了。

(3)_observe到信息之后,就是思考+动作的react函数了,简单看下,这块还没仔细看,就不讲了,怕误人子弟。

async def react(self) -> Message:
        """Entry to one of three strategies by which Role reacts to the observed Message"""
        if self.rc.react_mode == RoleReactMode.REACT:
            rsp = await self._react()
        elif self.rc.react_mode == RoleReactMode.BY_ORDER:
            rsp = await self._act_by_order()
        elif self.rc.react_mode == RoleReactMode.PLAN_AND_ACT:
            rsp = await self._plan_and_act()
        self._set_state(state=-1)  # current reaction is complete, reset state to -1 and todo back to None
        return rsp

理解了单智能体的运行周期后,很容易理解多智能体间的协作。

看下图(图片来自:https://docs.deepwisdom.ai/main/zh/guide/tutorials/multi_agent_101.html):

其实就是:

(1)每一个Role都在不断观察环境中的信息(_observe函数)

(2)当观察到自己想要的信息后,就会触发后续相应的动作

(3)如果没有观察到想要的信息,则会一直循环观察等待

(4)执行完动作后,会将产生的msg放到环境中(publish_message),供其它Role智能体来使用。

拿我们实现过的例子来看(【AI Agent系列】【MetaGPT】7. 一句话订阅专属信息 - 订阅智能体进阶,实现一个更通用的订阅智能体):

class SubscriptionAssistant(Role):
    """Analyze user subscription requirements."""
    name: str = "同学小张的订阅助手"
    profile: str = "Subscription Assistant"
    goal: str = "analyze user subscription requirements to provide personalized subscription services."
    constraints: str = "utilize the same language as the User Requirement"
    def __init__(self, **kwargs) -> None:
        super().__init__(**kwargs)
        self._init_actions([ParseSubRequirement, RunSubscription]) ## 2. 先解析用户需求,然后运行订阅
        self._watch([UserRequirement, WriteCrawlerCode])  ## 触发

我们实现了一个SubscriptionAssistant的智能体,它_watch了UserRequirement用户消息和WriteCrawlerCode消息。

运行后,它就会_observe环境:

  • 当用户输入信息时,环境中存在了UserRequirement消息,它_observe到了,就会触发后续相应动作。从而实现了与用户的协作。
  • 当其它智能体的WriteCrawlerCode执行完毕,会向环境中写入执行结果的msg,来源(cause_by标记为WriteCrawlerCode),然后SubscriptionAssistant的_observe观察到了,就会触发后续相应动作。从而实现了与其它智能体的协作,也就是多智能体间的协作。

3. 本次课程的收获和感悟

3.1 收获

  • 第一个肯定是 MetaGPT 入门了,对Agent算是有了一个初步的系统的认知。
  • 其次,Python的一些零零散散的知识和用法。比如:
  • 直接在Python中调用系统命令来自动执行程序subprocess(第三章)
  • Python推送微信消息(第四章)
  • Python推送邮箱消息(第四章)
  • GPT写小说的步骤(第五章)
  • 最简单的爬虫程序怎么写(第四章、第五章)

3.2 感悟

  1. MetaGPT目前是一个Agent实现框架,是一个个角色和动作的抽象。要想实现Agent,感觉最重要的还是SOP(标准作业程序),只有有了SOP,才知道怎么定义一个个角色和动作,才知道需要怎么串联每个角色和每个动作。
  2. 目前只是入门,没有具体的需求,所以认识很有限,所以我上面讲的大家选择性的听听即可,希望能给大家一点启发。
  3. 希望后面有需求可以一起讨论学习。
  4. 我也会持续学习MetaGPT教程和源码(官方例子可以开始尝试研究了)。

本文就到这,能力有限,希望大家批评指正。

弱弱地说:欢迎 点赞 + 关注 👏,促使我持续学习,持续干货输出。

+v: jasper_8017 一起交流💬,一起进步💪。微信公众号也可搜【同学小张】 🙏

4. MetaGPT入门系列文章

相关文章
|
5月前
|
人工智能 运维 Java
Spring AI Alibaba Admin 开源!以数据为中心的 Agent 开发平台
Spring AI Alibaba Admin 正式发布!一站式实现 Prompt 管理、动态热更新、评测集构建、自动化评估与全链路可观测,助力企业高效构建可信赖的 AI Agent 应用。开源共建,现已上线!
6078 82
|
6月前
|
存储 人工智能 测试技术
手把手带你入门AI智能体:从核心概念到第一个能跑的Agent
AI智能体是一种能感知环境、自主决策并执行任务的人工智能系统。它不仅能生成回应,还可通过工具使用、计划制定和记忆管理完成复杂工作,如自动化测试、脚本编写、缺陷分析等。核心包括大语言模型(LLM)、任务规划、工具调用和记忆系统。通过实践可逐步构建高效智能体,提升软件测试效率与质量。
|
5月前
|
人工智能 搜索推荐 数据可视化
当AI学会“使用工具”:智能体(Agent)如何重塑人机交互
当AI学会“使用工具”:智能体(Agent)如何重塑人机交互
557 115
|
5月前
|
人工智能 自然语言处理 安全
从工具到伙伴:AI代理(Agent)是下一场革命
从工具到伙伴:AI代理(Agent)是下一场革命
537 117
|
6月前
|
存储 人工智能 搜索推荐
一种专为AI代理设计的内存层,能够在交互过程中记忆、学习和进化
Mem0 是专为 AI 代理设计的内存层,支持记忆、学习与进化。提供多种记忆类型,可快速集成,适用于开源与托管场景,助力 AI 代理高效交互与成长。
676 123
一种专为AI代理设计的内存层,能够在交互过程中记忆、学习和进化
|
5月前
|
人工智能 定位技术 API
智能体(Agent):AI不再只是聊天,而是能替你干活
智能体(Agent):AI不再只是聊天,而是能替你干活
1123 99
|
6月前
|
机器学习/深度学习 人工智能 自然语言处理
迁移学习:让小数据也能驱动AI大模型
迁移学习:让小数据也能驱动AI大模型
402 99
|
5月前
|
人工智能 缓存 运维
【智造】AI应用实战:6个agent搞定复杂指令和工具膨胀
本文介绍联调造数场景下的AI应用演进:从单Agent模式到多Agent协同的架构升级。针对复杂指令执行不准、响应慢等问题,通过意图识别、工具引擎、推理执行等多Agent分工协作,结合工程化手段提升准确性与效率,并分享了关键设计思路与实践心得。
844 20
【智造】AI应用实战:6个agent搞定复杂指令和工具膨胀
|
人工智能 Cloud Native 搜索推荐
【2025云栖大会】阿里云AI搜索年度发布:开启Agent时代,重构搜索新范式
2025云栖大会阿里云AI搜索专场上,发布了年度AI搜索技术与产品升级成果,推出Agentic Search架构创新与云原生引擎技术突破,实现从“信息匹配”到“智能问题解决”的跨越,支持多模态检索、百亿向量处理,助力企业降本增效,推动搜索迈向主动服务新时代。
633 0