一个计算机技术爱好者与学习者

0%

基于MetaGPT实现一个订阅智能体:第四章 OSS订阅智能体

1. 前言

本章任务:

  • 了解订阅智能体
  • 了解爬虫
  • 了解MetaGPT订阅模块
  • 实现订阅智能体

2. 什么是订阅智能体?

MetaGPT提供了Agent的开发能力,Agent可以协助我们解决日常的一些问题,其中一个应用场景就是我们可以让Agent为我们关注某些想关注的信息,当有我们关注的事件发生时,Agent获取信息并进行处理,然后通过一些如邮件、微信、discord等通知渠道将处理后的信息发送给我们,我们将这类Agent称为订阅智能体。

在这里,Agent的Role是以一个“资讯订阅员”的身份为你服务,而Agent中包含的Action则主要有两种:从外界信息源中搜集信息和对搜集得到的信息进行总结。

完成上述任务后,我们可以为这个Agent开发更多额外功能:定时运行的功能和发送到通知渠道的功能。

3. 什么是爬虫?

本文中所说的爬虫是可以抓取网页内容的程序工具。
想要让Agent获取网络中的信息,需要实现爬虫进行抓取。

实现爬虫时常用的 Python 工具:

  • aiohttp:使用 aiohttp ,发起网络请求
  • beautifulsoup:使用 beautifulsoup,从HTML中提取信息

4. MetaGPT订阅模块

在MetaGPT中,metagpt.subscription模块提供了SubscriptionRunner类,与metagpt.team.Team类似,SubscriptionRunner类是提供了一个Role的运行方式,基于SubscriptionRunner类,我们可以定时触发运行一个Role,然后将Role的执行输出通知给用户,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import asyncio
from metagpt.subscription import SubscriptionRunner
from metagpt.roles import Searcher
from metagpt.schema import Message

async def trigger():
while True:
yield Message("the latest news about OpenAI")
await asyncio.sleep(3600 * 24)

async def callback(msg: Message):
print(msg.content)

async def main():
pb = SubscriptionRunner()
await pb.subscribe(Searcher(), trigger(), callback)
await pb.run()

asyncio.run(main())

从例子可以知道订阅智能体的实现主要有3个要素,分别是Role、Trigger、Pusher,即智能体本身、触发器、数据推送器。

这里的Role就是我们的Agent的实际代码实现,所以订阅智能体在代码实现上并没有什么特别的地方,可以看到上面的例子实际运行的就是MetaGPT中的Searcher Role,它早就存在了我们的MetaGPT仓库中。

不过需要注意的是,我们虽然不对订阅智能体的Role做限制,但是不是所有的Role都适合用来做订阅智能体,比如MetaGPT软件公司中的几个角色,例如产品经理、架构师、工程师等,因为当给这些Role一个需求输入时,它们的产出往往是类似的,并没有定时执行然后发送给我们的必要。所以从应用的角度出发,订阅智能体的输出应该具有实时性,相同的一个需求描述输入,输出的内容一般是会随着时间的变化而不同,例如新闻资讯、技术前沿进展、热门的开源项目等。

这里的Trigger是指Role运行的触发条件,可以是定时触发或者是某个网站有更新时触发。Trigger是个异步生成器,详情参考 https://peps.python.org/pep-0525/
这里的Pusher用于处理Role生成的信息,我们可以将数据发送到微信或者discord。

5. 实现OSS订阅智能体

5.1. 本节任务

实现一个OSS(Open Source Software)订阅智能体,它要能够从github获取热门开源项目的信息,并进行汇总分析。

5.2. 需求拆解

订阅智能体的实现主要有3个要素,分别是Role、Trigger、Pusher。
因此,我们可以订阅智能体进行拆解:
1、实现一个 OSSWatcher Role:OSS 即 Open source software,我们对OSS 智能体定位是,帮我们关注并分析热门的开源项目,当有相关信息时将信息推送给我们,这里需要确定让 OSS 从哪个网页获取信息
2、实现Trigger:指这个OSSWatcher角色运行的触发条件,可以是定时触发或者是某个网站有更新时触发
3、实现Pusher:处理OSSWatcher角色运行生成的信息,我们可以将数据发送到微信或者discord

5.3. 网络需求

教程涉中需要访问到一些国外的网站,可能会遇到网络问题,因为 aiohttp 默认不走系统代理,所以需要代理配置。
MetaGPT中已经提供了GLOBAL_PROXY参数用来表示全局代理配置,教程中遇到使用aiohttp进行请求的地方,都会将代理设置为GLOBAL_PROXY的值。
通过在config/key.yaml配置文件中,添加自己代理服务器的配置,以解决网络问题,例如:

1
GLOBAL_PROXY: http://127.0.0.1:7890  # 改成自己的代理服务器地址

如果配置 GLOBAL_PROXY 无效,可以尝试使用全局代理。

1
export https_proxy=http://127.0.0.1:7890 http_proxy=http://127.0.0.1:7890 all_proxy=socks5://127.0.0.1:7890

注意:中国大陆地区无法访问Discord,使用代理也不行,暂未找到解决办法。详情参考how to connect a discord bot through proxy

5.4. 实现OSSWatcher Role

实现OSSWatcher的Role前,需要先确定我们要 OSSWatcher 做哪些事情,即需要实现哪些 Action。
OSSWatcher可以拆分出两个Action,爬取热门开源项目数据和分析热门开源项目数据。

5.4.1. 爬取数据Action

爬虫部分的代码可以借助ChatGPT来辅助开发,询问ChatGPT之前,建议先对html代码进行精简。Prompt参考爬虫解析GitHub数据

爬取热门开源项目数据 Action ,实现代码 crawl_data.py

5.4.2. 分析数据Action

网页爬取的Action实现后,我们就可以让LLM基于爬取的网页内容进行分析了,这个Action实现比较简单,主要是写提示词。
在提示词中我们可以要求LLM从几个角度进行分析,并按照一定的格式进行输出,例如:

  • 今天榜单的整体趋势,例如哪几个编程语言比较热门、最热门的项目是哪些、主要集中在哪些领域
  • 榜单的仓库分类
  • 推荐进一步关注哪些仓库,推荐原因是什么

分析热门开源项目数据 Action,代码文件 analyze_data.py

5.4.3. 关注者Role

热门开源项目关注者 Role,代码文件 oss_watcher.py

5.5. 实现Trigger

Trigger即触发器,代表了OSSWatcher角色的执行时机,最简单的触发方式即定时触发。
Github Trending不是实时更新的,参考 Do you know when trending repositories on GitHub are usually updated?,可以了解到Github Trending更新时间大约是在 10:00 AM UTC,实测更新时间不是很准时,所以我们可以一天触发一次,选取一个比较适合自己的推送时间即可,比如每天早上9点。

基于aiocron实现Trigger,代码文件 trigger.py

5.6. 实现Pusher

Pusher就是定义了如何处理智能体生成的信息,本示例中将智能体产生的数据发送到Discord和微信。

5.6.1. 配置Discord

Discord开发者面板添加BOT,并将BOT添加到某个服务器中,并获取到Bot的Token,Bot的Token对应接下来代码中的 DISCORD_TOKEN。
具体操作步骤参考Creating a Bot Account或者《转发Discord消息到飞书》

5.6.2. 配置微信

之前MetaGPT有尝试通过微信机器人同步不同社区群的消息,不过由于引起了过大的讨论,最终关闭了该功能,当时是使用wechaty实现的,但是使用该方式较为繁琐,而且由于我们的内容是markdown格式的,直接发送微信消息阅读体验较差,所以我们需要寻找合适的微信消息发送方式。
公众号可以发送富本文消息,比较符合我们的场景,但是为了个推送的功能,开发个公众号的成本也是比较大,但是如果可以通过已有的一个公众号给我们发送消息,那实现将会非常简单。虽然微信官方没有提供类似的功能,但是已有许多的第三方公众号提供了消息推送的功能,例如server酱、wxpusher、Pushplus等,我们可以选择其中之一,例如wxpusher,它的代码是开源的,也有详细的文档,开发文档参考WxPusher微信推送服务

参考文档获取appToken,appToken 对应接下来代码中的 WXPUSHER_TOKEN。

5.6.3. Discord和微信Pusher

调用Discord API发送消息到Discord,调用WXPusher发送消息到微信,代码文件 pusher.py

5.7. 运行代码

1
2
3
4
5
export DISCORD_TOKEN=xxx.xxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
export DISCORD_CHANNEL_ID=xxxxxx
export WXPUSHER_TOKEN=AT_xxxxxxxxxxxxxxxxxxxxxx
export WXPUSHER_UIDS=UID_xxxxxxxxxxxxxxxxxxxxxxxxx
python main.py

5.8. 完整代码

本节完整代码,请参阅ai-agent-based-on-metagpt/oss-agent
关于代码的解释,请参阅《MetaGPT智能体开发入门》教程,写的非常详细了。

6. 本章作业

根据上面教程的介绍,你已经学会了如何针对具体场景开发一个实用的资讯收集助手。
现在,你可以试着完成一个能订阅自己感兴趣的资讯的Agent。

  • 根据前面你所学习的爬虫基本知识(如果你对写爬虫代码感到不熟练,使用GPT帮助你),为你的Agent自定义两个获取资讯的Action类
    • Action 1:独立实现对Github Trending页面的爬取,并获取每一个项目的 名称、URL链接、描述
    • Action 2:独立完成对Huggingface Papers页面的爬取,先获取到每一篇Paper的链接(提示:标题元素中的href标签),并通过链接访问标题的描述页面(例如:https://huggingface.co/papers/2312.03818 ),在页面中获取一篇Paper的 标题、摘要
  • 参考第三章【实现一个更复杂的Agent:技术文档助手】的内容,重写有关方法,使你的Agent能自动生成总结内容的目录,然后根据二级标题进行分块,每块内容做出对应的总结,形成一篇资讯文档
  • 自定义Agent的SubscriptionRunner类,独立实现Trigger、Pusher的功能,让你的Agent定时为通知渠道发送以上总结的资讯文档(尝试实现邮箱发送的功能,这是加分项)