From 7691e2280463aabe7af344d2b164270f65711220 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Wed, 31 Jan 2024 15:37:23 +0100 Subject: [PATCH 1/5] Don't pop ChatInterface variables --- panel/chat/feed.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/panel/chat/feed.py b/panel/chat/feed.py index d7301cb8a8..c409f10fe5 100644 --- a/panel/chat/feed.py +++ b/panel/chat/feed.py @@ -231,8 +231,8 @@ def __init__(self, *objects, **params): # forward message params to ChatMessage for convenience message_params = params.get("message_params", {}) - for param_key in list(params.keys()): - if param_key not in ChatFeed.param and param_key in ChatMessage.param: + for param_key in params.copy(): + if param_key not in self.param and param_key in ChatMessage.param: message_params[param_key] = params.pop(param_key) params["message_params"] = message_params From 3a45b43cd1f9d6d1d3e66401f861f887a8dd05bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Wed, 31 Jan 2024 17:14:38 +0100 Subject: [PATCH 2/5] Add test --- panel/tests/chat/test_interface.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/panel/tests/chat/test_interface.py b/panel/tests/chat/test_interface.py index 3594f168e4..532d678582 100644 --- a/panel/tests/chat/test_interface.py +++ b/panel/tests/chat/test_interface.py @@ -358,6 +358,10 @@ def post_callback(instance, event): assert chat_interface.objects[1].object == "2" assert chat_interface.objects[2].object == "3" + def test_manual_user(self): + chat_interface = ChatInterface(user="New User") + assert chat_interface.user == "New User" + class TestChatInterfaceWidgetsSizingMode: def test_none(self): chat_interface = ChatInterface() From 715311df0a782ca4002b821b1d9d09df05110683 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Wed, 31 Jan 2024 18:29:59 +0100 Subject: [PATCH 3/5] Update panel/tests/chat/test_interface.py Co-authored-by: Andrew <15331990+ahuang11@users.noreply.github.com> --- panel/tests/chat/test_interface.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/panel/tests/chat/test_interface.py b/panel/tests/chat/test_interface.py index 532d678582..3cd717f679 100644 --- a/panel/tests/chat/test_interface.py +++ b/panel/tests/chat/test_interface.py @@ -361,6 +361,8 @@ def post_callback(instance, event): def test_manual_user(self): chat_interface = ChatInterface(user="New User") assert chat_interface.user == "New User" + chat_interface.send("Test") + assert chat_interface.objects[0].user == "New User" class TestChatInterfaceWidgetsSizingMode: def test_none(self): From 94ac15917eb71805cfb9711d2582452c1b842707 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Wed, 31 Jan 2024 19:47:57 +0100 Subject: [PATCH 4/5] Inherit send and stream --- panel/chat/interface.py | 70 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/panel/chat/interface.py b/panel/chat/interface.py index 097758ca72..7d7c466af4 100644 --- a/panel/chat/interface.py +++ b/panel/chat/interface.py @@ -597,3 +597,73 @@ async def _cleanup_response(self): """ await super()._cleanup_response() await self._update_input_disabled() + + + def send( + self, + value: ChatMessage | dict | Any, + user: str | None = None, + avatar: str | bytes | BytesIO | None = None, + respond: bool = True, + ) -> ChatMessage | None: + """ + Sends a value and creates a new message in the chat log. + + If `respond` is `True`, additionally executes the callback, if provided. + + Arguments + --------- + value : ChatMessage | dict | Any + The message contents to send. + user : str | None + The user to send as; overrides the message message's user if provided. + Will default to the user parameter. + avatar : str | bytes | BytesIO | None + The avatar to use; overrides the message message's avatar if provided. + Will default to the avatar parameter. + respond : bool + Whether to execute the callback. + + Returns + ------- + The message that was created. + """ + return super().send(value, user=user or self.user, avatar=avatar or self.avatar, respond=respond) + + def stream( + self, + value: str, + user: str | None = None, + avatar: str | bytes | BytesIO | None = None, + message: ChatMessage | None = None, + replace: bool = False, + ) -> ChatMessage | None: + """ + Streams a token and updates the provided message, if provided. + Otherwise creates a new message in the chat log, so be sure the + returned message is passed back into the method, e.g. + `message = chat.stream(token, message=message)`. + + This method is primarily for outputs that are not generators-- + notably LangChain. For most cases, use the send method instead. + + Arguments + --------- + value : str | dict | ChatMessage + The new token value to stream. + user : str | None + The user to stream as; overrides the message's user if provided. + Will default to the user parameter. + avatar : str | bytes | BytesIO | None + The avatar to use; overrides the message's avatar if provided. + Will default to the avatar parameter. + message : ChatMessage | None + The message to update. + replace : bool + Whether to replace the existing text when streaming a string or dict. + + Returns + ------- + The message that was updated. + """ + return super().stream(value, user=user or self.user, avatar=avatar or self.avatar, message=message, replace=replace) From ad3c846daf027abd403fbc40a322f88aaae42ff4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Wed, 31 Jan 2024 20:58:02 +0100 Subject: [PATCH 5/5] Handle if value is ChatMessage --- panel/chat/interface.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/panel/chat/interface.py b/panel/chat/interface.py index 7d7c466af4..b9f3b6f66c 100644 --- a/panel/chat/interface.py +++ b/panel/chat/interface.py @@ -628,7 +628,12 @@ def send( ------- The message that was created. """ - return super().send(value, user=user or self.user, avatar=avatar or self.avatar, respond=respond) + if not isinstance(value, ChatMessage): + if user is None: + user = self.user + if avatar is None: + avatar = self.avatar + return super().send(value, user=user, avatar=avatar, respond=respond) def stream( self,