Obscura:30MB的轻量浏览器
每天早晨,thinkidiot.com/digest/daily发布一个简短的AI新闻摘要,没有一个人类参与。三个模型负责撰写、审核和配图,全部运行在我家里的一台机器上——一台放在桌上整夜嗡嗡作响的DGX Spark。我一开始就给自己定了一条规则:一切都发生在那台盒子上,使用免费开源工具,我应该能够忘记这整个东西的存在。
很长一段时间我无法忘记它,因为有一个部分一直在把我拖回来。写作没问题,图片没问题,发布没问题,但有一件事一直在失败:你能想象到的最基本的步骤——去一个网站阅读它的内容。
如果这听起来应该是容易的部分,请跟我一起,因为事实证明这是整个项目中最难的问题。最终解决它的是一个如此之小的浏览器,它以单个文件的形式发布,它比我添加的任何模型都更多地改变了我的早晨。
1、为什么阅读网站是困难的部分
摘要有一个承诺,其他一切都依赖于它:每个故事都要对照原始来源进行核实。不是公告的摘要,不是关于论文的推文,而是新闻最初出现的实际页面。想象一个记者在打印谣言之前拒绝刊发,直到她亲自阅读了文件,这就是我的管道所遵循的规则。
如此严格是有非常实际的原因的。给语言模型一个来自聚合器的两行片段并要求摘要,它会兴高采烈地编造片段遗漏的细节,用自信的语气,没有一丝猜测的迹象。一个听起来确定但事实错误的新闻摘要比没有摘要更糟糕。所以收集新闻的智能体必须打开真实的页面阅读真实的文字。
这就是障碍所在,而且比看起来更高。大网站不喜欢机器人,所以它们运行检查试图在显示任何内容之前发现自动化浏览器。我的管道使用Chrome的"无头"模式,这只是意味着没有窗口运行的Chrome,无头Chrome从一英里外就闻起来像机器人。智能体会收到一个谜题页面、一个cookie墙或一个空白响应,而不是文章,而且来源越重要,关门的可能性就越大。
所以我的早晨形成了一种我后来害怕的模式。一个来源会悄悄开始拒绝智能体,一个获取会返回空或半空的内容,那一天的期刊会比我想要的更多地依赖二手报道。整个管道的重点是找到并阅读原始新闻,而找到并阅读原始新闻是它无法可靠做到的一件事。我会在喝咖啡时发现这个差距,登录Spark,调整设置,让事情勉强运行,直到下一个网站升起吊桥。
2、我不引以为豪的变通办法
我的修复方法,持续了好几天,是让研究智能体一次访问一个来源。它会打开一个网站,等待Chrome加载或失败,如果失败就重试,然后移至下一个,就像一个有坏浏览器的耐心实习生。我添加的每个来源都让夜间运行时间更长,每个新网站都是一个更容易被阻止的地方。
必须一次一个是有原因的。Chrome很重,每个副本在加载单个页面之前就需要大约200MB内存。在我的Spark上,这些内存已经属于三个模型:Nemotron 3.5 Lightning负责研究,Qwen 3.8负责撰写期刊,SenseNova U1.5负责绘制信息图。在它们旁边运行一群Chrome副本从来不是一个选项,所以智能体排队逐个访问网站。
Chrome也从不单独行动,这是另一种问题。要从代码驱动它,你需要Node、一个叫Puppeteer的库、一个特殊的Chrome自动化构建版本,以及所有三个版本互相兼容。对于一个应该在早上6点安静运行的任务来说,这有太多活动部件,而这台机器的真正目的是运行模型。
明显的逃跑方式在我甚至考虑之前就被排除了。付费抓取服务和租用的浏览器农场会在一夜之间解决阻止问题,但它们也会打破我唯一的规则:它在我的桌子上运行,使用开源工具,没有任何按请求收费的东西。所以我忍受着胶带修补,老实说,我一直找理由处理管道的任何部分,除了这个。
3、好消息让事情变得更糟
几周前,管道的创意部分终于完成了。我添加了SenseNova U1.5来为每期绘制信息图,此前一个图像模型一直破坏它试图写入的每个单词。第一次,整个摘要——文字、标题和一张你能真正阅读的图片——都从我家里一台盒子上的模型中产出。直到现在,我会称这是项目有史以来最大的升级。
它也照亮了弱点。一旦文字和图片都稳定了,期刊中剩下的每个缺陷都追溯到同一个地方:一个一直被拒之门外的获取步骤。一个建立在智能体从未能够阅读的页面上的精美撰写的摘要,仍然只是一个精心打扮的猜测。
4、我确信是假的帖子
Obscura找到了我,就像现在大多数工具找到人一样,通过一个在LinkedIn上病毒式传播的帖子,数字看起来是编造的。一个完整的浏览器在单个70MB文件中,使用大约30MB内存,而Chrome使用200MB以上,以85毫秒而不是500毫秒加载页面,并且开箱即用就能绕过机器人检查。我已经被足够多的"奇迹"抓取工具烧过,我的第一本能是关闭标签页。
它是一个没有窗口的浏览器,为程序而非人类构建,用Rust编写并作为免费开源发布。
它使用Chrome使用的相同引擎运行网站的JavaScript,并且它说Chrome使用的相同控制语言(Chrome DevTools Protocol,如果你想知道名字的话),所以像Puppeteer这样为驱动Chrome而构建的工具可以驱动Obscura而不会注意到替换。它里面没有隐藏的Chrome,周围也不需要Node,因为它自己绘制页面并作为一个可下载文件到达。
5、实际发生了什么
我以最谨慎的方式开始,让Obscura与我现有的设置并排运行,并将我的旧脚本指向它,其他什么都不改变。
那就是整个迁移,因为我的脚本真的无法分辨它们在与什么新东西对话。Chrome仍然安装着,所以我可以并排运行两者,在信任任何东西之前逐个来源比较每个返回的内容。三件事在真实流量通过后几乎立即改变了。
首先,那些已经关闭多天的门打开了。那些曾经用谜题页面迎接智能体的网站现在交出了文章,我已经将最恶劣的违规者转移到Obscura的额外隐身构建上以防万一。对于摘要来说,这意味着一件具体的事情:每个摘要现在都是从原始页面撰写的,因为智能体终于可以到达它,而不是从别人的转述中撰写。当我说新闻现在被核实时,这正是我的意思,这个项目一直绊倒的问题就这样消失了。
其次,文本变得更干净,而我没有改变任何提示。我期望广告和跟踪器阻止对速度有影响,结果它对输出内容有影响。更少的cookie横幅和"立即订阅"弹窗最终出现在抓取的文本中,所以更少的它们最终出现在撰写期刊的模型面前,我后来删除了一堆提示指令,它们的唯一工作是将新闻通讯弹窗排除在摘要之外。
第三,一次访问一个网站的时代终于结束了。每个副本大约30MB,Obscura足够轻量,可以同时获取所有来源,在同一台持有三个模型内存的机器上。研究循环曾经在列表中艰难跋涉,现在并行获取所有内容,夜间运行时间变短了,添加新来源不再从我做内存数学开始。
把所有这些放在一起,早晨终于看起来像我开始时画的草图。调度器触发,Obscura在来源中展开并带回干净的页面,Nemotron阅读原始内容并挑选故事,Qwen撰写它们,SenseNova绘制图形,网站发布,全部在一个盒子上,除了完成的摘要外没有任何东西离开它。
6、下一步,以及你应该尝试吗
当前设置是刻意谨慎的:Obscura在我旧脚本后面代替Chrome,最敌对的来源使用隐身构建。下一步是从获取阶段完全删除Node,因为Obscura有自己的命令来并行抓取多个页面,到那时整个摘要变成一个小二进制文件、三个本地模型和一个调度器。更新一个文件也比保持Node、Puppeteer和Chrome构建版本一致要好。
那么,你应该把这个指向你自己的抓取器吗?如果你抓取网站、构建需要阅读网络的智能体,或者运行任何依赖Chrome行为的无人值守任务,我会毫不犹豫地说是。它是免费的,许可证是Apache-2.0,安装只需一条命令,你可以在承诺之前将其与当前设置并排运行并比较结果。
原文链接:A 30MB Rust Browser Fixed the Worst Part of My AI News Pipeline
汇智网翻译整理,转载请标明出处