AI News HubLIVE
站内改写4 分钟阅读

Parse-Flow:开源可视化文档智能工作流设计器

Parse-Flow 是一个开源项目,通过可视化工作流设计器、异步工作器和实时事件仪表板,将文档处理的四个基本操作——解析、分类、拆分和提取——整合在一起。后端基于 llama-agents 工作流引擎,使用 Redis 和 Postgres 实现任务队列与事件持久化。本文详细介绍了系统架构、工作流定义、基于状态机的执行引擎以及设计优势。

非结构化文档仍然是企业存储和共享信息的主要方式。从合同到发票再到报告,这些文档的共同点是包含布局、语言和上下文的混合,下游系统无法直接消费。文档智能——即将这些文档转化为结构化机器可读数据的学科——是使现代AI堆栈对企业真正有用的关键层。如果没有强大的解析、分类、拆分和提取,任何检索流水线、智能体或分析仪表板都将建立在脆弱的基础之上。

Parse-Flow 是一个小型开源项目,它将四个文档处理原语——解析(Parsing)、提取(Extraction)、分类(Classification)和拆分(Splitting)——置于可视化工作流设计器、异步工作器和实时事件仪表板的中心。用户将步骤拖到画布上,放入文档,然后观察流水线运行时事件的流回。本文介绍了它的构建方式,特别关注后端工作流如何在 llama-agents 工作流之上设计。

系统形状

Parse-Flow 分为四个协作进程:

  • React 前端:托管基于节点的工作流设计器、运行视图和作业仪表板。
  • Bun 服务器:处理上传、与 LlamaParse 平台通信、将作业排队、从 Postgres 读取历史记录,并通过服务器发送事件将事件流桥接到浏览器。
  • Python 工作器:消费作业并执行实际的文档工作流。
  • Redis:作为作业队列和事件总线,Postgres 作为作业及其事件历史的系统记录。

通信模式如下:Bun 服务器将作业推送到 Redis 列表,工作器拉取作业,并在作业运行时,每个事件被添加到每个作业的 Redis 流中,同时持久化到 Postgres。Bun 服务器通过创建专用订阅者连接将该流桥接到浏览器,发送心跳,并在观察到最终事件时关闭连接。

这种分离带来了两个主要好处:工作器可以慢速运行而不阻塞 HTTP 层;每个事件被捕获两次(一次在实时流中,一次在持久存储中),因此重新加载页面的用户可以查看并重放从 Postgres 重建的完整历史记录。

四个原语,任意组合

工作流词汇表有意围绕 LlamaParse 平台提供的服务收窄:

  • 解析:使用 Parse 将文档转为干净的 Markdown 和文本,可选择层级和提示。
  • 分类:根据一组用户定义的规则为文档分配类别,附带推理和置信度分数。
  • 拆分:根据类别列表将文档分割成有类型的块。
  • 提取:根据用户提供的 JSON 模式从文档中提取结构化 JSON。

系统的表达能力并非来自原语本身,而是来自限制它们如何链接的允许对图。并非每个转换都有意义:提取总是终端,解析可以交给其他三个,分类和拆分可以根据匹配的规则或类别路由到解析或提取。前端在提交之前根据此图验证流程,后端在进入时重新验证。

结果是一个基于 JSON 的小型领域特定语言:一个包含有序步骤和类型化交接的 FlowDefinition,足以描述大多数真实的文档流水线(解析后提取、分类后路由到正确模式、按章节拆分后分别解析),同时保持足够小以进行彻底推理。

核心的 LlamaAgent 工作流

有趣的设计工作在工作器中,单个 LlamaAgent Workflow 在运行时解释用户定义的流程。

llama-agents 框架提供了一个事件驱动的、非固执己见的工作流引擎:每个 @step 是一个异步函数,接收一个事件并返回一个或多个事件,运行时将事件路由到类型签名匹配的任何步骤。状态保存在类型化的 Context 存储中,步骤可以事务性地读取和编辑。通过 ctx.write_event_to_stream 写入的事件会被观察运行的人看到(在我们的例子中是工作器,它将事件转发到 Redis 和 Postgres)。

Parse-Flow 的 DocumentWorkflow 正好暴露三个步骤,执行系统的关键在于它们如何协作以遍历任意长度的流程。

步骤 1 — 引导

第一个步骤接收一个携带解析后的 FlowDefinition 和 LlamaCloud 文件 ID 的 RedisInitialEvent。它将流程写入工作流状态,记录当前索引为零,并发出第一个步骤对应的类型化输入事件(ParsingInputEvent、ClassifyInputEvent、SplitInputEvent 或 ExtractInputEvent)。从此以后,工作流由数据驱动;引导步骤不再运行。

步骤 2 — 工作器

工作器步骤有一个故意的宽输入类型:任何 InputEvent。它根据事件类型进行模式匹配,推进步骤索引,并分派到 LlamaParse 平台上的相应操作。每个操作返回一个类似 Rust 的 Result,该结果被解包为类型化的成功事件(带有解析后的 Markdown、分类判定、分割块或提取的 JSON)或携带失败消息的 ErrorOutputEvent。

一个重要细节:一旦解析步骤产生了 parse_job_id,后续的分类和提取操作会优先使用该 ID 而不是原始文件。这意味着当用户链接解析 → 提取时,提取步骤操作的是已解析的表示,而不是从头重新解析文件,这是跨步骤共享状态带来的免费延迟和成本降低。

步骤 3 — 路由器

后处理步骤是在运行时实际执行允许对图的地方。它查看最后一个输出事件、流程中的当前步骤以及上一步骤记录的交握描述符。从这三条信息中,它决定下一步发出什么:

  • 如果已经走到流程末尾,则将最后一个输出包装在 WrapperStopEvent 中,工作流终止。
  • 如果输出是错误,则短路至停止。
  • 否则,它根据交握(如 classify-extract、parse-classify、split-parse 等)构造下一个输入事件。对于路由交握,这意味着查找与前一步骤匹配的规则对应的 JSON 模式、解析层级和提示或类别,并将它们打包到下一个输入事件中。

然后,该路由器再次发出 InputEvent,直接循环回工作器步骤。引导-工作器-路由器三元组成为一个状态机,一步一步地遍历用户的工作流,每个转换都是类型化的,每个交握都经过验证,每个事件都可观察。

仪表板显示 Parse-Flow 运行期间的事件

为什么这种设计成立

三个属性使设计令人愉悦:

  1. 流程存在于事件中,而非代码中。相同的 DocumentWorkflow 运行每个作业。新流水线不需要新的 Python 代码,只需要一个新的 JSON 流程定义。这使得在其之上构建可视化设计器变得可行。
  2. 每个转换都是可观察的。因为每个步骤在返回之前将其事件写入流,仪表板看到的工作流与工作流自身看到的一样。没有单独的日志层会与现实不同步。
  3. 失败是一个值。错误是一等输出事件,路由器知道如何将其转为干净的停止。用户收到一个带有真实消息的最终事件;系统永远不会静默挂起。

文档智能是重要的层

在 2026 年,很容易将解析和提取视为隐藏在模型调用后面的已解决问题。事实并非如此。一个用错误模式分类发票、或在错误边界拆分合同、或从错误页面提取日期的流水线,会以下游无法恢复的方式失败。持久的系统是那些将文档智能视为头等工程问题的系统:可组合的原语、验证过的转换、可观察的运行、持久化的历史。

Parse-Flow 是当你让工作流层得到正确设计时的一个小例子:四个原语、一个类型化交握图和一个只负责遍历它的 LlamaAgent 工作流。

尝试它

完整源码是开源的。克隆它,指向一个 LlamaCloud 密钥,然后带上你自己的文档。 → github.com/run-llama/parse-flow