p4

Kvasir 背后的引擎:一套以事件寻址的协议——agent 拥有节点、stage server 持有层,而放置是运营者写明的,不是网络猜出来的。

p4 把一个模型切成若干 stage——连续的层切片——并让每个 stage 独占一个进程,从而在多台机器上运行它。agent 拥有一台主机上的节点:它启动 stage server、在它们之间路由事件,并为其生命周期负责。这里没有决定东西该放在哪里的调度器;运营者写一份放置方案、加载它,网络随后就精确地照此服务。

一次请求在 p4 部署中的路径。

browser / SDK
  → gateway :8791              # payment, settlement, the wallet app
  → bridge :19000              # OUTER: session, submit, gather
  → p4 agent                   # owns this host's nodes
  → stage servers              # one process per layer slice
寻址

一个 stage 拨通下一个 stage 的 agent

当一个 stage 跑完自己的层,它把结果交给下一个 stage 的方式,是请自己的 agent 去连接那个 stage 的 agent,按那个 agent 所公示的地址。因此公示地址绝非装饰:它必须能被环中其他每一台主机访问,并且应当指向它们共享的最快网络。公示 loopback,一个双主机的环就会悄悄地拨给自己。

生命周期

一个数字把一次加载绑在一起

  • load generation 由加载者选定,并在每一次会话、推理、结算和卸载时按完全相等比对。它在机器上不留任何记录,所以加载者要在第一条命令发出*之前*把它写到磁盘上——没有它,已加载的模型连拆都拆不掉。
  • 节点的 generation 与 load generation 是同一个数字。适配器会把 release receipt 的来源 generation 与它所属的那次加载比对,不一致就停掉该节点——因此一个用两个不同数字加载的环,服务完一次请求就会失去头部。
  • 模型加载之前必须有运行日志(operational journal):它是让一次加载可重放安全的准入记录,而不是调试辅助。
它不做什么

刻意的省略

p4 不套用任何对话模板——它转发不透明的提示词,并期待调用方已经渲染好模型的轮次格式。它不做任何放置决策。它也没有"谁该收钱"的概念:stage 汇报自己跑过的 token 行数,结算是别人的契约。每一项都是 Kvasir 在 [bridge](/wiki/bridge) 中填补的接缝,也正因如此,引擎才窄到足以持续跟上上游。

agent 与原生 stage server 是同一个发行版。用更新的代码树构建的 agent 会在 READY 阶段失败,原因是 stage server 的 HELLO 中缺少某项能力——而且是在整个模型加载完之后。两者要从同一个 checkout 构建。