Skip to content

Commit 5e822fc

Browse files
committed
Cut public .append_message_chunk() method; rename context manager method
1 parent bb171f7 commit 5e822fc

File tree

2 files changed

+21
-55
lines changed
  • shiny/ui
  • tests/playwright/shiny/components/chat/message-stream

2 files changed

+21
-55
lines changed

shiny/ui/_chat.py

Lines changed: 18 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -590,68 +590,32 @@ async def append_message(
590590
icon=icon,
591591
)
592592

593-
async def append_message_chunk(self, message_chunk: Any):
594-
"""
595-
Append a message chunk to the current message stream.
596-
597-
Append a chunk of message content to either a stream started with
598-
`.message_stream()` or an active `.append_message_stream()`.
599-
600-
Parameters
601-
----------
602-
message_chunk
603-
A message chunk to inject.
604-
605-
Note
606-
----
607-
A useful pattern for displaying tool calls in a chat is for the tools to display
608-
content using an "inner" `.message_stream()` while the response generation is
609-
happening in an "outer" `.append_message_stream()`. This allows the inner stream
610-
to display "ephemeral" content, then eventually show a final state with
611-
`.append_message_chunk(operation="replace")`.
612-
613-
Raises
614-
------
615-
ValueError
616-
If there is active stream (i.e., no `.message_stream()` or
617-
`.append_message_stream()`)
618-
"""
619-
stream_id = self._current_stream_id
620-
if stream_id is None:
621-
raise ValueError(
622-
"Can't .append_message_chunk() without an active message stream. "
623-
"Use .message_stream() or .append_message_stream() to start one."
624-
)
625-
626-
return await self._append_message_chunk(
627-
message_chunk,
628-
stream_id=stream_id,
629-
)
630-
631593
@asynccontextmanager
632-
async def message_stream(self):
594+
async def append_message_context(self):
633595
"""
634596
Message stream context manager.
635597
636-
A context manager for streaming messages into the chat. Note this stream
637-
can occur within a longer running `.append_message_stream()` or used on its own.
598+
A context manager for streaming messages into the chat. Note this context
599+
manager can be used in isolation, nested within itself, or used while a
600+
long-running `.append_message_stream()` is in progress.
638601
639602
Yields
640603
------
641604
:
642-
A `MessageStream` instance with a method for `.append()`ing message chunks
643-
and a method for `.restore()`ing the stream back to it's initial state.
605+
A `MessageStream` class instance, which has a method for `.append()`ing
606+
message chunks to as well as way to `.restore()` the stream back to it's
607+
initial state.
644608
645609
Note
646610
----
647-
A useful pattern for displaying tool calls in a chat interface is for the
648-
tool to display using `.message_stream()` while the the response generation
649-
is happening through `.append_message_stream()`. This allows the inner stream
650-
to display "ephemeral" content, then eventually show a final state
651-
with `.append_message_chunk(operation="replace")`.
611+
A useful pattern for displaying tool calls in a chatbot is for the tool to
612+
display using `.append_message_context()` while the the response generation is
613+
happening through `.append_message_stream()`. This allows the tool to display
614+
things like progress updates (or other "ephemeral" content) and optionally
615+
`.restore()` the stream back to it's initial state when ready to display the
616+
"final" content.
652617
"""
653-
# Save the current stream state in a checkpoint (so that we can handle
654-
# ``.append_message_chunk(operation="replace")` correctly)
618+
# Checkpoint the current stream state so operation="replace" can return to it
655619
old_checkpoint = self._message_stream_checkpoint
656620
self._message_stream_checkpoint = self._current_stream_message
657621

@@ -665,7 +629,7 @@ async def message_stream(self):
665629
try:
666630
yield MessageStream(self, stream_id)
667631
finally:
668-
# Restore the previous stream state
632+
# Restore the checkpoint
669633
self._message_stream_checkpoint = old_checkpoint
670634

671635
# If this was the root stream, end it
@@ -1493,7 +1457,9 @@ def chat_ui(
14931457

14941458

14951459
class MessageStream:
1496-
""""""
1460+
"""
1461+
An object to yield from a `.append_message_context()` context manager.
1462+
"""
14971463

14981464
def __init__(self, chat: Chat, stream_id: str):
14991465
self._chat = chat

tests/playwright/shiny/components/chat/message-stream/app.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,15 @@ async def _():
3737
" Progress: 50%",
3838
" Progress: 100%",
3939
]
40-
async with chat.message_stream() as stream:
40+
async with chat.append_message_context() as stream:
4141
for chunk in chunks:
4242
await stream.append(chunk)
4343
await asyncio.sleep(SLEEP_TIME)
4444
await stream.restore()
4545
await stream.append("Completed stream 1 ✅")
4646

4747

48-
# TODO: add test here for nested .message_stream()
48+
# TODO: add test here for nested .append_message_context()
4949

5050

5151
@reactive.effect
@@ -69,7 +69,7 @@ async def mock_tool():
6969
" Progress: 50%",
7070
" Progress: 100%",
7171
]
72-
async with chat.message_stream() as stream:
72+
async with chat.append_message_context() as stream:
7373
for chunk in chunks:
7474
await stream.append(chunk)
7575
await asyncio.sleep(SLEEP_TIME)

0 commit comments

Comments
 (0)