Skip to content

Commit

Permalink
Improve like/dislike functionality (#6572)
Browse files Browse the repository at this point in the history
* amend like/dislike logic

* add like/dislike to chatbot demo and add e2e test

* add changeset

* e2e test changes

* revert chatbot_component changes

* tweak

* generate notebooks

* tweak

---------

Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
  • Loading branch information
hannahblair and gradio-pr-bot committed Nov 24, 2023
1 parent 2b625ad commit 206af31
Show file tree
Hide file tree
Showing 8 changed files with 49 additions and 31 deletions.
7 changes: 7 additions & 0 deletions .changeset/long-candles-burn.md
@@ -0,0 +1,7 @@
---
"@gradio/chatbot": patch
"@gradio/icons": patch
"gradio": patch
---

fix:Improve like/dislike functionality
2 changes: 1 addition & 1 deletion 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.Textbox(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, api_name=\"bot_response\"\n", " )\n", " txt_msg.then(lambda: gr.Textbox(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}
{"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 print_like_dislike(x: gr.LikeData):\n", " print(x.index, x.value, x.liked)\n", "\n", "\n", "def add_text(history, text):\n", " history = history + [(text, None)]\n", " return history, gr.Textbox(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, api_name=\"bot_response\"\n", " )\n", " txt_msg.then(lambda: gr.Textbox(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", " chatbot.like(print_like_dislike, None, None)\n", "\n", "\n", "demo.queue()\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
7 changes: 7 additions & 0 deletions demo/chatbot_multimodal/run.py
Expand Up @@ -5,6 +5,10 @@
# Chatbot demo with multimodal input (text, markdown, LaTeX, code blocks, image, audio, & video). Plus shows support for streaming text.


def print_like_dislike(x: gr.LikeData):
print(x.index, x.value, x.liked)


def add_text(history, text):
history = history + [(text, None)]
return history, gr.Textbox(value="", interactive=False)
Expand Down Expand Up @@ -49,6 +53,9 @@ def bot(history):
bot, chatbot, chatbot
)

chatbot.like(print_like_dislike, None, None)


demo.queue()
if __name__ == "__main__":
demo.launch()
11 changes: 11 additions & 0 deletions js/app/test/chatbot_multimodal.spec.ts
Expand Up @@ -177,3 +177,14 @@ test("when a new message is sent the chatbot should scroll to the latest message
const bot_message_text = bot_message.textContent();
await expect(bot_message_text).toBeTruthy();
});

test("chatbot like and dislike functionality", async ({ page }) => {
await page.getByTestId("textbox").click();
await page.getByTestId("textbox").fill("hello");
await page.keyboard.press("Enter");
await page.getByLabel("like", { exact: true }).click();
await page.getByLabel("dislike").click();

expect(await page.getByLabel("clicked dislike").count()).toEqual(1);
expect(await page.getByLabel("clicked like").count()).toEqual(0);
});
12 changes: 4 additions & 8 deletions js/chatbot/shared/ChatBot.svelte
Expand Up @@ -98,12 +98,12 @@
i: number,
j: number,
message: string | { file: FileData; alt_text: string | null } | null,
liked: boolean
selected: string | null
): void {
dispatch("like", {
index: [i, j],
value: message,
liked: liked
liked: selected === "like"
});
}
</script>
Expand Down Expand Up @@ -238,12 +238,8 @@
>
{#if likeable && j == 1}
<LikeDislike
action="like"
handle_action={() => handle_like(i, j, message, true)}
/>
<LikeDislike
action="dislike"
handle_action={() => handle_like(i, j, message, false)}
handle_action={(selected) =>
handle_like(i, j, message, selected)}
/>
{/if}
{#if show_copy_button && message && typeof message === "string"}
Expand Down
33 changes: 15 additions & 18 deletions js/chatbot/shared/LikeDislike.svelte
Expand Up @@ -2,32 +2,29 @@
import { Like } from "@gradio/icons";
import { Dislike } from "@gradio/icons";
export let action: "like" | "dislike";
export let handle_action: () => void;
export let handle_action: (selected: string | null) => void;
let actioned = false;
let Icon = action === "like" ? Like : Dislike;
function action_feedback(): void {
actioned = true;
}
let selected: "like" | "dislike" | null = null;
</script>

<button
on:click={() => {
action_feedback();
handle_action();
selected = "like";
handle_action(selected);
}}
on:keydown={(e) => {
if (e.key === "Enter") {
action_feedback();
handle_action();
}
aria-label={selected === "like" ? "clicked like" : "like"}
>
<Like selected={selected === "like"} />
</button>

<button
on:click={() => {
selected = "dislike";
handle_action(selected);
}}
title={action + " message"}
aria-label={actioned ? `clicked ${action}` : action}
aria-label={selected === "dislike" ? "clicked dislike" : "dislike"}
>
<Icon {actioned} />
<Dislike selected={selected === "dislike"} />
</button>

<style>
Expand Down
4 changes: 2 additions & 2 deletions js/icons/src/Dislike.svelte
@@ -1,13 +1,13 @@
<script lang="ts">
export let actioned: boolean;
export let selected: boolean;
</script>

<svg
xmlns="http://www.w3.org/2000/svg"
width="15px"
height="15px"
viewBox="0 0 24 24"
fill={actioned ? "currentColor" : "none"}
fill={selected ? "currentColor" : "none"}
stroke-width="1.5"
color="currentColor"
><path
Expand Down
4 changes: 2 additions & 2 deletions js/icons/src/Like.svelte
@@ -1,13 +1,13 @@
<script lang="ts">
export let actioned: boolean;
export let selected: boolean;
</script>

<svg
xmlns="http://www.w3.org/2000/svg"
width="15px"
height="15px"
viewBox="0 0 24 24"
fill={actioned ? "currentColor" : "none"}
fill={selected ? "currentColor" : "none"}
stroke-width="1.5"
color="currentColor"
><path
Expand Down

0 comments on commit 206af31

Please sign in to comment.