Skip to content

Commit 1d59974

Browse files
committed
docs(samples): Add streaming message example
Update message workflow sample to demonstrate streaming token chunks using Event(message=..., partial=True). Change-Id: Iaa44a293dda1aec1a689b26997b83e4e17ae31ef
1 parent dc2adf9 commit 1d59974

2 files changed

Lines changed: 47 additions & 5 deletions

File tree

contributing/workflow_samples/message/README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ This sample demonstrates different ways to send a message to a user using `Event
77
1. **String Messages**: Standard string text replies.
88
1. **Multi-modal Messages**: Returning mixed modality inputs, such as a string combined with an inline image.
99
1. **Multiple Messages**: Emitting multiple full messages from the same node with a delay between them.
10+
1. **Streaming Messages**: Simulating an LLM streaming response by breaking a message into chunks and yielding them with the `partial=True` flag at intervals.
1011

1112
## Sample Inputs
1213

@@ -27,6 +28,9 @@ This workflow executes sequentially and successfully without any expected user i
2728
[ multiple_messages ]
2829
|
2930
v
31+
[ stream_sentence ]
32+
|
33+
v
3034
(Workflow Ends)
3135
```
3236

@@ -69,3 +73,19 @@ To send messages in an ADK node, yield an `Event` object with the `message` argu
6973

7074
yield Event(message="Done processing.")
7175
```
76+
77+
1. **Stream a message in chunks**:
78+
Provide the `partial=True` flag for intermediate chunks. This provides a better user experience by allowing the UI to show the response in a streaming fashion, thereby lowering the latency to see the first word. ADK automatically accumulates all partial messages and merges them into a final message for you for session storage.
79+
80+
> **Note**: To stream multiple messages or tokens smoothly, your node function **must be an asynchronous generator** (`async def`). This allows ADK to yield messages to the client immediately without blocking.
81+
82+
```python
83+
import asyncio
84+
85+
async def stream_sentence(node_input: str):
86+
yield Event(message="How ", partial=True)
87+
await asyncio.sleep(0.5)
88+
yield Event(message="may I", partial=True)
89+
await asyncio.sleep(0.5)
90+
yield Event(message=" help you?", partial=True)
91+
```

contributing/workflow_samples/message/agent.py

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
def send_string(node_input: Any = None):
2525
"""Sends a single string message."""
26-
yield Event(message="1. This is a simple string message.")
26+
yield Event(message="#1 This is a simple string message.")
2727

2828

2929
def send_multimodal(node_input: Any = None):
@@ -36,7 +36,7 @@ def send_multimodal(node_input: Any = None):
3636
message=[
3737
types.Part.from_text(
3838
text=(
39-
"2. Here is a multi-modal message with an inline image (red"
39+
"#2 Here is a multi-modal message with an inline image (red"
4040
" square):"
4141
)
4242
),
@@ -47,13 +47,34 @@ def send_multimodal(node_input: Any = None):
4747

4848
async def multiple_messages(node_input: Any = None):
4949
"""Sends multiple complete messages from the same node with an interval."""
50-
yield Event(message="3. Processing step 1...")
50+
yield Event(message="#3 Multiple messages")
5151
await asyncio.sleep(1.0)
5252

53-
yield Event(message="3. Processing step 2...")
53+
yield Event(message="Processing step 1...")
5454
await asyncio.sleep(1.0)
5555

56-
yield Event(message="3. Done processing.")
56+
yield Event(message="Processing step 2...")
57+
await asyncio.sleep(1.0)
58+
59+
yield Event(message="Done processing.")
60+
61+
62+
async def stream_sentence(node_input: Any = None):
63+
"""
64+
Demonstrates streaming by sending a sentence in chunks.
65+
The `partial=True` flag tells the UI that this is part of an ongoing message.
66+
"""
67+
yield Event(message="#4 Starting to stream...")
68+
sentence = """\
69+
This is a streaming message sent in chunks.
70+
71+
You need to enable 'Token Streaming' in the UI to see this message in chunks.
72+
"""
73+
74+
for i in range(0, len(sentence), 5):
75+
chunk = sentence[i : i + 5]
76+
yield Event(message=chunk, partial=True)
77+
await asyncio.sleep(0.2)
5778

5879

5980
root_agent = Workflow(
@@ -64,6 +85,7 @@ async def multiple_messages(node_input: Any = None):
6485
send_string,
6586
send_multimodal,
6687
multiple_messages,
88+
stream_sentence,
6789
),
6890
],
6991
)

0 commit comments

Comments
 (0)