Huginn 系统设计详解

date
Oct 3, 2023
slug
huginn-system-design-explained
status
Published
summary
Huginn 是一个开源的自动化工具,允许用户自定义流程以完成特定任务,市面上也有很多类似的产品,比如说国外的 Zapier、n8n 和 IFTTT,以及国内的腾讯轻联,不同于它们,Huginn 的系统设计比较特殊,它主要依赖于一个名为 "Agent" 的概念来构建流程
tags
RSS
产品设计
LLMs
产品体验
type
Post

前言

Huginn 是一个开源的自动化工具,允许用户自定义流程以完成特定任务,市面上也有很多类似的产品,比如说国外的 Zapier、n8n 和 IFTTT,以及国内的腾讯轻联,不同于它们,Huginn 的系统设计比较特殊,它主要依赖于一个名为 "Agent" 的概念来构建流程。

Huginn 的特殊之处

市面上大多数产品都是基于 "Trigger-Action" 模型,这一整套的运行规则和逻辑是目前最为通用和应用广泛的。这一类的产品通常是让你首先新建一个流程,在流程中设置一个触发器,告诉系统在什么情况下触发流程,然后再让你去添加一些执行动作,例如说发送短信、邮件、系统通知等等。
而在 Huginn 中,你可以直接添加一个 Agent,Agent 是 Huginn 的核心运行组件,作为执行特定任务的独立单元。它可以接收输入,并根据预定规则执行各种动作。Agent 涵盖了第三方服务、内部组件等等元素,有 Web 源、RSS 源、数据库查询等,也有发送电子邮件、推送通知等。不同的 Agent 可以通过事件触发和数据传输进行相互连接,因此它既充当传统意义上的触发器,也承担执行动作的角色。
notion image

流程的触发

因此在 Huginn 中,流程的触发通常需要设置 Agent 的检查频率,比如说每分钟、每天等。然后在指定的时间,Huginn 会执行设置好的 Agent。当然除了常规的触发方式,还有一种特殊的 Agent,即 Webhook Agent,它需要通过访问系统提供的链接来触发。这与其他自动化产品相似,因此这里就不详细介绍了。
notion image
这样一套触发逻辑有优点也有缺点,优点在于用户不需要理解流程是什么,直接上手新建一个 Agent 即可,比如说有一个场景是用户想要每天定时发送邮件提醒小组成员完成日报,那么在基于 "Trigger-Action" 模型的产品中需要分别添加一个触发器,再添加一个发送邮件的动作,而在 Huginn 中只需要添加一个 Agent 就行了。
但是这样做的缺点在于概念耦合,学习曲线比较陡峭。而在基于 "Trigger-Action" 模型的产品中,用户界面和工作流程通常可以设计得更加直观,用户通常会被引导通过几个简单的步骤来创建一个自动化流程,例如:选择触发器 → 设置条件 → 选择动作,这种分步进行的方式可以降低用户的认知负担。
另外在没有流程概念的 Huginn 中,用户想要让两个 Agent 相互通信,还需要了解如何设置要下一个执行的 Agent 以及如何在它们之间传递数据。

流程的执行

上面提到了 Agent 如何触发。如果想要让一个 Agent 执行完成后触发另一个 Agent,那么就需要在 Agent 设置中的 Receivers 选择你要触发的 Agent。
notion image
设置完成后,在下一步骤 Agent 的 Sources 中看到。
notion image
而 Zapier 和 IFTTT 它们会更便于用户理解,因为在它们类型的产品中,流程中的每个步骤天生就是一组的,只需要一步一步向后添加即可,而在 Huginn 中不是这样的,这里没有流程的概念,因此完全需要用户手动设置,甚至在这里没有绝对的先后概念,你完全可以创造一个循环:
notion image
当然,Huginn 这样的系统设计也有好处,比如能很方便地适应多触发器的场景,这是很多自动化工具所不具备的:例如每周一早上和每月 1 日早上发送简报;又或者可以有多个 Agent 分别监控不同的新闻源或博客,并在满足特定关键词或主题条件时,触发一个内容聚合 Agent,该 Agent 负责将这些信息汇总后发送给你。
那么如何在它们之间传递数据呢?这里需要引入一个新的概念——Event。Event 在 Huginn 的流程设置中扮演着关键角色,作为 Agent 之间信息传递的基础单位。Event 源自 Agent 在运行过程中生成的数据,所有 Agent 输出的数据都统一称为 Event。

数据的传递

Event 可以在一个 Agent 执行完成后传递给下一个 Agent 作为输入。在 Huginn 系统中,Event 是一个相对独立的实体。您可以查看一个 Agent 创建的所有 Event,或使用特定的 Event 重新执行流程。更进一步,Event 在 Huginn 中更像是数据库中的数据记录,可供随后使用。例如,某些 Agent 可以批量显示保存的 Event,这极大地方便了 RSS 订阅源的创建,无需接入外部数据库,比如当我使用 n8n 制作 RSS 源时,需要将多个来源的数据统一到一起,这个时候就需要接入数据库来使用,尤其就算是这样,还存在数据唯一性的问题,使用起来特别麻烦。
举个例子来说明:当我想每天检查10个网页,并将数据输出为RSS时,会遇到一个问题——执行时间太长。因此必须拆分流程,一个流程用于抓取任务并将数据保存在数据库中,另一个流程用于响应Webhook 以便 RSS 工具进行抓取。然而,在写入数据库时又遇到了另一个问题——定时抓取的数据可能会有重复。因此还需要解决重复数据写入的问题。从这个场景可以看出,Huginn 的 Events 机制非常适合解决这类问题。
notion image
但是这种数据传递方式也存在一个问题:所有的数据都是一对一传输的,假设有一个流程是 A→B→C,我想要在 C 步骤引用 A 步骤的数据很麻烦,需要通过 B 中转。而这在基于 "Trigger-Action" 模型的产品设计中几乎不会成为问题:一个流程含有多个步骤,多个步骤有绝对的先后顺序,当然除非特意不开放在 C 步骤中获取 A 步骤的数据。

总结

Huginn 的 Agent 概念允许用户创建高度自定义的工作流程。每个 Agent 都是一个独立的执行单元,可以接收输入并执行特定的动作。这种设计方式提供了极高的灵活性,这使得用户可以创建高度自定义的自动化流程。例如,你可以创建一个 Agent 来监控股票价格,并在达到特定阈值时触发另一个 Agent 发送警报,同时还可以将另外一个监控黄金价格的 Agent 也接入进来,用同样的 Agent 发送警报,可以大大减少流程的步骤和复杂度。这种模块化和可组合性也为它带来了很多的非常多的可能性。
同时,Huginn 是依赖事件驱动的,如果某个 Agent 依赖的上个步骤没有产生 Event,那么就不会执行。因此假设考虑一个更复杂的场景,比如你想要自动化社交媒体管理,你可以创建一个 Agent 来监控 Twitter 上的特定关键词,然后将其与一个用于分析文本情感的 Agent 连接:如果分析结果是正面的,那么可以触发另一个 Agent 自动发布一条感谢的推文。其中,是否为正面的判断可以完全由 Event 驱动,无需使用 'IF-ELSE' 模式。相比之下,大多数产品会依赖于条件判断来满足这一场景的。
同时,我觉得 Huginn 这种设计最大的问题在于太抽象了,这一点拦住了很多想要深入了解和使用它的人(当然,需要自行部署才是首先要面对的问题),而相对传统的 “Trigger-Action” 模式则相对更好理解一些。

熟悉感

实际上,当我开始使用 LangChain 时,Huginn 甚至对我还存在一定的帮助。当时我在刚接触的时候主要是希望通过 LangChain 使用 LLMs 完成一系列任务,因此了解到了 Agents 这一概念,我也自定义过 Agents Toolkits,这时就莫名觉得有一种熟悉感,感觉和 Huginn 很像:我给 LLMs 提供多个 Tools,它将作为推理引擎来确定要使用哪些 Tool 以及按什么顺序去执行以完成给出的指令,而区别在于 Huginn 的组合需要人工手动搭建,某种程度上来说,就像是 LLMs 作为一个助手帮你基于一堆 Agents 自行搭建出一套流程,当然目前在 LLMs 端或应用框架端(例如 LangChain)似乎都不会将一套完整的执行组合保存下来,每次收到新的指令都需要进行新的推理过程。

References