AI项目博客
记录 AI 工程实践与大模型应用

Spring AI Alibaba 75|Graph Core · 流式输出 · 理解 Graph 中的流

在 Spring AI Alibaba Graph 中,流式输出通过以下方式工作:

流式输出的层次结构

┌─────────────────────────────────────────────────────────────────┐
│                     图级别流式输出 (Graph Level)                  │
│                                                                 │
│  ┌──────────────┐      ┌──────────────┐      ┌──────────────┐  │
│  │   Node A     │ ───> │   Node B     │ ───> │   Node C     │  │
│  │ (普通节点)    │      │ (流式LLM节点) │      │ (普通节点)    │  │
│  └──────────────┘      └──────────────┘      └──────────────┘  │
│         │                    │                      │          │
│    NodeOutput          ┌─────┴─────┐          NodeOutput      │
│                        │           │                          │
│                  StreamingOutput  StreamingOutput            │
│                  (Token 1)        (Token 2)                    │
│                                                                 │
│  获取方式:                                                      │
│  • graph.stream() → Flux<NodeOutput>                           │
└─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐
│                   节点级别流式输出 (Node Level)                   │
│                                                                 │
│  ┌──────────────────────────────────────────────────────────┐  │
│  │              StreamingNode (LLM 节点)                     │  │
│  │                                                            │  │
│  │  chatClient.prompt()                                      │  │
│  │    .user(query)                                           │  │
│  │    .stream()                                              │  │
│  │    .chatResponse()                                        │  │
│  │                                                            │  │
│  │  ┌──────┐  ┌──────┐  ┌──────┐  ┌──────┐  ┌──────┐      │  │
│  │  │Token1│→ │Token2│→ │Token3│→ │Token4│→ │Token5│→ ... │  │
│  │  └──────┘  └──────┘  └──────┘  └──────┘  └──────┘      │  │
│  │                                                            │  │
│  │  这些 Token 会作为整个图流的一部分输出                      │  │
│  └──────────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐
│                   流输出数据类型层次 (Data Types)                  │
│                                                                 │
│                          NodeOutput                            │
│                         (基类/接口)                             │
│                              │                                  │
│        ┌─────────────────────┼─────────────────────┐          │
│        │                     │                     │          │
│   ┌────▼────┐        ┌───────▼───────┐      ┌─────▼─────┐   │
│   │NodeOutput│        │StreamingOutput│      │CustomOutput│   │
│   │(普通节点) │        │  (LLM流式节点) │      │ (用户自定义) │   │
│   └─────────┘        └───────────────┘      └───────────┘   │
│                                                                 │
│  包含内容:                                                      │
│  • OverallState (全局状态)                                      │
│  • Message (节点消息)                                           │
│  • Node ID (节点标识)                                           │
└─────────────────────────────────────────────────────────────────┘

详细说明

1. 节点级别流式输出

单独看图中一个具体的 Node 节点,它可能会产生流式输出,比如调用模型得到流式 token 输出,这些 token 会作为整个流输出的一部分。

示例流程:

LLM 节点内部:
  Query → LLM API → Token1 → Token2 → Token3 → ... → TokenN
         (流式响应)

这些 Token 会被包装成 StreamingOutput,成为图流的一部分

2. 图级别流式输出

站在整个图的视角,图有多个节点且每个节点都会有输出,那么执行图的多个节点自然就形成一个流式过程。有两种方法可以获取整个图的执行流(注意,这包含节点的流式输出内容)。

方法对比:

方法 返回类型 使用场景
graph.stream() Flux<NodeOutput> 普通图执行,直接获取节点输出流
graph.graphResponseStream() Flux<GraphResponse<NodeOutput>> 嵌套子图场景,需要 GraphResponse 包装

图流执行示例:

graph.stream() 返回的流:

NodeOutput(node="A", state={...})           ← 节点 A 输出
  ↓
StreamingOutput(chunk="Hello")             ← LLM 节点流式 Token 1
  ↓
StreamingOutput(chunk=" World")            ← LLM 节点流式 Token 2
  ↓
StreamingOutput(chunk="!")                 ← LLM 节点流式 Token 3
  ↓
NodeOutput(node="C", state={...})          ← 节点 C 输出
  ↓
NodeOutput(node="__END__", state={...})    ← 图执行完成

3. 流输出数据类型

流式输出的核心数据类型是 NodeOutput,代表节点的输出,NodeOutput 中包含整个图的当前全局 OverallState 状态、当前节点的 Message 输出等,不同的节点可能返回不同子类型:

类型层次:

// 基类:所有节点输出的基础类型
NodeOutput {
  - node: String              // 节点 ID
  - state: OverallState      // 全局状态
  - message: Object          // 节点消息
}

// 子类型 1:LLM 流式输出(框架内置)
StreamingOutput extends NodeOutput {
  - chunk: String            // 流式 Token 内容
}

// 子类型 2:普通节点输出(框架默认)
NodeOutput (普通实例)

// 子类型 3:用户自定义(可扩展)
CustomOutput extends NodeOutput {
  - customField: Object      // 用户自定义字段
}

使用场景:

  • StreamingOutput:框架自动为 LLM 流式节点创建,标识流式 Token 输出块
  • NodeOutput:普通节点的标准输出类型
  • 自定义类型:用户可以基于 NodeOutput 扩展任意类型,在自定义节点中返回

如果你有多个并行节点(普通节点或者嵌套子图),可以参考 并行节点的流式处理 来了解详情。

  1. 使用适当的订阅方式:根据需求选择 subscribe()、blockLast() 或其他 Reactor 操作符
  2. 错误处理:始终使用 doOnError() 处理流式输出中的错误
  3. 资源清理:确保在流完成或取消时正确清理资源
  4. 性能考虑:对于大量数据,使用背压(backpressure)机制控制流的速度
  • 快速入门 – Graph 基础使用
  • Spring Reactor 文档 – Reactor 流式处理参考

本文整理自 Spring AI Alibaba 官方文档《流式输出》:https://java2ai.com/docs/frameworks/graph-core/core/streaming

赞(0)
未经允许不得转载:AI项目博客 » Spring AI Alibaba 75|Graph Core · 流式输出 · 理解 Graph 中的流

评论 抢沙发

AI项目博客

专注 AI 工程化落地 —— 覆盖智能体、大模型、Java AI 与 Python 的学习笔记,以及 AI 平台的项目实战记录。

关于本站文章归档

登录

找回密码

注册