Files
gh-hiroshi75-protografico-p…/skills/langgraph-master/05_advanced_features_streaming.md
2025-11-29 18:45:58 +08:00

5.0 KiB

Streaming

A feature to monitor graph execution progress in real-time.

Overview

Streaming is a feature that receives real-time updates during graph execution. You can stream LLM tokens, state changes, custom events, and more.

Types of stream_mode

1. values (Complete State Snapshot)

Complete state after each step:

for chunk in graph.stream(input, stream_mode="values"):
    print(chunk)

# Example output
# {"messages": [{"role": "user", "content": "Hello"}]}
# {"messages": [{"role": "user", "content": "Hello"}, {"role": "assistant", "content": "Hi!"}]}

2. updates (Only State Changes)

Only changes at each step:

for chunk in graph.stream(input, stream_mode="updates"):
    print(chunk)

# Example output
# {"messages": [{"role": "assistant", "content": "Hi!"}]}

3. messages (LLM Tokens)

Stream at token level from LLM:

for msg, metadata in graph.stream(input, stream_mode="messages"):
    if msg.content:
        print(msg.content, end="", flush=True)

# Output: "H" "i" "!" " " "H" "o" "w" ... (token by token)

4. debug (Debug Information)

Detailed graph execution information:

for chunk in graph.stream(input, stream_mode="debug"):
    print(chunk)

# Details like node execution, edge transitions, etc.

5. custom (Custom Data)

Send custom data from nodes:

from langgraph.config import get_stream_writer

def my_node(state: State):
    writer = get_stream_writer()

    for i in range(10):
        writer({"progress": i * 10})  # Custom data

    return {"result": "done"}

for mode, chunk in graph.stream(input, stream_mode=["updates", "custom"]):
    if mode == "custom":
        print(f"Progress: {chunk['progress']}%")

LLM Token Streaming

Stream Only Specific Nodes

for msg, metadata in graph.stream(input, stream_mode="messages"):
    # Display tokens only from specific node
    if metadata["langgraph_node"] == "chatbot":
        if msg.content:
            print(msg.content, end="", flush=True)

print()  # Newline

Filter by Tags

# Set tags on LLM
llm = init_chat_model("gpt-5", tags=["main_llm"])

for msg, metadata in graph.stream(input, stream_mode="messages"):
    if "main_llm" in metadata.get("tags", []):
        if msg.content:
            print(msg.content, end="", flush=True)

Using Multiple Modes Simultaneously

for mode, chunk in graph.stream(input, stream_mode=["values", "messages"]):
    if mode == "values":
        print(f"\nState: {chunk}")
    elif mode == "messages":
        if chunk[0].content:
            print(chunk[0].content, end="", flush=True)

Subgraph Streaming

# Include subgraph outputs
for chunk in graph.stream(
    input,
    stream_mode="updates",
    subgraphs=True  # Include subgraphs
):
    print(chunk)

Practical Example: Progress Bar

from tqdm import tqdm

def process_with_progress(items: list):
    """Processing with progress bar"""
    total = len(items)

    with tqdm(total=total) as pbar:
        for chunk in graph.stream(
            {"items": items},
            stream_mode="custom"
        ):
            if "progress" in chunk:
                pbar.update(1)

    return "Complete!"

Practical Example: Real-time UI Updates

import streamlit as st

def run_with_ui_updates(user_input: str):
    """Update Streamlit UI in real-time"""
    status = st.empty()
    output = st.empty()

    full_response = ""

    for msg, metadata in graph.stream(
        {"messages": [{"role": "user", "content": user_input}]},
        stream_mode="messages"
    ):
        if msg.content:
            full_response += msg.content
            output.markdown(full_response + "▌")

        status.text(f"Node: {metadata['langgraph_node']}")

    output.markdown(full_response)
    status.text("Complete!")

Async Streaming

async def async_stream_example():
    """Async streaming"""
    async for chunk in graph.astream(input, stream_mode="updates"):
        print(chunk)
        await asyncio.sleep(0)  # Yield to other tasks

Sending Custom Events

from langgraph.config import get_stream_writer

def multi_step_node(state: State):
    """Report progress of multiple steps"""
    writer = get_stream_writer()

    # Step 1
    writer({"status": "Analyzing..."})
    analysis = analyze_data(state["data"])

    # Step 2
    writer({"status": "Processing..."})
    result = process_analysis(analysis)

    # Step 3
    writer({"status": "Finalizing..."})
    final = finalize(result)

    return {"result": final}

# Receive
for mode, chunk in graph.stream(input, stream_mode=["updates", "custom"]):
    if mode == "custom":
        print(chunk["status"])

Summary

Streaming monitors progress in real-time and improves user experience. Choose the appropriate stream_mode based on your use case.