Skip to content

Commit d6a349b

Browse files
committed
Add messages parameter to .ui() and chat_ui()
1 parent d9357fd commit d6a349b

File tree

5 files changed

+46
-19
lines changed

5 files changed

+46
-19
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2929

3030
* Added [narwhals](https://posit-dev.github.io/py-narwhals) support for `@render.table`. This allows for any eager data frame supported by narwhals to be returned from a `@render.table` output method. (#1570)
3131

32+
* `chat_ui()` and `Chat.ui()` gain a `messages` parameter for providing starting messages.
33+
3234
### Other changes
3335

3436
* Incorporated `orjson` for faster data serialization in `@render.data_frame` outputs. (#1570)

js/chat/chat.ts

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -313,14 +313,7 @@ class ChatContainer extends LightElement {
313313
private resizeObserver!: ResizeObserver;
314314

315315
render(): ReturnType<LitElement["render"]> {
316-
const input_id = this.id + "_user_input";
317-
return html`
318-
<shiny-chat-messages></shiny-chat-messages>
319-
<shiny-chat-input
320-
id=${input_id}
321-
placeholder=${this.placeholder}
322-
></shiny-chat-input>
323-
`;
316+
return html``;
324317
}
325318

326319
firstUpdated(): void {

shiny/ui/_chat.py

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
Callable,
99
Iterable,
1010
Literal,
11+
Optional,
1112
Sequence,
1213
Tuple,
1314
Union,
@@ -193,7 +194,8 @@ def __init__(
193194
reactive.Value(None)
194195
)
195196

196-
# Initialize the chat with the provided messages
197+
# TODO: deprecate messages once we start promoting managing LLM message
198+
# state through other means
197199
@reactive.effect
198200
async def _init_chat():
199201
for msg in messages:
@@ -233,6 +235,7 @@ async def _on_user_input():
233235
def ui(
234236
self,
235237
*,
238+
messages: Optional[Sequence[str | ChatMessage]] = None,
236239
placeholder: str = "Enter a message...",
237240
width: CssUnit = "min(680px, 100%)",
238241
height: CssUnit = "auto",
@@ -247,6 +250,11 @@ def ui(
247250
248251
Parameters
249252
----------
253+
messages
254+
A sequence of messages to display in the chat. Each message can be either a
255+
string or a dictionary with `content` and `role` keys. The `content` key
256+
should contain the message text, and the `role` key can be "assistant" or
257+
"user".
250258
placeholder
251259
Placeholder text for the chat input.
252260
width
@@ -261,6 +269,7 @@ def ui(
261269
"""
262270
return chat_ui(
263271
id=self.id,
272+
messages=messages,
264273
placeholder=placeholder,
265274
width=width,
266275
height=height,
@@ -1025,6 +1034,7 @@ async def _send_custom_message(self, handler: str, obj: ClientMessage | None):
10251034
def chat_ui(
10261035
id: str,
10271036
*,
1037+
messages: Optional[Sequence[str | ChatMessage]] = None,
10281038
placeholder: str = "Enter a message...",
10291039
width: CssUnit = "min(680px, 100%)",
10301040
height: CssUnit = "auto",
@@ -1042,6 +1052,10 @@ def chat_ui(
10421052
----------
10431053
id
10441054
A unique identifier for the chat UI.
1055+
messages
1056+
A sequence of messages to display in the chat. Each message can be either a string
1057+
or a dictionary with a `content` and `role` key. The `content` key should contain
1058+
the message text, and the `role` key can be "assistant" or "user".
10451059
placeholder
10461060
Placeholder text for the chat input.
10471061
width
@@ -1056,8 +1070,32 @@ def chat_ui(
10561070

10571071
id = resolve_id(id)
10581072

1073+
message_tags: list[Tag] = []
1074+
if messages is None:
1075+
messages = []
1076+
for msg in messages:
1077+
if isinstance(msg, str):
1078+
msg = {"content": msg, "role": "assistant"}
1079+
elif isinstance(msg, dict):
1080+
if "content" not in msg:
1081+
raise ValueError("Each message must have a 'content' key.")
1082+
if "role" not in msg:
1083+
raise ValueError("Each message must have a 'role' key.")
1084+
else:
1085+
raise ValueError("Each message must be a string or a dictionary.")
1086+
1087+
message_tags.append(
1088+
Tag("shiny-chat-message", content=msg["content"], role=msg["role"])
1089+
)
1090+
10591091
res = Tag(
10601092
"shiny-chat-container",
1093+
Tag("shiny-chat-messages", *message_tags),
1094+
Tag(
1095+
"shiny-chat-input",
1096+
id=f"{id}_user_input",
1097+
placeholder=placeholder,
1098+
),
10611099
chat_deps(),
10621100
{
10631101
"style": css(

shiny/www/py-shiny/chat/chat.js

Lines changed: 1 addition & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

shiny/www/py-shiny/chat/chat.js.map

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)