12作者: anerli大约 1 个月前原帖
大家好,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作者: ww520大约 1 个月前原帖
在严格的静态类型语言中进行动态调度是很困难的。像下面这样简单的代码: ```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)