12作者: anerli8 个月前原帖
大家好,HN 的朋友们,我是 Anders 和 Tom。两个月前,我们发布了一篇关于我们的 AI 测试自动化框架的帖子,获得了相当不错的关注(<a href="https://news.ycombinator.com/item?id=43796003">https://news.ycombinator.com/item?id=43796003</a>)。<p>我们收到了社区的很多积极反馈,其中最受欢迎的意见是关于我们在浏览器代理中采用的以视觉为先的设计理念。然而,许多人希望能够在测试领域之外使用底层代理。因此,今天我们发布了功能齐全的 AI 浏览器自动化框架。<p>您可以使用它来自动化网页上的任务、在没有 API 的情况下在应用之间进行集成、提取数据、测试您的网页应用,或者作为您自己浏览器代理的构建模块。<p>传统上,浏览器自动化只能通过 DOM 完成,尽管这并不是人类使用浏览器的方式。大多数浏览器代理仍然停留在这种范式中。通过以视觉为先的方法,我们避免依赖不稳定的 DOM 导航,并在各种复杂交互中表现更好,例如:<p>- 拖放交互<p>- 数据可视化、图表和表格<p>- 带有嵌套 iframe 的遗留应用<p>- 以 Canvas 和 webGL 为重的网站(如设计工具或照片编辑)<p>- 通过浏览器流式传输的远程桌面<p>为了准确与浏览器进行交互,我们使用视觉基础模型根据像素坐标执行精确操作。Magnitude 使用的模型必须足够智能,以规划操作,同时也能够执行这些操作。并不是所有模型都既聪明又具有视觉基础。我们强烈推荐 Claude Sonnet 4 以获得最佳性能,但如果您更喜欢开源,我们也支持 Qwen-2.5-VL 72B。<p>大多数浏览器代理从未投入生产。这是因为(1)上述提到的不稳定的 DOM 导航,以及(2)大多数浏览器代理提供的控制能力不足。主流范式是您给代理一个高层次的任务和工具,然后希望一切顺利。然而,这对于需要可靠和具体的生产自动化来说很快就会失效。使用 Magnitude,您可以通过我们的 `act()` 和 `extract()` 语法对代理进行细粒度控制,并根据需要与您自己的代码混合使用。您还可以在操作和代理级别完全控制提示。<p>```ts<p>&#x2F;&#x2F; Magnitude 可以处理高层次的任务<p>await agent.act(&#x27;创建一个问题&#x27;, {<p><pre><code> &#x2F;&#x2F; 可选地传递代理在适当情况下将使用的数据 data: { title: &#x27;使用 Magnitude&#x27;, description: &#x27;运行 &quot;npx create-magnitude-app&quot; 并按照说明操作&#x27;, }, </code></pre> });<p>&#x2F;&#x2F; 它也可以处理低层次的操作<p>await agent.act(&#x27;将 &quot;使用 Magnitude&quot; 拖到进行中的列顶部&#x27;);<p>&#x2F;&#x2F; 根据与提供的 zod 模式匹配的 DOM 内容智能提取数据<p>const tasks = await agent.extract(<p><pre><code> &#x27;列出进行中的问题&#x27;, z.array(z.object({ title: z.string(), description: z.string(), &#x2F;&#x2F; 代理可以提取现有数据或新的见解 difficulty: z.number().describe(&#x27;请给出 1-5 的难度评分&#x27;) })), </code></pre> );<p>```<p>我们有一个设置脚本,可以轻松开始使用示例,只需运行 &quot;npx create-magnitude-app&quot;。我们期待听到您的想法!<p>仓库:<a href="https://github.com/magnitudedev/magnitude">https://github.com/magnitudedev/magnitude</a>
3作者: ww5208 个月前原帖
在严格的静态类型语言中进行动态调度是很困难的。像下面这样简单的代码: ```zig map.put("add", add); map.put("hello", hello); fn add(a: i32, b: i32) i32 { return a + b; } fn hello() []const u8 { return "Hello World"; } ``` 是不可行的,因为映射的键值对的值类型必须相同,但所有函数的类型都是不同的。动态调用具有不同参数数量、不同参数类型和不同返回类型的函数是非常困难的。 其他语言通常使用动态类型、运行时反射、宏,或者传入一个大的泛型参数,让函数自行处理。 在ZigJR中,我使用Zig的编译时特性进行编译时反射,以确定函数的参数类型、返回类型和返回错误。我将这些信息打包成一个特定的调用对象,并使用接口模式生成一个统一类型的对象,以便放入映射中。这并不容易,但可以实现。 [1] [1] [https://github.com/williamw520/zigjr/blob/master/src/rpc/json_call.zig](https://github.com/williamw520/zigjr/blob/master/src/rpc/json_call.zig)
3作者: jbryu8 个月前原帖
我在一台单一的Hetzner CCX23 x86云服务器上托管一个回合制多人浏览器游戏(4个虚拟CPU,16GB内存,80GB磁盘)。后端使用Node.js和Socket.IO构建,并通过Docker Swarm运行。我还使用Traefik进行负载均衡。 匹配机制采用轮询分片的方法:每个房间始终由同一个后端实例处理,这让我可以将游戏状态保存在内存中,并在不使用Redis的情况下进行横向扩展。 现在遇到的问题是: 在大约500名同时在线玩家和约60个房间(每个房间最多8名玩家)时,我观察到CPU使用率较低,但事件循环延迟较高。游戏中的一个功能是在玩家回合期间输入文字——每个限制的按键都会实时广播给其他玩家。如果我移除这个逻辑,我可以轻松处理1000名以上的玩家。 在我的单服务器上扩展后端实例并没有帮助。我原本期待每个后端实例的负载减少会有所改善,但我仍然在大约500名玩家时遇到同样的限制。这让我觉得瓶颈并不是CPU或应用逻辑,而是更深层次的原因。但我不太确定是什么。 在500名玩家时的一些服务器指标: - CPU:每个核心25%(根据htop) - PPS:约3000进/约3000出 - 带宽:约100KBps进/约800KBps出 500名同时在线玩家是否只是我单服务器设置的一个现实上限,还是有什么配置错误?我知道扩展新服务器应该能解决这个问题,但我想先在网上咨询一下,看看我是否遗漏了什么。我对多人架构还很陌生,因此任何见解都将不胜感激。
2作者: kc38 个月前原帖
随着Mozilla Pocket将在大约两周后关闭,我想分享一个快速工具,以便在迁移到linkding时对其他人有所帮助。 在审查了自托管的Pocket替代方案后,我决定linkding具有最佳的功能组合。(linkding的创建者做得非常出色——不过,我计划最终创建一个基于linkding的新工具,增加一些作者表示不想包含的新功能【我目前正在使用一个分支,但我想进一步扩展它】。) 关于关闭公告的HN讨论串: [https://news.ycombinator.com/item?id=44063662](https://news.ycombinator.com/item?id=44063662) Mozilla公告: [https://support.mozilla.org/en-US/kb/future-of-pocket](https://support.mozilla.org/en-US/kb/future-of-pocket) linkding: [https://linkding.link/](https://linkding.link/) 请注意,Pocket将于2025年7月8日关闭,但导出服务将持续提供,直到2025年10月8日。 【编辑】修正标题中的错字和格式问题。