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 | import asyncio |
从例子可以知道订阅智能体的实现主要有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 | export DISCORD_TOKEN=xxx.xxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx |
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定时为通知渠道发送以上总结的资讯文档(尝试实现邮箱发送的功能,这是加分项)