From c5bf91385a632dc9f612499ee01166ac6ae509a9 Mon Sep 17 00:00:00 2001 From: Dawood Khan Date: Mon, 28 Aug 2023 20:48:52 -0400 Subject: [PATCH] Add chat bubble width param (#5334) * chat width * add changeset * fixes * fix * test * reformat --------- Co-authored-by: gradio-pr-bot --- .changeset/tough-poets-yell.md | 6 ++++++ demo/chatbot_multimodal/run.ipynb | 2 +- demo/chatbot_multimodal/run.py | 1 + gradio/components/chatbot.py | 6 ++++++ js/chatbot/Chatbot.stories.svelte | 7 +++++++ js/chatbot/static/ChatBot.svelte | 9 ++++++++- js/chatbot/static/StaticChatbot.svelte | 2 ++ test/test_components.py | 1 + 8 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 .changeset/tough-poets-yell.md diff --git a/.changeset/tough-poets-yell.md b/.changeset/tough-poets-yell.md new file mode 100644 index 000000000000..cf2eaaa3cf8c --- /dev/null +++ b/.changeset/tough-poets-yell.md @@ -0,0 +1,6 @@ +--- +"@gradio/chatbot": minor +"gradio": minor +--- + +feat:Add chat bubble width param diff --git a/demo/chatbot_multimodal/run.ipynb b/demo/chatbot_multimodal/run.ipynb index c3726d628a5f..e978080af308 100644 --- a/demo/chatbot_multimodal/run.ipynb +++ b/demo/chatbot_multimodal/run.ipynb @@ -1 +1 @@ -{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: chatbot_multimodal"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/chatbot_multimodal/avatar.png"]}, {"cell_type": "code", "execution_count": null, "id": 44380577570523278879349135829904343037, "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import os\n", "import time\n", "\n", "# Chatbot demo with multimodal input (text, markdown, LaTeX, code blocks, image, audio, & video). Plus shows support for streaming text.\n", "\n", "\n", "def add_text(history, text):\n", " history = history + [(text, None)]\n", " return history, gr.update(value=\"\", interactive=False)\n", "\n", "\n", "def add_file(history, file):\n", " history = history + [((file.name,), None)]\n", " return history\n", "\n", "\n", "def bot(history):\n", " response = \"**That's cool!**\"\n", " history[-1][1] = \"\"\n", " for character in response:\n", " history[-1][1] += character\n", " time.sleep(0.05)\n", " yield history\n", "\n", "\n", "with gr.Blocks() as demo:\n", " chatbot = gr.Chatbot(\n", " [],\n", " elem_id=\"chatbot\",\n", " avatar_images=(None, (os.path.join(os.path.abspath(''), \"avatar.png\"))),\n", " )\n", "\n", " with gr.Row():\n", " txt = gr.Textbox(\n", " scale=4,\n", " show_label=False,\n", " placeholder=\"Enter text and press enter, or upload an image\",\n", " container=False,\n", " )\n", " btn = gr.UploadButton(\"\ud83d\udcc1\", file_types=[\"image\", \"video\", \"audio\"])\n", "\n", " txt_msg = txt.submit(add_text, [chatbot, txt], [chatbot, txt], queue=False).then(\n", " bot, chatbot, chatbot\n", " )\n", " txt_msg.then(lambda: gr.update(interactive=True), None, [txt], queue=False)\n", " file_msg = btn.upload(add_file, [chatbot, btn], [chatbot], queue=False).then(\n", " bot, chatbot, chatbot\n", " )\n", "\n", "demo.queue()\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file +{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: chatbot_multimodal"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/chatbot_multimodal/avatar.png"]}, {"cell_type": "code", "execution_count": null, "id": 44380577570523278879349135829904343037, "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import os\n", "import time\n", "\n", "# Chatbot demo with multimodal input (text, markdown, LaTeX, code blocks, image, audio, & video). Plus shows support for streaming text.\n", "\n", "\n", "def add_text(history, text):\n", " history = history + [(text, None)]\n", " return history, gr.update(value=\"\", interactive=False)\n", "\n", "\n", "def add_file(history, file):\n", " history = history + [((file.name,), None)]\n", " return history\n", "\n", "\n", "def bot(history):\n", " response = \"**That's cool!**\"\n", " history[-1][1] = \"\"\n", " for character in response:\n", " history[-1][1] += character\n", " time.sleep(0.05)\n", " yield history\n", "\n", "\n", "with gr.Blocks() as demo:\n", " chatbot = gr.Chatbot(\n", " [],\n", " elem_id=\"chatbot\",\n", " bubble_full_width=False,\n", " avatar_images=(None, (os.path.join(os.path.abspath(''), \"avatar.png\"))),\n", " )\n", "\n", " with gr.Row():\n", " txt = gr.Textbox(\n", " scale=4,\n", " show_label=False,\n", " placeholder=\"Enter text and press enter, or upload an image\",\n", " container=False,\n", " )\n", " btn = gr.UploadButton(\"\ud83d\udcc1\", file_types=[\"image\", \"video\", \"audio\"])\n", "\n", " txt_msg = txt.submit(add_text, [chatbot, txt], [chatbot, txt], queue=False).then(\n", " bot, chatbot, chatbot\n", " )\n", " txt_msg.then(lambda: gr.update(interactive=True), None, [txt], queue=False)\n", " file_msg = btn.upload(add_file, [chatbot, btn], [chatbot], queue=False).then(\n", " bot, chatbot, chatbot\n", " )\n", "\n", "demo.queue()\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file diff --git a/demo/chatbot_multimodal/run.py b/demo/chatbot_multimodal/run.py index a17297451ad5..9c0d84a16d0e 100644 --- a/demo/chatbot_multimodal/run.py +++ b/demo/chatbot_multimodal/run.py @@ -28,6 +28,7 @@ def bot(history): chatbot = gr.Chatbot( [], elem_id="chatbot", + bubble_full_width=False, avatar_images=(None, (os.path.join(os.path.dirname(__file__), "avatar.png"))), ) diff --git a/gradio/components/chatbot.py b/gradio/components/chatbot.py index 867b1792f9b7..79fc6afb940b 100644 --- a/gradio/components/chatbot.py +++ b/gradio/components/chatbot.py @@ -55,6 +55,7 @@ def __init__( show_share_button: bool | None = None, show_copy_button: bool = False, avatar_images: tuple[str | Path | None, str | Path | None] | None = None, + bubble_full_width: bool = True, **kwargs, ): """ @@ -76,6 +77,7 @@ def __init__( show_share_button: If True, will show a share icon in the corner of the component that allows user to share outputs to Hugging Face Spaces Discussions. If False, icon does not appear. If set to None (default behavior), then the icon appears if this Gradio app is launched on Spaces, but not otherwise. show_copy_button: If True, will show a copy button for each chatbot message. avatar_images: Tuple of two avatar image paths or URLs for user and bot (in that order). Pass None for either the user or bot image to skip. Must be within the working directory of the Gradio app or an external URL. + bubble_full_width: If False, the chat bubble will fit to the content of the message. If True (default), the chat bubble will be the full width of the component. """ if color_map is not None: warn_deprecation("The 'color_map' parameter has been deprecated.") @@ -97,6 +99,7 @@ def __init__( else show_share_button ) self.show_copy_button = show_copy_button + self.bubble_full_width = bubble_full_width IOComponent.__init__( self, label=label, @@ -122,6 +125,7 @@ def get_config(self): "rtl": self.rtl, "show_copy_button": self.show_copy_button, "avatar_images": self.avatar_images, + "bubble_full_width": self.bubble_full_width, **IOComponent.get_config(self), } @@ -142,6 +146,7 @@ def update( show_share_button: bool | None = None, show_copy_button: bool | None = None, avatar_images: tuple[str | Path | None] | None = None, + bubble_full_width: bool | None = None, ): updated_config = { "label": label, @@ -157,6 +162,7 @@ def update( "latex_delimiters": latex_delimiters, "show_copy_button": show_copy_button, "avatar_images": avatar_images, + "bubble_full_width": bubble_full_width, "__type__": "update", } return updated_config diff --git a/js/chatbot/Chatbot.stories.svelte b/js/chatbot/Chatbot.stories.svelte index b7437110049d..fbe342c9b761 100644 --- a/js/chatbot/Chatbot.stories.svelte +++ b/js/chatbot/Chatbot.stories.svelte @@ -66,3 +66,10 @@ show_copy_button: true }} /> + + diff --git a/js/chatbot/static/ChatBot.svelte b/js/chatbot/static/ChatBot.svelte index d462b9db7911..a0e7aa2f2fe8 100644 --- a/js/chatbot/static/ChatBot.svelte +++ b/js/chatbot/static/ChatBot.svelte @@ -5,7 +5,6 @@ import { beforeUpdate, afterUpdate, createEventDispatcher } from "svelte"; import { ShareButton } from "@gradio/atoms"; import type { SelectData } from "@gradio/utils"; - import type { ThemeMode } from "js/app/src/components/types"; import type { FileData } from "@gradio/upload"; import { MarkdownCode as Markdown } from "@gradio/markdown/static"; import { get_fetchable_url_or_file } from "@gradio/upload"; @@ -28,6 +27,7 @@ export let rtl = false; export let show_copy_button = false; export let avatar_images: [string | null, string | null] = [null, null]; + export let bubble_full_width = true; export let root: string; export let root_url: null | string; @@ -116,6 +116,7 @@ data-testid={j == 0 ? "user" : "bot"} class:latest={i === value.length - 1} class="message {j == 0 ? 'user' : 'bot'}" + class:message-fit={!bubble_full_width} class:hide={message === null} class:selectable on:click={() => handle_select(i, j, message)} @@ -235,6 +236,12 @@ line-height: var(--line-lg); overflow-wrap: break-word; } + .message-fit { + width: fit-content !important; + } + .message-fit.user { + margin-left: auto; + } .user { align-self: flex-end; border-bottom-right-radius: 0; diff --git a/js/chatbot/static/StaticChatbot.svelte b/js/chatbot/static/StaticChatbot.svelte index 40d0cd284e86..8000cae939ab 100644 --- a/js/chatbot/static/StaticChatbot.svelte +++ b/js/chatbot/static/StaticChatbot.svelte @@ -23,6 +23,7 @@ export let show_share_button = false; export let rtl = false; export let show_copy_button = false; + export let bubble_full_width = true; export let latex_delimiters: { left: string; right: string; @@ -96,6 +97,7 @@ on:share={(e) => gradio.dispatch("share", e.detail)} on:error={(e) => gradio.dispatch("error", e.detail)} {avatar_images} + {bubble_full_width} {root_url} {root} /> diff --git a/test/test_components.py b/test/test_components.py index d780ccc5c1af..50d7cf33865b 100644 --- a/test/test_components.py +++ b/test/test_components.py @@ -2018,6 +2018,7 @@ def test_component_functions(self): "rtl": False, "show_copy_button": False, "avatar_images": (None, None), + "bubble_full_width": True, }