Skip to content

Commit

Permalink
delegate gradio events via a custom event dispatcher (#5279)
Browse files Browse the repository at this point in the history
* delegate gradio events via a custom event dispatcher

* improve md perf + share code

* fix df markdown

* prevent model3d from rerending too frequently

* tweaks

* fix more event bugs with video

* add changeset

* optimise handle mount

* does this do anything

* fix

* remove old dispatches

* fix dropdown position

* oops

* fixes

* fix tests

* fix types

* format

* fix markdown code

* add changeset

* fix typecheck

* fix typecheck

* fix demos

* notebooks

* fix tests

* changer

* maybe this

* fixes

* add changeset

* fix chatbot alignment mobile

* fix chantbot

* add changeset

* changeset

* changeset

* storybook

---------

Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
Co-authored-by: Abubakar Abid <abubakar@huggingface.co>
  • Loading branch information
3 people committed Aug 23, 2023
1 parent cf167cd commit fe05730
Show file tree
Hide file tree
Showing 117 changed files with 3,216 additions and 2,461 deletions.
56 changes: 56 additions & 0 deletions .changeset/chilly-chefs-hug.md
@@ -0,0 +1,56 @@
---
"@gradio/annotatedimage": patch
"@gradio/app": patch
"@gradio/atoms": patch
"@gradio/audio": patch
"@gradio/button": patch
"@gradio/chatbot": patch
"@gradio/checkbox": patch
"@gradio/checkboxgroup": patch
"@gradio/code": patch
"@gradio/colorpicker": patch
"@gradio/dataframe": patch
"@gradio/dropdown": patch
"@gradio/file": patch
"@gradio/gallery": patch
"@gradio/highlightedtext": patch
"@gradio/html": patch
"@gradio/image": patch
"@gradio/json": patch
"@gradio/label": patch
"@gradio/markdown": patch
"@gradio/model3d": patch
"@gradio/number": patch
"@gradio/plot": patch
"@gradio/radio": patch
"@gradio/slider": patch
"@gradio/tabitem": patch
"@gradio/tabs": patch
"@gradio/textbox": patch
"@gradio/theme": patch
"@gradio/timeseries": patch
"@gradio/tootils": patch
"@gradio/upload": patch
"@gradio/uploadbutton": patch
"@gradio/utils": patch
"@gradio/video": patch
"gradio": patch
"website": patch
---

highlight:

#### Improve startup performance and markdown support

##### Improved markdown support

We now have better support for markdown in `gr.Markdown` and `gr.Dataframe`. Including syntax highlighting and Github Flavoured Markdown. We also have more consistent markdown behaviour and styling.

##### Various performance improvements

These improvements will be particularly beneficial to large applications.

- Rather than attaching events manually, they are now delegated, leading to a significant performance improvement and addressing a performance regression introduced in a recent version of Gradio. App startup for large applications is now around twice as fast.
- Optimised the mounting of individual components, leading to a modest performance improvement during startup (~30%).
- Corrected an issue that was causing markdown to re-render infinitely.
- Ensured that the `gr.3DModel` does re-render prematurely.
2 changes: 1 addition & 1 deletion demo/event_trigger/run.ipynb
@@ -1 +1 @@
{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: event_trigger"]}, {"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", "os.mkdir('img')\n", "!wget -q -O img/a.jpg https://github.com/gradio-app/gradio/raw/main/demo/event_trigger/img/a.jpg\n", "!wget -q -O img/b.jpg https://github.com/gradio-app/gradio/raw/main/demo/event_trigger/img/b.jpg\n", "os.mkdir('mp4')\n", "!wget -q -O mp4/a.mp4 https://github.com/gradio-app/gradio/raw/main/demo/event_trigger/mp4/a.mp4\n", "!wget -q -O mp4/b.mp4 https://github.com/gradio-app/gradio/raw/main/demo/event_trigger/mp4/b.mp4"]}, {"cell_type": "code", "execution_count": null, "id": 44380577570523278879349135829904343037, "metadata": {}, "outputs": [], "source": ["# %%\n", "import gradio as gr\n", "\n", "\n", "TEST_VIDEO_A = \"mp4/a.mp4\"\n", "TEST_VIDEO_B = \"mp4/b.mp4\"\n", "\n", "TEST_IMAGE_A = \"img/a.jpg\"\n", "TEST_IMAGE_B = \"img/b.jpg\"\n", "\n", "\n", "def alert_change(component, value):\n", " print(f\"Detected {component} change, {type(value)}\")\n", "\n", " if type(value) == list or type(value) == str:\n", " print(value)\n", "\n", "\n", "def change_interactive(state):\n", " return gr.update(interactive=not state), not state\n", "\n", "\n", "with gr.Blocks() as demo:\n", " with gr.Tab(label=\"Text change\"):\n", " with gr.Row():\n", " with gr.Column():\n", " textbox1 = gr.Textbox()\n", " textbox2 = gr.Textbox(interactive=True)\n", "\n", " with gr.Column():\n", " btn = gr.Button()\n", "\n", " def btn_click(state):\n", " return state\n", "\n", " def text_change(value):\n", " print(\"text_change\", value)\n", "\n", " btn.click(fn=btn_click, inputs=textbox1, outputs=textbox2)\n", " textbox2.change(fn=alert_change, inputs=[gr.State(\"Text\"), textbox2])\n", "\n", " with gr.Tab(label=\"Video change, play, pause\"):\n", " with gr.Row():\n", " with gr.Column():\n", " radio1 = gr.Radio(\n", " choices=[TEST_VIDEO_A, TEST_VIDEO_B],\n", " interactive=True,\n", " type=\"index\",\n", " )\n", "\n", " video_btn = gr.Button(\"Change interactive\")\n", "\n", " with gr.Column():\n", " video1 = gr.Video(value=TEST_VIDEO_A, interactive=False)\n", " video1_interactive = gr.State(value=False)\n", "\n", " def change_video(index):\n", " if index == 0:\n", " return TEST_VIDEO_A\n", " elif index == 1:\n", " return TEST_VIDEO_B\n", "\n", " def video_play():\n", " print(\"video_play\")\n", "\n", " def video_pause():\n", " print(\"video_pause\")\n", "\n", " def video_stop():\n", " print(\"video_stop\")\n", "\n", " video1.play(fn=video_play)\n", " video1.pause(fn=video_pause)\n", " video1.stop(fn=video_stop)\n", "\n", " radio1.change(fn=change_video, inputs=radio1, outputs=video1)\n", " video1.change(fn=alert_change, inputs=[gr.State(\"Video\"), video1])\n", "\n", " video_btn.click(\n", " fn=change_interactive,\n", " inputs=video1_interactive,\n", " outputs=[video1, video1_interactive],\n", " )\n", "\n", " with gr.Tab(label=\"Image change\"):\n", " with gr.Row():\n", " with gr.Column():\n", " radio2 = gr.Radio(\n", " choices=[TEST_IMAGE_A, TEST_IMAGE_B],\n", " interactive=True,\n", " type=\"index\",\n", " )\n", "\n", " with gr.Column():\n", " image1 = gr.Image(value=TEST_IMAGE_A, interactive=True)\n", "\n", " def change_image(index):\n", " if index == 0:\n", " return TEST_IMAGE_A\n", " elif index == 1:\n", " return TEST_IMAGE_B\n", "\n", " radio2.change(fn=change_image, inputs=radio2, outputs=image1)\n", " image1.change(fn=alert_change, inputs=[gr.State(\"Image\"), image1])\n", "\n", " with gr.Tab(label=\"File\"):\n", " with gr.Row():\n", " with gr.Column():\n", " radio3 = gr.Radio(\n", " choices=[\"A\", \"B\", \"AB\"],\n", " interactive=True,\n", " type=\"index\",\n", " )\n", "\n", " file_btn = gr.Button(\"Change interactive\")\n", "\n", " with gr.Column():\n", " file1 = gr.File(\n", " value=[TEST_IMAGE_A, TEST_IMAGE_B],\n", " interactive=False,\n", " file_count=\"multiple\",\n", " )\n", " file1_interactive = gr.State(value=False)\n", "\n", " def change_file(index):\n", " if index == 0:\n", " return [TEST_IMAGE_A]\n", " elif index == 1:\n", " return [TEST_IMAGE_A]\n", " elif index == 2:\n", " return [TEST_IMAGE_A, TEST_IMAGE_B]\n", "\n", " radio3.change(fn=change_file, inputs=radio3, outputs=file1)\n", " file1.change(fn=alert_change, inputs=[gr.State(\"File\"), file1])\n", "\n", " file_btn.click(\n", " fn=change_interactive,\n", " inputs=file1_interactive,\n", " outputs=[file1, file1_interactive],\n", " )\n", "\n", "demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: event_trigger"]}, {"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", "os.mkdir('img')\n", "!wget -q -O img/a.jpg https://github.com/gradio-app/gradio/raw/main/demo/event_trigger/img/a.jpg\n", "!wget -q -O img/b.jpg https://github.com/gradio-app/gradio/raw/main/demo/event_trigger/img/b.jpg\n", "os.mkdir('mp4')\n", "!wget -q -O mp4/a.mp4 https://github.com/gradio-app/gradio/raw/main/demo/event_trigger/mp4/a.mp4\n", "!wget -q -O mp4/b.mp4 https://github.com/gradio-app/gradio/raw/main/demo/event_trigger/mp4/b.mp4"]}, {"cell_type": "code", "execution_count": null, "id": 44380577570523278879349135829904343037, "metadata": {}, "outputs": [], "source": ["# %%\n", "import gradio as gr\n", "\n", "\n", "TEST_VIDEO_A = \"mp4/a.mp4\"\n", "TEST_VIDEO_B = \"mp4/b.mp4\"\n", "\n", "TEST_IMAGE_A = \"img/a.jpg\"\n", "TEST_IMAGE_B = \"img/b.jpg\"\n", "\n", "\n", "def alert_change(component, value):\n", " print(f\"Detected {component} change, {type(value)}\")\n", "\n", " if type(value) == list or type(value) == str:\n", " print(value)\n", "\n", "\n", "def change_interactive(state):\n", " return gr.update(interactive=not state), not state\n", "\n", "\n", "with gr.Blocks() as demo:\n", " with gr.Tab(label=\"Text change\"):\n", " with gr.Row():\n", " with gr.Column():\n", " textbox1 = gr.Textbox()\n", " textbox2 = gr.Textbox(interactive=True)\n", "\n", " with gr.Column():\n", " btn = gr.Button()\n", "\n", " def btn_click(state):\n", " return state\n", "\n", " def text_change(value):\n", " print(\"text_change\", value)\n", "\n", " btn.click(fn=btn_click, inputs=textbox1, outputs=textbox2)\n", " textbox2.change(fn=alert_change, inputs=[gr.State(\"Text\"), textbox2])\n", "\n", " with gr.Tab(label=\"Video change, play, pause\"):\n", " with gr.Row():\n", " with gr.Column():\n", " radio1 = gr.Radio(\n", " choices=[TEST_VIDEO_A, TEST_VIDEO_B],\n", " interactive=True,\n", " type=\"index\",\n", " )\n", "\n", " video_btn = gr.Button(\"Change interactive\")\n", "\n", " with gr.Column():\n", " video1 = gr.Video(value=TEST_VIDEO_A, interactive=False)\n", " video1_interactive = gr.State(value=False)\n", "\n", " def change_video(index):\n", " if index == 0:\n", " return TEST_VIDEO_A\n", " elif index == 1:\n", " return TEST_VIDEO_B\n", "\n", " def video_play():\n", " print(\"video_play\")\n", "\n", " def video_pause():\n", " print(\"video_pause\")\n", "\n", " def video_stop():\n", " print(\"video_stop\")\n", "\n", " def video_end():\n", " print(\"video_end\")\n", "\n", " video1.play(fn=video_play)\n", " video1.pause(fn=video_pause)\n", " video1.stop(fn=video_stop)\n", " video1.end(fn=video_end)\n", "\n", " radio1.change(fn=change_video, inputs=radio1, outputs=video1)\n", " video1.change(fn=alert_change, inputs=[gr.State(\"Video\"), video1])\n", "\n", " video_btn.click(\n", " fn=change_interactive,\n", " inputs=video1_interactive,\n", " outputs=[video1, video1_interactive],\n", " )\n", "\n", " with gr.Tab(label=\"Image change\"):\n", " with gr.Row():\n", " with gr.Column():\n", " radio2 = gr.Radio(\n", " choices=[TEST_IMAGE_A, TEST_IMAGE_B],\n", " interactive=True,\n", " type=\"index\",\n", " )\n", "\n", " with gr.Column():\n", " image1 = gr.Image(value=TEST_IMAGE_A, interactive=True)\n", "\n", " def change_image(index):\n", " if index == 0:\n", " return TEST_IMAGE_A\n", " elif index == 1:\n", " return TEST_IMAGE_B\n", "\n", " radio2.change(fn=change_image, inputs=radio2, outputs=image1)\n", " image1.change(fn=alert_change, inputs=[gr.State(\"Image\"), image1])\n", "\n", " with gr.Tab(label=\"File\"):\n", " with gr.Row():\n", " with gr.Column():\n", " radio3 = gr.Radio(\n", " choices=[\"A\", \"B\", \"AB\"],\n", " interactive=True,\n", " type=\"index\",\n", " )\n", "\n", " file_btn = gr.Button(\"Change interactive\")\n", "\n", " with gr.Column():\n", " file1 = gr.File(\n", " value=[TEST_IMAGE_A, TEST_IMAGE_B],\n", " interactive=False,\n", " file_count=\"multiple\",\n", " )\n", " file1_interactive = gr.State(value=False)\n", "\n", " def change_file(index):\n", " if index == 0:\n", " return [TEST_IMAGE_A]\n", " elif index == 1:\n", " return [TEST_IMAGE_A]\n", " elif index == 2:\n", " return [TEST_IMAGE_A, TEST_IMAGE_B]\n", "\n", " radio3.change(fn=change_file, inputs=radio3, outputs=file1)\n", " file1.change(fn=alert_change, inputs=[gr.State(\"File\"), file1])\n", "\n", " file_btn.click(\n", " fn=change_interactive,\n", " inputs=file1_interactive,\n", " outputs=[file1, file1_interactive],\n", " )\n", "\n", "demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
4 changes: 4 additions & 0 deletions demo/event_trigger/run.py
Expand Up @@ -69,9 +69,13 @@ def video_pause():
def video_stop():
print("video_stop")

def video_end():
print("video_end")

video1.play(fn=video_play)
video1.pause(fn=video_pause)
video1.stop(fn=video_stop)
video1.end(fn=video_end)

radio1.change(fn=change_video, inputs=radio1, outputs=video1)
video1.change(fn=alert_change, inputs=[gr.State("Video"), video1])
Expand Down
2 changes: 1 addition & 1 deletion demo/latex/run.ipynb
@@ -1 +1 @@
{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: latex"]}, {"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": ["import gradio as gr\n", "\n", "with gr.Blocks() as demo:\n", " gr.Markdown(\n", " r\"\"\"\n", " # Hello World! $\\frac{\\sqrt{x + y}}{4}$ is today's lesson\n", "\n", " ## the $\\sqrt{x + y}$ is first\n", "\n", " Start with $\\frac{\\frac{x+1}{x+2}}{x+3}$ then we get $ 2+x $ and $3$.\n", " \n", " There are three formulas to know:\n", " \n", " the first is $\\gamma^2 + \\theta^2 = \\omega^2$\n", " \n", " $\\sqrt{x^2+1}\n", " $ is next\n", " \n", " Integral $\\int_{a}^{b} x^2 \\,dx$ is last\n", "\n", " Start typing below to see the output.\n", "\n", " I spent $5 at the grocery store. Then I bought a $2.50 ice cream cone.\n", " \"\"\")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: latex"]}, {"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": ["import gradio as gr\n", "\n", "with gr.Blocks() as demo:\n", " gr.Markdown(\n", " r\"\"\"\n", " # Hello World! $\\frac{\\sqrt{x + y}}{4}$ is today's lesson\n", "\n", " ## the $\\sqrt{x + y}$ is first\n", "\n", " Start with $\\frac{\\frac{x+1}{x+2}}{x+3}$ then we get $ 2+x $ and $3$.\n", " \n", " There are three formulas to know:\n", " \n", " the first is $\\gamma^2 + \\theta^2 = \\omega^2$\n", " \n", " $\\sqrt{x^2+1}$ is next\n", " \n", " Integral $\\int_{a}^{b} x^2 \\,dx$ is last\n", "\n", " Start typing below to see the output.\n", "\n", " I spent $5 at the grocery store. Then I bought a $2.50 ice cream cone.\n", " \"\"\")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
3 changes: 1 addition & 2 deletions demo/latex/run.py
Expand Up @@ -13,8 +13,7 @@
the first is $\gamma^2 + \theta^2 = \omega^2$
$\sqrt{x^2+1}
$ is next
$\sqrt{x^2+1}$ is next
Integral $\int_{a}^{b} x^2 \,dx$ is last
Expand Down

0 comments on commit fe05730

Please sign in to comment.