1. OSS订阅智能体的思考与优化
前面的教程中,沃恩实现了OSS订阅智能体,将Github Trending的信息由智能体总结之后,通过discord或者微信的渠道发送给了我们。
订阅智能体的实现过程,要分别完成SubscriptionRunner运行需要的三个要素:Role、Trigger、Pusher。
Trigger是触发器,我们实现了一个定时触发器;Pusher是推送器,我们实现了将消息发送到discord/微信;Pusher,Trigger这二者比较固定,实现后可以复用。
比较特殊的是Role的实现,订阅智能体设计思路基本就是源数据获取+信息提取+总结分析,我们的OSS订阅智能体就是:aiohttp爬取Github Trending -> bs4解析html提取榜单信息 -> LLM总结分析。
通过自己写智能体的方式虽然完成了订阅智能体的功能,但是这个智能体的作用是被局限在某一特定领域的,当我们需要订阅另外一个数据源的分析结果时,我们需要手动再写一个Role。基于上面的分析,我们知道,Role并不能像Pusher,Trigger这样通用,这就会让我们的订阅智能体实现起来需要较多的开发成本。
那有没有什么办法让Role变得通用呢?可以有两个思路:
思路一:我们实现一个智能体,它可以爬取我们要求的任意网站,然后进行数据的分析,最后再总结。
思路二:实现一个可以写订阅智能体代码的智能体,这个智能体可以浏览我们需要爬取的网页,写爬虫和网页信息提取的代码,生成Role,甚至根据我们的订阅需求,直接完整调用SubscriptionRunner,实现我们的订阅需求。
2. 通用订阅智能体设计思路
2.1. 思路一:爬取任意网站的智能体
实现一个可以爬取我们要求的任意网站的智能体,首先要有一个通用的网页数据获取方式。
在前面的OSS订阅智能体中,我们使用了aiohttp成功爬取了Github Trending的数据,但如果对爬虫有进一步了解的话,就知道使用这种传统的爬取方式会有一定的限制,在面对取动态页面,需要执行JavaScript代码或绕过简单的反爬措施等需求时,都需要花费更高的成本。
相比之下,我们可以使用浏览器自动化的方式来爬取网页,从而让我们的网页爬取实现更加简单,python中也有很多的浏览器自动化工具,例如Selenium、Playwright,浏览器自动化是通过编程方式控制和操作浏览器的过程,即通过浏览器直接打开网页,所以正常人可以浏览的页面,基本都可以通过这个方式进行爬取。
初步来看,浏览器自动化的爬取方式可以满足我们的通用爬取需求。
aiohttp使用较简单,主打高性能场景,但是我们的订阅智能体爬取需求,并不需要太高的性能,因为一般订阅的触发时间间隔也比较长,一次运行也不需要爬取非常多数量的网页;浏览器自动化的爬取方式性能虽然较差,但是也完全能够满足我们的需求,同时又可以覆盖较多的爬虫场景,所以这边使用浏览器自动化的爬取方式是非常合适的。
根据上面的分析,我们可以有一种较为通用的爬取网页的方式。
但是不幸的是,我们并不能找到一个通用的网页特定信息提取方式,比如Github Trending的数据爬取之后,在没人工和大模型的介入的前提下,我们并不能从网页中提取出今天的Github Trending列表。
当然,我们也可以选择让大模型来帮我们先提取信息,但是,明显这会需要消耗很多token,因为一般情况下,网页中会有大量的与我们主题无关的信息,所以使用这种方式,很大部分的token都是浪费了的,特别地,因为订阅智能体是定时触发,那么这个成本是直线上升的。那有没有什么方式可以降低这个成本呢?有的,那就是我们的思路二:会写订阅智能体的智能体。
2.2. 思路二:会写订阅智能体的智能体
我们在前面的OSS订阅智能体实现过程中,让chatgpt帮助我们生成了Github Trending的爬取代码,我们发现,当我们把html内容和提取需求提供给大模型,大模型是可以写出正确的爬虫代码的,所以让大模型帮我们写爬虫代码是可行的。
另外需要做的主要是需要解决html内容过长的问题,一是减少token消耗,二是防止上下文过长导致请求失败。
因此,通过以上两种技术实现路线分析,我们需要通过思路二来实现我们的通用订阅智能体。
接下来,我们主要探讨一下思路二的实现路线。
1、上述网页的爬取的结论仍然适用,使用浏览器自动化的方式爬取网页
2、让大模型写从html中提取用户需要的数据,把获取到网页内容提取的代码和浏览器自动化的方式爬取网页的代码进行结合,就可以得到爬取指定网页信息的Action
3、将提取后的数据,让大模型进行处理和分析,这就得到网页数据分析的Action
4、将这两个Action组合,就可以得到一个特定网页的Watcher Role
当然,这里还有很多个问题没解决,例如,待爬取的网页URL、网页数据提取需求、分析需求等怎么获取,写爬虫代码时的html该如何简化,Role实现后该如何运行等,我们将在接下来一个个解决。
3. Role和Action设计
为了实现通用订阅智能体,我们计划设计两个Role,分别是订阅助手和爬虫工程师。
整个工作流程如下:
1、用户给出订阅某个站点信息的需求。
2、订阅助手把用户需求转换为标准的订阅格式。对应Action ParseSubRequirement
3、爬虫工程师基于Playwright获取网页,并且调用LLM编写解析网页的代码。对应Action WriteCrawlerCode
4、订阅助手基于Playwright获取网页,调用爬虫工程师写的代码解析网页,解析后的内容调用LLM进行总结。对应Action ParseSubRequirement
5、总结后的内容,推送到微信或Discord。
4. 完整代码
本章完整代码,请参阅ai-agent-based-on-metagpt/universal-subscription-agent
关于代码的解释,请参阅《MetaGPT智能体开发入门》教程,写的非常详细了。
注意需要安装playwright依赖:
1 | pip install 'metagpt[playwright]' |
5. 本章作业
1、根据“通用订阅智能体设计思路”中提供的思路一,尝试实现思路一,即使用llm提取出需要的信息而不是写爬虫代码。
2、目前,订阅智能体是通过RunSubscription运行的,即RunSubscription这个action,不仅创建了订阅智能体代码,并启动了SubscriptionRunner,这会让我们的RunSubscription一直无法退出,请尝试将二者分离,即从RunSubscription分离出AddSubscriptionTask的action,并且让SubscriptionRunner单独运行(可以是同一个进程也可以是不同的进程)。
测试用例:
1 | 从36kr创投平台融资快报 - 36氪爬取所有初创企业融资的信息,获取标题,链接, 时间,总结今天的融资新闻,然后在14:55发送给我 |