Skip to content

Commit ea83a33

Browse files
committed
Rename ChatMessage -> ChatMessageDict; ChatUIMessage -> ChatMessage
1 parent b16e8a2 commit ea83a33

File tree

5 files changed

+63
-64
lines changed

5 files changed

+63
-64
lines changed

shiny/ui/_chat.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,15 @@
3838
as_provider_message,
3939
)
4040
from ._chat_tokenizer import TokenEncoding, TokenizersEncoding, get_default_tokenizer
41-
from ._chat_types import ChatMessage, ChatUIMessage, ClientMessage, TransformedMessage
41+
from ._chat_types import ChatMessage, ChatMessageDict, ClientMessage, TransformedMessage
4242
from ._html_deps_py_shiny import chat_deps
4343
from .fill import as_fill_item, as_fillable_container
4444

4545
__all__ = (
4646
"Chat",
4747
"ChatExpress",
4848
"chat_ui",
49-
"ChatMessage",
49+
"ChatMessageDict",
5050
)
5151

5252

@@ -240,7 +240,7 @@ async def _init_chat():
240240
@reactive.effect(priority=9999)
241241
@reactive.event(self._user_input)
242242
async def _on_user_input():
243-
msg = ChatUIMessage(content=self._user_input(), role="user")
243+
msg = ChatMessage(content=self._user_input(), role="user")
244244
# It's possible that during the transform, a message is appended, so get
245245
# the length now, so we can insert the new message at the right index
246246
n_pre = len(self._messages())
@@ -415,7 +415,7 @@ def messages(
415415
token_limits: tuple[int, int] | None = None,
416416
transform_user: Literal["all", "last", "none"] = "all",
417417
transform_assistant: bool = False,
418-
) -> tuple[ChatMessage, ...]: ...
418+
) -> tuple[ChatMessageDict, ...]: ...
419419

420420
def messages(
421421
self,
@@ -424,7 +424,7 @@ def messages(
424424
token_limits: tuple[int, int] | None = None,
425425
transform_user: Literal["all", "last", "none"] = "all",
426426
transform_assistant: bool = False,
427-
) -> tuple[ChatMessage | ProviderMessage, ...]:
427+
) -> tuple[ChatMessageDict | ProviderMessage, ...]:
428428
"""
429429
Reactively read chat messages
430430
@@ -492,7 +492,7 @@ def messages(
492492
if token_limits is not None:
493493
messages = self._trim_messages(messages, token_limits, format)
494494

495-
res: list[ChatMessage | ProviderMessage] = []
495+
res: list[ChatMessageDict | ProviderMessage] = []
496496
for i, m in enumerate(messages):
497497
transform = False
498498
if m.role == "assistant":
@@ -505,7 +505,7 @@ def messages(
505505
m, "transform_key" if transform else "pre_transform_key"
506506
)
507507
content = getattr(m, content_key)
508-
chat_msg = ChatMessage(content=str(content), role=m.role)
508+
chat_msg = ChatMessageDict(content=str(content), role=m.role)
509509
if not isinstance(format, MISSING_TYPE):
510510
chat_msg = as_provider_message(chat_msg, format)
511511
res.append(chat_msg)
@@ -745,7 +745,7 @@ async def _append_message_stream(
745745
):
746746
id = _utils.private_random_id()
747747

748-
empty = ChatMessage(content="", role="assistant")
748+
empty = ChatMessageDict(content="", role="assistant")
749749
await self._append_message(empty, chunk="start", stream_id=id, icon=icon)
750750

751751
try:
@@ -934,7 +934,7 @@ async def _transform_wrapper(content: str, chunk: str, done: bool):
934934

935935
async def _transform_message(
936936
self,
937-
message: ChatUIMessage,
937+
message: ChatMessage,
938938
chunk: ChunkOption = False,
939939
chunk_content: str | None = None,
940940
) -> TransformedMessage | None:
@@ -1201,7 +1201,7 @@ class ChatExpress(Chat):
12011201
def ui(
12021202
self,
12031203
*,
1204-
messages: Optional[Sequence[str | ChatMessage]] = None,
1204+
messages: Optional[Sequence[str | ChatMessageDict]] = None,
12051205
placeholder: str = "Enter a message...",
12061206
width: CssUnit = "min(680px, 100%)",
12071207
height: CssUnit = "auto",
@@ -1251,7 +1251,7 @@ def ui(
12511251
def chat_ui(
12521252
id: str,
12531253
*,
1254-
messages: Optional[Sequence[TagChild | ChatMessage]] = None,
1254+
messages: Optional[Sequence[TagChild | ChatMessageDict]] = None,
12551255
placeholder: str = "Enter a message...",
12561256
width: CssUnit = "min(680px, 100%)",
12571257
height: CssUnit = "auto",

shiny/ui/_chat_normalize.py

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
from htmltools import HTML, Tagifiable
66

7-
from ._chat_types import ChatUIMessage
7+
from ._chat_types import ChatMessage
88

99
if TYPE_CHECKING:
1010
from anthropic.types import Message as AnthropicMessage
@@ -25,11 +25,11 @@ class GenerateContentResponse:
2525

2626
class BaseMessageNormalizer(ABC):
2727
@abstractmethod
28-
def normalize(self, message: Any) -> ChatUIMessage:
28+
def normalize(self, message: Any) -> ChatMessage:
2929
pass
3030

3131
@abstractmethod
32-
def normalize_chunk(self, chunk: Any) -> ChatUIMessage:
32+
def normalize_chunk(self, chunk: Any) -> ChatMessage:
3333
pass
3434

3535
@abstractmethod
@@ -42,13 +42,13 @@ def can_normalize_chunk(self, chunk: Any) -> bool:
4242

4343

4444
class StringNormalizer(BaseMessageNormalizer):
45-
def normalize(self, message: Any) -> ChatUIMessage:
45+
def normalize(self, message: Any) -> ChatMessage:
4646
x = cast(Optional[str], message)
47-
return ChatUIMessage(content=x or "", role="assistant")
47+
return ChatMessage(content=x or "", role="assistant")
4848

49-
def normalize_chunk(self, chunk: Any) -> ChatUIMessage:
49+
def normalize_chunk(self, chunk: Any) -> ChatMessage:
5050
x = cast(Optional[str], chunk)
51-
return ChatUIMessage(content=x or "", role="assistant")
51+
return ChatMessage(content=x or "", role="assistant")
5252

5353
def can_normalize(self, message: Any) -> bool:
5454
return isinstance(message, (str, HTML)) or message is None
@@ -58,17 +58,17 @@ def can_normalize_chunk(self, chunk: Any) -> bool:
5858

5959

6060
class DictNormalizer(BaseMessageNormalizer):
61-
def normalize(self, message: Any) -> ChatUIMessage:
61+
def normalize(self, message: Any) -> ChatMessage:
6262
x = cast("dict[str, Any]", message)
6363
if "content" not in x:
6464
raise ValueError("Message must have 'content' key")
65-
return ChatUIMessage(content=x["content"], role=x.get("role", "assistant"))
65+
return ChatMessage(content=x["content"], role=x.get("role", "assistant"))
6666

67-
def normalize_chunk(self, chunk: Any) -> ChatUIMessage:
67+
def normalize_chunk(self, chunk: Any) -> ChatMessage:
6868
x = cast("dict[str, Any]", chunk)
6969
if "content" not in x:
7070
raise ValueError("Message must have 'content' key")
71-
return ChatUIMessage(content=x["content"], role=x.get("role", "assistant"))
71+
return ChatMessage(content=x["content"], role=x.get("role", "assistant"))
7272

7373
def can_normalize(self, message: Any) -> bool:
7474
return isinstance(message, dict)
@@ -78,11 +78,11 @@ def can_normalize_chunk(self, chunk: Any) -> bool:
7878

7979

8080
class TagifiableNormalizer(DictNormalizer):
81-
def normalize(self, message: Any) -> ChatUIMessage:
81+
def normalize(self, message: Any) -> ChatMessage:
8282
x = cast("Tagifiable", message)
8383
return super().normalize({"content": x})
8484

85-
def normalize_chunk(self, chunk: Any) -> ChatUIMessage:
85+
def normalize_chunk(self, chunk: Any) -> ChatMessage:
8686
x = cast("Tagifiable", chunk)
8787
return super().normalize_chunk({"content": x})
8888

@@ -94,23 +94,23 @@ def can_normalize_chunk(self, chunk: Any) -> bool:
9494

9595

9696
class LangChainNormalizer(BaseMessageNormalizer):
97-
def normalize(self, message: Any) -> ChatUIMessage:
97+
def normalize(self, message: Any) -> ChatMessage:
9898
x = cast("BaseMessage", message)
9999
if isinstance(x.content, list): # type: ignore
100100
raise ValueError(
101101
"The `message.content` provided seems to represent numerous messages. "
102102
"Consider iterating over `message.content` and calling .append_message() on each iteration."
103103
)
104-
return ChatUIMessage(content=x.content, role="assistant")
104+
return ChatMessage(content=x.content, role="assistant")
105105

106-
def normalize_chunk(self, chunk: Any) -> ChatUIMessage:
106+
def normalize_chunk(self, chunk: Any) -> ChatMessage:
107107
x = cast("BaseMessageChunk", chunk)
108108
if isinstance(x.content, list): # type: ignore
109109
raise ValueError(
110110
"The `message.content` provided seems to represent numerous messages. "
111111
"Consider iterating over `message.content` and calling .append_message() on each iteration."
112112
)
113-
return ChatUIMessage(content=x.content, role="assistant")
113+
return ChatMessage(content=x.content, role="assistant")
114114

115115
def can_normalize(self, message: Any) -> bool:
116116
try:
@@ -130,11 +130,11 @@ def can_normalize_chunk(self, chunk: Any) -> bool:
130130

131131

132132
class OpenAINormalizer(StringNormalizer):
133-
def normalize(self, message: Any) -> ChatUIMessage:
133+
def normalize(self, message: Any) -> ChatMessage:
134134
x = cast("ChatCompletion", message)
135135
return super().normalize(x.choices[0].message.content)
136136

137-
def normalize_chunk(self, chunk: Any) -> ChatUIMessage:
137+
def normalize_chunk(self, chunk: Any) -> ChatMessage:
138138
x = cast("ChatCompletionChunk", chunk)
139139
return super().normalize_chunk(x.choices[0].delta.content)
140140

@@ -156,17 +156,17 @@ def can_normalize_chunk(self, chunk: Any) -> bool:
156156

157157

158158
class AnthropicNormalizer(BaseMessageNormalizer):
159-
def normalize(self, message: Any) -> ChatUIMessage:
159+
def normalize(self, message: Any) -> ChatMessage:
160160
x = cast("AnthropicMessage", message)
161161
content = x.content[0]
162162
if content.type != "text":
163163
raise ValueError(
164164
f"Anthropic message type {content.type} not supported. "
165165
"Only 'text' type is currently supported"
166166
)
167-
return ChatUIMessage(content=content.text, role="assistant")
167+
return ChatMessage(content=content.text, role="assistant")
168168

169-
def normalize_chunk(self, chunk: Any) -> ChatUIMessage:
169+
def normalize_chunk(self, chunk: Any) -> ChatMessage:
170170
x = cast("MessageStreamEvent", chunk)
171171
content = ""
172172
if x.type == "content_block_delta":
@@ -177,7 +177,7 @@ def normalize_chunk(self, chunk: Any) -> ChatUIMessage:
177177
)
178178
content = x.delta.text
179179

180-
return ChatUIMessage(content=content, role="assistant")
180+
return ChatMessage(content=content, role="assistant")
181181

182182
def can_normalize(self, message: Any) -> bool:
183183
try:
@@ -214,13 +214,13 @@ def can_normalize_chunk(self, chunk: Any) -> bool:
214214

215215

216216
class GoogleNormalizer(BaseMessageNormalizer):
217-
def normalize(self, message: Any) -> ChatUIMessage:
217+
def normalize(self, message: Any) -> ChatMessage:
218218
x = cast("GenerateContentResponse", message)
219-
return ChatUIMessage(content=x.text, role="assistant")
219+
return ChatMessage(content=x.text, role="assistant")
220220

221-
def normalize_chunk(self, chunk: Any) -> ChatUIMessage:
221+
def normalize_chunk(self, chunk: Any) -> ChatMessage:
222222
x = cast("GenerateContentResponse", chunk)
223-
return ChatUIMessage(content=x.text, role="assistant")
223+
return ChatMessage(content=x.text, role="assistant")
224224

225225
def can_normalize(self, message: Any) -> bool:
226226
try:
@@ -238,11 +238,11 @@ def can_normalize_chunk(self, chunk: Any) -> bool:
238238

239239

240240
class OllamaNormalizer(DictNormalizer):
241-
def normalize(self, message: Any) -> ChatUIMessage:
241+
def normalize(self, message: Any) -> ChatMessage:
242242
x = cast("dict[str, Any]", message["message"])
243243
return super().normalize(x)
244244

245-
def normalize_chunk(self, chunk: "dict[str, Any]") -> ChatUIMessage:
245+
def normalize_chunk(self, chunk: "dict[str, Any]") -> ChatMessage:
246246
msg = cast("dict[str, Any]", chunk["message"])
247247
return super().normalize_chunk(msg)
248248

@@ -295,7 +295,7 @@ def register(
295295
message_normalizer_registry = NormalizerRegistry()
296296

297297

298-
def normalize_message(message: Any) -> ChatUIMessage:
298+
def normalize_message(message: Any) -> ChatMessage:
299299
strategies = message_normalizer_registry._strategies
300300
for strategy in strategies.values():
301301
if strategy.can_normalize(message):
@@ -306,7 +306,7 @@ def normalize_message(message: Any) -> ChatUIMessage:
306306
)
307307

308308

309-
def normalize_message_chunk(chunk: Any) -> ChatUIMessage:
309+
def normalize_message_chunk(chunk: Any) -> ChatMessage:
310310
strategies = message_normalizer_registry._strategies
311311
for strategy in strategies.values():
312312
if strategy.can_normalize_chunk(chunk):

shiny/ui/_chat_provider_types.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import sys
22
from typing import TYPE_CHECKING, Literal, Union
33

4-
from ._chat_types import ChatMessage
4+
from ._chat_types import ChatMessageDict
55

66
if TYPE_CHECKING:
77
from anthropic.types import MessageParam as AnthropicMessage
@@ -47,7 +47,7 @@
4747
# TODO: use a strategy pattern to allow others to register
4848
# their own message formats
4949
def as_provider_message(
50-
message: ChatMessage, format: ProviderMessageFormat
50+
message: ChatMessageDict, format: ProviderMessageFormat
5151
) -> "ProviderMessage":
5252
if format == "anthropic":
5353
return as_anthropic_message(message)
@@ -62,7 +62,7 @@ def as_provider_message(
6262
raise ValueError(f"Unknown format: {format}")
6363

6464

65-
def as_anthropic_message(message: ChatMessage) -> "AnthropicMessage":
65+
def as_anthropic_message(message: ChatMessageDict) -> "AnthropicMessage":
6666
from anthropic.types import MessageParam as AnthropicMessage
6767

6868
if message["role"] == "system":
@@ -72,7 +72,7 @@ def as_anthropic_message(message: ChatMessage) -> "AnthropicMessage":
7272
return AnthropicMessage(content=message["content"], role=message["role"])
7373

7474

75-
def as_google_message(message: ChatMessage) -> "GoogleMessage":
75+
def as_google_message(message: ChatMessageDict) -> "GoogleMessage":
7676
if sys.version_info < (3, 9):
7777
raise ValueError("Google requires Python 3.9")
7878

@@ -89,7 +89,7 @@ def as_google_message(message: ChatMessage) -> "GoogleMessage":
8989
return gtypes.ContentDict(parts=[message["content"]], role=role)
9090

9191

92-
def as_langchain_message(message: ChatMessage) -> "LangChainMessage":
92+
def as_langchain_message(message: ChatMessageDict) -> "LangChainMessage":
9393
from langchain_core.messages import AIMessage, HumanMessage, SystemMessage
9494

9595
content = message["content"]
@@ -103,7 +103,7 @@ def as_langchain_message(message: ChatMessage) -> "LangChainMessage":
103103
raise ValueError(f"Unknown role: {message['role']}")
104104

105105

106-
def as_openai_message(message: ChatMessage) -> "OpenAIMessage":
106+
def as_openai_message(message: ChatMessageDict) -> "OpenAIMessage":
107107
from openai.types.chat import (
108108
ChatCompletionAssistantMessageParam,
109109
ChatCompletionSystemMessageParam,
@@ -121,7 +121,7 @@ def as_openai_message(message: ChatMessage) -> "OpenAIMessage":
121121
raise ValueError(f"Unknown role: {role}")
122122

123123

124-
def as_ollama_message(message: ChatMessage) -> "OllamaMessage":
124+
def as_ollama_message(message: ChatMessageDict) -> "OllamaMessage":
125125
from ollama import Message as OllamaMessage
126126

127127
return OllamaMessage(content=message["content"], role=message["role"])

shiny/ui/_chat_types.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@
1313

1414
# TODO: content should probably be [{"type": "text", "content": "..."}, {"type": "image", ...}]
1515
# in order to support multiple content types...
16-
class ChatMessage(TypedDict):
16+
class ChatMessageDict(TypedDict):
1717
content: str
1818
role: Role
1919

2020

21-
class ChatUIMessage:
21+
class ChatMessage:
2222
def __init__(
2323
self,
2424
content: TagChild,
@@ -50,7 +50,7 @@ class TransformedMessage:
5050
html_deps: list[dict[str, str]] | None = None
5151

5252
@classmethod
53-
def from_chat_message(cls, message: ChatUIMessage) -> "TransformedMessage":
53+
def from_chat_message(cls, message: ChatMessage) -> "TransformedMessage":
5454
if message.role == "user":
5555
transform_key = "content_server"
5656
pre_transform_key = "content_client"

0 commit comments

Comments
 (0)