数据截至 (上游 commit 7cdd13a1beec)
词汇表:节点、数据值与图模型
30 秒导读: 讲引擎之前,得先认字。Rivet 是一个"可视化 AI 编程"工具——你拖节点、连线,就搭出一个跑 LLM 的程序。这一章只干一件事:把 Rivet 里那几个最基础的名词讲清楚——一个"节点"作为数据长什么样、端口上流动的"值"有哪些类型、节点靠什么被系统认识。不讲引擎怎么调度这些节点(那是 02),也不讲那个诡异的
control-flow-excluded值背后的语义(那是 03)。读完你就能看懂后面几章在说什么。
本章属于 Rivet 系列的第 1 章。想先看"Rivet 是什么、整体怎么转",去 index;想看这些数据被谁消费,去 02 引擎。
1. 为什么先学词汇
Rivet 把一个 AI 工作流表示成一张有向图:方框是节点(node),节点边缘的小圆点是端口(port),端口之间的连线是连接(connection)。运行时,数据从一个节点的输出端口"流"到下一个节点的输入端口。
这里的关键直觉是:图本身只是数据,不是代码。一张图存到磁盘上,就是一坨 JSON——里面有节点列表、连接列表,每个节点记着自己的 type(类型字符串)、位置、配置数据。真正"这个节点该怎么运行"的逻辑,不在图里,而在一个按 type 查出来的实现类里。
所以这一章要认的字,分成三组:
| 组 | 名词 | 一句话 |
|---|---|---|
| 图的骨架 | ChartNode · NodeConnection · PortId | 节点、连线、端口的纯数据形状 |
| 节点的行为 | NodeImpl · PluginNodeImpl | 抽象类:定义端口、执行 process |
| 端口上的值 | DataValue · coerceType | 带类型标签的值,以及类型间的强制转换 |
外加两个"装东西的容器"——NodeGraph / Project(图和项目),和一个"电话簿"——NodeRegistration(把 type 字符串映射到实现类)。
2. 顶层全景:这些名词怎么拼在一起
下面这张图是本章所有名词的"合影"。从左到右是从数据到行为的路径:一张图里的一个 ChartNode 记着 type,引擎拿 type 去 NodeRegistration 查出 NodeImpl 实现,实现类通过端口定义和 process 与外界交换 DataValue。
Project(一个项目 = 多张图 + 引用)
└─ graphs: Record<GraphId, NodeGraph>
└─ NodeGraph { nodes[], connections[] }
│
┌───────┴─────────────────────────────┐
│ │
ChartNode NodeConnection
{ type:'if', id, data, visualData } (outputNodeId.outputId
│ type = 'if' → inputNodeId.inputId)
│
▼ 查电话簿
NodeRegistration ── 'if' ──▶ IfNodeImpl (一个 NodeImpl 子类)
│
┌────────────────┼────────────────────┐
▼ ▼ ▼
getInputDefinitions getOutputDefinitions process(inputs)
(声明入端口) (声明出端口) (真正干活)
│ │
▼ ▼
NodeInputDefinition[] Inputs / Outputs
(每个端口有 PortId + dataType) = Record<PortId, DataValue>
│
▼
DataValue { type, value }
'string' | 'number' | 'chat-message'
| 'control-flow-excluded' | …
各部件一句话职责:
| 部件 | 干什么 | 在哪个文件 |
|---|---|---|
ChartNode | 图里一个节点的纯数据(type/id/data/位置) | packages/core/src/model/NodeBase.ts:68 |
NodeConnection | 一条连线:从哪个节点的哪个出端口,到哪个入端口 | NodeBase.ts:143 |
PortId | 端口的唯一标识(节点内唯一) | NodeBase.ts:9 |
NodeInputDefinition / NodeOutputDefinition | 节点声明自己有哪些端口、各是什么类型 | NodeBase.ts:95 / :122 |
NodeImpl | 抽象类:一个节点类型的行为(定义端口 + process) | NodeImpl.ts:42 |
PluginNodeImpl | 插件作者实现的"扁平"接口,被桥接成 NodeImpl | NodeImpl.ts:16 |
DataValue | 端口上流动的值,带 type 标签的判别联合 | DataValue.ts:155 |
coerceType | 把一个 DataValue 强制转成想要的类型 | utils/coerceType.ts:61 |
NodeGraph / Project | 图 / 项目容器 | NodeGraph.ts:8 / Project.ts:10 |
NodeRegistration | type 字符串 → 实现类的注册表(电话簿) | NodeRegistration.ts:8 |