[ { "id": 0, "parent": null, "path": "03_building-with-blocks/02_controlling-layout.md", "level": 1, "title": "Controlling Layout", "content": "By default, Components in Blocks are arranged vertically. Let's take a look at how we can rearrange Components. Under the hood, this layout structure uses the [flexbox model of web development](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Basic_Concepts_of_Flexbox)." }, { "id": 1, "parent": 0, "path": "03_building-with-blocks/02_controlling-layout.md", "level": 2, "title": "Rows", "content": "Elements within a `with gr.Row` clause will all be displayed horizontally. For example, to display two Buttons side by side:\n\n```python\nwith gr.Blocks() as demo:\n with gr.Row():\n btn1 = gr.Button(\"Button 1\")\n btn2 = gr.Button(\"Button 2\")\n```\n\nYou can set every element in a Row to have the same height. Configure this with the `equal_height` argument.\n\n```python\nwith gr.Blocks() as demo:\n with gr.Row(equal_height=True):\n textbox = gr.Textbox()\n btn2 = gr.Button(\"Button 2\")\n```\n\nThe widths of elements in a Row can be controlled via a combination of `scale` and `min_width` arguments that are present in every Component.\n\n- `scale` is an integer that defines how an element will take up space in a Row. If scale is set to `0`, the element will not expand to take up space. If scale is set to `1` or greater, the element will expand. Multiple elements in a row will expand proportional to their scale. Below, `btn2` will expand twice as much as `btn1`, while `btn0` will not expand at all:\n\n```python\nwith gr.Blocks() as demo:\n with gr.Row():\n btn0 = gr.Button(\"Button 0\", scale=0)\n btn1 = gr.Button(\"Button 1\", scale=1)\n btn2 = gr.Button(\"Button 2\", scale=2)\n```\n\n- `min_width` will set the minimum width the element will take. The Row will wrap if there isn't sufficient space to satisfy all `min_width` values.\n\nLearn more about Rows in the [docs](https://gradio.app/docs/row)." }, { "id": 2, "parent": 0, "path": "03_building-with-blocks/02_controlling-layout.md", "level": 2, "title": "Columns and Nesting", "content": "Components within a Column will be placed vertically atop each other. Since the vertical layout is the default layout for Blocks apps anyway, to be useful, Columns are usually nested within Rows. For example:\n\n```py\nimport gradio as gr\n\nwith gr.Blocks() as demo:\n with gr.Row():\n text1 = gr.Textbox(label=\"t1\")\n slider2 = gr.Textbox(label=\"s2\")\n drop3 = gr.Dropdown([\"a\", \"b\", \"c\"], label=\"d3\")\n with gr.Row():\n with gr.Column(scale=1, min_width=300):\n text1 = gr.Textbox(label=\"prompt 1\")\n text2 = gr.Textbox(label=\"prompt 2\")\n inbtw = gr.Button(\"Between\")\n text4 = gr.Textbox(label=\"prompt 1\")\n text5 = gr.Textbox(label=\"prompt 2\")\n with gr.Column(scale=2, min_width=300):\n img1 = gr.Image(\"images/cheetah.jpg\")\n btn = gr.Button(\"Go\")\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n$demo_rows_and_columns\n\nSee how the first column has two Textboxes arranged vertically. The second column has an Image and Button arranged vertically. Notice how the relative widths of the two columns is set by the `scale` parameter. The column with twice the `scale` value takes up twice the width.\n\nLearn more about Columns in the [docs](https://gradio.app/docs/column)." }, { "id": 3, "parent": null, "path": "03_building-with-blocks/02_controlling-layout.md", "level": 1, "title": "Fill Browser Height / Width", "content": "To make an app take the full width of the browser by removing the side padding, use `gr.Blocks(fill_width=True)`. \n\nTo make top level Components expand to take the full height of the browser, use `fill_height` and apply scale to the expanding Components.\n\n```python\nimport gradio as gr\n\nwith gr.Blocks(fill_height=True) as demo:\n gr.Chatbot(scale=1)\n gr.Textbox(scale=0)\n```" }, { "id": 4, "parent": 3, "path": "03_building-with-blocks/02_controlling-layout.md", "level": 2, "title": "Dimensions", "content": "Some components support setting height and width. These parameters accept either a number (interpreted as pixels) or a string. Using a string allows the direct application of any CSS unit to the encapsulating Block element.\n\nBelow is an example illustrating the use of viewport width (vw):\n\n```python\nimport gradio as gr\n\nwith gr.Blocks() as demo:\n im = gr.ImageEditor(width=\"50vw\")\n\ndemo.launch()\n```" }, { "id": 5, "parent": 3, "path": "03_building-with-blocks/02_controlling-layout.md", "level": 2, "title": "Tabs and Accordions", "content": "You can also create Tabs using the `with gr.Tab('tab_name'):` clause. Any component created inside of a `with gr.Tab('tab_name'):` context appears in that tab. Consecutive Tab clauses are grouped together so that a single tab can be selected at one time, and only the components within that Tab's context are shown.\n\nFor example:\n\n```py\nimport numpy as np\nimport gradio as gr\n\ndef flip_text(x):\n return x[::-1]\n\ndef flip_image(x):\n return np.fliplr(x)\n\nwith gr.Blocks() as demo:\n gr.Markdown(\"Flip text or image files using this demo.\")\n with gr.Tab(\"Flip Text\"):\n text_input = gr.Textbox()\n text_output = gr.Textbox()\n text_button = gr.Button(\"Flip\")\n with gr.Tab(\"Flip Image\"):\n with gr.Row():\n image_input = gr.Image()\n image_output = gr.Image()\n image_button = gr.Button(\"Flip\")\n\n with gr.Accordion(\"Open for More!\", open=False):\n gr.Markdown(\"Look at me...\")\n temp_slider = gr.Slider(\n 0, 1,\n value=0.1,\n step=0.1,\n interactive=True,\n label=\"Slide me\",\n )\n\n text_button.click(flip_text, inputs=text_input, outputs=text_output)\n image_button.click(flip_image, inputs=image_input, outputs=image_output)\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n$demo_blocks_flipper\n\nAlso note the `gr.Accordion('label')` in this example. The Accordion is a layout that can be toggled open or closed. Like `Tabs`, it is a layout element that can selectively hide or show content. Any components that are defined inside of a `with gr.Accordion('label'):` will be hidden or shown when the accordion's toggle icon is clicked.\n\nLearn more about [Tabs](https://gradio.app/docs/tab) and [Accordions](https://gradio.app/docs/accordion) in the docs." }, { "id": 6, "parent": 3, "path": "03_building-with-blocks/02_controlling-layout.md", "level": 2, "title": "Visibility", "content": "Both Components and Layout elements have a `visible` argument that can set initially and also updated. Setting `gr.Column(visible=...)` on a Column can be used to show or hide a set of Components.\n\n```py\nimport gradio as gr\n\nwith gr.Blocks() as demo:\n name_box = gr.Textbox(label=\"Name\")\n age_box = gr.Number(label=\"Age\", minimum=0, maximum=100)\n symptoms_box = gr.CheckboxGroup([\"Cough\", \"Fever\", \"Runny Nose\"])\n submit_btn = gr.Button(\"Submit\")\n\n with gr.Column(visible=False) as output_col:\n diagnosis_box = gr.Textbox(label=\"Diagnosis\")\n patient_summary_box = gr.Textbox(label=\"Patient Summary\")\n\n def submit(name, age, symptoms):\n return {\n submit_btn: gr.Button(visible=False),\n output_col: gr.Column(visible=True),\n diagnosis_box: \"covid\" if \"Cough\" in symptoms else \"flu\",\n patient_summary_box: f\"{name}, {age} y/o\",\n }\n\n submit_btn.click(\n submit,\n [name_box, age_box, symptoms_box],\n [submit_btn, diagnosis_box, patient_summary_box, output_col],\n )\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n$demo_blocks_form" }, { "id": 7, "parent": 3, "path": "03_building-with-blocks/02_controlling-layout.md", "level": 2, "title": "Defining and Rendering Components Separately", "content": "In some cases, you might want to define components before you actually render them in your UI. For instance, you might want to show an examples section using `gr.Examples` above the corresponding `gr.Textbox` input. Since `gr.Examples` requires as a parameter the input component object, you will need to first define the input component, but then render it later, after you have defined the `gr.Examples` object.\n\nThe solution to this is to define the `gr.Textbox` outside of the `gr.Blocks()` scope and use the component's `.render()` method wherever you'd like it placed in the UI.\n\nHere's a full code example:\n\n```python\ninput_textbox = gr.Textbox()\n\nwith gr.Blocks() as demo:\n gr.Examples([\"hello\", \"bonjour\", \"merhaba\"], input_textbox)\n input_textbox.render()\n```" }, { "id": 8, "parent": null, "path": "03_building-with-blocks/03_state-in-blocks.md", "level": 1, "title": "State in Blocks", "content": "We covered [State in Interfaces](https://gradio.app/interface-state), this guide takes a look at state in Blocks, which works mostly the same." }, { "id": 9, "parent": 8, "path": "03_building-with-blocks/03_state-in-blocks.md", "level": 2, "title": "Global State", "content": "Global state in Blocks works the same as in Interface. Any variable created outside a function call is a reference shared between all users." }, { "id": 10, "parent": 8, "path": "03_building-with-blocks/03_state-in-blocks.md", "level": 2, "title": "Session State", "content": "Gradio supports session **state**, where data persists across multiple submits within a page session, in Blocks apps as well. To reiterate, session data is _not_ shared between different users of your model. To store data in a session state, you need to do three things:\n\n1. Create a `gr.State()` object. If there is a default value to this stateful object, pass that into the constructor.\n2. In the event listener, put the `State` object as an input and output as needed.\n3. In the event listener function, add the variable to the input parameters and the return value.\n\nLet's take a look at a simple example. We have a simple checkout app below where you add items to a cart. You can also see the size of the cart.\n\n```py\nimport gradio as gr\n\nwith gr.Blocks() as demo:\n cart = gr.State([])\n items_to_add = gr.CheckboxGroup([\"Cereal\", \"Milk\", \"Orange Juice\", \"Water\"])\n\n def add_items(new_items, previous_cart):\n cart = previous_cart + new_items\n return cart\n\n gr.Button(\"Add Items\").click(add_items, [items_to_add, cart], cart)\n\n cart_size = gr.Number(label=\"Cart Size\")\n cart.change(lambda cart: len(cart), cart, cart_size)\n\nif __name__ == \"__main__\":\n demo.launch()\n```\n$demo_simple_state\n\nNotice how we do this with state:\n1. We store the cart items in a `gr.State()` object, initialized here to be an empty list.\n2. When adding items to the cart, the event listener uses the cart as both input and output - it returns the updated cart with all the items inside. \n3. We can attach a `.change` listener to cart, that uses the state variable as input as well.\n\nYou can think of `gr.State` as an invisible Component that can store any kind of value. Here, `cart` is not visible in the frontend but is used for calculations.\n\nThe `.change` listener for a state variable triggers after any event listener changes the value of a state variable. If the state variable holds a sequence (like a list, set, or dict), a change is triggered if any of the elements inside change. If it holds an object or primitive, a change is triggered if the **hash** of the value changes. So if you define a custom class and create a `gr.State` variable that is an instance of that class, make sure that the the class includes a sensible `__hash__` implementation.\n\nThe value of a session State variable is cleared when the user refreshes the page. The value is stored on in the app backend for 60 minutes after the user closes the tab (this can be configured by the `delete_cache` parameter in `gr.Blocks`).\n\nLearn more about `State` in the [docs](https://gradio.app/docs/gradio/state)." }, { "id": 11, "parent": 8, "path": "03_building-with-blocks/03_state-in-blocks.md", "level": 2, "title": "Local State", "content": "Gradio also supports **local state**, where data persists in the browser's localStorage even after the page is refreshed or closed. This is useful for storing user preferences, settings, API keys, or other data that should persist across sessions. To use local state:\n\n1. Create a `gr.BrowserState()` object. You can optionally provide an initial default value and a key to identify the data in the browser's localStorage.\n2. Use it like a regular `gr.State` component in event listeners as inputs and outputs.\n\nHere's a simple example that saves a user's username and password across sessions:\n\n```py\nimport random\nimport string\nimport gradio as gr\n\nwith gr.Blocks() as demo:\n gr.Markdown(\"Your Username and Password will get saved in the browser's local storage. \"\n \"If you refresh the page, the values will be retained.\")\n username = gr.Textbox(label=\"Username\")\n password = gr.Textbox(label=\"Password\", type=\"password\")\n btn = gr.Button(\"Generate Randomly\")\n local_storage = gr.BrowserState([\"\", \"\"])\n\n @btn.click(outputs=[username, password])\n def generate_randomly():\n u = \"\".join(random.choices(string.ascii_letters + string.digits, k=10))\n p = \"\".join(random.choices(string.ascii_letters + string.digits, k=10))\n return u, p\n\n @demo.load(inputs=[local_storage], outputs=[username, password])\n def load_from_local_storage(saved_values):\n print(\"loading from local storage\", saved_values)\n return saved_values[0], saved_values[1]\n\n @gr.on([username.change, password.change], inputs=[username, password], outputs=[local_storage])\n def save_to_local_storage(username, password):\n return [username, password]\n\ndemo.launch()\n\n```" }, { "id": 12, "parent": null, "path": "03_building-with-blocks/01_blocks-and-event-listeners.md", "level": 1, "title": "Blocks and Event Listeners", "content": "We briefly descirbed the Blocks class in the [Quickstart](/main/guides/quickstart#custom-demos-with-gr-blocks) as a way to build custom demos. Let's dive deeper." }, { "id": 13, "parent": 12, "path": "03_building-with-blocks/01_blocks-and-event-listeners.md", "level": 2, "title": "Blocks Structure", "content": "Take a look at the demo below.\n\n```py\nimport gradio as gr\n\n\ndef greet(name):\n return \"Hello \" + name + \"!\"\n\n\nwith gr.Blocks() as demo:\n name = gr.Textbox(label=\"Name\")\n output = gr.Textbox(label=\"Output Box\")\n greet_btn = gr.Button(\"Greet\")\n greet_btn.click(fn=greet, inputs=name, outputs=output, api_name=\"greet\")\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n$demo_hello_blocks\n\n- First, note the `with gr.Blocks() as demo:` clause. The Blocks app code will be contained within this clause.\n- Next come the Components. These are the same Components used in `Interface`. However, instead of being passed to some constructor, Components are automatically added to the Blocks as they are created within the `with` clause.\n- Finally, the `click()` event listener. Event listeners define the data flow within the app. In the example above, the listener ties the two Textboxes together. The Textbox `name` acts as the input and Textbox `output` acts as the output to the `greet` method. This dataflow is triggered when the Button `greet_btn` is clicked. Like an Interface, an event listener can take multiple inputs or outputs.\n\nYou can also attach event listeners using decorators - skip the `fn` argument and assign `inputs` and `outputs` directly:\n\n```py\nimport gradio as gr\n\nwith gr.Blocks() as demo:\n name = gr.Textbox(label=\"Name\")\n output = gr.Textbox(label=\"Output Box\")\n greet_btn = gr.Button(\"Greet\")\n\n @greet_btn.click(inputs=name, outputs=output)\n def greet(name):\n return \"Hello \" + name + \"!\"\n\nif __name__ == \"__main__\":\n demo.launch()\n```" }, { "id": 14, "parent": 12, "path": "03_building-with-blocks/01_blocks-and-event-listeners.md", "level": 2, "title": "Event Listeners and Interactivity", "content": "In the example above, you'll notice that you are able to edit Textbox `name`, but not Textbox `output`. This is because any Component that acts as an input to an event listener is made interactive. However, since Textbox `output` acts only as an output, Gradio determines that it should not be made interactive. You can override the default behavior and directly configure the interactivity of a Component with the boolean `interactive` keyword argument, e.g. `gr.Textbox(interactive=True)`.\n\n```python\noutput = gr.Textbox(label=\"Output\", interactive=True)\n```\n\n_Note_: What happens if a Gradio component is neither an input nor an output? If a component is constructed with a default value, then it is presumed to be displaying content and is rendered non-interactive. Otherwise, it is rendered interactive. Again, this behavior can be overridden by specifying a value for the `interactive` argument." }, { "id": 15, "parent": 12, "path": "03_building-with-blocks/01_blocks-and-event-listeners.md", "level": 2, "title": "Types of Event Listeners", "content": "Take a look at the demo below:\n\n```py\nimport gradio as gr\n\ndef welcome(name):\n return f\"Welcome to Gradio, {name}!\"\n\nwith gr.Blocks() as demo:\n gr.Markdown(\n \"\"\"\n # Hello World!\n Start typing below to see the output.\n \"\"\")\n inp = gr.Textbox(placeholder=\"What is your name?\")\n out = gr.Textbox()\n inp.change(welcome, inp, out)\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n$demo_blocks_hello\n\nInstead of being triggered by a click, the `welcome` function is triggered by typing in the Textbox `inp`. This is due to the `change()` event listener. Different Components support different event listeners. For example, the `Video` Component supports a `play()` event listener, triggered when a user presses play. See the [Docs](http://gradio.app/docs#components) for the event listeners for each Component." }, { "id": 16, "parent": 12, "path": "03_building-with-blocks/01_blocks-and-event-listeners.md", "level": 2, "title": "Multiple Data Flows", "content": "A Blocks app is not limited to a single data flow the way Interfaces are. Take a look at the demo below:\n\n```py\nimport gradio as gr\n\ndef increase(num):\n return num + 1\n\nwith gr.Blocks() as demo:\n a = gr.Number(label=\"a\")\n b = gr.Number(label=\"b\")\n atob = gr.Button(\"a > b\")\n btoa = gr.Button(\"b > a\")\n atob.click(increase, a, b)\n btoa.click(increase, b, a)\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n$demo_reversible_flow\n\nNote that `num1` can act as input to `num2`, and also vice-versa! As your apps get more complex, you will have many data flows connecting various Components.\n\nHere's an example of a \"multi-step\" demo, where the output of one model (a speech-to-text model) gets fed into the next model (a sentiment classifier).\n\n```py\nfrom transformers import pipeline\n\nimport gradio as gr\n\nasr = pipeline(\"automatic-speech-recognition\", \"facebook/wav2vec2-base-960h\")\nclassifier = pipeline(\"text-classification\")\n\ndef speech_to_text(speech):\n text = asr(speech)[\"text\"] # type: ignore\n return text\n\ndef text_to_sentiment(text):\n return classifier(text)[0][\"label\"] # type: ignore\n\ndemo = gr.Blocks()\n\nwith demo:\n audio_file = gr.Audio(type=\"filepath\")\n text = gr.Textbox()\n label = gr.Label()\n\n b1 = gr.Button(\"Recognize Speech\")\n b2 = gr.Button(\"Classify Sentiment\")\n\n b1.click(speech_to_text, inputs=audio_file, outputs=text)\n b2.click(text_to_sentiment, inputs=text, outputs=label)\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n$demo_blocks_speech_text_sentiment" }, { "id": 17, "parent": 12, "path": "03_building-with-blocks/01_blocks-and-event-listeners.md", "level": 2, "title": "Function Input List vs Dict", "content": "The event listeners you've seen so far have a single input component. If you'd like to have multiple input components pass data to the function, you have two options on how the function can accept input component values:\n\n1. as a list of arguments, or\n2. as a single dictionary of values, keyed by the component\n\nLet's see an example of each:\n```py\nimport gradio as gr\n\nwith gr.Blocks() as demo:\n a = gr.Number(label=\"a\")\n b = gr.Number(label=\"b\")\n with gr.Row():\n add_btn = gr.Button(\"Add\")\n sub_btn = gr.Button(\"Subtract\")\n c = gr.Number(label=\"sum\")\n\n def add(num1, num2):\n return num1 + num2\n add_btn.click(add, inputs=[a, b], outputs=c)\n\n def sub(data):\n return data[a] - data[b]\n sub_btn.click(sub, inputs={a, b}, outputs=c)\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n\nBoth `add()` and `sub()` take `a` and `b` as inputs. However, the syntax is different between these listeners.\n\n1. To the `add_btn` listener, we pass the inputs as a list. The function `add()` takes each of these inputs as arguments. The value of `a` maps to the argument `num1`, and the value of `b` maps to the argument `num2`.\n2. To the `sub_btn` listener, we pass the inputs as a set (note the curly brackets!). The function `sub()` takes a single dictionary argument `data`, where the keys are the input components, and the values are the values of those components.\n\nIt is a matter of preference which syntax you prefer! For functions with many input components, option 2 may be easier to manage.\n\n$demo_calculator_list_and_dict" }, { "id": 18, "parent": 12, "path": "03_building-with-blocks/01_blocks-and-event-listeners.md", "level": 2, "title": "Function Return List vs Dict", "content": "Similarly, you may return values for multiple output components either as:\n\n1. a list of values, or\n2. a dictionary keyed by the component\n\nLet's first see an example of (1), where we set the values of two output components by returning two values:\n\n```python\nwith gr.Blocks() as demo:\n food_box = gr.Number(value=10, label=\"Food Count\")\n status_box = gr.Textbox()\n\n def eat(food):\n if food > 0:\n return food - 1, \"full\"\n else:\n return 0, \"hungry\"\n\n gr.Button(\"Eat\").click(\n fn=eat,\n inputs=food_box,\n outputs=[food_box, status_box]\n )\n```\n\nAbove, each return statement returns two values corresponding to `food_box` and `status_box`, respectively.\n\nInstead of returning a list of values corresponding to each output component in order, you can also return a dictionary, with the key corresponding to the output component and the value as the new value. This also allows you to skip updating some output components.\n\n```python\nwith gr.Blocks() as demo:\n food_box = gr.Number(value=10, label=\"Food Count\")\n status_box = gr.Textbox()\n\n def eat(food):\n if food > 0:\n return {food_box: food - 1, status_box: \"full\"}\n else:\n return {status_box: \"hungry\"}\n\n gr.Button(\"Eat\").click(\n fn=eat,\n inputs=food_box,\n outputs=[food_box, status_box]\n )\n```\n\nNotice how when there is no food, we only update the `status_box` element. We skipped updating the `food_box` component.\n\nDictionary returns are helpful when an event listener affects many components on return, or conditionally affects outputs and not others.\n\nKeep in mind that with dictionary returns, we still need to specify the possible outputs in the event listener." }, { "id": 19, "parent": 12, "path": "03_building-with-blocks/01_blocks-and-event-listeners.md", "level": 2, "title": "Updating Component Configurations", "content": "The return value of an event listener function is usually the updated value of the corresponding output Component. Sometimes we want to update the configuration of the Component as well, such as the visibility. In this case, we return a new Component, setting the properties we want to change.\n\n```py\nimport gradio as gr\n\ndef change_textbox(choice):\n if choice == \"short\":\n return gr.Textbox(lines=2, visible=True)\n elif choice == \"long\":\n return gr.Textbox(lines=8, visible=True, value=\"Lorem ipsum dolor sit amet\")\n else:\n return gr.Textbox(visible=False)\n\nwith gr.Blocks() as demo:\n radio = gr.Radio(\n [\"short\", \"long\", \"none\"], label=\"What kind of essay would you like to write?\"\n )\n text = gr.Textbox(lines=2, interactive=True, show_copy_button=True)\n radio.change(fn=change_textbox, inputs=radio, outputs=text)\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n$demo_blocks_essay_simple\n\nSee how we can configure the Textbox itself through a new `gr.Textbox()` method. The `value=` argument can still be used to update the value along with Component configuration. Any arguments we do not set will preserve their previous values." }, { "id": 20, "parent": 12, "path": "03_building-with-blocks/01_blocks-and-event-listeners.md", "level": 2, "title": "Not Changing a Component's Value", "content": "In some cases, you may want to leave a component's value unchanged. Gradio includes a special function, `gr.skip()`, which can be returned from your function. Returning this function will keep the output component (or components') values as is. Let us illustrate with an example:\n\n```py\nimport random\nimport gradio as gr\n\nwith gr.Blocks() as demo:\n with gr.Row():\n clear_button = gr.Button(\"Clear\")\n skip_button = gr.Button(\"Skip\")\n random_button = gr.Button(\"Random\")\n numbers = [gr.Number(), gr.Number()]\n\n clear_button.click(lambda : (None, None), outputs=numbers)\n skip_button.click(lambda : [gr.skip(), gr.skip()], outputs=numbers)\n random_button.click(lambda : (random.randint(0, 100), random.randint(0, 100)), outputs=numbers)\n\nif __name__ == \"__main__\":\n demo.launch()\n```\n$demo_skip\n\nNote the difference between returning `None` (which generally resets a component's value to an empty state) versus returning `gr.skip()`, which leaves the component value unchanged.\n\nTip: if you have multiple output components, and you want to leave all of their values unchanged, you can just return a single `gr.skip()` instead of returning a tuple of skips, one for each element." }, { "id": 21, "parent": 12, "path": "03_building-with-blocks/01_blocks-and-event-listeners.md", "level": 2, "title": "Running Events Consecutively", "content": "You can also run events consecutively by using the `then` method of an event listener. This will run an event after the previous event has finished running. This is useful for running events that update components in multiple steps.\n\nFor example, in the chatbot example below, we first update the chatbot with the user message immediately, and then update the chatbot with the computer response after a simulated delay.\n\n```py\nimport gradio as gr\nimport random\nimport time\n\nwith gr.Blocks() as demo:\n chatbot = gr.Chatbot()\n msg = gr.Textbox()\n clear = gr.Button(\"Clear\")\n\n def user(user_message, history):\n return \"\", history + [[user_message, None]]\n\n def bot(history):\n bot_message = random.choice([\"How are you?\", \"I love you\", \"I'm very hungry\"])\n time.sleep(2)\n history[-1][1] = bot_message\n return history\n\n msg.submit(user, [msg, chatbot], [msg, chatbot], queue=False).then(\n bot, chatbot, chatbot\n )\n clear.click(lambda: None, None, chatbot, queue=False)\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n$demo_chatbot_consecutive\n\nThe `.then()` method of an event listener executes the subsequent event regardless of whether the previous event raised any errors. If you'd like to only run subsequent events if the previous event executed successfully, use the `.success()` method, which takes the same arguments as `.then()`." }, { "id": 22, "parent": 12, "path": "03_building-with-blocks/01_blocks-and-event-listeners.md", "level": 2, "title": "Binding Multiple Triggers to a Function", "content": "Often times, you may want to bind multiple triggers to the same function. For example, you may want to allow a user to click a submit button, or press enter to submit a form. You can do this using the `gr.on` method and passing a list of triggers to the `trigger`.\n\n```py\nimport gradio as gr\n\nwith gr.Blocks() as demo:\n name = gr.Textbox(label=\"Name\")\n output = gr.Textbox(label=\"Output Box\")\n greet_btn = gr.Button(\"Greet\")\n trigger = gr.Textbox(label=\"Trigger Box\")\n\n def greet(name, evt_data: gr.EventData):\n return \"Hello \" + name + \"!\", evt_data.target.__class__.__name__\n\n def clear_name(evt_data: gr.EventData):\n return \"\"\n\n gr.on(\n triggers=[name.submit, greet_btn.click],\n fn=greet,\n inputs=name,\n outputs=[output, trigger],\n ).then(clear_name, outputs=[name])\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n$demo_on_listener_basic\n\nYou can use decorator syntax as well:\n\n```py\nimport gradio as gr\n\nwith gr.Blocks() as demo:\n name = gr.Textbox(label=\"Name\")\n output = gr.Textbox(label=\"Output Box\")\n greet_btn = gr.Button(\"Greet\")\n\n @gr.on(triggers=[name.submit, greet_btn.click], inputs=name, outputs=output)\n def greet(name):\n return \"Hello \" + name + \"!\"\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n\nYou can use `gr.on` to create \"live\" events by binding to the `change` event of components that implement it. If you do not specify any triggers, the function will automatically bind to all `change` event of all input components that include a `change` event (for example `gr.Textbox` has a `change` event whereas `gr.Button` does not).\n\n```py\nimport gradio as gr\n\nwith gr.Blocks() as demo:\n with gr.Row():\n num1 = gr.Slider(1, 10)\n num2 = gr.Slider(1, 10)\n num3 = gr.Slider(1, 10)\n output = gr.Number(label=\"Sum\")\n\n @gr.on(inputs=[num1, num2, num3], outputs=output)\n def sum(a, b, c):\n return a + b + c\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n$demo_on_listener_live\n\nYou can follow `gr.on` with `.then`, just like any regular event listener. This handy method should save you from having to write a lot of repetitive code!" }, { "id": 23, "parent": 12, "path": "03_building-with-blocks/01_blocks-and-event-listeners.md", "level": 2, "title": "Binding a Component Value Directly to a Function of Other Components", "content": "If you want to set a Component's value to always be a function of the value of other Components, you can use the following shorthand:\n\n```python\nwith gr.Blocks() as demo:\n num1 = gr.Number()\n num2 = gr.Number()\n product = gr.Number(lambda a, b: a * b, inputs=[num1, num2])\n```\n\nThis functionally the same as:\n```python\nwith gr.Blocks() as demo:\n num1 = gr.Number()\n num2 = gr.Number()\n product = gr.Number()\n\n gr.on(\n [num1.change, num2.change, demo.load], \n lambda a, b: a * b, \n inputs=[num1, num2], \n outputs=product\n )\n```" }, { "id": 24, "parent": null, "path": "03_building-with-blocks/07_using-blocks-like-functions.md", "level": 1, "title": "Using Gradio Blocks Like Functions", "content": "Tags: TRANSLATION, HUB, SPACES\n\n**Prerequisite**: This Guide builds on the Blocks Introduction. Make sure to [read that guide first](https://gradio.app/blocks-and-event-listeners)." }, { "id": 25, "parent": 24, "path": "03_building-with-blocks/07_using-blocks-like-functions.md", "level": 2, "title": "Introduction", "content": "Did you know that apart from being a full-stack machine learning demo, a Gradio Blocks app is also a regular-old python function!?\n\nThis means that if you have a gradio Blocks (or Interface) app called `demo`, you can use `demo` like you would any python function.\n\nSo doing something like `output = demo(\"Hello\", \"friend\")` will run the first event defined in `demo` on the inputs \"Hello\" and \"friend\" and store it\nin the variable `output`.\n\nIf I put you to sleep 🥱, please bear with me! By using apps like functions, you can seamlessly compose Gradio apps.\nThe following section will show how." }, { "id": 26, "parent": 24, "path": "03_building-with-blocks/07_using-blocks-like-functions.md", "level": 2, "title": "Treating Blocks like functions", "content": "Let's say we have the following demo that translates english text to german text.\n\n```py\nimport gradio as gr\n\nfrom transformers import pipeline\n\npipe = pipeline(\"translation\", model=\"t5-base\")\n\ndef translate(text):\n return pipe(text)[0][\"translation_text\"] # type: ignore\n\nwith gr.Blocks() as demo:\n with gr.Row():\n with gr.Column():\n english = gr.Textbox(label=\"English text\")\n translate_btn = gr.Button(value=\"Translate\")\n with gr.Column():\n german = gr.Textbox(label=\"German Text\")\n\n translate_btn.click(translate, inputs=english, outputs=german, api_name=\"translate-to-german\")\n examples = gr.Examples(examples=[\"I went to the supermarket yesterday.\", \"Helen is a good swimmer.\"],\n inputs=[english])\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n\nI already went ahead and hosted it in Hugging Face spaces at [gradio/english_translator](https://huggingface.co/spaces/gradio/english_translator).\n\nYou can see the demo below as well:\n\n$demo_english_translator\n\nNow, let's say you have an app that generates english text, but you wanted to additionally generate german text.\n\nYou could either:\n\n1. Copy the source code of my english-to-german translation and paste it in your app.\n\n2. Load my english-to-german translation in your app and treat it like a normal python function.\n\nOption 1 technically always works, but it often introduces unwanted complexity.\n\nOption 2 lets you borrow the functionality you want without tightly coupling our apps.\n\nAll you have to do is call the `Blocks.load` class method in your source file.\nAfter that, you can use my translation app like a regular python function!\n\nThe following code snippet and demo shows how to use `Blocks.load`.\n\nNote that the variable `english_translator` is my english to german app, but its used in `generate_text` like a regular function.\n\n```py\nimport gradio as gr\n\nfrom transformers import pipeline\n\nenglish_translator = gr.load(name=\"spaces/gradio/english_translator\")\nenglish_generator = pipeline(\"text-generation\", model=\"distilgpt2\")\n\ndef generate_text(text):\n english_text = english_generator(text)[0][\"generated_text\"] # type: ignore\n german_text = english_translator(english_text)\n return english_text, german_text\n\nwith gr.Blocks() as demo:\n with gr.Row():\n with gr.Column():\n seed = gr.Text(label=\"Input Phrase\")\n with gr.Column():\n english = gr.Text(label=\"Generated English Text\")\n german = gr.Text(label=\"Generated German Text\")\n btn = gr.Button(\"Generate\")\n btn.click(generate_text, inputs=[seed], outputs=[english, german])\n gr.Examples([\"My name is Clara and I am\"], inputs=[seed])\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n\n$demo_generate_english_german" }, { "id": 27, "parent": 24, "path": "03_building-with-blocks/07_using-blocks-like-functions.md", "level": 2, "title": "How to control which function in the app to use", "content": "If the app you are loading defines more than one function, you can specify which function to use\nwith the `fn_index` and `api_name` parameters.\n\nIn the code for our english to german demo, you'll see the following line:\n\n```python\ntranslate_btn.click(translate, inputs=english, outputs=german, api_name=\"translate-to-german\")\n```\n\nThe `api_name` gives this function a unique name in our app. You can use this name to tell gradio which\nfunction in the upstream space you want to use:\n\n```python\nenglish_generator(text, api_name=\"translate-to-german\")[0][\"generated_text\"]\n```\n\nYou can also use the `fn_index` parameter.\nImagine my app also defined an english to spanish translation function.\nIn order to use it in our text generation app, we would use the following code:\n\n```python\nenglish_generator(text, fn_index=1)[0][\"generated_text\"]\n```\n\nFunctions in gradio spaces are zero-indexed, so since the spanish translator would be the second function in my space,\nyou would use index 1." }, { "id": 28, "parent": 24, "path": "03_building-with-blocks/07_using-blocks-like-functions.md", "level": 2, "title": "Parting Remarks", "content": "We showed how treating a Blocks app like a regular python helps you compose functionality across different apps.\nAny Blocks app can be treated like a function, but a powerful pattern is to `load` an app hosted on\n[Hugging Face Spaces](https://huggingface.co/spaces) prior to treating it like a function in your own app.\nYou can also load models hosted on the [Hugging Face Model Hub](https://huggingface.co/models) - see the [Using Hugging Face Integrations](/using_hugging_face_integrations) guide for an example.\n\nHappy building! ⚒️" }, { "id": 29, "parent": null, "path": "03_building-with-blocks/06_custom-CSS-and-JS.md", "level": 1, "title": "Customizing your demo with CSS and Javascript", "content": "Gradio allows you to customize your demo in several ways. You can customize the layout of your demo, add custom HTML, and add custom theming as well. This tutorial will go beyond that and walk you through how to add custom CSS and JavaScript code to your demo in order to add custom styling, animations, custom UI functionality, analytics, and more." }, { "id": 30, "parent": 29, "path": "03_building-with-blocks/06_custom-CSS-and-JS.md", "level": 2, "title": "Adding custom CSS to your demo", "content": "Gradio themes are the easiest way to customize the look and feel of your app. You can choose from a variety of themes, or create your own. To do so, pass the `theme=` kwarg to the `Blocks` constructor. For example:\n\n```python\nwith gr.Blocks(theme=gr.themes.Glass()):\n ...\n```\n\nGradio comes with a set of prebuilt themes which you can load from `gr.themes.*`. You can extend these themes or create your own themes from scratch - see the [Theming guide](/guides/theming-guide) for more details.\n\nFor additional styling ability, you can pass any CSS to your app using the `css=` kwarg. You can either the filepath to a CSS file, or a string of CSS code.\n\n**Warning**: The use of query selectors in custom JS and CSS is _not_ guaranteed to work across Gradio versions that bind to Gradio's own HTML elements as the Gradio HTML DOM may change. We recommend using query selectors sparingly.\n\nThe base class for the Gradio app is `gradio-container`, so here's an example that changes the background color of the Gradio app:\n\n```python\nwith gr.Blocks(css=\".gradio-container {background-color: red}\") as demo:\n ...\n```\n\nIf you'd like to reference external files in your css, preface the file path (which can be a relative or absolute path) with `\"file=\"`, for example:\n\n```python\nwith gr.Blocks(css=\".gradio-container {background: url('file=clouds.jpg')}\") as demo:\n ...\n```\n\nNote: By default, files in the host machine are not accessible to users running the Gradio app. As a result, you should make sure that any referenced files (such as `clouds.jpg` here) are either URLs or allowed via the `allow_list` parameter in `launch()`. Read more in our [section on Security and File Access](/main/guides/file-access)." }, { "id": 31, "parent": 29, "path": "03_building-with-blocks/06_custom-CSS-and-JS.md", "level": 2, "title": "The `elem_id` and `elem_classes` Arguments", "content": "You can `elem_id` to add an HTML element `id` to any component, and `elem_classes` to add a class or list of classes. This will allow you to select elements more easily with CSS. This approach is also more likely to be stable across Gradio versions as built-in class names or ids may change (however, as mentioned in the warning above, we cannot guarantee complete compatibility between Gradio versions if you use custom CSS as the DOM elements may themselves change).\n\n```python\ncss = \"\"\"\n#warning {background-color: #FFCCCB}\n.feedback textarea {font-size: 24px !important}\n\"\"\"\n\nwith gr.Blocks(css=css) as demo:\n box1 = gr.Textbox(value=\"Good Job\", elem_classes=\"feedback\")\n box2 = gr.Textbox(value=\"Failure\", elem_id=\"warning\", elem_classes=\"feedback\")\n```\n\nThe CSS `#warning` ruleset will only target the second Textbox, while the `.feedback` ruleset will target both. Note that when targeting classes, you might need to put the `!important` selector to override the default Gradio styles." }, { "id": 32, "parent": 29, "path": "03_building-with-blocks/06_custom-CSS-and-JS.md", "level": 2, "title": "Adding custom JavaScript to your demo", "content": "There are 3 ways to add javascript code to your Gradio demo:\n\n1. You can add JavaScript code as a string or as a filepath to the `js` parameter of the `Blocks` or `Interface` initializer. This will run the JavaScript code when the demo is first loaded.\n\nBelow is an example of adding custom js to show an animated welcome message when the demo first loads.\n\n```py\nimport gradio as gr\n\ndef welcome(name):\n return f\"Welcome to Gradio, {name}!\"\n\njs = \"\"\"\nfunction createGradioAnimation() {\n var container = document.createElement('div');\n container.id = 'gradio-animation';\n container.style.fontSize = '2em';\n container.style.fontWeight = 'bold';\n container.style.textAlign = 'center';\n container.style.marginBottom = '20px';\n\n var text = 'Welcome to Gradio!';\n for (var i = 0; i < text.length; i++) {\n (function(i){\n setTimeout(function(){\n var letter = document.createElement('span');\n letter.style.opacity = '0';\n letter.style.transition = 'opacity 0.5s';\n letter.innerText = text[i];\n\n container.appendChild(letter);\n\n setTimeout(function() {\n letter.style.opacity = '1';\n }, 50);\n }, i * 250);\n })(i);\n }\n\n var gradioContainer = document.querySelector('.gradio-container');\n gradioContainer.insertBefore(container, gradioContainer.firstChild);\n\n return 'Animation created';\n}\n\"\"\"\nwith gr.Blocks(js=js) as demo:\n inp = gr.Textbox(placeholder=\"What is your name?\")\n out = gr.Textbox()\n inp.change(welcome, inp, out)\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n$demo_blocks_js_load\n\nNote: You can also supply your custom js code as a file path. For example, if you have a file called `custom.js` in the same directory as your Python script, you can add it to your demo like so: `with gr.Blocks(js=\"custom.js\") as demo:`. Same goes for `Interface` (ex: `gr.Interface(..., js=\"custom.js\")`).\n\n2. When using `Blocks` and event listeners, events have a `js` argument that can take a JavaScript function as a string and treat it just like a Python event listener function. You can pass both a JavaScript function and a Python function (in which case the JavaScript function is run first) or only Javascript (and set the Python `fn` to `None`). Take a look at the code below:\n \n```py\nimport gradio as gr\n\nblocks = gr.Blocks()\n\nwith blocks as demo:\n subject = gr.Textbox(placeholder=\"subject\")\n verb = gr.Radio([\"ate\", \"loved\", \"hated\"])\n object = gr.Textbox(placeholder=\"object\")\n\n with gr.Row():\n btn = gr.Button(\"Create sentence.\")\n reverse_btn = gr.Button(\"Reverse sentence.\")\n foo_bar_btn = gr.Button(\"Append foo\")\n reverse_then_to_the_server_btn = gr.Button(\n \"Reverse sentence and send to server.\"\n )\n\n def sentence_maker(w1, w2, w3):\n return f\"{w1} {w2} {w3}\"\n\n output1 = gr.Textbox(label=\"output 1\")\n output2 = gr.Textbox(label=\"verb\")\n output3 = gr.Textbox(label=\"verb reversed\")\n output4 = gr.Textbox(label=\"front end process and then send to backend\")\n\n btn.click(sentence_maker, [subject, verb, object], output1)\n reverse_btn.click(\n None, [subject, verb, object], output2, js=\"(s, v, o) => o + ' ' + v + ' ' + s\"\n )\n verb.change(lambda x: x, verb, output3, js=\"(x) => [...x].reverse().join('')\")\n foo_bar_btn.click(None, [], subject, js=\"(x) => x + ' foo'\")\n\n reverse_then_to_the_server_btn.click(\n sentence_maker,\n [subject, verb, object],\n output4,\n js=\"(s, v, o) => [s, v, o].map(x => [...x].reverse().join(''))\",\n )\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n$demo_blocks_js_methods\n\n3. Lastly, you can add JavaScript code to the `head` param of the `Blocks` initializer. This will add the code to the head of the HTML document. For example, you can add Google Analytics to your demo like so:\n\n\n```python\nhead = f\"\"\"\n\n\n\"\"\"\n\nwith gr.Blocks(head=head) as demo:\n ...demo code...\n```\n\nThe `head` parameter accepts any HTML tags you would normally insert into the `` of a page. For example, you can also include `` tags to `head`.\n\nNote that injecting custom HTML can affect browser behavior and compatibility (e.g. keyboard shortcuts). You should test your interface across different browsers and be mindful of how scripts may interact with browser defaults.\nHere's an example where pressing `Shift + s` triggers the `click` event of a specific `Button` component if the browser focus is _not_ on an input component (e.g. `Textbox` component):\n\n```python\nimport gradio as gr\n\nshortcut_js = \"\"\"\n\n\"\"\"\n\nwith gr.Blocks(head=shortcut_js) as demo:\n action_button = gr.Button(value=\"Name\", elem_id=\"my_btn\")\n textbox = gr.Textbox()\n action_button.click(lambda : \"button pressed\", None, textbox)\n \ndemo.launch()\n```" }, { "id": 33, "parent": null, "path": "03_building-with-blocks/04_dynamic-apps-with-render-decorator.md", "level": 1, "title": "Dynamic Apps with the Render Decorator", "content": "The components and event listeners you define in a Blocks so far have been fixed - once the demo was launched, new components and listeners could not be added, and existing one could not be removed. \n\nThe `@gr.render` decorator introduces the ability to dynamically change this. Let's take a look." }, { "id": 34, "parent": 33, "path": "03_building-with-blocks/04_dynamic-apps-with-render-decorator.md", "level": 2, "title": "Dynamic Number of Components", "content": "In the example below, we will create a variable number of Textboxes. When the user edits the input Textbox, we create a Textbox for each letter in the input. Try it out below:\n\n```py\nimport gradio as gr\n\nwith gr.Blocks() as demo:\n input_text = gr.Textbox(label=\"input\")\n\n @gr.render(inputs=input_text)\n def show_split(text):\n if len(text) == 0:\n gr.Markdown(\"## No Input Provided\")\n else:\n for letter in text:\n gr.Textbox(letter)\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n$demo_render_split_simple\n\nSee how we can now create a variable number of Textboxes using our custom logic - in this case, a simple `for` loop. The `@gr.render` decorator enables this with the following steps:\n\n1. Create a function and attach the @gr.render decorator to it.\n2. Add the input components to the `inputs=` argument of @gr.render, and create a corresponding argument in your function for each component. This function will automatically re-run on any change to a component.\n3. Add all components inside the function that you want to render based on the inputs.\n\nNow whenever the inputs change, the function re-runs, and replaces the components created from the previous function run with the latest run. Pretty straightforward! Let's add a little more complexity to this app:\n\n```py\nimport gradio as gr\n\nwith gr.Blocks() as demo:\n input_text = gr.Textbox(label=\"input\")\n mode = gr.Radio([\"textbox\", \"button\"], value=\"textbox\")\n\n @gr.render(inputs=[input_text, mode], triggers=[input_text.submit])\n def show_split(text, mode):\n if len(text) == 0:\n gr.Markdown(\"## No Input Provided\")\n else:\n for letter in text:\n if mode == \"textbox\":\n gr.Textbox(letter)\n else:\n gr.Button(letter)\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n$demo_render_split\n\nBy default, `@gr.render` re-runs are triggered by the `.load` listener to the app and the `.change` listener to any input component provided. We can override this by explicitly setting the triggers in the decorator, as we have in this app to only trigger on `input_text.submit` instead. \nIf you are setting custom triggers, and you also want an automatic render at the start of the app, make sure to add `demo.load` to your list of triggers." }, { "id": 35, "parent": 33, "path": "03_building-with-blocks/04_dynamic-apps-with-render-decorator.md", "level": 2, "title": "Dynamic Event Listeners", "content": "If you're creating components, you probably want to attach event listeners to them as well. Let's take a look at an example that takes in a variable number of Textbox as input, and merges all the text into a single box.\n\n```py\nimport gradio as gr\n\nwith gr.Blocks() as demo:\n text_count = gr.State(1)\n add_btn = gr.Button(\"Add Box\")\n add_btn.click(lambda x: x + 1, text_count, text_count)\n\n @gr.render(inputs=text_count)\n def render_count(count):\n boxes = []\n for i in range(count):\n box = gr.Textbox(key=i, label=f\"Box {i}\")\n boxes.append(box)\n\n def merge(*args):\n return \" \".join(args)\n\n merge_btn.click(merge, boxes, output)\n\n merge_btn = gr.Button(\"Merge\")\n output = gr.Textbox(label=\"Merged Output\")\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n$demo_render_merge_simple\n\nLet's take a look at what's happening here:\n\n1. The state variable `text_count` is keeping track of the number of Textboxes to create. By clicking on the Add button, we increase `text_count` which triggers the render decorator.\n2. Note that in every single Textbox we create in the render function, we explicitly set a `key=` argument. This key allows us to preserve the value of this Component between re-renders. If you type in a value in a textbox, and then click the Add button, all the Textboxes re-render, but their values aren't cleared because the `key=` maintains the the value of a Component across a render.\n3. We've stored the Textboxes created in a list, and provide this list as input to the merge button event listener. Note that **all event listeners that use Components created inside a render function must also be defined inside that render function**. The event listener can still reference Components outside the render function, as we do here by referencing `merge_btn` and `output` which are both defined outside the render function.\n\nJust as with Components, whenever a function re-renders, the event listeners created from the previous render are cleared and the new event listeners from the latest run are attached. \n\nThis allows us to create highly customizable and complex interactions!" }, { "id": 36, "parent": 33, "path": "03_building-with-blocks/04_dynamic-apps-with-render-decorator.md", "level": 2, "title": "Putting it Together", "content": "Let's look at two examples that use all the features above. First, try out the to-do list app below: \n\n```py\nimport gradio as gr\n\nwith gr.Blocks() as demo:\n\n tasks = gr.State([])\n new_task = gr.Textbox(label=\"Task Name\", autofocus=True)\n\n def add_task(tasks, new_task_name):\n return tasks + [{\"name\": new_task_name, \"complete\": False}], \"\"\n\n new_task.submit(add_task, [tasks, new_task], [tasks, new_task])\n\n @gr.render(inputs=tasks)\n def render_todos(task_list):\n complete = [task for task in task_list if task[\"complete\"]]\n incomplete = [task for task in task_list if not task[\"complete\"]]\n gr.Markdown(f\"### Incomplete Tasks ({len(incomplete)})\")\n for task in incomplete:\n with gr.Row():\n gr.Textbox(task['name'], show_label=False, container=False)\n done_btn = gr.Button(\"Done\", scale=0)\n def mark_done(task=task):\n task[\"complete\"] = True\n return task_list\n done_btn.click(mark_done, None, [tasks])\n\n delete_btn = gr.Button(\"Delete\", scale=0, variant=\"stop\")\n def delete(task=task):\n task_list.remove(task)\n return task_list\n delete_btn.click(delete, None, [tasks])\n\n gr.Markdown(f\"### Complete Tasks ({len(complete)})\")\n for task in complete:\n gr.Textbox(task['name'], show_label=False, container=False)\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n$demo_todo_list\n\nNote that almost the entire app is inside a single `gr.render` that reacts to the tasks `gr.State` variable. This variable is a nested list, which presents some complexity. If you design a `gr.render` to react to a list or dict structure, ensure you do the following:\n\n1. Any event listener that modifies a state variable in a manner that should trigger a re-render must set the state variable as an output. This lets Gradio know to check if the variable has changed behind the scenes. \n2. In a `gr.render`, if a variable in a loop is used inside an event listener function, that variable should be \"frozen\" via setting it to itself as a default argument in the function header. See how we have `task=task` in both `mark_done` and `delete`. This freezes the variable to its \"loop-time\" value.\n\nLet's take a look at one last example that uses everything we learned. Below is an audio mixer. Provide multiple audio tracks and mix them together.\n\n```py\nimport gradio as gr\n\nwith gr.Blocks() as demo:\n track_count = gr.State(1)\n add_track_btn = gr.Button(\"Add Track\")\n\n add_track_btn.click(lambda count: count + 1, track_count, track_count)\n\n @gr.render(inputs=track_count)\n def render_tracks(count):\n audios = []\n volumes = []\n with gr.Row():\n for i in range(count):\n with gr.Column(variant=\"panel\", min_width=200):\n gr.Textbox(placeholder=\"Track Name\", key=f\"name-{i}\", show_label=False)\n track_audio = gr.Audio(label=f\"Track {i}\", key=f\"track-{i}\")\n track_volume = gr.Slider(0, 100, value=100, label=\"Volume\", key=f\"volume-{i}\")\n audios.append(track_audio)\n volumes.append(track_volume)\n\n def merge(data):\n sr, output = None, None\n for audio, volume in zip(audios, volumes):\n sr, audio_val = data[audio]\n volume_val = data[volume]\n final_track = audio_val * (volume_val / 100)\n if output is None:\n output = final_track\n else:\n min_shape = tuple(min(s1, s2) for s1, s2 in zip(output.shape, final_track.shape))\n trimmed_output = output[:min_shape[0], ...][:, :min_shape[1], ...] if output.ndim > 1 else output[:min_shape[0]]\n trimmed_final = final_track[:min_shape[0], ...][:, :min_shape[1], ...] if final_track.ndim > 1 else final_track[:min_shape[0]]\n output += trimmed_output + trimmed_final\n return (sr, output)\n\n merge_btn.click(merge, set(audios + volumes), output_audio)\n\n merge_btn = gr.Button(\"Merge Tracks\")\n output_audio = gr.Audio(label=\"Output\", interactive=False)\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n$demo_audio_mixer\n\nTwo things to note in this app:\n1. Here we provide `key=` to all the components! We need to do this so that if we add another track after setting the values for an existing track, our input values to the existing track do not get reset on re-render.\n2. When there are lots of components of different types and arbitrary counts passed to an event listener, it is easier to use the set and dictionary notation for inputs rather than list notation. Above, we make one large set of all the input `gr.Audio` and `gr.Slider` components when we pass the inputs to the `merge` function. In the function body we query the component values as a dict.\n\nThe `gr.render` expands gradio capabilities extensively - see what you can make out of it!" }, { "id": 37, "parent": null, "path": "08_custom-components/01_custom-components-in-five-minutes.md", "level": 1, "title": "Custom Components in 5 minutes", "content": "Gradio includes the ability for developers to create their own custom components and use them in Gradio apps.You can publish your components as Python packages so that other users can use them as well.\n\nUsers will be able to use all of Gradio's existing functions, such as `gr.Blocks`, `gr.Interface`, API usage, themes, etc. with Custom Components. This guide will cover how to get started making custom components." }, { "id": 38, "parent": 37, "path": "08_custom-components/01_custom-components-in-five-minutes.md", "level": 2, "title": "Installation", "content": "You will need to have:\n\n* Python 3.10+ (install here)\n* pip 21.3+ (`python -m pip install --upgrade pip`)\n* Node.js 20+ (install here)\n* npm 9+ (install here)\n* Gradio 5+ (`pip install --upgrade gradio`)" }, { "id": 39, "parent": 37, "path": "08_custom-components/01_custom-components-in-five-minutes.md", "level": 2, "title": "The Workflow", "content": "The Custom Components workflow consists of 4 steps: create, dev, build, and publish.\n\n1. create: creates a template for you to start developing a custom component.\n2. dev: launches a development server with a sample app & hot reloading allowing you to easily develop your custom component\n3. build: builds a python package containing to your custom component's Python and JavaScript code -- this makes things official!\n4. publish: uploads your package to [PyPi](https://pypi.org/) and/or a sample app to [HuggingFace Spaces](https://hf.co/spaces).\n\nEach of these steps is done via the Custom Component CLI. You can invoke it with `gradio cc` or `gradio component`\n\nTip: Run `gradio cc --help` to get a help menu of all available commands. There are some commands that are not covered in this guide. You can also append `--help` to any command name to bring up a help page for that command, e.g. `gradio cc create --help`." }, { "id": 40, "parent": 37, "path": "08_custom-components/01_custom-components-in-five-minutes.md", "level": 2, "title": "1. create", "content": "Bootstrap a new template by running the following in any working directory:\n\n```bash\ngradio cc create MyComponent --template SimpleTextbox\n```\n\nInstead of `MyComponent`, give your component any name.\n\nInstead of `SimpleTextbox`, you can use any Gradio component as a template. `SimpleTextbox` is actually a special component that a stripped-down version of the `Textbox` component that makes it particularly useful when creating your first custom component.\nSome other components that are good if you are starting out: `SimpleDropdown`, `SimpleImage`, or `File`.\n\nTip: Run `gradio cc show` to get a list of available component templates.\n\nThe `create` command will:\n\n1. Create a directory with your component's name in lowercase with the following structure:\n```directory\n- backend/ <- The python code for your custom component\n- frontend/ <- The javascript code for your custom component\n- demo/ <- A sample app using your custom component. Modify this to develop your component!\n- pyproject.toml <- Used to build the package and specify package metadata.\n```\n\n2. Install the component in development mode\n\nEach of the directories will have the code you need to get started developing!" }, { "id": 41, "parent": 37, "path": "08_custom-components/01_custom-components-in-five-minutes.md", "level": 2, "title": "2. dev", "content": "Once you have created your new component, you can start a development server by `entering the directory` and running\n\n```bash\ngradio cc dev\n```\n\nYou'll see several lines that are printed to the console.\nThe most important one is the one that says:\n\n> Frontend Server (Go here): http://localhost:7861/\n\nThe port number might be different for you.\nClick on that link to launch the demo app in hot reload mode.\nNow, you can start making changes to the backend and frontend you'll see the results reflected live in the sample app!\nWe'll go through a real example in a later guide.\n\nTip: You don't have to run dev mode from your custom component directory. The first argument to `dev` mode is the path to the directory. By default it uses the current directory." }, { "id": 42, "parent": 37, "path": "08_custom-components/01_custom-components-in-five-minutes.md", "level": 2, "title": "3. build", "content": "Once you are satisfied with your custom component's implementation, you can `build` it to use it outside of the development server.\n\nFrom your component directory, run:\n\n```bash\ngradio cc build\n```\n\nThis will create a `tar.gz` and `.whl` file in a `dist/` subdirectory.\nIf you or anyone installs that `.whl` file (`pip install `) they will be able to use your custom component in any gradio app!\n\nThe `build` command will also generate documentation for your custom component. This takes the form of an interactive space and a static `README.md`. You can disable this by passing `--no-generate-docs`. You can read more about the documentation generator in [the dedicated guide](https://gradio.app/guides/documenting-custom-components)." }, { "id": 43, "parent": 37, "path": "08_custom-components/01_custom-components-in-five-minutes.md", "level": 2, "title": "4. publish", "content": "Right now, your package is only available on a `.whl` file on your computer.\nYou can share that file with the world with the `publish` command!\n\nSimply run the following command from your component directory:\n\n```bash\ngradio cc publish\n```\n\nThis will guide you through the following process:\n\n1. Upload your distribution files to PyPi. This is optional. If you decide to upload to PyPi, you will need a PyPI username and password. You can get one [here](https://pypi.org/account/register/).\n2. Upload a demo of your component to hugging face spaces. This is also optional.\n\n\nHere is an example of what publishing looks like:\n\n" }, { "id": 44, "parent": 37, "path": "08_custom-components/01_custom-components-in-five-minutes.md", "level": 2, "title": "Conclusion", "content": "Now that you know the high-level workflow of creating custom components, you can go in depth in the next guides!\nAfter reading the guides, check out this [collection](https://huggingface.co/collections/gradio/custom-components-65497a761c5192d981710b12) of custom components on the HuggingFace Hub so you can learn from other's code.\n\nTip: If you want to start off from someone else's custom component see this [guide](./frequently-asked-questions#do-i-always-need-to-start-my-component-from-scratch)." }, { "id": 45, "parent": null, "path": "08_custom-components/02_key-component-concepts.md", "level": 1, "title": "Gradio Components: The Key Concepts", "content": "In this section, we discuss a few important concepts when it comes to components in Gradio.\nIt's important to understand these concepts when developing your own component.\nOtherwise, your component may behave very different to other Gradio components!\n\nTip: You can skip this section if you are familiar with the internals of the Gradio library, such as each component's preprocess and postprocess methods." }, { "id": 46, "parent": 45, "path": "08_custom-components/02_key-component-concepts.md", "level": 2, "title": "Interactive vs Static", "content": "Every component in Gradio comes in a `static` variant, and most come in an `interactive` version as well.\nThe `static` version is used when a component is displaying a value, and the user can **NOT** change that value by interacting with it. \nThe `interactive` version is used when the user is able to change the value by interacting with the Gradio UI.\n\nLet's see some examples:\n\n```python\nimport gradio as gr\n\nwith gr.Blocks() as demo:\n gr.Textbox(value=\"Hello\", interactive=True)\n gr.Textbox(value=\"Hello\", interactive=False)\n\ndemo.launch()\n\n```\nThis will display two textboxes.\nThe only difference: you'll be able to edit the value of the Gradio component on top, and you won't be able to edit the variant on the bottom (i.e. the textbox will be disabled).\n\nPerhaps a more interesting example is with the `Image` component:\n\n```python\nimport gradio as gr\n\nwith gr.Blocks() as demo:\n gr.Image(interactive=True)\n gr.Image(interactive=False)\n\ndemo.launch()\n```\n\nThe interactive version of the component is much more complex -- you can upload images or snap a picture from your webcam -- while the static version can only be used to display images.\n\nNot every component has a distinct interactive version. For example, the `gr.AnnotatedImage` only appears as a static version since there's no way to interactively change the value of the annotations or the image." }, { "id": 47, "parent": 46, "path": "08_custom-components/02_key-component-concepts.md", "level": 3, "title": "What you need to remember", "content": "* Gradio will use the interactive version (if available) of a component if that component is used as the **input** to any event; otherwise, the static version will be used.\n\n* When you design custom components, you **must** accept the boolean interactive keyword in the constructor of your Python class. In the frontend, you **may** accept the `interactive` property, a `bool` which represents whether the component should be static or interactive. If you do not use this property in the frontend, the component will appear the same in interactive or static mode." }, { "id": 48, "parent": 45, "path": "08_custom-components/02_key-component-concepts.md", "level": 2, "title": "The value and how it is preprocessed/postprocessed", "content": "The most important attribute of a component is its `value`.\nEvery component has a `value`.\nThe value that is typically set by the user in the frontend (if the component is interactive) or displayed to the user (if it is static). \nIt is also this value that is sent to the backend function when a user triggers an event, or returned by the user's function e.g. at the end of a prediction.\n\nSo this value is passed around quite a bit, but sometimes the format of the value needs to change between the frontend and backend. \nTake a look at this example:\n\n```python\nimport numpy as np\nimport gradio as gr\n\ndef sepia(input_img):\n sepia_filter = np.array([\n [0.393, 0.769, 0.189], \n [0.349, 0.686, 0.168], \n [0.272, 0.534, 0.131]\n ])\n sepia_img = input_img.dot(sepia_filter.T)\n sepia_img /= sepia_img.max()\n return sepia_img\n\ndemo = gr.Interface(sepia, gr.Image(width=200, height=200), \"image\")\ndemo.launch()\n```\n\nThis will create a Gradio app which has an `Image` component as the input and the output. \nIn the frontend, the Image component will actually **upload** the file to the server and send the **filepath** but this is converted to a `numpy` array before it is sent to a user's function. \nConversely, when the user returns a `numpy` array from their function, the numpy array is converted to a file so that it can be sent to the frontend and displayed by the `Image` component.\n\nTip: By default, the `Image` component sends numpy arrays to the python function because it is a common choice for machine learning engineers, though the Image component also supports other formats using the `type` parameter. Read the `Image` docs [here](https://www.gradio.app/docs/image) to learn more.\n\nEach component does two conversions:\n\n1. `preprocess`: Converts the `value` from the format sent by the frontend to the format expected by the python function. This usually involves going from a web-friendly **JSON** structure to a **python-native** data structure, like a `numpy` array or `PIL` image. The `Audio`, `Image` components are good examples of `preprocess` methods.\n\n2. `postprocess`: Converts the value returned by the python function to the format expected by the frontend. This usually involves going from a **python-native** data-structure, like a `PIL` image to a **JSON** structure." }, { "id": 49, "parent": 48, "path": "08_custom-components/02_key-component-concepts.md", "level": 3, "title": "What you need to remember", "content": "* Every component must implement `preprocess` and `postprocess` methods. In the rare event that no conversion needs to happen, simply return the value as-is. `Textbox` and `Number` are examples of this. \n\n* As a component author, **YOU** control the format of the data displayed in the frontend as well as the format of the data someone using your component will receive. Think of an ergonomic data-structure a **python** developer will find intuitive, and control the conversion from a **Web-friendly JSON** data structure (and vice-versa) with `preprocess` and `postprocess.`" }, { "id": 50, "parent": 45, "path": "08_custom-components/02_key-component-concepts.md", "level": 2, "title": "The \"Example Version\" of a Component", "content": "Gradio apps support providing example inputs -- and these are very useful in helping users get started using your Gradio app. \nIn `gr.Interface`, you can provide examples using the `examples` keyword, and in `Blocks`, you can provide examples using the special `gr.Examples` component.\n\nAt the bottom of this screenshot, we show a miniature example image of a cheetah that, when clicked, will populate the same image in the input Image component:\n\n![img](https://user-images.githubusercontent.com/1778297/277548211-a3cb2133-2ffc-4cdf-9a83-3e8363b57ea6.png)\n\n\nTo enable the example view, you must have the following two files in the top of the `frontend` directory:\n\n* `Example.svelte`: this corresponds to the \"example version\" of your component\n* `Index.svelte`: this corresponds to the \"regular version\"\n\nIn the backend, you typically don't need to do anything. The user-provided example `value` is processed using the same `.postprocess()` method described earlier. If you'd like to do process the data differently (for example, if the `.postprocess()` method is computationally expensive), then you can write your own `.process_example()` method for your custom component, which will be used instead. \n\nThe `Example.svelte` file and `process_example()` method will be covered in greater depth in the dedicated [frontend](./frontend) and [backend](./backend) guides respectively." }, { "id": 51, "parent": 50, "path": "08_custom-components/02_key-component-concepts.md", "level": 3, "title": "What you need to remember", "content": "* If you expect your component to be used as input, it is important to define an \"Example\" view.\n* If you don't, Gradio will use a default one but it won't be as informative as it can be!" }, { "id": 52, "parent": 45, "path": "08_custom-components/02_key-component-concepts.md", "level": 2, "title": "Conclusion", "content": "Now that you know the most important pieces to remember about Gradio components, you can start to design and build your own!" }, { "id": 53, "parent": null, "path": "08_custom-components/05_frontend.md", "level": 1, "title": "The Frontend 🌐⭐️", "content": "This guide will cover everything you need to know to implement your custom component's frontend.\n\nTip: Gradio components use Svelte. Writing Svelte is fun! If you're not familiar with it, we recommend checking out their interactive [guide](https://learn.svelte.dev/tutorial/welcome-to-svelte)." }, { "id": 54, "parent": 53, "path": "08_custom-components/05_frontend.md", "level": 2, "title": "The directory structure ", "content": "The frontend code should have, at minimum, three files:\n\n* `Index.svelte`: This is the main export and where your component's layout and logic should live.\n* `Example.svelte`: This is where the example view of the component is defined.\n\nFeel free to add additional files and subdirectories. \nIf you want to export any additional modules, remember to modify the `package.json` file\n\n```json\n\"exports\": {\n \".\": \"./Index.svelte\",\n \"./example\": \"./Example.svelte\",\n \"./package.json\": \"./package.json\"\n},\n```" }, { "id": 55, "parent": 53, "path": "08_custom-components/05_frontend.md", "level": 2, "title": "The Index.svelte file", "content": "Your component should expose the following props that will be passed down from the parent Gradio application.\n\n```typescript\nimport type { LoadingStatus } from \"@gradio/statustracker\";\nimport type { Gradio } from \"@gradio/utils\";\n\nexport let gradio: Gradio<{\n event_1: never;\n event_2: never;\n}>;\n\nexport let elem_id = \"\";\nexport let elem_classes: string[] = [];\nexport let scale: number | null = null;\nexport let min_width: number | undefined = undefined;\nexport let loading_status: LoadingStatus | undefined = undefined;\nexport let mode: \"static\" | \"interactive\";\n```\n\n* `elem_id` and `elem_classes` allow Gradio app developers to target your component with custom CSS and JavaScript from the Python `Blocks` class.\n\n* `scale` and `min_width` allow Gradio app developers to control how much space your component takes up in the UI.\n\n* `loading_status` is used to display a loading status over the component when it is the output of an event.\n\n* `mode` is how the parent Gradio app tells your component whether the `interactive` or `static` version should be displayed.\n\n* `gradio`: The `gradio` object is created by the parent Gradio app. It stores some application-level configuration that will be useful in your component, like internationalization. You must use it to dispatch events from your component.\n\nA minimal `Index.svelte` file would look like:\n\n```svelte\n\n\n\n\t{#if loading_status}\n\t\t\n\t{/if}\n

{value}

\n\n```" }, { "id": 56, "parent": 53, "path": "08_custom-components/05_frontend.md", "level": 2, "title": "The Example.svelte file", "content": "The `Example.svelte` file should expose the following props:\n\n```typescript\n export let value: string;\n export let type: \"gallery\" | \"table\";\n export let selected = false;\n export let index: number;\n```\n\n* `value`: The example value that should be displayed.\n\n* `type`: This is a variable that can be either `\"gallery\"` or `\"table\"` depending on how the examples are displayed. The `\"gallery\"` form is used when the examples correspond to a single input component, while the `\"table\"` form is used when a user has multiple input components, and the examples need to populate all of them. \n\n* `selected`: You can also adjust how the examples are displayed if a user \"selects\" a particular example by using the selected variable.\n\n* `index`: The current index of the selected value.\n\n* Any additional props your \"non-example\" component takes!\n\nThis is the `Example.svelte` file for the code `Radio` component:\n\n```svelte\n\n\n\n\t{value}\n\n\n\n```" }, { "id": 57, "parent": 53, "path": "08_custom-components/05_frontend.md", "level": 2, "title": "Handling Files", "content": "If your component deals with files, these files **should** be uploaded to the backend server. \nThe `@gradio/client` npm package provides the `upload` and `prepare_files` utility functions to help you do this.\n\nThe `prepare_files` function will convert the browser's `File` datatype to gradio's internal `FileData` type.\nYou should use the `FileData` data in your component to keep track of uploaded files.\n\nThe `upload` function will upload an array of `FileData` values to the server.\n\nHere's an example of loading files from an `` element when its value changes.\n\n\n```svelte\n\n\n\n```\n\nThe component exposes a prop named `root`. \nThis is passed down by the parent gradio app and it represents the base url that the files will be uploaded to and fetched from.\n\nFor WASM support, you should get the upload function from the `Context` and pass that as the third parameter of the `upload` function.\n\n```typescript\n\n```" }, { "id": 58, "parent": 53, "path": "08_custom-components/05_frontend.md", "level": 2, "title": "Leveraging Existing Gradio Components", "content": "Most of Gradio's frontend components are published on [npm](https://www.npmjs.com/), the javascript package repository.\nThis means that you can use them to save yourself time while incorporating common patterns in your component, like uploading files.\nFor example, the `@gradio/upload` package has `Upload` and `ModifyUpload` components for properly uploading files to the Gradio server. \nHere is how you can use them to create a user interface to upload and display PDF files.\n\n```svelte\n\n\n\n{#if value === null && interactive}\n \n \n \n{:else if value !== null}\n {#if interactive}\n \n {/if}\n \n{:else}\n \t\n{/if}\n```\n\nYou can also combine existing Gradio components to create entirely unique experiences.\nLike rendering a gallery of chatbot conversations. \nThe possibilities are endless, please read the documentation on our javascript packages [here](https://gradio.app/main/docs/js).\nWe'll be adding more packages and documentation over the coming weeks!" }, { "id": 59, "parent": 53, "path": "08_custom-components/05_frontend.md", "level": 2, "title": "Matching Gradio Core's Design System", "content": "You can explore our component library via Storybook. You'll be able to interact with our components and see them in their various states.\n\nFor those interested in design customization, we provide the CSS variables consisting of our color palette, radii, spacing, and the icons we use - so you can easily match up your custom component with the style of our core components. This Storybook will be regularly updated with any new additions or changes.\n\n[Storybook Link](https://gradio.app/main/docs/js/storybook)" }, { "id": 60, "parent": 53, "path": "08_custom-components/05_frontend.md", "level": 2, "title": "Custom configuration", "content": "If you want to make use of the vast vite ecosystem, you can use the `gradio.config.js` file to configure your component's build process. This allows you to make use of tools like tailwindcss, mdsvex, and more.\n\nCurrently, it is possible to configure the following:\n\nVite options:\n- `plugins`: A list of vite plugins to use.\n\nSvelte options:\n- `preprocess`: A list of svelte preprocessors to use.\n- `extensions`: A list of file extensions to compile to `.svelte` files.\n- `build.target`: The target to build for, this may be necessary to support newer javascript features. See the [esbuild docs](https://esbuild.github.io/api/#target) for more information.\n\nThe `gradio.config.js` file should be placed in the root of your component's `frontend` directory. A default config file is created for you when you create a new component. But you can also create your own config file, if one doesn't exist, and use it to customize your component's build process." }, { "id": 61, "parent": 60, "path": "08_custom-components/05_frontend.md", "level": 3, "title": "Example for a Vite plugin", "content": "Custom components can use Vite plugins to customize the build process. Check out the [Vite Docs](https://vitejs.dev/guide/using-plugins.html) for more information. \n\nHere we configure [TailwindCSS](https://tailwindcss.com), a utility-first CSS framework. Setup is easiest using the version 4 prerelease. \n\n```\nnpm install tailwindcss@next @tailwindcss/vite@next\n```\n\nIn `gradio.config.js`:\n\n```typescript\nimport tailwindcss from \"@tailwindcss/vite\";\nexport default {\n plugins: [tailwindcss()]\n};\n```\n\nThen create a `style.css` file with the following content:\n\n```css\n@import \"tailwindcss\";\n```\n\nImport this file into `Index.svelte`. Note, that you need to import the css file containing `@import` and cannot just use a `\n```\n\nNow import `PdfUploadText.svelte` in your `\n\n\n\t\n\n\n\n```\n\n\nTip: Exercise for the reader - reduce the code duplication between `Index.svelte` and `Example.svelte` 😊\n\n\nYou will not be able to render examples until we make some changes to the backend code in the next step!" }, { "id": 84, "parent": 73, "path": "08_custom-components/07_pdf-component-example.md", "level": 2, "title": "Step 9: The backend", "content": "The backend changes needed are smaller.\nWe're almost done!\n\nWhat we're going to do is:\n* Add `change` and `upload` events to our component.\n* Add a `height` property to let users control the height of the PDF.\n* Set the `data_model` of our component to be `FileData`. This is so that Gradio can automatically cache and safely serve any files that are processed by our component.\n* Modify the `preprocess` method to return a string corresponding to the path of our uploaded PDF.\n* Modify the `postprocess` to turn a path to a PDF created in an event handler to a `FileData`.\n\nWhen all is said an done, your component's backend code should look like this:\n\n```python\nfrom __future__ import annotations\nfrom typing import Any, Callable, TYPE_CHECKING\n\nfrom gradio.components.base import Component\nfrom gradio.data_classes import FileData\nfrom gradio import processing_utils\nif TYPE_CHECKING:\n from gradio.components import Timer\n\nclass PDF(Component):\n\n EVENTS = [\"change\", \"upload\"]\n\n data_model = FileData\n\n def __init__(self, value: Any = None, *,\n height: int | None = None,\n label: str | None = None, info: str | None = None,\n show_label: bool | None = None,\n container: bool = True,\n scale: int | None = None,\n min_width: int | None = None,\n interactive: bool | None = None,\n visible: bool = True,\n elem_id: str | None = None,\n elem_classes: list[str] | str | None = None,\n render: bool = True,\n load_fn: Callable[..., Any] | None = None,\n every: Timer | float | None = None):\n super().__init__(value, label=label, info=info,\n show_label=show_label, container=container,\n scale=scale, min_width=min_width,\n interactive=interactive, visible=visible,\n elem_id=elem_id, elem_classes=elem_classes,\n render=render, load_fn=load_fn, every=every)\n self.height = height\n\n def preprocess(self, payload: FileData) -> str:\n return payload.path\n\n def postprocess(self, value: str | None) -> FileData:\n if not value:\n return None\n return FileData(path=value)\n\n def example_payload(self):\n return \"https://gradio-builds.s3.amazonaws.com/assets/pdf-guide/fw9.pdf\"\n\n def example_value(self):\n return \"https://gradio-builds.s3.amazonaws.com/assets/pdf-guide/fw9.pdf\"\n```" }, { "id": 85, "parent": 73, "path": "08_custom-components/07_pdf-component-example.md", "level": 2, "title": "Step 10: Add a demo and publish!", "content": "To test our backend code, let's add a more complex demo that performs Document Question and Answering with huggingface transformers.\n\nIn our `demo` directory, create a `requirements.txt` file with the following packages\n\n```\ntorch\ntransformers\npdf2image\npytesseract\n```\n\n\nTip: Remember to install these yourself and restart the dev server! You may need to install extra non-python dependencies for `pdf2image`. See [here](https://pypi.org/project/pdf2image/). Feel free to write your own demo if you have trouble.\n\n\n```python\nimport gradio as gr\nfrom gradio_pdf import PDF\nfrom pdf2image import convert_from_path\nfrom transformers import pipeline\nfrom pathlib import Path\n\ndir_ = Path(__file__).parent\n\np = pipeline(\n \"document-question-answering\",\n model=\"impira/layoutlm-document-qa\",\n)\n\ndef qa(question: str, doc: str) -> str:\n img = convert_from_path(doc)[0]\n output = p(img, question)\n return sorted(output, key=lambda x: x[\"score\"], reverse=True)[0]['answer']\n\n\ndemo = gr.Interface(\n qa,\n [gr.Textbox(label=\"Question\"), PDF(label=\"Document\")],\n gr.Textbox(),\n)\n\ndemo.launch()\n```\n\nSee our demo in action below!\n\n\n\nFinally lets build our component with `gradio cc build` and publish it with the `gradio cc publish` command!\nThis will guide you through the process of uploading your component to [PyPi](https://pypi.org/) and [HuggingFace Spaces](https://huggingface.co/spaces).\n\n\nTip: You may need to add the following lines to the `Dockerfile` of your HuggingFace Space.\n\n```Dockerfile\nRUN mkdir -p /tmp/cache/\nRUN chmod a+rwx -R /tmp/cache/\nRUN apt-get update && apt-get install -y poppler-utils tesseract-ocr\n\nENV TRANSFORMERS_CACHE=/tmp/cache/\n```" }, { "id": 86, "parent": 73, "path": "08_custom-components/07_pdf-component-example.md", "level": 2, "title": "Conclusion", "content": "In order to use our new component in **any** gradio 4.0 app, simply install it with pip, e.g. `pip install gradio-pdf`. Then you can use it like the built-in `gr.File()` component (except that it will only accept and display PDF files).\n\nHere is a simple demo with the Blocks api:\n\n```python\nimport gradio as gr\nfrom gradio_pdf import PDF\n\nwith gr.Blocks() as demo:\n pdf = PDF(label=\"Upload a PDF\", interactive=True)\n name = gr.Textbox()\n pdf.upload(lambda f: f, pdf, name)\n\ndemo.launch()\n```\n\n\nI hope you enjoyed this tutorial!\nThe complete source code for our component is [here](https://huggingface.co/spaces/freddyaboulton/gradio_pdf/tree/main/src).\nPlease don't hesitate to reach out to the gradio community on the [HuggingFace Discord](https://discord.gg/hugging-face-879548962464493619) if you get stuck." }, { "id": 87, "parent": null, "path": "08_custom-components/04_backend.md", "level": 1, "title": "The Backend 🐍", "content": "This guide will cover everything you need to know to implement your custom component's backend processing." }, { "id": 88, "parent": 87, "path": "08_custom-components/04_backend.md", "level": 2, "title": "Which Class to Inherit From", "content": "All components inherit from one of three classes `Component`, `FormComponent`, or `BlockContext`.\nYou need to inherit from one so that your component behaves like all other gradio components.\nWhen you start from a template with `gradio cc create --template`, you don't need to worry about which one to choose since the template uses the correct one. \nFor completeness, and in the event that you need to make your own component from scratch, we explain what each class is for.\n\n* `FormComponent`: Use this when you want your component to be grouped together in the same `Form` layout with other `FormComponents`. The `Slider`, `Textbox`, and `Number` components are all `FormComponents`.\n* `BlockContext`: Use this when you want to place other components \"inside\" your component. This enabled `with MyComponent() as component:` syntax.\n* `Component`: Use this for all other cases.\n\nTip: If your component supports streaming output, inherit from the `StreamingOutput` class.\n\nTip: If you inherit from `BlockContext`, you also need to set the metaclass to be `ComponentMeta`. See example below.\n\n```python\nfrom gradio.blocks import BlockContext\nfrom gradio.component_meta import ComponentMeta\n\n\n\n\n@document()\nclass Row(BlockContext, metaclass=ComponentMeta):\n pass\n```" }, { "id": 89, "parent": 87, "path": "08_custom-components/04_backend.md", "level": 2, "title": "The methods you need to implement", "content": "When you inherit from any of these classes, the following methods must be implemented.\nOtherwise the Python interpreter will raise an error when you instantiate your component!" }, { "id": 90, "parent": 89, "path": "08_custom-components/04_backend.md", "level": 3, "title": "`preprocess` and `postprocess`", "content": "Explained in the [Key Concepts](./key-component-concepts#the-value-and-how-it-is-preprocessed-postprocessed) guide. \nThey handle the conversion from the data sent by the frontend to the format expected by the python function.\n\n```python\n def preprocess(self, x: Any) -> Any:\n \"\"\"\n Convert from the web-friendly (typically JSON) value in the frontend to the format expected by the python function.\n \"\"\"\n return x\n\n def postprocess(self, y):\n \"\"\"\n Convert from the data returned by the python function to the web-friendly (typically JSON) value expected by the frontend.\n \"\"\"\n return y\n```" }, { "id": 91, "parent": 89, "path": "08_custom-components/04_backend.md", "level": 3, "title": "`process_example`", "content": "Takes in the original Python value and returns the modified value that should be displayed in the examples preview in the app. \nIf not provided, the `.postprocess()` method is used instead. Let's look at the following example from the `SimpleDropdown` component.\n\n```python\ndef process_example(self, input_data):\n return next((c[0] for c in self.choices if c[1] == input_data), None)\n```\n\nSince `self.choices` is a list of tuples corresponding to (`display_name`, `value`), this converts the value that a user provides to the display value (or if the value is not present in `self.choices`, it is converted to `None`)." }, { "id": 92, "parent": 89, "path": "08_custom-components/04_backend.md", "level": 3, "title": "`api_info`", "content": "A JSON-schema representation of the value that the `preprocess` expects. \nThis powers api usage via the gradio clients. \nYou do **not** need to implement this yourself if you components specifies a `data_model`. \nThe `data_model` in the following section.\n\n```python\ndef api_info(self) -> dict[str, list[str]]:\n \"\"\"\n A JSON-schema representation of the value that the `preprocess` expects and the `postprocess` returns.\n \"\"\"\n pass\n```" }, { "id": 93, "parent": 89, "path": "08_custom-components/04_backend.md", "level": 3, "title": "`example_payload`", "content": "An example payload for your component, e.g. something that can be passed into the `.preprocess()` method\nof your component. The example input is displayed in the `View API` page of a Gradio app that uses your custom component. \nMust be JSON-serializable. If your component expects a file, it is best to use a publicly accessible URL.\n\n```python\ndef example_payload(self) -> Any:\n \"\"\"\n The example inputs for this component for API usage. Must be JSON-serializable.\n \"\"\"\n pass\n```" }, { "id": 94, "parent": 89, "path": "08_custom-components/04_backend.md", "level": 3, "title": "`example_value`", "content": "An example value for your component, e.g. something that can be passed into the `.postprocess()` method\nof your component. This is used as the example value in the default app that is created in custom component development.\n\n```python\ndef example_payload(self) -> Any:\n \"\"\"\n The example inputs for this component for API usage. Must be JSON-serializable.\n \"\"\"\n pass\n```" }, { "id": 95, "parent": 89, "path": "08_custom-components/04_backend.md", "level": 3, "title": "`flag`", "content": "Write the component's value to a format that can be stored in the `csv` or `json` file used for flagging.\nYou do **not** need to implement this yourself if you components specifies a `data_model`. \nThe `data_model` in the following section.\n\n```python\ndef flag(self, x: Any | GradioDataModel, flag_dir: str | Path = \"\") -> str:\n pass\n```" }, { "id": 96, "parent": 89, "path": "08_custom-components/04_backend.md", "level": 3, "title": "`read_from_flag`", "content": "Convert from the format stored in the `csv` or `json` file used for flagging to the component's python `value`.\nYou do **not** need to implement this yourself if you components specifies a `data_model`. \nThe `data_model` in the following section.\n\n```python\ndef read_from_flag(\n self,\n x: Any,\n) -> GradioDataModel | Any:\n \"\"\"\n Convert the data from the csv or jsonl file into the component state.\n \"\"\"\n return x\n```" }, { "id": 97, "parent": 87, "path": "08_custom-components/04_backend.md", "level": 2, "title": "The `data_model`", "content": "The `data_model` is how you define the expected data format your component's value will be stored in the frontend.\nIt specifies the data format your `preprocess` method expects and the format the `postprocess` method returns.\nIt is not necessary to define a `data_model` for your component but it greatly simplifies the process of creating a custom component.\nIf you define a custom component you only need to implement four methods - `preprocess`, `postprocess`, `example_payload`, and `example_value`!\n\nYou define a `data_model` by defining a [pydantic model](https://docs.pydantic.dev/latest/concepts/models/#basic-model-usage) that inherits from either `GradioModel` or `GradioRootModel`.\n\nThis is best explained with an example. Let's look at the core `Video` component, which stores the video data as a JSON object with two keys `video` and `subtitles` which point to separate files.\n\n```python\nfrom gradio.data_classes import FileData, GradioModel\n\nclass VideoData(GradioModel):\n video: FileData\n subtitles: Optional[FileData] = None\n\nclass Video(Component):\n data_model = VideoData\n```\n\nBy adding these four lines of code, your component automatically implements the methods needed for API usage, the flagging methods, and example caching methods!\nIt also has the added benefit of self-documenting your code.\nAnyone who reads your component code will know exactly the data it expects.\n\nTip: If your component expects files to be uploaded from the frontend, your must use the `FileData` model! It will be explained in the following section. \n\nTip: Read the pydantic docs [here](https://docs.pydantic.dev/latest/concepts/models/#basic-model-usage).\n\nThe difference between a `GradioModel` and a `GradioRootModel` is that the `RootModel` will not serialize the data to a dictionary.\nFor example, the `Names` model will serialize the data to `{'names': ['freddy', 'pete']}` whereas the `NamesRoot` model will serialize it to `['freddy', 'pete']`.\n\n```python\nfrom typing import List\n\nclass Names(GradioModel):\n names: List[str]\n\nclass NamesRoot(GradioRootModel):\n root: List[str]\n```\n\nEven if your component does not expect a \"complex\" JSON data structure it can be beneficial to define a `GradioRootModel` so that you don't have to worry about implementing the API and flagging methods.\n\nTip: Use classes from the Python typing library to type your models. e.g. `List` instead of `list`." }, { "id": 98, "parent": 87, "path": "08_custom-components/04_backend.md", "level": 2, "title": "Handling Files", "content": "If your component expects uploaded files as input, or returns saved files to the frontend, you **MUST** use the `FileData` to type the files in your `data_model`.\n\nWhen you use the `FileData`:\n\n* Gradio knows that it should allow serving this file to the frontend. Gradio automatically blocks requests to serve arbitrary files in the computer running the server.\n\n* Gradio will automatically place the file in a cache so that duplicate copies of the file don't get saved.\n\n* The client libraries will automatically know that they should upload input files prior to sending the request. They will also automatically download files.\n\nIf you do not use the `FileData`, your component will not work as expected!" }, { "id": 99, "parent": 87, "path": "08_custom-components/04_backend.md", "level": 2, "title": "Adding Event Triggers To Your Component", "content": "The events triggers for your component are defined in the `EVENTS` class attribute.\nThis is a list that contains the string names of the events.\nAdding an event to this list will automatically add a method with that same name to your component!\n\nYou can import the `Events` enum from `gradio.events` to access commonly used events in the core gradio components.\n\nFor example, the following code will define `text_submit`, `file_upload` and `change` methods in the `MyComponent` class.\n\n```python\nfrom gradio.events import Events\nfrom gradio.components import FormComponent\n\nclass MyComponent(FormComponent):\n\n EVENTS = [\n \"text_submit\",\n \"file_upload\",\n Events.change\n ]\n```\n\n\nTip: Don't forget to also handle these events in the JavaScript code!" }, { "id": 100, "parent": 87, "path": "08_custom-components/04_backend.md", "level": 2, "title": "Conclusion", "content": "" }, { "id": 101, "parent": null, "path": "08_custom-components/06_frequently-asked-questions.md", "level": 1, "title": "Frequently Asked Questions", "content": "" }, { "id": 102, "parent": 101, "path": "08_custom-components/06_frequently-asked-questions.md", "level": 2, "title": "What do I need to install before using Custom Components?", "content": "Before using Custom Components, make sure you have Python 3.10+, Node.js v18+, npm 9+, and Gradio 4.0+ (preferably Gradio 5.0+) installed." }, { "id": 103, "parent": 101, "path": "08_custom-components/06_frequently-asked-questions.md", "level": 2, "title": "Are custom components compatible between Gradio 4.0 and 5.0?", "content": "Custom components built with Gradio 5.0 should be compatible with Gradio 4.0. If you built your custom component in Gradio 4.0 you will have to rebuild your component to be compatible with Gradio 5.0. Simply follow these steps:\n1. Update the `@gradio/preview` package. `cd` into the `frontend` directory and run `npm update`.\n2. Modify the `dependencies` key in `pyproject.toml` to pin the maximum allowed Gradio version at version 5, e.g. `dependencies = [\"gradio>=4.0,<6.0\"]`.\n3. Run the build and publish commands" }, { "id": 104, "parent": 101, "path": "08_custom-components/06_frequently-asked-questions.md", "level": 2, "title": "What templates can I use to create my custom component?", "content": "Run `gradio cc show` to see the list of built-in templates.\nYou can also start off from other's custom components!\nSimply `git clone` their repository and make your modifications." }, { "id": 105, "parent": 101, "path": "08_custom-components/06_frequently-asked-questions.md", "level": 2, "title": "What is the development server?", "content": "When you run `gradio cc dev`, a development server will load and run a Gradio app of your choosing.\nThis is like when you run `python .py`, however the `gradio` command will hot reload so you can instantly see your changes." }, { "id": 106, "parent": 101, "path": "08_custom-components/06_frequently-asked-questions.md", "level": 2, "title": "The development server didn't work for me ", "content": "**1. Check your terminal and browser console**\n\nMake sure there are no syntax errors or other obvious problems in your code. Exceptions triggered from python will be displayed in the terminal. Exceptions from javascript will be displayed in the browser console and/or the terminal.\n\n**2. Are you developing on Windows?**\n\nChrome on Windows will block the local compiled svelte files for security reasons. We recommend developing your custom component in the windows subsystem for linux (WSL) while the team looks at this issue.\n\n**3. Inspect the window.__GRADIO_CC__ variable**\n\nIn the browser console, print the `window.__GRADIO__CC` variable (just type it into the console). If it is an empty object, that means\nthat the CLI could not find your custom component source code. Typically, this happens when the custom component is installed in a different virtual environment than the one used to run the dev command. Please use the `--python-path` and `gradio-path` CLI arguments to specify the path of the python and gradio executables for the environment your component is installed in. For example, if you are using a virtualenv located at `/Users/mary/venv`, pass in `/Users/mary/bin/python` and `/Users/mary/bin/gradio` respectively.\n\nIf the `window.__GRADIO__CC` variable is not empty (see below for an example), then the dev server should be working correctly. \n\n![](https://gradio-builds.s3.amazonaws.com/demo-files/gradio_CC_DEV.png)\n\n**4. Make sure you are using a virtual environment**\nIt is highly recommended you use a virtual environment to prevent conflicts with other python dependencies installed in your system." }, { "id": 107, "parent": 101, "path": "08_custom-components/06_frequently-asked-questions.md", "level": 2, "title": "Do I always need to start my component from scratch?", "content": "No! You can start off from an existing gradio component as a template, see the [five minute guide](./custom-components-in-five-minutes).\nYou can also start from an existing custom component if you'd like to tweak it further. Once you find the source code of a custom component you like, clone the code to your computer and run `gradio cc install`. Then you can run the development server to make changes.If you run into any issues, contact the author of the component by opening an issue in their repository. The [gallery](https://www.gradio.app/custom-components/gallery) is a good place to look for published components. For example, to start from the [PDF component](https://www.gradio.app/custom-components/gallery?id=freddyaboulton%2Fgradio_pdf), clone the space with `git clone https://huggingface.co/spaces/freddyaboulton/gradio_pdf`, `cd` into the `src` directory, and run `gradio cc install`." }, { "id": 108, "parent": 101, "path": "08_custom-components/06_frequently-asked-questions.md", "level": 2, "title": "Do I need to host my custom component on HuggingFace Spaces?", "content": "You can develop and build your custom component without hosting or connecting to HuggingFace.\nIf you would like to share your component with the gradio community, it is recommended to publish your package to PyPi and host a demo on HuggingFace so that anyone can install it or try it out." }, { "id": 109, "parent": 101, "path": "08_custom-components/06_frequently-asked-questions.md", "level": 2, "title": "What methods are mandatory for implementing a custom component in Gradio?", "content": "You must implement the `preprocess`, `postprocess`, `example_payload`, and `example_value` methods. If your component does not use a data model, you must also define the `api_info`, `flag`, and `read_from_flag` methods. Read more in the [backend guide](./backend)." }, { "id": 110, "parent": 101, "path": "08_custom-components/06_frequently-asked-questions.md", "level": 2, "title": "What is the purpose of a `data_model` in Gradio custom components?", "content": "A `data_model` defines the expected data format for your component, simplifying the component development process and self-documenting your code. It streamlines API usage and example caching." }, { "id": 111, "parent": 101, "path": "08_custom-components/06_frequently-asked-questions.md", "level": 2, "title": "Why is it important to use `FileData` for components dealing with file uploads?", "content": "Utilizing `FileData` is crucial for components that expect file uploads. It ensures secure file handling, automatic caching, and streamlined client library functionality." }, { "id": 112, "parent": 101, "path": "08_custom-components/06_frequently-asked-questions.md", "level": 2, "title": "How can I add event triggers to my custom Gradio component?", "content": "You can define event triggers in the `EVENTS` class attribute by listing the desired event names, which automatically adds corresponding methods to your component." }, { "id": 113, "parent": 101, "path": "08_custom-components/06_frequently-asked-questions.md", "level": 2, "title": "Can I implement a custom Gradio component without defining a `data_model`?", "content": "Yes, it is possible to create custom components without a `data_model`, but you are going to have to manually implement `api_info`, `flag`, and `read_from_flag` methods." }, { "id": 114, "parent": 101, "path": "08_custom-components/06_frequently-asked-questions.md", "level": 2, "title": "Are there sample custom components I can learn from?", "content": "We have prepared this [collection](https://huggingface.co/collections/gradio/custom-components-65497a761c5192d981710b12) of custom components on the HuggingFace Hub that you can use to get started!" }, { "id": 115, "parent": 101, "path": "08_custom-components/06_frequently-asked-questions.md", "level": 2, "title": "How can I find custom components created by the Gradio community?", "content": "We're working on creating a gallery to make it really easy to discover new custom components.\nIn the meantime, you can search for HuggingFace Spaces that are tagged as a `gradio-custom-component` [here](https://huggingface.co/search/full-text?q=gradio-custom-component&type=space)" }, { "id": 116, "parent": null, "path": "08_custom-components/09_documenting-custom-components.md", "level": 1, "title": "Documenting Custom Components", "content": "In 4.15, we added a new `gradio cc docs` command to the Gradio CLI to generate rich documentation for your custom component. This command will generate documentation for users automatically, but to get the most out of it, you need to do a few things." }, { "id": 117, "parent": 116, "path": "08_custom-components/09_documenting-custom-components.md", "level": 2, "title": "How do I use it?", "content": "The documentation will be generated when running `gradio cc build`. You can pass the `--no-generate-docs` argument to turn off this behaviour.\n\nThere is also a standalone `docs` command that allows for greater customisation. If you are running this command manually it should be run _after_ the `version` in your `pyproject.toml` has been bumped but before building the component.\n\nAll arguments are optional.\n\n```bash\ngradio cc docs\n path # The directory of the custom component.\n --demo-dir # Path to the demo directory.\n --demo-name # Name of the demo file\n --space-url # URL of the Hugging Face Space to link to\n --generate-space # create a documentation space.\n --no-generate-space # do not create a documentation space\n --readme-path # Path to the README.md file.\n --generate-readme # create a REAMDE.md file\n --no-generate-readme # do not create a README.md file\n --suppress-demo-check # suppress validation checks and warnings\n```" }, { "id": 118, "parent": 116, "path": "08_custom-components/09_documenting-custom-components.md", "level": 2, "title": "What gets generated?", "content": "The `gradio cc docs` command will generate an interactive Gradio app and a static README file with various features. You can see an example here:\n\n- [Gradio app deployed on Hugging Face Spaces]()\n- [README.md rendered by GitHub]()\n\nThe README.md and space both have the following features:\n\n- A description.\n- Installation instructions.\n- A fully functioning code snippet.\n- Optional links to PyPi, GitHub, and Hugging Face Spaces.\n- API documentation including:\n - An argument table for component initialisation showing types, defaults, and descriptions.\n - A description of how the component affects the user's predict function.\n - A table of events and their descriptions.\n - Any additional interfaces or classes that may be used during initialisation or in the pre- or post- processors.\n\nAdditionally, the Gradio includes:\n\n- A live demo.\n- A richer, interactive version of the parameter tables.\n- Nicer styling!" }, { "id": 119, "parent": 116, "path": "08_custom-components/09_documenting-custom-components.md", "level": 2, "title": "What do I need to do?", "content": "The documentation generator uses existing standards to extract the necessary information, namely Type Hints and Docstrings. There are no Gradio-specific APIs for documentation, so following best practices will generally yield the best results.\n\nIf you already use type hints and docstrings in your component source code, you don't need to do much to benefit from this feature, but there are some details that you should be aware of." }, { "id": 120, "parent": 119, "path": "08_custom-components/09_documenting-custom-components.md", "level": 3, "title": "Python version", "content": "To get the best documentation experience, you need to use Python `3.10` or greater when generating documentation. This is because some introspection features used to generate the documentation were only added in `3.10`." }, { "id": 121, "parent": 119, "path": "08_custom-components/09_documenting-custom-components.md", "level": 3, "title": "Type hints", "content": "Python type hints are used extensively to provide helpful information for users. \n\n
\n What are type hints?\n\n\nIf you need to become more familiar with type hints in Python, they are a simple way to express what Python types are expected for arguments and return values of functions and methods. They provide a helpful in-editor experience, aid in maintenance, and integrate with various other tools. These types can be simple primitives, like `list` `str` `bool`; they could be more compound types like `list[str]`, `str | None` or `tuple[str, float | int]`; or they can be more complex types using utility classed like [`TypedDict`](https://peps.python.org/pep-0589/#abstract).\n\n[Read more about type hints in Python.](https://realpython.com/lessons/type-hinting/)\n\n\n
" }, { "id": 122, "parent": 121, "path": "08_custom-components/09_documenting-custom-components.md", "level": 4, "title": "What do I need to add hints to?", "content": "You do not need to add type hints to every part of your code. For the documentation to work correctly, you will need to add type hints to the following component methods:\n\n- `__init__` parameters should be typed.\n- `postprocess` parameters and return value should be typed.\n- `preprocess` parameters and return value should be typed.\n\nIf you are using `gradio cc create`, these types should already exist, but you may need to tweak them based on any changes you make." }, { "id": 123, "parent": 122, "path": "08_custom-components/09_documenting-custom-components.md", "level": 5, "title": "`__init__`", "content": "Here, you only need to type the parameters. If you have cloned a template with `gradio` cc create`, these should already be in place. You will only need to add new hints for anything you have added or changed:\n\n```py\ndef __init__(\n self,\n value: str | None = None,\n *,\n sources: Literal[\"upload\", \"microphone\"] = \"upload,\n every: Timer | float | None = None,\n ...\n):\n ...\n```" }, { "id": 124, "parent": 122, "path": "08_custom-components/09_documenting-custom-components.md", "level": 5, "title": "`preprocess` and `postprocess`", "content": "The `preprocess` and `postprocess` methods determine the value passed to the user function and the value that needs to be returned.\n\nEven if the design of your component is primarily as an input or an output, it is worth adding type hints to both the input parameters and the return values because Gradio has no way of limiting how components can be used.\n\nIn this case, we specifically care about:\n\n- The return type of `preprocess`.\n- The input type of `postprocess`.\n\n```py\ndef preprocess(\n self, payload: FileData | None # input is optional\n) -> tuple[int, str] | str | None:" }, { "id": 125, "parent": null, "path": "08_custom-components/09_documenting-custom-components.md", "level": 1, "title": "user function input is the preprocess return ▲", "content": "" }, { "id": 126, "parent": null, "path": "08_custom-components/09_documenting-custom-components.md", "level": 1, "title": "user function output is the postprocess input ▼", "content": "def postprocess(\n self, value: tuple[int, str] | None\n) -> FileData | bytes | None: # return is optional\n ...\n```" }, { "id": 127, "parent": 126, "path": "08_custom-components/09_documenting-custom-components.md", "level": 3, "title": "Docstrings", "content": "Docstrings are also used extensively to extract more meaningful, human-readable descriptions of certain parts of the API.\n\n
\n What are docstrings?\n\n\nIf you need to become more familiar with docstrings in Python, they are a way to annotate parts of your code with human-readable decisions and explanations. They offer a rich in-editor experience like type hints, but unlike type hints, they don't have any specific syntax requirements. They are simple strings and can take almost any form. The only requirement is where they appear. Docstrings should be \"a string literal that occurs as the first statement in a module, function, class, or method definition\".\n\n[Read more about Python docstrings.](https://peps.python.org/pep-0257/#what-is-a-docstring)\n\n
\n\nWhile docstrings don't have any syntax requirements, we need a particular structure for documentation purposes.\n\nAs with type hint, the specific information we care about is as follows:\n\n- `__init__` parameter docstrings.\n- `preprocess` return docstrings.\n- `postprocess` input parameter docstrings.\n\nEverything else is optional.\n\nDocstrings should always take this format to be picked up by the documentation generator:" }, { "id": 128, "parent": 127, "path": "08_custom-components/09_documenting-custom-components.md", "level": 4, "title": "Classes", "content": "```py\n\"\"\"\nA description of the class.\n\nThis can span multiple lines and can _contain_ *markdown*.\n\"\"\"\n```" }, { "id": 129, "parent": 127, "path": "08_custom-components/09_documenting-custom-components.md", "level": 4, "title": "Methods and functions ", "content": "Markdown in these descriptions will not be converted into formatted text.\n\n```py\n\"\"\"\nParameters:\n param_one: A description for this parameter.\n param_two: A description for this parameter.\nReturns:\n A description for this return value.\n\"\"\"\n```" }, { "id": 130, "parent": 126, "path": "08_custom-components/09_documenting-custom-components.md", "level": 3, "title": "Events", "content": "In custom components, events are expressed as a list stored on the `events` field of the component class. While we do not need types for events, we _do_ need a human-readable description so users can understand the behaviour of the event.\n\nTo facilitate this, we must create the event in a specific way.\n\nThere are two ways to add events to a custom component." }, { "id": 131, "parent": 130, "path": "08_custom-components/09_documenting-custom-components.md", "level": 4, "title": "Built-in events", "content": "Gradio comes with a variety of built-in events that may be enough for your component. If you are using built-in events, you do not need to do anything as they already have descriptions we can extract:\n\n```py\nfrom gradio.events import Events\n\nclass ParamViewer(Component):\n ...\n\n EVENTS = [\n Events.change,\n Events.upload,\n ]\n```" }, { "id": 132, "parent": 130, "path": "08_custom-components/09_documenting-custom-components.md", "level": 4, "title": "Custom events", "content": "You can define a custom event if the built-in events are unsuitable for your use case. This is a straightforward process, but you must create the event in this way for docstrings to work correctly:\n\n```py\nfrom gradio.events import Events, EventListener\n\nclass ParamViewer(Component):\n ...\n\n EVENTS = [\n Events.change,\n EventListener(\n \"bingbong\",\n doc=\"This listener is triggered when the user does a bingbong.\"\n )\n ]\n```" }, { "id": 133, "parent": 126, "path": "08_custom-components/09_documenting-custom-components.md", "level": 3, "title": "Demo", "content": "The `demo/app.py`, often used for developing the component, generates the live demo and code snippet. The only strict rule here is that the `demo.launch()` command must be contained with a `__name__ == \"__main__\"` conditional as below:\n\n```py\nif __name__ == \"__main__\":\n demo.launch()\n```\n\nThe documentation generator will scan for such a clause and error if absent. If you are _not_ launching the demo inside the `demo/app.py`, then you can pass `--suppress-demo-check` to turn off this check." }, { "id": 134, "parent": 133, "path": "08_custom-components/09_documenting-custom-components.md", "level": 4, "title": "Demo recommendations", "content": "Although there are no additional rules, there are some best practices you should bear in mind to get the best experience from the documentation generator.\n\nThese are only guidelines, and every situation is unique, but they are sound principles to remember." }, { "id": 135, "parent": 134, "path": "08_custom-components/09_documenting-custom-components.md", "level": 5, "title": "Keep the demo compact", "content": "Compact demos look better and make it easier for users to understand what the demo does. Try to remove as many extraneous UI elements as possible to focus the users' attention on the core use case. \n\nSometimes, it might make sense to have a `demo/app.py` just for the docs and an additional, more complex app for your testing purposes. You can also create other spaces, showcasing more complex examples and linking to them from the main class docstring or the `pyproject.toml` description." }, { "id": 136, "parent": 133, "path": "08_custom-components/09_documenting-custom-components.md", "level": 4, "title": "Keep the code concise", "content": "The 'getting started' snippet utilises the demo code, which should be as short as possible to keep users engaged and avoid confusion.\n\nIt isn't the job of the sample snippet to demonstrate the whole API; this snippet should be the shortest path to success for a new user. It should be easy to type or copy-paste and easy to understand. Explanatory comments should be brief and to the point." }, { "id": 137, "parent": 133, "path": "08_custom-components/09_documenting-custom-components.md", "level": 4, "title": "Avoid external dependencies", "content": "As mentioned above, users should be able to copy-paste a snippet and have a fully working app. Try to avoid third-party library dependencies to facilitate this.\n\nYou should carefully consider any examples; avoiding examples that require additional files or that make assumptions about the environment is generally a good idea." }, { "id": 138, "parent": 133, "path": "08_custom-components/09_documenting-custom-components.md", "level": 4, "title": "Ensure the `demo` directory is self-contained", "content": "Only the `demo` directory will be uploaded to Hugging Face spaces in certain instances, as the component will be installed via PyPi if possible. It is essential that this directory is self-contained and any files needed for the correct running of the demo are present." }, { "id": 139, "parent": 126, "path": "08_custom-components/09_documenting-custom-components.md", "level": 3, "title": "Additional URLs", "content": "The documentation generator will generate a few buttons, providing helpful information and links to users. They are obtained automatically in some cases, but some need to be explicitly included in the `pyproject.yaml`. \n\n- PyPi Version and link - This is generated automatically.\n- GitHub Repository - This is populated via the `pyproject.toml`'s `project.urls.repository`.\n- Hugging Face Space - This is populated via the `pyproject.toml`'s `project.urls.space`.\n\nAn example `pyproject.toml` urls section might look like this:\n\n```toml\n[project.urls]\nrepository = \"https://github.com/user/repo-name\"\nspace = \"https://huggingface.co/spaces/user/space-name\"\n```" }, { "id": 140, "parent": null, "path": "08_custom-components/03_configuration.md", "level": 1, "title": "Configuring Your Custom Component", "content": "The custom components workflow focuses on [convention over configuration](https://en.wikipedia.org/wiki/Convention_over_configuration) to reduce the number of decisions you as a developer need to make when developing your custom component.\nThat being said, you can still configure some aspects of the custom component package and directory.\nThis guide will cover how." }, { "id": 141, "parent": 140, "path": "08_custom-components/03_configuration.md", "level": 2, "title": "The Package Name", "content": "By default, all custom component packages are called `gradio_` where `component-name` is the name of the component's python class in lowercase.\n\nAs an example, let's walkthrough changing the name of a component from `gradio_mytextbox` to `supertextbox`. \n\n1. Modify the `name` in the `pyproject.toml` file. \n\n```bash\n[project]\nname = \"supertextbox\"\n```\n\n2. Change all occurrences of `gradio_` in `pyproject.toml` to ``\n\n```bash\n[tool.hatch.build]\nartifacts = [\"/backend/supertextbox/templates\", \"*.pyi\"]\n\n[tool.hatch.build.targets.wheel]\npackages = [\"/backend/supertextbox\"]\n```\n\n3. Rename the `gradio_` directory in `backend/` to ``\n\n```bash\nmv backend/gradio_mytextbox backend/supertextbox\n```\n\n\nTip: Remember to change the import statement in `demo/app.py`!" }, { "id": 142, "parent": 140, "path": "08_custom-components/03_configuration.md", "level": 2, "title": "Top Level Python Exports", "content": "By default, only the custom component python class is a top level export. \nThis means that when users type `from gradio_ import ...`, the only class that will be available is the custom component class.\nTo add more classes as top level exports, modify the `__all__` property in `__init__.py`\n\n```python\nfrom .mytextbox import MyTextbox\nfrom .mytextbox import AdditionalClass, additional_function\n\n__all__ = ['MyTextbox', 'AdditionalClass', 'additional_function']\n```" }, { "id": 143, "parent": 140, "path": "08_custom-components/03_configuration.md", "level": 2, "title": "Python Dependencies", "content": "You can add python dependencies by modifying the `dependencies` key in `pyproject.toml`\n\n```bash\ndependencies = [\"gradio\", \"numpy\", \"PIL\"]\n```\n\n\nTip: Remember to run `gradio cc install` when you add dependencies!" }, { "id": 144, "parent": 140, "path": "08_custom-components/03_configuration.md", "level": 2, "title": "Javascript Dependencies", "content": "You can add JavaScript dependencies by modifying the `\"dependencies\"` key in `frontend/package.json`\n\n```json\n\"dependencies\": {\n \"@gradio/atoms\": \"0.2.0-beta.4\",\n \"@gradio/statustracker\": \"0.3.0-beta.6\",\n \"@gradio/utils\": \"0.2.0-beta.4\",\n \"your-npm-package\": \"\"\n}\n```" }, { "id": 145, "parent": 140, "path": "08_custom-components/03_configuration.md", "level": 2, "title": "Directory Structure", "content": "By default, the CLI will place the Python code in `backend` and the JavaScript code in `frontend`.\nIt is not recommended to change this structure since it makes it easy for a potential contributor to look at your source code and know where everything is.\nHowever, if you did want to this is what you would have to do:\n\n1. Place the Python code in the subdirectory of your choosing. Remember to modify the `[tool.hatch.build]` `[tool.hatch.build.targets.wheel]` in the `pyproject.toml` to match!\n\n2. Place the JavaScript code in the subdirectory of your choosing.\n\n2. Add the `FRONTEND_DIR` property on the component python class. It must be the relative path from the file where the class is defined to the location of the JavaScript directory.\n\n```python\nclass SuperTextbox(Component):\n FRONTEND_DIR = \"../../frontend/\"\n```\n\nThe JavaScript and Python directories must be under the same common directory!" }, { "id": 146, "parent": 140, "path": "08_custom-components/03_configuration.md", "level": 2, "title": "Conclusion", "content": "Sticking to the defaults will make it easy for others to understand and contribute to your custom component.\nAfter all, the beauty of open source is that anyone can help improve your code!\nBut if you ever need to deviate from the defaults, you know how!" }, { "id": 147, "parent": null, "path": "10_other-tutorials/styling-the-gradio-dataframe.md", "level": 1, "title": "How to Style the Gradio Dataframe", "content": "Tags: DATAFRAME, STYLE, COLOR" }, { "id": 148, "parent": 147, "path": "10_other-tutorials/styling-the-gradio-dataframe.md", "level": 2, "title": "Introduction", "content": "Data visualization is a crucial aspect of data analysis and machine learning. The Gradio `DataFrame` component is a popular way to display tabular data (particularly data in the form of a `pandas` `DataFrame` object) within a web application. \n\nThis post will explore the recent enhancements in Gradio that allow users to integrate the styling options of pandas, e.g. adding colors to the DataFrame component, or setting the display precision of numbers. \n\n![](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/df-highlight.png)\n\nLet's dive in!\n\n**Prerequisites**: We'll be using the `gradio.Blocks` class in our examples.\nYou can [read the Guide to Blocks first](https://gradio.app/blocks-and-event-listeners) if you are not already familiar with it. Also please make sure you are using the **latest version** version of Gradio: `pip install --upgrade gradio`." }, { "id": 149, "parent": 147, "path": "10_other-tutorials/styling-the-gradio-dataframe.md", "level": 2, "title": "Overview", "content": "The Gradio `DataFrame` component now supports values of the type `Styler` from the `pandas` class. This allows us to reuse the rich existing API and documentation of the `Styler` class instead of inventing a new style format on our own. Here's a complete example of how it looks:\n\n```python\nimport pandas as pd \nimport gradio as gr" }, { "id": 150, "parent": null, "path": "10_other-tutorials/styling-the-gradio-dataframe.md", "level": 1, "title": "Creating a sample dataframe", "content": "df = pd.DataFrame({\n \"A\" : [14, 4, 5, 4, 1], \n \"B\" : [5, 2, 54, 3, 2], \n \"C\" : [20, 20, 7, 3, 8], \n \"D\" : [14, 3, 6, 2, 6], \n \"E\" : [23, 45, 64, 32, 23]\n})" }, { "id": 151, "parent": null, "path": "10_other-tutorials/styling-the-gradio-dataframe.md", "level": 1, "title": "Applying style to highlight the maximum value in each row", "content": "styler = df.style.highlight_max(color = 'lightgreen', axis = 0)" }, { "id": 152, "parent": null, "path": "10_other-tutorials/styling-the-gradio-dataframe.md", "level": 1, "title": "Displaying the styled dataframe in Gradio", "content": "with gr.Blocks() as demo:\n gr.DataFrame(styler)\n \ndemo.launch()\n```\n\nThe Styler class can be used to apply conditional formatting and styling to dataframes, making them more visually appealing and interpretable. You can highlight certain values, apply gradients, or even use custom CSS to style the DataFrame. The Styler object is applied to a DataFrame and it returns a new object with the relevant styling properties, which can then be previewed directly, or rendered dynamically in a Gradio interface.\n\nTo read more about the Styler object, read the official `pandas` documentation at: https://pandas.pydata.org/docs/user_guide/style.html\n\nBelow, we'll explore a few examples:" }, { "id": 153, "parent": 152, "path": "10_other-tutorials/styling-the-gradio-dataframe.md", "level": 2, "title": "Highlighting Cells", "content": "Ok, so let's revisit the previous example. We start by creating a `pd.DataFrame` object and then highlight the highest value in each row with a light green color:\n\n```python\nimport pandas as pd" }, { "id": 154, "parent": null, "path": "10_other-tutorials/styling-the-gradio-dataframe.md", "level": 1, "title": "Creating a sample dataframe", "content": "df = pd.DataFrame({\n \"A\" : [14, 4, 5, 4, 1], \n \"B\" : [5, 2, 54, 3, 2], \n \"C\" : [20, 20, 7, 3, 8], \n \"D\" : [14, 3, 6, 2, 6], \n \"E\" : [23, 45, 64, 32, 23]\n})" }, { "id": 155, "parent": null, "path": "10_other-tutorials/styling-the-gradio-dataframe.md", "level": 1, "title": "Applying style to highlight the maximum value in each row", "content": "styler = df.style.highlight_max(color = 'lightgreen', axis = 0)\n```\n\nNow, we simply pass this object into the Gradio `DataFrame` and we can visualize our colorful table of data in 4 lines of python:\n\n```python\nimport gradio as gr\n\nwith gr.Blocks() as demo:\n gr.Dataframe(styler)\n \ndemo.launch()\n```\n\nHere's how it looks:\n\n![](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/df-highlight.png)" }, { "id": 156, "parent": 155, "path": "10_other-tutorials/styling-the-gradio-dataframe.md", "level": 2, "title": "Font Colors", "content": "Apart from highlighting cells, you might want to color specific text within the cells. Here's how you can change text colors for certain columns:\n\n```python\nimport pandas as pd \nimport gradio as gr" }, { "id": 157, "parent": null, "path": "10_other-tutorials/styling-the-gradio-dataframe.md", "level": 1, "title": "Creating a sample dataframe", "content": "df = pd.DataFrame({\n \"A\" : [14, 4, 5, 4, 1], \n \"B\" : [5, 2, 54, 3, 2], \n \"C\" : [20, 20, 7, 3, 8], \n \"D\" : [14, 3, 6, 2, 6], \n \"E\" : [23, 45, 64, 32, 23]\n})" }, { "id": 158, "parent": null, "path": "10_other-tutorials/styling-the-gradio-dataframe.md", "level": 1, "title": "Function to apply text color", "content": "def highlight_cols(x): \n df = x.copy() \n df.loc[:, :] = 'color: purple'\n df[['B', 'C', 'E']] = 'color: green'\n return df" }, { "id": 159, "parent": null, "path": "10_other-tutorials/styling-the-gradio-dataframe.md", "level": 1, "title": "Applying the style function", "content": "s = df.style.apply(highlight_cols, axis = None)" }, { "id": 160, "parent": null, "path": "10_other-tutorials/styling-the-gradio-dataframe.md", "level": 1, "title": "Displaying the styled dataframe in Gradio", "content": "with gr.Blocks() as demo:\n gr.DataFrame(s)\n \ndemo.launch()\n```\n\nIn this script, we define a custom function highlight_cols that changes the text color to purple for all cells, but overrides this for columns B, C, and E with green. Here's how it looks:\n\n![](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/df-color.png)" }, { "id": 161, "parent": 160, "path": "10_other-tutorials/styling-the-gradio-dataframe.md", "level": 2, "title": "Display Precision ", "content": "Sometimes, the data you are dealing with might have long floating numbers, and you may want to display only a fixed number of decimals for simplicity. The pandas Styler object allows you to format the precision of numbers displayed. Here's how you can do this:\n\n```python\nimport pandas as pd\nimport gradio as gr" }, { "id": 162, "parent": null, "path": "10_other-tutorials/styling-the-gradio-dataframe.md", "level": 1, "title": "Creating a sample dataframe with floating numbers", "content": "df = pd.DataFrame({\n \"A\" : [14.12345, 4.23456, 5.34567, 4.45678, 1.56789], \n \"B\" : [5.67891, 2.78912, 54.89123, 3.91234, 2.12345], \n # ... other columns\n})" }, { "id": 163, "parent": null, "path": "10_other-tutorials/styling-the-gradio-dataframe.md", "level": 1, "title": "Setting the precision of numbers to 2 decimal places", "content": "s = df.style.format(\"{:.2f}\")" }, { "id": 164, "parent": null, "path": "10_other-tutorials/styling-the-gradio-dataframe.md", "level": 1, "title": "Displaying the styled dataframe in Gradio", "content": "with gr.Blocks() as demo:\n gr.DataFrame(s)\n \ndemo.launch()\n```\n\nIn this script, the format method of the Styler object is used to set the precision of numbers to two decimal places. Much cleaner now:\n\n![](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/df-precision.png)" }, { "id": 165, "parent": 164, "path": "10_other-tutorials/styling-the-gradio-dataframe.md", "level": 2, "title": "Note about Interactivity", "content": "One thing to keep in mind is that the gradio `DataFrame` component only accepts `Styler` objects when it is non-interactive (i.e. in \"static\" mode). If the `DataFrame` component is interactive, then the styling information is ignored and instead the raw table values are shown instead. \n\nThe `DataFrame` component is by default non-interactive, unless it is used as an input to an event. In which case, you can force the component to be non-interactive by setting the `interactive` prop like this:\n\n```python\nc = gr.DataFrame(styler, interactive=False)\n```" }, { "id": 166, "parent": 164, "path": "10_other-tutorials/styling-the-gradio-dataframe.md", "level": 2, "title": "Conclusion 🎉", "content": "This is just a taste of what's possible using the `gradio.DataFrame` component with the `Styler` class from `pandas`. Try it out and let us know what you think!" }, { "id": 167, "parent": null, "path": "10_other-tutorials/image-classification-in-pytorch.md", "level": 1, "title": "Image Classification in PyTorch", "content": "Related spaces: https://huggingface.co/spaces/abidlabs/pytorch-image-classifier, https://huggingface.co/spaces/pytorch/ResNet, https://huggingface.co/spaces/pytorch/ResNext, https://huggingface.co/spaces/pytorch/SqueezeNet\nTags: VISION, RESNET, PYTORCH" }, { "id": 168, "parent": 167, "path": "10_other-tutorials/image-classification-in-pytorch.md", "level": 2, "title": "Introduction", "content": "Image classification is a central task in computer vision. Building better classifiers to classify what object is present in a picture is an active area of research, as it has applications stretching from autonomous vehicles to medical imaging.\n\nSuch models are perfect to use with Gradio's _image_ input component, so in this tutorial we will build a web demo to classify images using Gradio. We will be able to build the whole web application in Python, and it will look like the demo on the bottom of the page.\n\nLet's get started!" }, { "id": 169, "parent": 168, "path": "10_other-tutorials/image-classification-in-pytorch.md", "level": 3, "title": "Prerequisites", "content": "Make sure you have the `gradio` Python package already [installed](/getting_started). We will be using a pretrained image classification model, so you should also have `torch` installed." }, { "id": 170, "parent": 167, "path": "10_other-tutorials/image-classification-in-pytorch.md", "level": 2, "title": "Step 1 — Setting up the Image Classification Model", "content": "First, we will need an image classification model. For this tutorial, we will use a pretrained Resnet-18 model, as it is easily downloadable from [PyTorch Hub](https://pytorch.org/hub/pytorch_vision_resnet/). You can use a different pretrained model or train your own.\n\n```python\nimport torch\n\nmodel = torch.hub.load('pytorch/vision:v0.6.0', 'resnet18', pretrained=True).eval()\n```\n\nBecause we will be using the model for inference, we have called the `.eval()` method." }, { "id": 171, "parent": 167, "path": "10_other-tutorials/image-classification-in-pytorch.md", "level": 2, "title": "Step 2 — Defining a `predict` function", "content": "Next, we will need to define a function that takes in the _user input_, which in this case is an image, and returns the prediction. The prediction should be returned as a dictionary whose keys are class name and values are confidence probabilities. We will load the class names from this [text file](https://git.io/JJkYN).\n\nIn the case of our pretrained model, it will look like this:\n\n```python\nimport requests\nfrom PIL import Image\nfrom torchvision import transforms" }, { "id": 172, "parent": null, "path": "10_other-tutorials/image-classification-in-pytorch.md", "level": 1, "title": "Download human-readable labels for ImageNet.", "content": "response = requests.get(\"https://git.io/JJkYN\")\nlabels = response.text.split(\"\\n\")\n\ndef predict(inp):\n inp = transforms.ToTensor()(inp).unsqueeze(0)\n with torch.no_grad():\n prediction = torch.nn.functional.softmax(model(inp)[0], dim=0)\n confidences = {labels[i]: float(prediction[i]) for i in range(1000)}\n return confidences\n```\n\nLet's break this down. The function takes one parameter:\n\n- `inp`: the input image as a `PIL` image\n\nThen, the function converts the image to a PIL Image and then eventually a PyTorch `tensor`, passes it through the model, and returns:\n\n- `confidences`: the predictions, as a dictionary whose keys are class labels and whose values are confidence probabilities" }, { "id": 173, "parent": 172, "path": "10_other-tutorials/image-classification-in-pytorch.md", "level": 2, "title": "Step 3 — Creating a Gradio Interface", "content": "Now that we have our predictive function set up, we can create a Gradio Interface around it.\n\nIn this case, the input component is a drag-and-drop image component. To create this input, we use `Image(type=\"pil\")` which creates the component and handles the preprocessing to convert that to a `PIL` image.\n\nThe output component will be a `Label`, which displays the top labels in a nice form. Since we don't want to show all 1,000 class labels, we will customize it to show only the top 3 images by constructing it as `Label(num_top_classes=3)`.\n\nFinally, we'll add one more parameter, the `examples`, which allows us to prepopulate our interfaces with a few predefined examples. The code for Gradio looks like this:\n\n```python\nimport gradio as gr\n\ngr.Interface(fn=predict,\n inputs=gr.Image(type=\"pil\"),\n outputs=gr.Label(num_top_classes=3),\n examples=[\"lion.jpg\", \"cheetah.jpg\"]).launch()\n```\n\nThis produces the following interface, which you can try right here in your browser (try uploading your own examples!):\n\n\n\n\n---\n\nAnd you're done! That's all the code you need to build a web demo for an image classifier. If you'd like to share with others, try setting `share=True` when you `launch()` the Interface!" }, { "id": 174, "parent": null, "path": "10_other-tutorials/using-flagging.md", "level": 1, "title": "Using Flagging", "content": "Related spaces: https://huggingface.co/spaces/gradio/calculator-flagging-crowdsourced, https://huggingface.co/spaces/gradio/calculator-flagging-options, https://huggingface.co/spaces/gradio/calculator-flag-basic\nTags: FLAGGING, DATA" }, { "id": 175, "parent": 174, "path": "10_other-tutorials/using-flagging.md", "level": 2, "title": "Introduction", "content": "When you demo a machine learning model, you might want to collect data from users who try the model, particularly data points in which the model is not behaving as expected. Capturing these \"hard\" data points is valuable because it allows you to improve your machine learning model and make it more reliable and robust.\n\nGradio simplifies the collection of this data by including a **Flag** button with every `Interface`. This allows a user or tester to easily send data back to the machine where the demo is running. In this Guide, we discuss more about how to use the flagging feature, both with `gradio.Interface` as well as with `gradio.Blocks`." }, { "id": 176, "parent": 174, "path": "10_other-tutorials/using-flagging.md", "level": 2, "title": "The **Flag** button in `gradio.Interface`", "content": "Flagging with Gradio's `Interface` is especially easy. By default, underneath the output components, there is a button marked **Flag**. When a user testing your model sees input with interesting output, they can click the flag button to send the input and output data back to the machine where the demo is running. The sample is saved to a CSV log file (by default). If the demo involves images, audio, video, or other types of files, these are saved separately in a parallel directory and the paths to these files are saved in the CSV file.\n\nThere are [four parameters](https://gradio.app/docs/interface#initialization) in `gradio.Interface` that control how flagging works. We will go over them in greater detail.\n\n- `flagging_mode`: this parameter can be set to either `\"manual\"` (default), `\"auto\"`, or `\"never\"`.\n - `manual`: users will see a button to flag, and samples are only flagged when the button is clicked.\n - `auto`: users will not see a button to flag, but every sample will be flagged automatically.\n - `never`: users will not see a button to flag, and no sample will be flagged.\n- `flagging_options`: this parameter can be either `None` (default) or a list of strings.\n - If `None`, then the user simply clicks on the **Flag** button and no additional options are shown.\n - If a list of strings are provided, then the user sees several buttons, corresponding to each of the strings that are provided. For example, if the value of this parameter is `[\"Incorrect\", \"Ambiguous\"]`, then buttons labeled **Flag as Incorrect** and **Flag as Ambiguous** appear. This only applies if `flagging_mode` is `\"manual\"`.\n - The chosen option is then logged along with the input and output.\n- `flagging_dir`: this parameter takes a string.\n - It represents what to name the directory where flagged data is stored.\n- `flagging_callback`: this parameter takes an instance of a subclass of the `FlaggingCallback` class\n - Using this parameter allows you to write custom code that gets run when the flag button is clicked\n - By default, this is set to an instance of `gr.JSONLogger`" }, { "id": 177, "parent": 174, "path": "10_other-tutorials/using-flagging.md", "level": 2, "title": "What happens to flagged data?", "content": "Within the directory provided by the `flagging_dir` argument, a JSON file will log the flagged data.\n\nHere's an example: The code below creates the calculator interface embedded below it:\n\n```python\nimport gradio as gr\n\n\ndef calculator(num1, operation, num2):\n if operation == \"add\":\n return num1 + num2\n elif operation == \"subtract\":\n return num1 - num2\n elif operation == \"multiply\":\n return num1 * num2\n elif operation == \"divide\":\n return num1 / num2\n\n\niface = gr.Interface(\n calculator,\n [\"number\", gr.Radio([\"add\", \"subtract\", \"multiply\", \"divide\"]), \"number\"],\n \"number\",\n allow_flagging=\"manual\"\n)\n\niface.launch()\n```\n\n\n\nWhen you click the flag button above, the directory where the interface was launched will include a new flagged subfolder, with a csv file inside it. This csv file includes all the data that was flagged.\n\n```directory\n+-- flagged/\n| +-- logs.csv\n```\n\n_flagged/logs.csv_\n\n```csv\nnum1,operation,num2,Output,timestamp\n5,add,7,12,2022-01-31 11:40:51.093412\n6,subtract,1.5,4.5,2022-01-31 03:25:32.023542\n```\n\nIf the interface involves file data, such as for Image and Audio components, folders will be created to store those flagged data as well. For example an `image` input to `image` output interface will create the following structure.\n\n```directory\n+-- flagged/\n| +-- logs.csv\n| +-- image/\n| | +-- 0.png\n| | +-- 1.png\n| +-- Output/\n| | +-- 0.png\n| | +-- 1.png\n```\n\n_flagged/logs.csv_\n\n```csv\nim,Output timestamp\nim/0.png,Output/0.png,2022-02-04 19:49:58.026963\nim/1.png,Output/1.png,2022-02-02 10:40:51.093412\n```\n\nIf you wish for the user to provide a reason for flagging, you can pass a list of strings to the `flagging_options` argument of Interface. Users will have to select one of these choices when flagging, and the option will be saved as an additional column to the CSV.\n\nIf we go back to the calculator example, the following code will create the interface embedded below it.\n\n```python\niface = gr.Interface(\n calculator,\n [\"number\", gr.Radio([\"add\", \"subtract\", \"multiply\", \"divide\"]), \"number\"],\n \"number\",\n flagging_mode=\"manual\",\n flagging_options=[\"wrong sign\", \"off by one\", \"other\"]\n)\n\niface.launch()\n```\n\n\n\nWhen users click the flag button, the csv file will now include a column indicating the selected option.\n\n_flagged/logs.csv_\n\n```csv\nnum1,operation,num2,Output,flag,timestamp\n5,add,7,-12,wrong sign,2022-02-04 11:40:51.093412\n6,subtract,1.5,3.5,off by one,2022-02-04 11:42:32.062512\n```" }, { "id": 178, "parent": 174, "path": "10_other-tutorials/using-flagging.md", "level": 2, "title": "Flagging with Blocks", "content": "What about if you are using `gradio.Blocks`? On one hand, you have even more flexibility\nwith Blocks -- you can write whatever Python code you want to run when a button is clicked,\nand assign that using the built-in events in Blocks.\n\nAt the same time, you might want to use an existing `FlaggingCallback` to avoid writing extra code.\nThis requires two steps:\n\n1. You have to run your callback's `.setup()` somewhere in the code prior to the\n first time you flag data\n2. When the flagging button is clicked, then you trigger the callback's `.flag()` method,\n making sure to collect the arguments correctly and disabling the typical preprocessing.\n\nHere is an example with an image sepia filter Blocks demo that lets you flag\ndata using the default `CSVLogger`:\n\n```py\nimport numpy as np\nimport gradio as gr\n\ndef sepia(input_img, strength):\n sepia_filter = strength * np.array(\n [[0.393, 0.769, 0.189], [0.349, 0.686, 0.168], [0.272, 0.534, 0.131]]\n ) + (1-strength) * np.identity(3)\n sepia_img = input_img.dot(sepia_filter.T)\n sepia_img /= sepia_img.max()\n return sepia_img\n\ncallback = gr.CSVLogger()\n\nwith gr.Blocks() as demo:\n with gr.Row():\n with gr.Column():\n img_input = gr.Image()\n strength = gr.Slider(0, 1, 0.5)\n img_output = gr.Image()\n with gr.Row():\n btn = gr.Button(\"Flag\")\n\n # This needs to be called at some point prior to the first call to callback.flag()\n callback.setup([img_input, strength, img_output], \"flagged_data_points\")\n\n img_input.change(sepia, [img_input, strength], img_output)\n strength.change(sepia, [img_input, strength], img_output)\n\n # We can choose which components to flag -- in this case, we'll flag all of them\n btn.click(lambda *args: callback.flag(list(args)), [img_input, strength, img_output], None, preprocess=False)\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n$demo_blocks_flag" }, { "id": 179, "parent": 174, "path": "10_other-tutorials/using-flagging.md", "level": 2, "title": "Privacy", "content": "Important Note: please make sure your users understand when the data they submit is being saved, and what you plan on doing with it. This is especially important when you use `flagging_mode=auto` (when all of the data submitted through the demo is being flagged)" }, { "id": 180, "parent": 179, "path": "10_other-tutorials/using-flagging.md", "level": 3, "title": "That's all! Happy building :)", "content": "" }, { "id": 181, "parent": null, "path": "10_other-tutorials/theming-guide.md", "level": 1, "title": "Theming", "content": "Tags: THEMES" }, { "id": 182, "parent": 181, "path": "10_other-tutorials/theming-guide.md", "level": 2, "title": "Introduction", "content": "Gradio features a built-in theming engine that lets you customize the look and feel of your app. You can choose from a variety of themes, or create your own. To do so, pass the `theme=` kwarg to the `Blocks` or `Interface` constructor. For example:\n\n```python\nwith gr.Blocks(theme=gr.themes.Soft()) as demo:\n ...\n```\n\n
\n\n
\n\nGradio comes with a set of prebuilt themes which you can load from `gr.themes.*`. These are:\n\n\n* `gr.themes.Base()` - the `\"base\"` theme sets the primary color to blue but otherwise has minimal styling, making it particularly useful as a base for creating new, custom themes.\n* `gr.themes.Default()` - the `\"default\"` Gradio 5 theme, with a vibrant orange primary color and gray secondary color.\n* `gr.themes.Origin()` - the `\"origin\"` theme is most similar to Gradio 4 styling. Colors, especially in light mode, are more subdued than the Gradio 5 default theme.\n* `gr.themes.Citrus()` - the `\"citrus\"` theme uses a yellow primary color, highlights form elements that are in focus, and includes fun 3D effects when buttons are clicked.\n* `gr.themes.Monochrome()` - the `\"monochrome\"` theme uses a black primary and white secondary color, and uses serif-style fonts, giving the appearance of a black-and-white newspaper. \n* `gr.themes.Soft()` - the `\"soft\"` theme uses a purpose primary color and white secondary color. It also increases the border radii and around buttons and form elements and highlights labels.\n* `gr.themes.Glass()` - the `\"glass\"` theme has a blue primary color and a transclucent gray secondary color. The theme also uses vertical gradients to create a glassy effect.\n* `gr.themes.Ocean()` - the `\"ocean\"` theme has a blue-green primary color and gray secondary color. The theme also uses horizontal gradients, especially for buttons and some form elements.\n\n\nEach of these themes set values for hundreds of CSS variables. You can use prebuilt themes as a starting point for your own custom themes, or you can create your own themes from scratch. Let's take a look at each approach." }, { "id": 183, "parent": 181, "path": "10_other-tutorials/theming-guide.md", "level": 2, "title": "Using the Theme Builder", "content": "The easiest way to build a theme is using the Theme Builder. To launch the Theme Builder locally, run the following code:\n\n```python\nimport gradio as gr\n\ngr.themes.builder()\n```\n\n$demo_theme_builder\n\nYou can use the Theme Builder running on Spaces above, though it runs much faster when you launch it locally via `gr.themes.builder()`.\n\nAs you edit the values in the Theme Builder, the app will preview updates in real time. You can download the code to generate the theme you've created so you can use it in any Gradio app.\n\nIn the rest of the guide, we will cover building themes programmatically." }, { "id": 184, "parent": 181, "path": "10_other-tutorials/theming-guide.md", "level": 2, "title": "Extending Themes via the Constructor", "content": "Although each theme has hundreds of CSS variables, the values for most these variables are drawn from 8 core variables which can be set through the constructor of each prebuilt theme. Modifying these 8 arguments allows you to quickly change the look and feel of your app." }, { "id": 185, "parent": 184, "path": "10_other-tutorials/theming-guide.md", "level": 3, "title": "Core Colors", "content": "The first 3 constructor arguments set the colors of the theme and are `gradio.themes.Color` objects. Internally, these Color objects hold brightness values for the palette of a single hue, ranging from 50, 100, 200..., 800, 900, 950. Other CSS variables are derived from these 3 colors.\n\nThe 3 color constructor arguments are:\n\n- `primary_hue`: This is the color draws attention in your theme. In the default theme, this is set to `gradio.themes.colors.orange`.\n- `secondary_hue`: This is the color that is used for secondary elements in your theme. In the default theme, this is set to `gradio.themes.colors.blue`.\n- `neutral_hue`: This is the color that is used for text and other neutral elements in your theme. In the default theme, this is set to `gradio.themes.colors.gray`.\n\nYou could modify these values using their string shortcuts, such as\n\n```python\nwith gr.Blocks(theme=gr.themes.Default(primary_hue=\"red\", secondary_hue=\"pink\")) as demo:\n ...\n```\n\nor you could use the `Color` objects directly, like this:\n\n```python\nwith gr.Blocks(theme=gr.themes.Default(primary_hue=gr.themes.colors.red, secondary_hue=gr.themes.colors.pink)) as demo:\n ...\n```\n\n
\n\n
\n\nPredefined colors are:\n\n- `slate`\n- `gray`\n- `zinc`\n- `neutral`\n- `stone`\n- `red`\n- `orange`\n- `amber`\n- `yellow`\n- `lime`\n- `green`\n- `emerald`\n- `teal`\n- `cyan`\n- `sky`\n- `blue`\n- `indigo`\n- `violet`\n- `purple`\n- `fuchsia`\n- `pink`\n- `rose`\n\nYou could also create your own custom `Color` objects and pass them in." }, { "id": 186, "parent": 184, "path": "10_other-tutorials/theming-guide.md", "level": 3, "title": "Core Sizing", "content": "The next 3 constructor arguments set the sizing of the theme and are `gradio.themes.Size` objects. Internally, these Size objects hold pixel size values that range from `xxs` to `xxl`. Other CSS variables are derived from these 3 sizes.\n\n- `spacing_size`: This sets the padding within and spacing between elements. In the default theme, this is set to `gradio.themes.sizes.spacing_md`.\n- `radius_size`: This sets the roundedness of corners of elements. In the default theme, this is set to `gradio.themes.sizes.radius_md`.\n- `text_size`: This sets the font size of text. In the default theme, this is set to `gradio.themes.sizes.text_md`.\n\nYou could modify these values using their string shortcuts, such as\n\n```python\nwith gr.Blocks(theme=gr.themes.Default(spacing_size=\"sm\", radius_size=\"none\")) as demo:\n ...\n```\n\nor you could use the `Size` objects directly, like this:\n\n```python\nwith gr.Blocks(theme=gr.themes.Default(spacing_size=gr.themes.sizes.spacing_sm, radius_size=gr.themes.sizes.radius_none)) as demo:\n ...\n```\n\n
\n\n
\n\nThe predefined size objects are:\n\n- `radius_none`\n- `radius_sm`\n- `radius_md`\n- `radius_lg`\n- `spacing_sm`\n- `spacing_md`\n- `spacing_lg`\n- `text_sm`\n- `text_md`\n- `text_lg`\n\nYou could also create your own custom `Size` objects and pass them in." }, { "id": 187, "parent": 184, "path": "10_other-tutorials/theming-guide.md", "level": 3, "title": "Core Fonts", "content": "The final 2 constructor arguments set the fonts of the theme. You can pass a list of fonts to each of these arguments to specify fallbacks. If you provide a string, it will be loaded as a system font. If you provide a `gradio.themes.GoogleFont`, the font will be loaded from Google Fonts.\n\n- `font`: This sets the primary font of the theme. In the default theme, this is set to `gradio.themes.GoogleFont(\"IBM Plex Sans\")`.\n- `font_mono`: This sets the monospace font of the theme. In the default theme, this is set to `gradio.themes.GoogleFont(\"IBM Plex Mono\")`.\n\nYou could modify these values such as the following:\n\n```python\nwith gr.Blocks(theme=gr.themes.Default(font=[gr.themes.GoogleFont(\"Inconsolata\"), \"Arial\", \"sans-serif\"])) as demo:\n ...\n```\n\n
\n\n
" }, { "id": 188, "parent": 181, "path": "10_other-tutorials/theming-guide.md", "level": 2, "title": "Extending Themes via `.set()`", "content": "You can also modify the values of CSS variables after the theme has been loaded. To do so, use the `.set()` method of the theme object to get access to the CSS variables. For example:\n\n```python\ntheme = gr.themes.Default(primary_hue=\"blue\").set(\n loader_color=\"#FF0000\",\n slider_color=\"#FF0000\",\n)\n\nwith gr.Blocks(theme=theme) as demo:\n ...\n```\n\nIn the example above, we've set the `loader_color` and `slider_color` variables to `#FF0000`, despite the overall `primary_color` using the blue color palette. You can set any CSS variable that is defined in the theme in this manner.\n\nYour IDE type hinting should help you navigate these variables. Since there are so many CSS variables, let's take a look at how these variables are named and organized." }, { "id": 189, "parent": 188, "path": "10_other-tutorials/theming-guide.md", "level": 3, "title": "CSS Variable Naming Conventions", "content": "CSS variable names can get quite long, like `button_primary_background_fill_hover_dark`! However they follow a common naming convention that makes it easy to understand what they do and to find the variable you're looking for. Separated by underscores, the variable name is made up of:\n\n1. The target element, such as `button`, `slider`, or `block`.\n2. The target element type or sub-element, such as `button_primary`, or `block_label`.\n3. The property, such as `button_primary_background_fill`, or `block_label_border_width`.\n4. Any relevant state, such as `button_primary_background_fill_hover`.\n5. If the value is different in dark mode, the suffix `_dark`. For example, `input_border_color_focus_dark`.\n\nOf course, many CSS variable names are shorter than this, such as `table_border_color`, or `input_shadow`." }, { "id": 190, "parent": 188, "path": "10_other-tutorials/theming-guide.md", "level": 3, "title": "CSS Variable Organization", "content": "Though there are hundreds of CSS variables, they do not all have to have individual values. They draw their values by referencing a set of core variables and referencing each other. This allows us to only have to modify a few variables to change the look and feel of the entire theme, while also getting finer control of individual elements that we may want to modify." }, { "id": 191, "parent": 190, "path": "10_other-tutorials/theming-guide.md", "level": 4, "title": "Referencing Core Variables", "content": "To reference one of the core constructor variables, precede the variable name with an asterisk. To reference a core color, use the `*primary_`, `*secondary_`, or `*neutral_` prefix, followed by the brightness value. For example:\n\n```python\ntheme = gr.themes.Default(primary_hue=\"blue\").set(\n button_primary_background_fill=\"*primary_200\",\n button_primary_background_fill_hover=\"*primary_300\",\n)\n```\n\nIn the example above, we've set the `button_primary_background_fill` and `button_primary_background_fill_hover` variables to `*primary_200` and `*primary_300`. These variables will be set to the 200 and 300 brightness values of the blue primary color palette, respectively.\n\nSimilarly, to reference a core size, use the `*spacing_`, `*radius_`, or `*text_` prefix, followed by the size value. For example:\n\n```python\ntheme = gr.themes.Default(radius_size=\"md\").set(\n button_primary_border_radius=\"*radius_xl\",\n)\n```\n\nIn the example above, we've set the `button_primary_border_radius` variable to `*radius_xl`. This variable will be set to the `xl` setting of the medium radius size range." }, { "id": 192, "parent": 190, "path": "10_other-tutorials/theming-guide.md", "level": 4, "title": "Referencing Other Variables", "content": "Variables can also reference each other. For example, look at the example below:\n\n```python\ntheme = gr.themes.Default().set(\n button_primary_background_fill=\"#FF0000\",\n button_primary_background_fill_hover=\"#FF0000\",\n button_primary_border=\"#FF0000\",\n)\n```\n\nHaving to set these values to a common color is a bit tedious. Instead, we can reference the `button_primary_background_fill` variable in the `button_primary_background_fill_hover` and `button_primary_border` variables, using a `*` prefix.\n\n```python\ntheme = gr.themes.Default().set(\n button_primary_background_fill=\"#FF0000\",\n button_primary_background_fill_hover=\"*button_primary_background_fill\",\n button_primary_border=\"*button_primary_background_fill\",\n)\n```\n\nNow, if we change the `button_primary_background_fill` variable, the `button_primary_background_fill_hover` and `button_primary_border` variables will automatically update as well.\n\nThis is particularly useful if you intend to share your theme - it makes it easy to modify the theme without having to change every variable.\n\nNote that dark mode variables automatically reference each other. For example:\n\n```python\ntheme = gr.themes.Default().set(\n button_primary_background_fill=\"#FF0000\",\n button_primary_background_fill_dark=\"#AAAAAA\",\n button_primary_border=\"*button_primary_background_fill\",\n button_primary_border_dark=\"*button_primary_background_fill_dark\",\n)\n```\n\n`button_primary_border_dark` will draw its value from `button_primary_background_fill_dark`, because dark mode always draw from the dark version of the variable." }, { "id": 193, "parent": 181, "path": "10_other-tutorials/theming-guide.md", "level": 2, "title": "Creating a Full Theme", "content": "Let's say you want to create a theme from scratch! We'll go through it step by step - you can also see the source of prebuilt themes in the gradio source repo for reference - [here's the source](https://github.com/gradio-app/gradio/blob/main/gradio/themes/monochrome.py) for the Monochrome theme.\n\nOur new theme class will inherit from `gradio.themes.Base`, a theme that sets a lot of convenient defaults. Let's make a simple demo that creates a dummy theme called Seafoam, and make a simple app that uses it.\n\n```py\nimport gradio as gr\nfrom gradio.themes.base import Base\nimport time\n\nclass Seafoam(Base):\n pass\n\nseafoam = Seafoam()\n\nwith gr.Blocks(theme=seafoam) as demo:\n textbox = gr.Textbox(label=\"Name\")\n slider = gr.Slider(label=\"Count\", minimum=0, maximum=100, step=1)\n with gr.Row():\n button = gr.Button(\"Submit\", variant=\"primary\")\n clear = gr.Button(\"Clear\")\n output = gr.Textbox(label=\"Output\")\n\n def repeat(name, count):\n time.sleep(3)\n return name * count\n\n button.click(repeat, [textbox, slider], output)\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n\n
\n\n
\n\nThe Base theme is very barebones, and uses `gr.themes.Blue` as it primary color - you'll note the primary button and the loading animation are both blue as a result. Let's change the defaults core arguments of our app. We'll overwrite the constructor and pass new defaults for the core constructor arguments.\n\nWe'll use `gr.themes.Emerald` as our primary color, and set secondary and neutral hues to `gr.themes.Blue`. We'll make our text larger using `text_lg`. We'll use `Quicksand` as our default font, loaded from Google Fonts.\n\n```py\nfrom __future__ import annotations\nfrom typing import Iterable\nimport gradio as gr\nfrom gradio.themes.base import Base\nfrom gradio.themes.utils import colors, fonts, sizes\nimport time\n\nclass Seafoam(Base):\n def __init__(\n self,\n *,\n primary_hue: colors.Color | str = colors.emerald,\n secondary_hue: colors.Color | str = colors.blue,\n neutral_hue: colors.Color | str = colors.gray,\n spacing_size: sizes.Size | str = sizes.spacing_md,\n radius_size: sizes.Size | str = sizes.radius_md,\n text_size: sizes.Size | str = sizes.text_lg,\n font: fonts.Font\n | str\n | Iterable[fonts.Font | str] = (\n fonts.GoogleFont(\"Quicksand\"),\n \"ui-sans-serif\",\n \"sans-serif\",\n ),\n font_mono: fonts.Font\n | str\n | Iterable[fonts.Font | str] = (\n fonts.GoogleFont(\"IBM Plex Mono\"),\n \"ui-monospace\",\n \"monospace\",\n ),\n ):\n super().__init__(\n primary_hue=primary_hue,\n secondary_hue=secondary_hue,\n neutral_hue=neutral_hue,\n spacing_size=spacing_size,\n radius_size=radius_size,\n text_size=text_size,\n font=font,\n font_mono=font_mono,\n )\n\nseafoam = Seafoam()\n\nwith gr.Blocks(theme=seafoam) as demo:\n textbox = gr.Textbox(label=\"Name\")\n slider = gr.Slider(label=\"Count\", minimum=0, maximum=100, step=1)\n with gr.Row():\n button = gr.Button(\"Submit\", variant=\"primary\")\n clear = gr.Button(\"Clear\")\n output = gr.Textbox(label=\"Output\")\n\n def repeat(name, count):\n time.sleep(3)\n return name * count\n\n button.click(repeat, [textbox, slider], output)\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n\n
\n\n
\n\nSee how the primary button and the loading animation are now green? These CSS variables are tied to the `primary_hue` variable.\n\nLet's modify the theme a bit more directly. We'll call the `set()` method to overwrite CSS variable values explicitly. We can use any CSS logic, and reference our core constructor arguments using the `*` prefix.\n\n```py\nfrom __future__ import annotations\nfrom typing import Iterable\nimport gradio as gr\nfrom gradio.themes.base import Base\nfrom gradio.themes.utils import colors, fonts, sizes\nimport time\n\nclass Seafoam(Base):\n def __init__(\n self,\n *,\n primary_hue: colors.Color | str = colors.emerald,\n secondary_hue: colors.Color | str = colors.blue,\n neutral_hue: colors.Color | str = colors.blue,\n spacing_size: sizes.Size | str = sizes.spacing_md,\n radius_size: sizes.Size | str = sizes.radius_md,\n text_size: sizes.Size | str = sizes.text_lg,\n font: fonts.Font\n | str\n | Iterable[fonts.Font | str] = (\n fonts.GoogleFont(\"Quicksand\"),\n \"ui-sans-serif\",\n \"sans-serif\",\n ),\n font_mono: fonts.Font\n | str\n | Iterable[fonts.Font | str] = (\n fonts.GoogleFont(\"IBM Plex Mono\"),\n \"ui-monospace\",\n \"monospace\",\n ),\n ):\n super().__init__(\n primary_hue=primary_hue,\n secondary_hue=secondary_hue,\n neutral_hue=neutral_hue,\n spacing_size=spacing_size,\n radius_size=radius_size,\n text_size=text_size,\n font=font,\n font_mono=font_mono,\n )\n super().set(\n body_background_fill=\"repeating-linear-gradient(45deg, *primary_200, *primary_200 10px, *primary_50 10px, *primary_50 20px)\",\n body_background_fill_dark=\"repeating-linear-gradient(45deg, *primary_800, *primary_800 10px, *primary_900 10px, *primary_900 20px)\",\n button_primary_background_fill=\"linear-gradient(90deg, *primary_300, *secondary_400)\",\n button_primary_background_fill_hover=\"linear-gradient(90deg, *primary_200, *secondary_300)\",\n button_primary_text_color=\"white\",\n button_primary_background_fill_dark=\"linear-gradient(90deg, *primary_600, *secondary_800)\",\n slider_color=\"*secondary_300\",\n slider_color_dark=\"*secondary_600\",\n block_title_text_weight=\"600\",\n block_border_width=\"3px\",\n block_shadow=\"*shadow_drop_lg\",\n button_primary_shadow=\"*shadow_drop_lg\",\n button_large_padding=\"32px\",\n )\n\nseafoam = Seafoam()\n\nwith gr.Blocks(theme=seafoam) as demo:\n textbox = gr.Textbox(label=\"Name\")\n slider = gr.Slider(label=\"Count\", minimum=0, maximum=100, step=1)\n with gr.Row():\n button = gr.Button(\"Submit\", variant=\"primary\")\n clear = gr.Button(\"Clear\")\n output = gr.Textbox(label=\"Output\")\n\n def repeat(name, count):\n time.sleep(3)\n return name * count\n\n button.click(repeat, [textbox, slider], output)\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n\n
\n\n
\n\nLook how fun our theme looks now! With just a few variable changes, our theme looks completely different.\n\nYou may find it helpful to explore the [source code of the other prebuilt themes](https://github.com/gradio-app/gradio/blob/main/gradio/themes) to see how they modified the base theme. You can also find your browser's Inspector useful to select elements from the UI and see what CSS variables are being used in the styles panel." }, { "id": 194, "parent": 181, "path": "10_other-tutorials/theming-guide.md", "level": 2, "title": "Sharing Themes", "content": "Once you have created a theme, you can upload it to the HuggingFace Hub to let others view it, use it, and build off of it!" }, { "id": 195, "parent": 194, "path": "10_other-tutorials/theming-guide.md", "level": 3, "title": "Uploading a Theme", "content": "There are two ways to upload a theme, via the theme class instance or the command line. We will cover both of them with the previously created `seafoam` theme.\n\n- Via the class instance\n\nEach theme instance has a method called `push_to_hub` we can use to upload a theme to the HuggingFace hub.\n\n```python\nseafoam.push_to_hub(repo_name=\"seafoam\",\n version=\"0.0.1\",\n\t\t\t\t\thf_token=\"\")\n```\n\n- Via the command line\n\nFirst save the theme to disk\n\n```python\nseafoam.dump(filename=\"seafoam.json\")\n```\n\nThen use the `upload_theme` command:\n\n```bash\nupload_theme\\\n\"seafoam.json\"\\\n\"seafoam\"\\\n--version \"0.0.1\"\\\n--hf_token \"\"\n```\n\nIn order to upload a theme, you must have a HuggingFace account and pass your [Access Token](https://huggingface.co/docs/huggingface_hub/quick-start#login)\nas the `hf_token` argument. However, if you log in via the [HuggingFace command line](https://huggingface.co/docs/huggingface_hub/quick-start#login) (which comes installed with `gradio`),\nyou can omit the `hf_token` argument.\n\nThe `version` argument lets you specify a valid [semantic version](https://www.geeksforgeeks.org/introduction-semantic-versioning/) string for your theme.\nThat way your users are able to specify which version of your theme they want to use in their apps. This also lets you publish updates to your theme without worrying\nabout changing how previously created apps look. The `version` argument is optional. If omitted, the next patch version is automatically applied." }, { "id": 196, "parent": 194, "path": "10_other-tutorials/theming-guide.md", "level": 3, "title": "Theme Previews", "content": "By calling `push_to_hub` or `upload_theme`, the theme assets will be stored in a [HuggingFace space](https://huggingface.co/docs/hub/spaces-overview).\n\nThe theme preview for our seafoam theme is here: [seafoam preview](https://huggingface.co/spaces/gradio/seafoam).\n\n
\n\n
" }, { "id": 197, "parent": 194, "path": "10_other-tutorials/theming-guide.md", "level": 3, "title": "Discovering Themes", "content": "The [Theme Gallery](https://huggingface.co/spaces/gradio/theme-gallery) shows all the public gradio themes. After publishing your theme,\nit will automatically show up in the theme gallery after a couple of minutes.\n\nYou can sort the themes by the number of likes on the space and from most to least recently created as well as toggling themes between light and dark mode.\n\n
\n\n
" }, { "id": 198, "parent": 194, "path": "10_other-tutorials/theming-guide.md", "level": 3, "title": "Downloading", "content": "To use a theme from the hub, use the `from_hub` method on the `ThemeClass` and pass it to your app:\n\n```python\nmy_theme = gr.Theme.from_hub(\"gradio/seafoam\")\n\nwith gr.Blocks(theme=my_theme) as demo:\n ....\n```\n\nYou can also pass the theme string directly to `Blocks` or `Interface` (`gr.Blocks(theme=\"gradio/seafoam\")`)\n\nYou can pin your app to an upstream theme version by using semantic versioning expressions.\n\nFor example, the following would ensure the theme we load from the `seafoam` repo was between versions `0.0.1` and `0.1.0`:\n\n```python\nwith gr.Blocks(theme=\"gradio/seafoam@>=0.0.1,<0.1.0\") as demo:\n ....\n```\n\nEnjoy creating your own themes! If you make one you're proud of, please share it with the world by uploading it to the hub!\nIf you tag us on [Twitter](https://twitter.com/gradio) we can give your theme a shout out!\n\n" }, { "id": 199, "parent": null, "path": "10_other-tutorials/01_using-hugging-face-integrations.md", "level": 1, "title": "Using Hugging Face Integrations", "content": "Related spaces: https://huggingface.co/spaces/gradio/en2es\nTags: HUB, SPACES, EMBED\n\nContributed by Omar Sanseviero 🦙" }, { "id": 200, "parent": 199, "path": "10_other-tutorials/01_using-hugging-face-integrations.md", "level": 2, "title": "Introduction", "content": "The Hugging Face Hub is a central platform that has hundreds of thousands of [models](https://huggingface.co/models), [datasets](https://huggingface.co/datasets) and [demos](https://huggingface.co/spaces) (also known as Spaces). \n\nGradio has multiple features that make it extremely easy to leverage existing models and Spaces on the Hub. This guide walks through these features." }, { "id": 201, "parent": 199, "path": "10_other-tutorials/01_using-hugging-face-integrations.md", "level": 2, "title": "Demos with the Hugging Face Inference Endpoints", "content": "Hugging Face has a service called [Serverless Inference Endpoints](https://huggingface.co/docs/api-inference/index), which allows you to send HTTP requests to models on the Hub. The API includes a generous free tier, and you can switch to [dedicated Inference Endpoints](https://huggingface.co/inference-endpoints/dedicated) when you want to use it in production. Gradio integrates directly with Serverless Inference Endpoints so that you can create a demo simply by specifying a model's name (e.g. `Helsinki-NLP/opus-mt-en-es`), like this:\n\n```python\nimport gradio as gr\n\ndemo = gr.load(\"Helsinki-NLP/opus-mt-en-es\", src=\"models\")\n\ndemo.launch()\n```\n\nFor any Hugging Face model supported in Inference Endpoints, Gradio automatically infers the expected input and output and make the underlying server calls, so you don't have to worry about defining the prediction function. \n\nNotice that we just put specify the model name and state that the `src` should be `models` (Hugging Face's Model Hub). There is no need to install any dependencies (except `gradio`) since you are not loading the model on your computer.\n\nYou might notice that the first inference takes a little bit longer. This happens since the Inference Endpoints is loading the model in the server. You get some benefits afterward:\n\n- The inference will be much faster.\n- The server caches your requests.\n- You get built-in automatic scaling." }, { "id": 202, "parent": 199, "path": "10_other-tutorials/01_using-hugging-face-integrations.md", "level": 2, "title": "Hosting your Gradio demos on Spaces", "content": "[Hugging Face Spaces](https://hf.co/spaces) allows anyone to host their Gradio demos freely, and uploading your Gradio demos take a couple of minutes. You can head to [hf.co/new-space](https://huggingface.co/new-space), select the Gradio SDK, create an `app.py` file, and voila! You have a demo you can share with anyone else. To learn more, read [this guide how to host on Hugging Face Spaces using the website](https://huggingface.co/blog/gradio-spaces).\n\nAlternatively, you can create a Space programmatically, making use of the [huggingface_hub client library](https://huggingface.co/docs/huggingface_hub/index) library. Here's an example:\n\n```python\nfrom huggingface_hub import (\n create_repo,\n get_full_repo_name,\n upload_file,\n)\ncreate_repo(name=target_space_name, token=hf_token, repo_type=\"space\", space_sdk=\"gradio\")\nrepo_name = get_full_repo_name(model_id=target_space_name, token=hf_token)\nfile_url = upload_file(\n path_or_fileobj=\"file.txt\",\n path_in_repo=\"app.py\",\n repo_id=repo_name,\n repo_type=\"space\",\n token=hf_token,\n)\n```\n\nHere, `create_repo` creates a gradio repo with the target name under a specific account using that account's Write Token. `repo_name` gets the full repo name of the related repo. Finally `upload_file` uploads a file inside the repo with the name `app.py`." }, { "id": 203, "parent": 199, "path": "10_other-tutorials/01_using-hugging-face-integrations.md", "level": 2, "title": "Loading demos from Spaces", "content": "You can also use and remix existing Gradio demos on Hugging Face Spaces. For example, you could take two existing Gradio demos on Spaces and put them as separate tabs and create a new demo. You can run this new demo locally, or upload it to Spaces, allowing endless possibilities to remix and create new demos!\n\nHere's an example that does exactly that:\n\n```python\nimport gradio as gr\n\nwith gr.Blocks() as demo:\n with gr.Tab(\"Translate to Spanish\"):\n gr.load(\"gradio/en2es\", src=\"spaces\")\n with gr.Tab(\"Translate to French\"):\n gr.load(\"abidlabs/en2fr\", src=\"spaces\")\n\ndemo.launch()\n```\n\nNotice that we use `gr.load()`, the same method we used to load models using Inference Endpoints. However, here we specify that the `src` is `spaces` (Hugging Face Spaces). \n\nNote: loading a Space in this way may result in slight differences from the original Space. In particular, any attributes that apply to the entire Blocks, such as the theme or custom CSS/JS, will not be loaded. You can copy these properties from the Space you are loading into your own `Blocks` object." }, { "id": 204, "parent": 199, "path": "10_other-tutorials/01_using-hugging-face-integrations.md", "level": 2, "title": "Demos with the `Pipeline` in `transformers`", "content": "Hugging Face's popular `transformers` library has a very easy-to-use abstraction, [`pipeline()`](https://huggingface.co/docs/transformers/v4.16.2/en/main_classes/pipelines#transformers.pipeline) that handles most of the complex code to offer a simple API for common tasks. By specifying the task and an (optional) model, you can build a demo around an existing model with few lines of Python:\n\n```python\nimport gradio as gr\n\nfrom transformers import pipeline\n\npipe = pipeline(\"translation\", model=\"Helsinki-NLP/opus-mt-en-es\")\n\ndef predict(text):\n return pipe(text)[0][\"translation_text\"]\n\ndemo = gr.Interface(\n fn=predict,\n inputs='text',\n outputs='text',\n)\n\ndemo.launch()\n```\n\nBut `gradio` actually makes it even easier to convert a `pipeline` to a demo, simply by using the `gradio.Interface.from_pipeline` methods, which skips the need to specify the input and output components:\n\n```python\nfrom transformers import pipeline\nimport gradio as gr\n\npipe = pipeline(\"translation\", model=\"Helsinki-NLP/opus-mt-en-es\")\n\ndemo = gr.Interface.from_pipeline(pipe)\ndemo.launch()\n```\n\nThe previous code produces the following interface, which you can try right here in your browser:\n\n" }, { "id": 205, "parent": 199, "path": "10_other-tutorials/01_using-hugging-face-integrations.md", "level": 2, "title": "Recap", "content": "That's it! Let's recap the various ways Gradio and Hugging Face work together:\n\n1. You can build a demo around Inference Endpoints without having to load the model, by using `gr.load()`.\n2. You host your Gradio demo on Hugging Face Spaces, either using the GUI or entirely in Python.\n3. You can load demos from Hugging Face Spaces to remix and create new Gradio demos using `gr.load()`.\n4. You can convert a `transformers` pipeline into a Gradio demo using `from_pipeline()`.\n\n🤗" }, { "id": 206, "parent": null, "path": "10_other-tutorials/named-entity-recognition.md", "level": 1, "title": "Named-Entity Recognition", "content": "Related spaces: https://huggingface.co/spaces/rajistics/biobert_ner_demo, https://huggingface.co/spaces/abidlabs/ner, https://huggingface.co/spaces/rajistics/Financial_Analyst_AI\nTags: NER, TEXT, HIGHLIGHT" }, { "id": 207, "parent": 206, "path": "10_other-tutorials/named-entity-recognition.md", "level": 2, "title": "Introduction", "content": "Named-entity recognition (NER), also known as token classification or text tagging, is the task of taking a sentence and classifying every word (or \"token\") into different categories, such as names of people or names of locations, or different parts of speech.\n\nFor example, given the sentence:\n\n> Does Chicago have any Pakistani restaurants?\n\nA named-entity recognition algorithm may identify:\n\n- \"Chicago\" as a **location**\n- \"Pakistani\" as an **ethnicity**\n\nand so on.\n\nUsing `gradio` (specifically the `HighlightedText` component), you can easily build a web demo of your NER model and share that with the rest of your team.\n\nHere is an example of a demo that you'll be able to build:\n\n$demo_ner_pipeline\n\nThis tutorial will show how to take a pretrained NER model and deploy it with a Gradio interface. We will show two different ways to use the `HighlightedText` component -- depending on your NER model, either of these two ways may be easier to learn!" }, { "id": 208, "parent": 207, "path": "10_other-tutorials/named-entity-recognition.md", "level": 3, "title": "Prerequisites", "content": "Make sure you have the `gradio` Python package already [installed](/getting_started). You will also need a pretrained named-entity recognition model. You can use your own, while in this tutorial, we will use one from the `transformers` library." }, { "id": 209, "parent": 207, "path": "10_other-tutorials/named-entity-recognition.md", "level": 3, "title": "Approach 1: List of Entity Dictionaries", "content": "Many named-entity recognition models output a list of dictionaries. Each dictionary consists of an _entity_, a \"start\" index, and an \"end\" index. This is, for example, how NER models in the `transformers` library operate:\n\n```py\nfrom transformers import pipeline\nner_pipeline = pipeline(\"ner\")\nner_pipeline(\"Does Chicago have any Pakistani restaurants\")\n```\n\nOutput:\n\n```bash\n[{'entity': 'I-LOC',\n 'score': 0.9988978,\n 'index': 2,\n 'word': 'Chicago',\n 'start': 5,\n 'end': 12},\n {'entity': 'I-MISC',\n 'score': 0.9958592,\n 'index': 5,\n 'word': 'Pakistani',\n 'start': 22,\n 'end': 31}]\n```\n\nIf you have such a model, it is very easy to hook it up to Gradio's `HighlightedText` component. All you need to do is pass in this **list of entities**, along with the **original text** to the model, together as dictionary, with the keys being `\"entities\"` and `\"text\"` respectively.\n\nHere is a complete example:\n\n```py\nfrom transformers import pipeline\n\nimport gradio as gr\n\nner_pipeline = pipeline(\"ner\")\n\nexamples = [\n \"Does Chicago have any stores and does Joe live here?\",\n]\n\ndef ner(text):\n output = ner_pipeline(text)\n return {\"text\": text, \"entities\": output}\n\ndemo = gr.Interface(ner,\n gr.Textbox(placeholder=\"Enter sentence here...\"),\n gr.HighlightedText(),\n examples=examples)\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n$demo_ner_pipeline" }, { "id": 210, "parent": 207, "path": "10_other-tutorials/named-entity-recognition.md", "level": 3, "title": "Approach 2: List of Tuples", "content": "An alternative way to pass data into the `HighlightedText` component is a list of tuples. The first element of each tuple should be the word or words that are being classified into a particular entity. The second element should be the entity label (or `None` if they should be unlabeled). The `HighlightedText` component automatically strings together the words and labels to display the entities.\n\nIn some cases, this can be easier than the first approach. Here is a demo showing this approach using Spacy's parts-of-speech tagger:\n\n```py\nimport gradio as gr\nimport os\nos.system('python -m spacy download en_core_web_sm')\nimport spacy\nfrom spacy import displacy\n\nnlp = spacy.load(\"en_core_web_sm\")\n\ndef text_analysis(text):\n doc = nlp(text)\n html = displacy.render(doc, style=\"dep\", page=True)\n html = (\n \"
\"\n + html\n + \"
\"\n )\n pos_count = {\n \"char_count\": len(text),\n \"token_count\": 0,\n }\n pos_tokens = []\n\n for token in doc:\n pos_tokens.extend([(token.text, token.pos_), (\" \", None)])\n\n return pos_tokens, pos_count, html\n\ndemo = gr.Interface(\n text_analysis,\n gr.Textbox(placeholder=\"Enter sentence here...\"),\n [\"highlight\", \"json\", \"html\"],\n examples=[\n [\"What a beautiful morning for a walk!\"],\n [\"It was the best of times, it was the worst of times.\"],\n ],\n)\n\ndemo.launch()\n\n```\n$demo_text_analysis\n\n---\n\nAnd you're done! That's all you need to know to build a web-based GUI for your NER model.\n\nFun tip: you can share your NER demo instantly with others simply by setting `share=True` in `launch()`." }, { "id": 211, "parent": null, "path": "10_other-tutorials/wrapping-layouts.md", "level": 1, "title": "Wrapping Layouts", "content": "Tags: LAYOUTS" }, { "id": 212, "parent": 211, "path": "10_other-tutorials/wrapping-layouts.md", "level": 2, "title": "Introduction", "content": "Gradio features [blocks](https://www.gradio.app/docs/blocks) to easily layout applications. To use this feature, you need to stack or nest layout components and create a hierarchy with them. This isn't difficult to implement and maintain for small projects, but after the project gets more complex, this component hierarchy becomes difficult to maintain and reuse.\n\nIn this guide, we are going to explore how we can wrap the layout classes to create more maintainable and easy-to-read applications without sacrificing flexibility." }, { "id": 213, "parent": 211, "path": "10_other-tutorials/wrapping-layouts.md", "level": 2, "title": "Example", "content": "We are going to follow the implementation from this Huggingface Space example:\n\n\n
" }, { "id": 214, "parent": 211, "path": "10_other-tutorials/wrapping-layouts.md", "level": 2, "title": "Implementation", "content": "The wrapping utility has two important classes. The first one is the ```LayoutBase``` class and the other one is the ```Application``` class.\n\nWe are going to look at the ```render``` and ```attach_event``` functions of them for brevity. You can look at the full implementation from [the example code](https://huggingface.co/spaces/WoWoWoWololo/wrapping-layouts/blob/main/app.py).\n\nSo let's start with the ```LayoutBase``` class." }, { "id": 215, "parent": 214, "path": "10_other-tutorials/wrapping-layouts.md", "level": 3, "title": "LayoutBase Class", "content": "1. Render Function\n\n Let's look at the ```render``` function in the ```LayoutBase``` class:\n\n```python" }, { "id": 216, "parent": null, "path": "10_other-tutorials/wrapping-layouts.md", "level": 1, "title": "other LayoutBase implementations", "content": "def render(self) -> None:\n with self.main_layout:\n for renderable in self.renderables:\n renderable.render()\n\n self.main_layout.render()\n```\nThis is a little confusing at first but if you consider the default implementation you can understand it easily.\nLet's look at an example:\n\nIn the default implementation, this is what we're doing:\n\n```python\nwith Row():\n left_textbox = Textbox(value=\"left_textbox\")\n right_textbox = Textbox(value=\"right_textbox\")\n```\n\nNow, pay attention to the Textbox variables. These variables' ```render``` parameter is true by default. So as we use the ```with``` syntax and create these variables, they are calling the ```render``` function under the ```with``` syntax.\n\nWe know the render function is called in the constructor with the implementation from the ```gradio.blocks.Block``` class:\n\n```python\nclass Block:\n # constructor parameters are omitted for brevity\n def __init__(self, ...):\n # other assign functions \n\n if render:\n self.render()\n```\n\nSo our implementation looks like this:\n\n```python" }, { "id": 217, "parent": null, "path": "10_other-tutorials/wrapping-layouts.md", "level": 1, "title": "self.main_layout -> Row()", "content": "with self.main_layout:\n left_textbox.render()\n right_textbox.render()\n```\n\nWhat this means is by calling the components' render functions under the ```with``` syntax, we are actually simulating the default implementation.\n\nSo now let's consider two nested ```with```s to see how the outer one works. For this, let's expand our example with the ```Tab``` component:\n\n```python\nwith Tab():\n with Row():\n first_textbox = Textbox(value=\"first_textbox\")\n second_textbox = Textbox(value=\"second_textbox\")\n```\n\nPay attention to the Row and Tab components this time. We have created the Textbox variables above and added them to Row with the ```with``` syntax. Now we need to add the Row component to the Tab component. You can see that the Row component is created with default parameters, so its render parameter is true, that's why the render function is going to be executed under the Tab component's ```with``` syntax.\n\nTo mimic this implementation, we need to call the ```render``` function of the ```main_layout``` variable after the ```with``` syntax of the ```main_layout``` variable.\n\nSo the implementation looks like this:\n\n```python\nwith tab_main_layout:\n with row_main_layout:\n first_textbox.render()\n second_textbox.render()\n\n row_main_layout.render()\n\ntab_main_layout.render()\n```\n\nThe default implementation and our implementation are the same, but we are using the render function ourselves. So it requires a little work.\n\nNow, let's take a look at the ```attach_event``` function.\n\n2. Attach Event Function\n\n The function is left as not implemented because it is specific to the class, so each class has to implement its `attach_event` function.\n\n```python\n # other LayoutBase implementations\n\n def attach_event(self, block_dict: Dict[str, Block]) -> None:\n raise NotImplementedError\n```\n\nCheck out the ```block_dict``` variable in the ```Application``` class's ```attach_event``` function." }, { "id": 218, "parent": 217, "path": "10_other-tutorials/wrapping-layouts.md", "level": 3, "title": "Application Class", "content": "1. Render Function\n\n```python\n # other Application implementations\n\n def _render(self):\n with self.app:\n for child in self.children:\n child.render()\n\n self.app.render()\n```\n\nFrom the explanation of the ```LayoutBase``` class's ```render``` function, we can understand the ```child.render``` part.\n\nSo let's look at the bottom part, why are we calling the ```app``` variable's ```render``` function? It's important to call this function because if we look at the implementation in the ```gradio.blocks.Blocks``` class, we can see that it is adding the components and event functions into the root component. To put it another way, it is creating and structuring the gradio application.\n\n2. Attach Event Function\n\n Let's see how we can attach events to components:\n\n```python\n # other Application implementations\n\n def _attach_event(self):\n block_dict: Dict[str, Block] = {}\n\n for child in self.children:\n block_dict.update(child.global_children_dict)\n\n with self.app:\n for child in self.children:\n try:\n child.attach_event(block_dict=block_dict)\n except NotImplementedError:\n print(f\"{child.name}'s attach_event is not implemented\")\n```\n\nYou can see why the ```global_children_list``` is used in the ```LayoutBase``` class from the example code. With this, all the components in the application are gathered into one dictionary, so the component can access all the components with their names.\n\nThe ```with``` syntax is used here again to attach events to components. If we look at the ```__exit__``` function in the ```gradio.blocks.Blocks``` class, we can see that it is calling the ```attach_load_events``` function which is used for setting event triggers to components. So we have to use the ```with``` syntax to trigger the ```__exit__``` function.\n\nOf course, we can call ```attach_load_events``` without using the ```with``` syntax, but the function needs a ```Context.root_block```, and it is set in the ```__enter__``` function. So we used the ```with``` syntax here rather than calling the function ourselves." }, { "id": 219, "parent": 217, "path": "10_other-tutorials/wrapping-layouts.md", "level": 2, "title": "Conclusion", "content": "In this guide, we saw\n\n- How we can wrap the layouts\n- How components are rendered\n- How we can structure our application with wrapped layout classes\n\nBecause the classes used in this guide are used for demonstration purposes, they may still not be totally optimized or modular. But that would make the guide much longer!\n\nI hope this guide helps you gain another view of the layout classes and gives you an idea about how you can use them for your needs. See the full implementation of our example [here](https://huggingface.co/spaces/WoWoWoWololo/wrapping-layouts/blob/main/app.py)." }, { "id": 220, "parent": null, "path": "10_other-tutorials/developing-faster-with-reload-mode.md", "level": 1, "title": "Developing Faster with Auto-Reloading", "content": "**Prerequisite**: This Guide requires you to know about Blocks. Make sure to [read the Guide to Blocks first](https://gradio.app/blocks-and-event-listeners).\n\nThis guide covers auto reloading, reloading in a Python IDE, and using gradio with Jupyter Notebooks." }, { "id": 221, "parent": 220, "path": "10_other-tutorials/developing-faster-with-reload-mode.md", "level": 2, "title": "Why Auto-Reloading?", "content": "When you are building a Gradio demo, particularly out of Blocks, you may find it cumbersome to keep re-running your code to test your changes.\n\nTo make it faster and more convenient to write your code, we've made it easier to \"reload\" your Gradio apps instantly when you are developing in a **Python IDE** (like VS Code, Sublime Text, PyCharm, or so on) or generally running your Python code from the terminal. We've also developed an analogous \"magic command\" that allows you to re-run cells faster if you use **Jupyter Notebooks** (or any similar environment like Colab).\n\nThis short Guide will cover both of these methods, so no matter how you write Python, you'll leave knowing how to build Gradio apps faster." }, { "id": 222, "parent": 220, "path": "10_other-tutorials/developing-faster-with-reload-mode.md", "level": 2, "title": "Python IDE Reload 🔥", "content": "If you are building Gradio Blocks using a Python IDE, your file of code (let's name it `run.py`) might look something like this:\n\n```python\nimport gradio as gr\n\nwith gr.Blocks() as demo:\n gr.Markdown(\"# Greetings from Gradio!\")\n inp = gr.Textbox(placeholder=\"What is your name?\")\n out = gr.Textbox()\n\n inp.change(fn=lambda x: f\"Welcome, {x}!\",\n inputs=inp,\n outputs=out)\n\nif __name__ == \"__main__\":\n demo.launch()\n```\n\nThe problem is that anytime that you want to make a change to your layout, events, or components, you have to close and rerun your app by writing `python run.py`.\n\nInstead of doing this, you can run your code in **reload mode** by changing 1 word: `python` to `gradio`:\n\nIn the terminal, run `gradio run.py`. That's it!\n\nNow, you'll see that after you'll see something like this:\n\n```bash\nWatching: '/Users/freddy/sources/gradio/gradio', '/Users/freddy/sources/gradio/demo/'\n\nRunning on local URL: http://127.0.0.1:7860\n```\n\nThe important part here is the line that says `Watching...` What's happening here is that Gradio will be observing the directory where `run.py` file lives, and if the file changes, it will automatically rerun the file for you. So you can focus on writing your code, and your Gradio demo will refresh automatically 🥳\n\nTip: the `gradio` command does not detect the parameters passed to the `launch()` methods because the `launch()` method is never called in reload mode. For example, setting `auth`, or `show_error` in `launch()` will not be reflected in the app.\n\nThere is one important thing to keep in mind when using the reload mode: Gradio specifically looks for a Gradio Blocks/Interface demo called `demo` in your code. If you have named your demo something else, you will need to pass in the name of your demo as the 2nd parameter in your code. So if your `run.py` file looked like this:\n\n```python\nimport gradio as gr\n\nwith gr.Blocks() as my_demo:\n gr.Markdown(\"# Greetings from Gradio!\")\n inp = gr.Textbox(placeholder=\"What is your name?\")\n out = gr.Textbox()\n\n inp.change(fn=lambda x: f\"Welcome, {x}!\",\n inputs=inp,\n outputs=out)\n\nif __name__ == \"__main__\":\n my_demo.launch()\n```\n\nThen you would launch it in reload mode like this: `gradio run.py --demo-name=my_demo`.\n\nBy default, the Gradio use UTF-8 encoding for scripts. **For reload mode**, If you are using encoding formats other than UTF-8 (such as cp1252), make sure you've done like this:\n\n1. Configure encoding declaration of python script, for example: `# -*- coding: cp1252 -*-`\n2. Confirm that your code editor has identified that encoding format. \n3. Run like this: `gradio run.py --encoding cp1252`\n\n🔥 If your application accepts command line arguments, you can pass them in as well. Here's an example:\n\n```python\nimport gradio as gr\nimport argparse\n\nparser = argparse.ArgumentParser()\nparser.add_argument(\"--name\", type=str, default=\"User\")\nargs, unknown = parser.parse_known_args()\n\nwith gr.Blocks() as demo:\n gr.Markdown(f\"# Greetings {args.name}!\")\n inp = gr.Textbox()\n out = gr.Textbox()\n\n inp.change(fn=lambda x: x, inputs=inp, outputs=out)\n\nif __name__ == \"__main__\":\n demo.launch()\n```\n\nWhich you could run like this: `gradio run.py --name Gretel`\n\nAs a small aside, this auto-reloading happens if you change your `run.py` source code or the Gradio source code. Meaning that this can be useful if you decide to [contribute to Gradio itself](https://github.com/gradio-app/gradio/blob/main/CONTRIBUTING.md) ✅" }, { "id": 223, "parent": 220, "path": "10_other-tutorials/developing-faster-with-reload-mode.md", "level": 2, "title": "Controlling the Reload 🎛️", "content": "By default, reload mode will re-run your entire script for every change you make.\nBut there are some cases where this is not desirable.\nFor example, loading a machine learning model should probably only happen once to save time. There are also some Python libraries that use C or Rust extensions that throw errors when they are reloaded, like `numpy` and `tiktoken`.\n\nIn these situations, you can place code that you do not want to be re-run inside an `if gr.NO_RELOAD:` codeblock. Here's an example of how you can use it to only load a transformers model once during the development process.\n\nTip: The value of `gr.NO_RELOAD` is `True`. So you don't have to change your script when you are done developing and want to run it in production. Simply run the file with `python` instead of `gradio`.\n\n```python\nimport gradio as gr\n\nif gr.NO_RELOAD:\n\tfrom transformers import pipeline\n\tpipe = pipeline(\"text-classification\", model=\"cardiffnlp/twitter-roberta-base-sentiment-latest\")\n\ndemo = gr.Interface(lambda s: pipe(s), gr.Textbox(), gr.Label())\n\nif __name__ == \"__main__\":\n demo.launch()\n```" }, { "id": 224, "parent": 220, "path": "10_other-tutorials/developing-faster-with-reload-mode.md", "level": 2, "title": "Jupyter Notebook Magic 🔮", "content": "What about if you use Jupyter Notebooks (or Colab Notebooks, etc.) to develop code? We got something for you too!\n\nWe've developed a **magic command** that will create and run a Blocks demo for you. To use this, load the gradio extension at the top of your notebook:\n\n`%load_ext gradio`\n\nThen, in the cell that you are developing your Gradio demo, simply write the magic command **`%%blocks`** at the top, and then write the layout and components like you would normally:\n\n```py\n%%blocks\n\nimport gradio as gr\n\nwith gr.Blocks() as demo:\n gr.Markdown(f\"# Greetings {args.name}!\")\n inp = gr.Textbox()\n out = gr.Textbox()\n\n inp.change(fn=lambda x: x, inputs=inp, outputs=out)\n```\n\nNotice that:\n\n- You do not need to launch your demo — Gradio does that for you automatically!\n\n- Every time you rerun the cell, Gradio will re-render your app on the same port and using the same underlying web server. This means you'll see your changes _much, much faster_ than if you were rerunning the cell normally.\n\nHere's what it looks like in a jupyter notebook:\n\n![](https://gradio-builds.s3.amazonaws.com/demo-files/jupyter_reload.gif)\n\n🪄 This works in colab notebooks too! [Here's a colab notebook](https://colab.research.google.com/drive/1zAuWoiTIb3O2oitbtVb2_ekv1K6ggtC1?usp=sharing) where you can see the Blocks magic in action. Try making some changes and re-running the cell with the Gradio code!\n\nThe Notebook Magic is now the author's preferred way of building Gradio demos. Regardless of how you write Python code, we hope either of these methods will give you a much better development experience using Gradio.\n\n---" }, { "id": 225, "parent": 220, "path": "10_other-tutorials/developing-faster-with-reload-mode.md", "level": 2, "title": "Next Steps", "content": "Now that you know how to develop quickly using Gradio, start building your own!\n\nIf you are looking for inspiration, try exploring demos other people have built with Gradio, [browse public Hugging Face Spaces](http://hf.space/) 🤗" }, { "id": 226, "parent": null, "path": "10_other-tutorials/creating-a-realtime-dashboard-from-google-sheets.md", "level": 1, "title": "Creating a Real-Time Dashboard from Google Sheets", "content": "Tags: TABULAR, DASHBOARD, PLOTS\n\n[Google Sheets](https://www.google.com/sheets/about/) are an easy way to store tabular data in the form of spreadsheets. With Gradio and pandas, it's easy to read data from public or private Google Sheets and then display the data or plot it. In this blog post, we'll build a small _real-time_ dashboard, one that updates when the data in the Google Sheets updates.\n\nBuilding the dashboard itself will just be 9 lines of Python code using Gradio, and our final dashboard will look like this:\n\n\n\n**Prerequisites**: This Guide uses [Gradio Blocks](/guides/quickstart/#blocks-more-flexibility-and-control), so make you are familiar with the Blocks class.\n\nThe process is a little different depending on if you are working with a publicly accessible or a private Google Sheet. We'll cover both, so let's get started!" }, { "id": 227, "parent": 226, "path": "10_other-tutorials/creating-a-realtime-dashboard-from-google-sheets.md", "level": 2, "title": "Public Google Sheets", "content": "Building a dashboard from a public Google Sheet is very easy, thanks to the [`pandas` library](https://pandas.pydata.org/):\n\n1\\. Get the URL of the Google Sheets that you want to use. To do this, simply go to the Google Sheets, click on the \"Share\" button in the top-right corner, and then click on the \"Get shareable link\" button. This will give you a URL that looks something like this:\n\n```html\nhttps://docs.google.com/spreadsheets/d/1UoKzzRzOCt-FXLLqDKLbryEKEgllGAQUEJ5qtmmQwpU/edit#gid=0\n```\n\n2\\. Now, let's modify this URL and then use it to read the data from the Google Sheets into a Pandas DataFrame. (In the code below, replace the `URL` variable with the URL of your public Google Sheet):\n\n```python\nimport pandas as pd\n\nURL = \"https://docs.google.com/spreadsheets/d/1UoKzzRzOCt-FXLLqDKLbryEKEgllGAQUEJ5qtmmQwpU/edit#gid=0\"\ncsv_url = URL.replace('/edit#gid=', '/export?format=csv&gid=')\n\ndef get_data():\n return pd.read_csv(csv_url)\n```\n\n3\\. The data query is a function, which means that it's easy to display it real-time using the `gr.DataFrame` component, or plot it real-time using the `gr.LinePlot` component (of course, depending on the data, a different plot may be appropriate). To do this, just pass the function into the respective components, and set the `every` parameter based on how frequently (in seconds) you would like the component to refresh. Here's the Gradio code:\n\n```python\nimport gradio as gr\n\nwith gr.Blocks() as demo:\n gr.Markdown(\"# 📈 Real-Time Line Plot\")\n with gr.Row():\n with gr.Column():\n gr.DataFrame(get_data, every=gr.Timer(5))\n with gr.Column():\n gr.LinePlot(get_data, every=gr.Timer(5), x=\"Date\", y=\"Sales\", y_title=\"Sales ($ millions)\", overlay_point=True, width=500, height=500)\n\ndemo.queue().launch() # Run the demo with queuing enabled\n```\n\nAnd that's it! You have a dashboard that refreshes every 5 seconds, pulling the data from your Google Sheet." }, { "id": 228, "parent": 226, "path": "10_other-tutorials/creating-a-realtime-dashboard-from-google-sheets.md", "level": 2, "title": "Private Google Sheets", "content": "For private Google Sheets, the process requires a little more work, but not that much! The key difference is that now, you must authenticate yourself to authorize access to the private Google Sheets." }, { "id": 229, "parent": 228, "path": "10_other-tutorials/creating-a-realtime-dashboard-from-google-sheets.md", "level": 3, "title": "Authentication", "content": "To authenticate yourself, obtain credentials from Google Cloud. Here's [how to set up google cloud credentials](https://developers.google.com/workspace/guides/create-credentials):\n\n1\\. First, log in to your Google Cloud account and go to the Google Cloud Console (https://console.cloud.google.com/)\n\n2\\. In the Cloud Console, click on the hamburger menu in the top-left corner and select \"APIs & Services\" from the menu. If you do not have an existing project, you will need to create one.\n\n3\\. Then, click the \"+ Enabled APIs & services\" button, which allows you to enable specific services for your project. Search for \"Google Sheets API\", click on it, and click the \"Enable\" button. If you see the \"Manage\" button, then Google Sheets is already enabled, and you're all set.\n\n4\\. In the APIs & Services menu, click on the \"Credentials\" tab and then click on the \"Create credentials\" button.\n\n5\\. In the \"Create credentials\" dialog, select \"Service account key\" as the type of credentials to create, and give it a name. **Note down the email of the service account**\n\n6\\. After selecting the service account, select the \"JSON\" key type and then click on the \"Create\" button. This will download the JSON key file containing your credentials to your computer. It will look something like this:\n\n```json\n{\n\t\"type\": \"service_account\",\n\t\"project_id\": \"your project\",\n\t\"private_key_id\": \"your private key id\",\n\t\"private_key\": \"private key\",\n\t\"client_email\": \"email\",\n\t\"client_id\": \"client id\",\n\t\"auth_uri\": \"https://accounts.google.com/o/oauth2/auth\",\n\t\"token_uri\": \"https://accounts.google.com/o/oauth2/token\",\n\t\"auth_provider_x509_cert_url\": \"https://www.googleapis.com/oauth2/v1/certs\",\n\t\"client_x509_cert_url\": \"https://www.googleapis.com/robot/v1/metadata/x509/email_id\"\n}\n```" }, { "id": 230, "parent": 228, "path": "10_other-tutorials/creating-a-realtime-dashboard-from-google-sheets.md", "level": 3, "title": "Querying", "content": "Once you have the credentials `.json` file, you can use the following steps to query your Google Sheet:\n\n1\\. Click on the \"Share\" button in the top-right corner of the Google Sheet. Share the Google Sheets with the email address of the service from Step 5 of authentication subsection (this step is important!). Then click on the \"Get shareable link\" button. This will give you a URL that looks something like this:\n\n```html\nhttps://docs.google.com/spreadsheets/d/1UoKzzRzOCt-FXLLqDKLbryEKEgllGAQUEJ5qtmmQwpU/edit#gid=0\n```\n\n2\\. Install the [`gspread` library](https://docs.gspread.org/en/v5.7.0/), which makes it easy to work with the [Google Sheets API](https://developers.google.com/sheets/api/guides/concepts) in Python by running in the terminal: `pip install gspread`\n\n3\\. Write a function to load the data from the Google Sheet, like this (replace the `URL` variable with the URL of your private Google Sheet):\n\n```python\nimport gspread\nimport pandas as pd" }, { "id": 231, "parent": null, "path": "10_other-tutorials/creating-a-realtime-dashboard-from-google-sheets.md", "level": 1, "title": "Authenticate with Google and get the sheet", "content": "URL = 'https://docs.google.com/spreadsheets/d/1_91Vps76SKOdDQ8cFxZQdgjTJiz23375sAT7vPvaj4k/edit#gid=0'\n\ngc = gspread.service_account(\"path/to/key.json\")\nsh = gc.open_by_url(URL)\nworksheet = sh.sheet1\n\ndef get_data():\n values = worksheet.get_all_values()\n df = pd.DataFrame(values[1:], columns=values[0])\n return df\n\n```\n\n4\\. The data query is a function, which means that it's easy to display it real-time using the `gr.DataFrame` component, or plot it real-time using the `gr.LinePlot` component (of course, depending on the data, a different plot may be appropriate). To do this, we just pass the function into the respective components, and set the `every` parameter based on how frequently (in seconds) we would like the component to refresh. Here's the Gradio code:\n\n```python\nimport gradio as gr\n\nwith gr.Blocks() as demo:\n gr.Markdown(\"# 📈 Real-Time Line Plot\")\n with gr.Row():\n with gr.Column():\n gr.DataFrame(get_data, every=gr.Timer(5))\n with gr.Column():\n gr.LinePlot(get_data, every=gr.Timer(5), x=\"Date\", y=\"Sales\", y_title=\"Sales ($ millions)\", overlay_point=True, width=500, height=500)\n\ndemo.queue().launch() # Run the demo with queuing enabled\n```\n\nYou now have a Dashboard that refreshes every 5 seconds, pulling the data from your Google Sheet." }, { "id": 232, "parent": 231, "path": "10_other-tutorials/creating-a-realtime-dashboard-from-google-sheets.md", "level": 2, "title": "Conclusion", "content": "And that's all there is to it! With just a few lines of code, you can use `gradio` and other libraries to read data from a public or private Google Sheet and then display and plot the data in a real-time dashboard." }, { "id": 233, "parent": null, "path": "10_other-tutorials/create-your-own-friends-with-a-gan.md", "level": 1, "title": "Create Your Own Friends with a GAN", "content": "Related spaces: https://huggingface.co/spaces/NimaBoscarino/cryptopunks, https://huggingface.co/spaces/nateraw/cryptopunks-generator\nTags: GAN, IMAGE, HUB\n\nContributed by Nima Boscarino and Nate Raw" }, { "id": 234, "parent": 233, "path": "10_other-tutorials/create-your-own-friends-with-a-gan.md", "level": 2, "title": "Introduction", "content": "It seems that cryptocurrencies, [NFTs](https://www.nytimes.com/interactive/2022/03/18/technology/nft-guide.html), and the web3 movement are all the rage these days! Digital assets are being listed on marketplaces for astounding amounts of money, and just about every celebrity is debuting their own NFT collection. While your crypto assets [may be taxable, such as in Canada](https://www.canada.ca/en/revenue-agency/programs/about-canada-revenue-agency-cra/compliance/digital-currency/cryptocurrency-guide.html), today we'll explore some fun and tax-free ways to generate your own assortment of procedurally generated [CryptoPunks](https://www.larvalabs.com/cryptopunks).\n\nGenerative Adversarial Networks, often known just as _GANs_, are a specific class of deep-learning models that are designed to learn from an input dataset to create (_generate!_) new material that is convincingly similar to elements of the original training set. Famously, the website [thispersondoesnotexist.com](https://thispersondoesnotexist.com/) went viral with lifelike, yet synthetic, images of people generated with a model called StyleGAN2. GANs have gained traction in the machine learning world, and are now being used to generate all sorts of images, text, and even [music](https://salu133445.github.io/musegan/)!\n\nToday we'll briefly look at the high-level intuition behind GANs, and then we'll build a small demo around a pre-trained GAN to see what all the fuss is about. Here's a [peek](https://nimaboscarino-cryptopunks.hf.space) at what we're going to be putting together." }, { "id": 235, "parent": 234, "path": "10_other-tutorials/create-your-own-friends-with-a-gan.md", "level": 3, "title": "Prerequisites", "content": "Make sure you have the `gradio` Python package already [installed](/getting_started). To use the pretrained model, also install `torch` and `torchvision`." }, { "id": 236, "parent": 233, "path": "10_other-tutorials/create-your-own-friends-with-a-gan.md", "level": 2, "title": "GANs: a very brief introduction", "content": "Originally proposed in [Goodfellow et al. 2014](https://arxiv.org/abs/1406.2661), GANs are made up of neural networks which compete with the intention of outsmarting each other. One network, known as the _generator_, is responsible for generating images. The other network, the _discriminator_, receives an image at a time from the generator along with a **real** image from the training data set. The discriminator then has to guess: which image is the fake?\n\nThe generator is constantly training to create images which are trickier for the discriminator to identify, while the discriminator raises the bar for the generator every time it correctly detects a fake. As the networks engage in this competitive (_adversarial!_) relationship, the images that get generated improve to the point where they become indistinguishable to human eyes!\n\nFor a more in-depth look at GANs, you can take a look at [this excellent post on Analytics Vidhya](https://www.analyticsvidhya.com/blog/2021/06/a-detailed-explanation-of-gan-with-implementation-using-tensorflow-and-keras/) or this [PyTorch tutorial](https://pytorch.org/tutorials/beginner/dcgan_faces_tutorial.html). For now, though, we'll dive into a demo!" }, { "id": 237, "parent": 233, "path": "10_other-tutorials/create-your-own-friends-with-a-gan.md", "level": 2, "title": "Step 1 — Create the Generator model", "content": "To generate new images with a GAN, you only need the generator model. There are many different architectures that the generator could use, but for this demo we'll use a pretrained GAN generator model with the following architecture:\n\n```python\nfrom torch import nn\n\nclass Generator(nn.Module):\n # Refer to the link below for explanations about nc, nz, and ngf\n # https://pytorch.org/tutorials/beginner/dcgan_faces_tutorial.html#inputs\n def __init__(self, nc=4, nz=100, ngf=64):\n super(Generator, self).__init__()\n self.network = nn.Sequential(\n nn.ConvTranspose2d(nz, ngf * 4, 3, 1, 0, bias=False),\n nn.BatchNorm2d(ngf * 4),\n nn.ReLU(True),\n nn.ConvTranspose2d(ngf * 4, ngf * 2, 3, 2, 1, bias=False),\n nn.BatchNorm2d(ngf * 2),\n nn.ReLU(True),\n nn.ConvTranspose2d(ngf * 2, ngf, 4, 2, 0, bias=False),\n nn.BatchNorm2d(ngf),\n nn.ReLU(True),\n nn.ConvTranspose2d(ngf, nc, 4, 2, 1, bias=False),\n nn.Tanh(),\n )\n\n def forward(self, input):\n output = self.network(input)\n return output\n```\n\nWe're taking the generator from [this repo by @teddykoker](https://github.com/teddykoker/cryptopunks-gan/blob/main/train.py#L90), where you can also see the original discriminator model structure.\n\nAfter instantiating the model, we'll load in the weights from the Hugging Face Hub, stored at [nateraw/cryptopunks-gan](https://huggingface.co/nateraw/cryptopunks-gan):\n\n```python\nfrom huggingface_hub import hf_hub_download\nimport torch\n\nmodel = Generator()\nweights_path = hf_hub_download('nateraw/cryptopunks-gan', 'generator.pth')\nmodel.load_state_dict(torch.load(weights_path, map_location=torch.device('cpu'))) # Use 'cuda' if you have a GPU available\n```" }, { "id": 238, "parent": 233, "path": "10_other-tutorials/create-your-own-friends-with-a-gan.md", "level": 2, "title": "Step 2 — Defining a `predict` function", "content": "The `predict` function is the key to making Gradio work! Whatever inputs we choose through the Gradio interface will get passed through our `predict` function, which should operate on the inputs and generate outputs that we can display with Gradio output components. For GANs it's common to pass random noise into our model as the input, so we'll generate a tensor of random numbers and pass that through the model. We can then use `torchvision`'s `save_image` function to save the output of the model as a `png` file, and return the file name:\n\n```python\nfrom torchvision.utils import save_image\n\ndef predict(seed):\n num_punks = 4\n torch.manual_seed(seed)\n z = torch.randn(num_punks, 100, 1, 1)\n punks = model(z)\n save_image(punks, \"punks.png\", normalize=True)\n return 'punks.png'\n```\n\nWe're giving our `predict` function a `seed` parameter, so that we can fix the random tensor generation with a seed. We'll then be able to reproduce punks if we want to see them again by passing in the same seed.\n\n_Note!_ Our model needs an input tensor of dimensions 100x1x1 to do a single inference, or (BatchSize)x100x1x1 for generating a batch of images. In this demo we'll start by generating 4 punks at a time." }, { "id": 239, "parent": 233, "path": "10_other-tutorials/create-your-own-friends-with-a-gan.md", "level": 2, "title": "Step 3 — Creating a Gradio interface", "content": "At this point you can even run the code you have with `predict()`, and you'll find your freshly generated punks in your file system at `./punks.png`. To make a truly interactive demo, though, we'll build out a simple interface with Gradio. Our goals here are to:\n\n- Set a slider input so users can choose the \"seed\" value\n- Use an image component for our output to showcase the generated punks\n- Use our `predict()` to take the seed and generate the images\n\nWith `gr.Interface()`, we can define all of that with a single function call:\n\n```python\nimport gradio as gr\n\ngr.Interface(\n predict,\n inputs=[\n gr.Slider(0, 1000, label='Seed', default=42),\n ],\n outputs=\"image\",\n).launch()\n```" }, { "id": 240, "parent": 233, "path": "10_other-tutorials/create-your-own-friends-with-a-gan.md", "level": 2, "title": "Step 4 — Even more punks!", "content": "Generating 4 punks at a time is a good start, but maybe we'd like to control how many we want to make each time. Adding more inputs to our Gradio interface is as simple as adding another item to the `inputs` list that we pass to `gr.Interface`:\n\n```python\ngr.Interface(\n predict,\n inputs=[\n gr.Slider(0, 1000, label='Seed', default=42),\n gr.Slider(4, 64, label='Number of Punks', step=1, default=10), # Adding another slider!\n ],\n outputs=\"image\",\n).launch()\n```\n\nThe new input will be passed to our `predict()` function, so we have to make some changes to that function to accept a new parameter:\n\n```python\ndef predict(seed, num_punks):\n torch.manual_seed(seed)\n z = torch.randn(num_punks, 100, 1, 1)\n punks = model(z)\n save_image(punks, \"punks.png\", normalize=True)\n return 'punks.png'\n```\n\nWhen you relaunch your interface, you should see a second slider that'll let you control the number of punks!" }, { "id": 241, "parent": 233, "path": "10_other-tutorials/create-your-own-friends-with-a-gan.md", "level": 2, "title": "Step 5 - Polishing it up", "content": "Your Gradio app is pretty much good to go, but you can add a few extra things to really make it ready for the spotlight ✨\n\nWe can add some examples that users can easily try out by adding this to the `gr.Interface`:\n\n```python\ngr.Interface(\n # ...\n # keep everything as it is, and then add\n examples=[[123, 15], [42, 29], [456, 8], [1337, 35]],\n).launch(cache_examples=True) # cache_examples is optional\n```\n\nThe `examples` parameter takes a list of lists, where each item in the sublists is ordered in the same order that we've listed the `inputs`. So in our case, `[seed, num_punks]`. Give it a try!\n\nYou can also try adding a `title`, `description`, and `article` to the `gr.Interface`. Each of those parameters accepts a string, so try it out and see what happens 👀 `article` will also accept HTML, as [explored in a previous guide](/guides/key-features/#descriptive-content)!\n\nWhen you're all done, you may end up with something like [this](https://nimaboscarino-cryptopunks.hf.space).\n\nFor reference, here is our full code:\n\n```python\nimport torch\nfrom torch import nn\nfrom huggingface_hub import hf_hub_download\nfrom torchvision.utils import save_image\nimport gradio as gr\n\nclass Generator(nn.Module):\n # Refer to the link below for explanations about nc, nz, and ngf\n # https://pytorch.org/tutorials/beginner/dcgan_faces_tutorial.html#inputs\n def __init__(self, nc=4, nz=100, ngf=64):\n super(Generator, self).__init__()\n self.network = nn.Sequential(\n nn.ConvTranspose2d(nz, ngf * 4, 3, 1, 0, bias=False),\n nn.BatchNorm2d(ngf * 4),\n nn.ReLU(True),\n nn.ConvTranspose2d(ngf * 4, ngf * 2, 3, 2, 1, bias=False),\n nn.BatchNorm2d(ngf * 2),\n nn.ReLU(True),\n nn.ConvTranspose2d(ngf * 2, ngf, 4, 2, 0, bias=False),\n nn.BatchNorm2d(ngf),\n nn.ReLU(True),\n nn.ConvTranspose2d(ngf, nc, 4, 2, 1, bias=False),\n nn.Tanh(),\n )\n\n def forward(self, input):\n output = self.network(input)\n return output\n\nmodel = Generator()\nweights_path = hf_hub_download('nateraw/cryptopunks-gan', 'generator.pth')\nmodel.load_state_dict(torch.load(weights_path, map_location=torch.device('cpu'))) # Use 'cuda' if you have a GPU available\n\ndef predict(seed, num_punks):\n torch.manual_seed(seed)\n z = torch.randn(num_punks, 100, 1, 1)\n punks = model(z)\n save_image(punks, \"punks.png\", normalize=True)\n return 'punks.png'\n\ngr.Interface(\n predict,\n inputs=[\n gr.Slider(0, 1000, label='Seed', default=42),\n gr.Slider(4, 64, label='Number of Punks', step=1, default=10),\n ],\n outputs=\"image\",\n examples=[[123, 15], [42, 29], [456, 8], [1337, 35]],\n).launch(cache_examples=True)\n```\n\n---\n\nCongratulations! You've built out your very own GAN-powered CryptoPunks generator, with a fancy Gradio interface that makes it easy for anyone to use. Now you can [scour the Hub for more GANs](https://huggingface.co/models?other=gan) (or train your own) and continue making even more awesome demos 🤗" }, { "id": 242, "parent": null, "path": "10_other-tutorials/setting-up-a-demo-for-maximum-performance.md", "level": 1, "title": "Setting Up a Demo for Maximum Performance", "content": "Tags: CONCURRENCY, LATENCY, PERFORMANCE\n\nLet's say that your Gradio demo goes _viral_ on social media -- you have lots of users trying it out simultaneously, and you want to provide your users with the best possible experience or, in other words, minimize the amount of time that each user has to wait in the queue to see their prediction.\n\nHow can you configure your Gradio demo to handle the most traffic? In this Guide, we dive into some of the parameters of Gradio's `.queue()` method as well as some other related parameters, and discuss how to set these parameters in a way that allows you to serve lots of users simultaneously with minimal latency.\n\nThis is an advanced guide, so make sure you know the basics of Gradio already, such as [how to create and launch a Gradio Interface](https://gradio.app/guides/quickstart/). Most of the information in this Guide is relevant whether you are hosting your demo on [Hugging Face Spaces](https://hf.space) or on your own server." }, { "id": 243, "parent": 242, "path": "10_other-tutorials/setting-up-a-demo-for-maximum-performance.md", "level": 2, "title": "Overview of Gradio's Queueing System", "content": "By default, every Gradio demo includes a built-in queuing system that scales to thousands of requests. When a user of your app submits a request (i.e. submits an input to your function), Gradio adds the request to the queue, and requests are processed in order, generally speaking (this is not exactly true, as discussed below). When the user's request has finished processing, the Gradio server returns the result back to the user using server-side events (SSE). The SSE protocol has several advantages over simply using HTTP POST requests: \n\n(1) They do not time out -- most browsers raise a timeout error if they do not get a response to a POST request after a short period of time (e.g. 1 min). This can be a problem if your inference function takes longer than 1 minute to run or if many people are trying out your demo at the same time, resulting in increased latency.\n\n(2) They allow the server to send multiple updates to the frontend. This means, for example, that the server can send a real-time ETA of how long your prediction will take to complete.\n\nTo configure the queue, simply call the `.queue()` method before launching an `Interface`, `TabbedInterface`, `ChatInterface` or any `Blocks`. Here's an example:\n\n```py\nimport gradio as gr\n\napp = gr.Interface(lambda x:x, \"image\", \"image\")\napp.queue() # <-- Sets up a queue with default parameters\napp.launch()\n```\n\n**How Requests are Processed from the Queue**\n\nWhen a Gradio server is launched, a pool of threads is used to execute requests from the queue. By default, the maximum size of this thread pool is `40` (which is the default inherited from FastAPI, on which the Gradio server is based). However, this does *not* mean that 40 requests are always processed in parallel from the queue. \n\nInstead, Gradio uses a **single-function-single-worker** model by default. This means that each worker thread is only assigned a single function from among all of the functions that could be part of your Gradio app. This ensures that you do not see, for example, out-of-memory errors, due to multiple workers calling a machine learning model at the same time. Suppose you have 3 functions in your Gradio app: A, B, and C. And you see the following sequence of 7 requests come in from users using your app:\n\n```\n1 2 3 4 5 6 7\n-------------\nA B A A C B A\n```\n\nInitially, 3 workers will get dispatched to handle requests 1, 2, and 5 (corresponding to functions: A, B, C). As soon as any of these workers finish, they will start processing the next function in the queue of the same function type, e.g. the worker that finished processing request 1 will start processing request 3, and so on.\n\nIf you want to change this behavior, there are several parameters that can be used to configure the queue and help reduce latency. Let's go through them one-by-one." }, { "id": 244, "parent": 243, "path": "10_other-tutorials/setting-up-a-demo-for-maximum-performance.md", "level": 3, "title": "The `default_concurrency_limit` parameter in `queue()`", "content": "The first parameter we will explore is the `default_concurrency_limit` parameter in `queue()`. This controls how many workers can execute the same event. By default, this is set to `1`, but you can set it to a higher integer: `2`, `10`, or even `None` (in the last case, there is no limit besides the total number of available workers). \n\nThis is useful, for example, if your Gradio app does not call any resource-intensive functions. If your app only queries external APIs, then you can set the `default_concurrency_limit` much higher. Increasing this parameter can **linearly multiply the capacity of your server to handle requests**.\n\nSo why not set this parameter much higher all the time? Keep in mind that since requests are processed in parallel, each request will consume memory to store the data and weights for processing. This means that you might get out-of-memory errors if you increase the `default_concurrency_limit` too high. You may also start to get diminishing returns if the `default_concurrency_limit` is too high because of costs of switching between different worker threads.\n\n**Recommendation**: Increase the `default_concurrency_limit` parameter as high as you can while you continue to see performance gains or until you hit memory limits on your machine. You can [read about Hugging Face Spaces machine specs here](https://huggingface.co/docs/hub/spaces-overview)." }, { "id": 245, "parent": 243, "path": "10_other-tutorials/setting-up-a-demo-for-maximum-performance.md", "level": 3, "title": "The `concurrency_limit` parameter in events", "content": "You can also set the number of requests that can be processed in parallel for each event individually. These take priority over the `default_concurrency_limit` parameter described previously.\n\nTo do this, set the `concurrency_limit` parameter of any event listener, e.g. `btn.click(..., concurrency_limit=20)` or in the `Interface` or `ChatInterface` classes: e.g. `gr.Interface(..., concurrency_limit=20)`. By default, this parameter is set to the global `default_concurrency_limit`." }, { "id": 246, "parent": 243, "path": "10_other-tutorials/setting-up-a-demo-for-maximum-performance.md", "level": 3, "title": "The `max_threads` parameter in `launch()`", "content": "If your demo uses non-async functions, e.g. `def` instead of `async def`, they will be run in a threadpool. This threadpool has a size of 40 meaning that only 40 threads can be created to run your non-async functions. If you are running into this limit, you can increase the threadpool size with `max_threads`. The default value is 40.\n\nTip: You should use async functions whenever possible to increase the number of concurrent requests your app can handle. Quick functions that are not CPU-bound are good candidates to be written as `async`. This [guide](https://fastapi.tiangolo.com/async/) is a good primer on the concept." }, { "id": 247, "parent": 243, "path": "10_other-tutorials/setting-up-a-demo-for-maximum-performance.md", "level": 3, "title": "The `max_size` parameter in `queue()`", "content": "A more blunt way to reduce the wait times is simply to prevent too many people from joining the queue in the first place. You can set the maximum number of requests that the queue processes using the `max_size` parameter of `queue()`. If a request arrives when the queue is already of the maximum size, it will not be allowed to join the queue and instead, the user will receive an error saying that the queue is full and to try again. By default, `max_size=None`, meaning that there is no limit to the number of users that can join the queue.\n\nParadoxically, setting a `max_size` can often improve user experience because it prevents users from being dissuaded by very long queue wait times. Users who are more interested and invested in your demo will keep trying to join the queue, and will be able to get their results faster.\n\n**Recommendation**: For a better user experience, set a `max_size` that is reasonable given your expectations of how long users might be willing to wait for a prediction." }, { "id": 248, "parent": 243, "path": "10_other-tutorials/setting-up-a-demo-for-maximum-performance.md", "level": 3, "title": "The `max_batch_size` parameter in events", "content": "Another way to increase the parallelism of your Gradio demo is to write your function so that it can accept **batches** of inputs. Most deep learning models can process batches of samples more efficiently than processing individual samples.\n\nIf you write your function to process a batch of samples, Gradio will automatically batch incoming requests together and pass them into your function as a batch of samples. You need to set `batch` to `True` (by default it is `False`) and set a `max_batch_size` (by default it is `4`) based on the maximum number of samples your function is able to handle. These two parameters can be passed into `gr.Interface()` or to an event in Blocks such as `.click()`.\n\nWhile setting a batch is conceptually similar to having workers process requests in parallel, it is often _faster_ than setting the `concurrency_count` for deep learning models. The downside is that you might need to adapt your function a little bit to accept batches of samples instead of individual samples.\n\nHere's an example of a function that does _not_ accept a batch of inputs -- it processes a single input at a time:\n\n```py\nimport time\n\ndef trim_words(word, length):\n return word[:int(length)]\n\n```\n\nHere's the same function rewritten to take in a batch of samples:\n\n```py\nimport time\n\ndef trim_words(words, lengths):\n trimmed_words = []\n for w, l in zip(words, lengths):\n trimmed_words.append(w[:int(l)])\n return [trimmed_words]\n\n```\n\nThe second function can be used with `batch=True` and an appropriate `max_batch_size` parameter.\n\n**Recommendation**: If possible, write your function to accept batches of samples, and then set `batch` to `True` and the `max_batch_size` as high as possible based on your machine's memory limits." }, { "id": 249, "parent": 242, "path": "10_other-tutorials/setting-up-a-demo-for-maximum-performance.md", "level": 2, "title": "Upgrading your Hardware (GPUs, TPUs, etc.)", "content": "If you have done everything above, and your demo is still not fast enough, you can upgrade the hardware that your model is running on. Changing the model from running on CPUs to running on GPUs will usually provide a 10x-50x increase in inference time for deep learning models.\n\nIt is particularly straightforward to upgrade your Hardware on Hugging Face Spaces. Simply click on the \"Settings\" tab in your Space and choose the Space Hardware you'd like.\n\n![](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/hub/spaces-gpu-settings.png)\n\nWhile you might need to adapt portions of your machine learning inference code to run on a GPU (here's a [handy guide](https://cnvrg.io/pytorch-cuda/) if you are using PyTorch), Gradio is completely agnostic to the choice of hardware and will work completely fine if you use it with CPUs, GPUs, TPUs, or any other hardware!\n\nNote: your GPU memory is different than your CPU memory, so if you upgrade your hardware,\nyou might need to adjust the value of the `default_concurrency_limit` parameter described above." }, { "id": 250, "parent": 242, "path": "10_other-tutorials/setting-up-a-demo-for-maximum-performance.md", "level": 2, "title": "Conclusion", "content": "Congratulations! You know how to set up a Gradio demo for maximum performance. Good luck on your next viral demo!" }, { "id": 251, "parent": null, "path": "10_other-tutorials/installing-gradio-in-a-virtual-environment.md", "level": 1, "title": "Installing Gradio in a Virtual Environment", "content": "Tags: INSTALLATION\n\nIn this guide, we will describe step-by-step how to install `gradio` within a virtual environment. This guide will cover both Windows and MacOS/Linux systems." }, { "id": 252, "parent": 251, "path": "10_other-tutorials/installing-gradio-in-a-virtual-environment.md", "level": 2, "title": "Virtual Environments", "content": "A virtual environment in Python is a self-contained directory that holds a Python installation for a particular version of Python, along with a number of additional packages. This environment is isolated from the main Python installation and other virtual environments. Each environment can have its own independent set of installed Python packages, which allows you to maintain different versions of libraries for different projects without conflicts.\n\n\nUsing virtual environments ensures that you can work on multiple Python projects on the same machine without any conflicts. This is particularly useful when different projects require different versions of the same library. It also simplifies dependency management and enhances reproducibility, as you can easily share the requirements of your project with others." }, { "id": 253, "parent": 251, "path": "10_other-tutorials/installing-gradio-in-a-virtual-environment.md", "level": 2, "title": "Installing Gradio on Windows", "content": "To install Gradio on a Windows system in a virtual environment, follow these steps:\n\n1. **Install Python**: Ensure you have Python 3.10 or higher installed. You can download it from [python.org](https://www.python.org/). You can verify the installation by running `python --version` or `python3 --version` in Command Prompt.\n\n\n2. **Create a Virtual Environment**:\n Open Command Prompt and navigate to your project directory. Then create a virtual environment using the following command:\n\n ```bash\n python -m venv gradio-env\n ```\n\n This command creates a new directory `gradio-env` in your project folder, containing a fresh Python installation.\n\n3. **Activate the Virtual Environment**:\n To activate the virtual environment, run:\n\n ```bash\n .\\gradio-env\\Scripts\\activate\n ```\n\n Your command prompt should now indicate that you are working inside `gradio-env`. Note: you can choose a different name than `gradio-env` for your virtual environment in this step.\n\n\n4. **Install Gradio**:\n Now, you can install Gradio using pip:\n\n ```bash\n pip install gradio\n ```\n\n5. **Verification**:\n To verify the installation, run `python` and then type:\n\n ```python\n import gradio as gr\n print(gr.__version__)\n ```\n\n This will display the installed version of Gradio." }, { "id": 254, "parent": 251, "path": "10_other-tutorials/installing-gradio-in-a-virtual-environment.md", "level": 2, "title": "Installing Gradio on MacOS/Linux", "content": "The installation steps on MacOS and Linux are similar to Windows but with some differences in commands.\n\n1. **Install Python**:\n Python usually comes pre-installed on MacOS and most Linux distributions. You can verify the installation by running `python --version` in the terminal (note that depending on how Python is installed, you might have to use `python3` instead of `python` throughout these steps). \n \n Ensure you have Python 3.10 or higher installed. If you do not have it installed, you can download it from [python.org](https://www.python.org/). \n\n2. **Create a Virtual Environment**:\n Open Terminal and navigate to your project directory. Then create a virtual environment using:\n\n ```bash\n python -m venv gradio-env\n ```\n\n Note: you can choose a different name than `gradio-env` for your virtual environment in this step.\n\n3. **Activate the Virtual Environment**:\n To activate the virtual environment on MacOS/Linux, use:\n\n ```bash\n source gradio-env/bin/activate\n ```\n\n4. **Install Gradio**:\n With the virtual environment activated, install Gradio using pip:\n\n ```bash\n pip install gradio\n ```\n\n5. **Verification**:\n To verify the installation, run `python` and then type:\n\n ```python\n import gradio as gr\n print(gr.__version__)\n ```\n\n This will display the installed version of Gradio.\n\nBy following these steps, you can successfully install Gradio in a virtual environment on your operating system, ensuring a clean and managed workspace for your Python projects." }, { "id": 255, "parent": null, "path": "10_other-tutorials/running-gradio-on-your-web-server-with-nginx.md", "level": 1, "title": "Running a Gradio App on your Web Server with Nginx", "content": "Tags: DEPLOYMENT, WEB SERVER, NGINX" }, { "id": 256, "parent": 255, "path": "10_other-tutorials/running-gradio-on-your-web-server-with-nginx.md", "level": 2, "title": "Introduction", "content": "Gradio is a Python library that allows you to quickly create customizable web apps for your machine learning models and data processing pipelines. Gradio apps can be deployed on [Hugging Face Spaces](https://hf.space) for free.\n\nIn some cases though, you might want to deploy a Gradio app on your own web server. You might already be using [Nginx](https://www.nginx.com/), a highly performant web server, to serve your website (say `https://www.example.com`), and you want to attach Gradio to a specific subpath on your website (e.g. `https://www.example.com/gradio-demo`).\n\nIn this Guide, we will guide you through the process of running a Gradio app behind Nginx on your own web server to achieve this.\n\n**Prerequisites**\n\n1. A Linux web server with [Nginx installed](https://www.nginx.com/blog/setting-up-nginx/) and [Gradio installed](/quickstart)\n2. A working Gradio app saved as a python file on your web server" }, { "id": 257, "parent": 255, "path": "10_other-tutorials/running-gradio-on-your-web-server-with-nginx.md", "level": 2, "title": "Editing your Nginx configuration file", "content": "1. Start by editing the Nginx configuration file on your web server. By default, this is located at: `/etc/nginx/nginx.conf`\n\nIn the `http` block, add the following line to include server block configurations from a separate file:\n\n```bash\ninclude /etc/nginx/sites-enabled/*;\n```\n\n2. Create a new file in the `/etc/nginx/sites-available` directory (create the directory if it does not already exist), using a filename that represents your app, for example: `sudo nano /etc/nginx/sites-available/my_gradio_app`\n\n3. Paste the following into your file editor:\n\n```bash\nserver {\n listen 80;\n server_name example.com www.example.com; # Change this to your domain name\n\n location /gradio-demo/ { # Change this if you'd like to server your Gradio app on a different path\n proxy_pass http://127.0.0.1:7860/; # Change this if your Gradio app will be running on a different port\n proxy_buffering off;\n proxy_redirect off;\n proxy_http_version 1.1;\n proxy_set_header Upgrade $http_upgrade;\n proxy_set_header Connection \"upgrade\";\n proxy_set_header Host $host;\n proxy_set_header X-Forwarded-Host $host;\n proxy_set_header X-Forwarded-Proto $scheme;\n }\n}\n```\n\n\nTip: Setting the `X-Forwarded-Host` and `X-Forwarded-Proto` headers is important as Gradio uses these, in conjunction with the `root_path` parameter discussed below, to construct the public URL that your app is being served on. Gradio uses the public URL to fetch various static assets. If these headers are not set, your Gradio app may load in a broken state.\n\n*Note:* The `$host` variable does not include the host port. If you are serving your Gradio application on a raw IP address and port, you should use the `$http_host` variable instead, in these lines:\n\n```bash\n proxy_set_header Host $host;\n proxy_set_header X-Forwarded-Host $host;\n```" }, { "id": 258, "parent": 255, "path": "10_other-tutorials/running-gradio-on-your-web-server-with-nginx.md", "level": 2, "title": "Run your Gradio app on your web server", "content": "1. Before you launch your Gradio app, you'll need to set the `root_path` to be the same as the subpath that you specified in your nginx configuration. This is necessary for Gradio to run on any subpath besides the root of the domain.\n\n *Note:* Instead of a subpath, you can also provide a complete URL for `root_path` (beginning with `http` or `https`) in which case the `root_path` is treated as an absolute URL instead of a URL suffix (but in this case, you'll need to update the `root_path` if the domain changes).\n\nHere's a simple example of a Gradio app with a custom `root_path` corresponding to the Nginx configuration above.\n\n```python\nimport gradio as gr\nimport time\n\ndef test(x):\ntime.sleep(4)\nreturn x\n\ngr.Interface(test, \"textbox\", \"textbox\").queue().launch(root_path=\"/gradio-demo\")\n```\n\n2. Start a `tmux` session by typing `tmux` and pressing enter (optional)\n\nIt's recommended that you run your Gradio app in a `tmux` session so that you can keep it running in the background easily\n\n3. Then, start your Gradio app. Simply type in `python` followed by the name of your Gradio python file. By default, your app will run on `localhost:7860`, but if it starts on a different port, you will need to update the nginx configuration file above." }, { "id": 259, "parent": 255, "path": "10_other-tutorials/running-gradio-on-your-web-server-with-nginx.md", "level": 2, "title": "Restart Nginx", "content": "1. If you are in a tmux session, exit by typing CTRL+B (or CMD+B), followed by the \"D\" key.\n\n2. Finally, restart nginx by running `sudo systemctl restart nginx`.\n\nAnd that's it! If you visit `https://example.com/gradio-demo` on your browser, you should see your Gradio app running there" }, { "id": 260, "parent": null, "path": "10_other-tutorials/creating-a-dashboard-from-supabase-data.md", "level": 1, "title": "Create a Dashboard from Supabase Data", "content": "Tags: TABULAR, DASHBOARD, PLOTS\n\n[Supabase](https://supabase.com/) is a cloud-based open-source backend that provides a PostgreSQL database, authentication, and other useful features for building web and mobile applications. In this tutorial, you will learn how to read data from Supabase and plot it in **real-time** on a Gradio Dashboard.\n\n**Prerequisites:** To start, you will need a free Supabase account, which you can sign up for here: [https://app.supabase.com/](https://app.supabase.com/)\n\nIn this end-to-end guide, you will learn how to:\n\n- Create tables in Supabase\n- Write data to Supabase using the Supabase Python Client\n- Visualize the data in a real-time dashboard using Gradio\n\nIf you already have data on Supabase that you'd like to visualize in a dashboard, you can skip the first two sections and go directly to [visualizing the data](#visualize-the-data-in-a-real-time-gradio-dashboard)!" }, { "id": 261, "parent": 260, "path": "10_other-tutorials/creating-a-dashboard-from-supabase-data.md", "level": 2, "title": "Create a table in Supabase", "content": "First of all, we need some data to visualize. Following this [excellent guide](https://supabase.com/blog/loading-data-supabase-python), we'll create fake commerce data and put it in Supabase.\n\n1\\. Start by creating a new project in Supabase. Once you're logged in, click the \"New Project\" button\n\n2\\. Give your project a name and database password. You can also choose a pricing plan (for our purposes, the Free Tier is sufficient!)\n\n3\\. You'll be presented with your API keys while the database spins up (can take up to 2 minutes).\n\n4\\. Click on \"Table Editor\" (the table icon) in the left pane to create a new table. We'll create a single table called `Product`, with the following schema:\n\n
\n\n\n\n\n\n
product_idint8
inventory_countint8
pricefloat8
product_namevarchar
\n
\n\n5\\. Click Save to save the table schema.\n\nOur table is now ready!" }, { "id": 262, "parent": 260, "path": "10_other-tutorials/creating-a-dashboard-from-supabase-data.md", "level": 2, "title": "Write data to Supabase", "content": "The next step is to write data to a Supabase dataset. We will use the Supabase Python library to do this.\n\n6\\. Install `supabase` by running the following command in your terminal:\n\n```bash\npip install supabase\n```\n\n7\\. Get your project URL and API key. Click the Settings (gear icon) on the left pane and click 'API'. The URL is listed in the Project URL box, while the API key is listed in Project API keys (with the tags `service_role`, `secret`)\n\n8\\. Now, run the following Python script to write some fake data to the table (note you have to put the values of `SUPABASE_URL` and `SUPABASE_SECRET_KEY` from step 7):\n\n```python\nimport supabase" }, { "id": 263, "parent": null, "path": "10_other-tutorials/creating-a-dashboard-from-supabase-data.md", "level": 1, "title": "Initialize the Supabase client", "content": "client = supabase.create_client('SUPABASE_URL', 'SUPABASE_SECRET_KEY')" }, { "id": 264, "parent": null, "path": "10_other-tutorials/creating-a-dashboard-from-supabase-data.md", "level": 1, "title": "Define the data to write", "content": "import random\n\nmain_list = []\nfor i in range(10):\n value = {'product_id': i,\n 'product_name': f\"Item {i}\",\n 'inventory_count': random.randint(1, 100),\n 'price': random.random()*100\n }\n main_list.append(value)" }, { "id": 265, "parent": null, "path": "10_other-tutorials/creating-a-dashboard-from-supabase-data.md", "level": 1, "title": "Write the data to the table", "content": "data = client.table('Product').insert(main_list).execute()\n```\n\nReturn to your Supabase dashboard and refresh the page, you should now see 10 rows populated in the `Product` table!" }, { "id": 266, "parent": 265, "path": "10_other-tutorials/creating-a-dashboard-from-supabase-data.md", "level": 2, "title": "Visualize the Data in a Real-Time Gradio Dashboard", "content": "Finally, we will read the data from the Supabase dataset using the same `supabase` Python library and create a realtime dashboard using `gradio`.\n\nNote: We repeat certain steps in this section (like creating the Supabase client) in case you did not go through the previous sections. As described in Step 7, you will need the project URL and API Key for your database.\n\n9\\. Write a function that loads the data from the `Product` table and returns it as a pandas Dataframe:\n\n```python\nimport supabase\nimport pandas as pd\n\nclient = supabase.create_client('SUPABASE_URL', 'SUPABASE_SECRET_KEY')\n\ndef read_data():\n response = client.table('Product').select(\"*\").execute()\n df = pd.DataFrame(response.data)\n return df\n```\n\n10\\. Create a small Gradio Dashboard with 2 Barplots that plots the prices and inventories of all of the items every minute and updates in real-time:\n\n```python\nimport gradio as gr\n\nwith gr.Blocks() as dashboard:\n with gr.Row():\n gr.BarPlot(read_data, x=\"product_id\", y=\"price\", title=\"Prices\", every=gr.Timer(60))\n gr.BarPlot(read_data, x=\"product_id\", y=\"inventory_count\", title=\"Inventory\", every=gr.Timer(60))\n\ndashboard.queue().launch()\n```\n\nNotice that by passing in a function to `gr.BarPlot()`, we have the BarPlot query the database as soon as the web app loads (and then again every 60 seconds because of the `every` parameter). Your final dashboard should look something like this:\n\n" }, { "id": 267, "parent": 265, "path": "10_other-tutorials/creating-a-dashboard-from-supabase-data.md", "level": 2, "title": "Conclusion", "content": "That's it! In this tutorial, you learned how to write data to a Supabase dataset, and then read that data and plot the results as bar plots. If you update the data in the Supabase database, you'll notice that the Gradio dashboard will update within a minute.\n\nTry adding more plots and visualizations to this example (or with a different dataset) to build a more complex dashboard!" }, { "id": 268, "parent": null, "path": "10_other-tutorials/how-to-use-3D-model-component.md", "level": 1, "title": "How to Use the 3D Model Component", "content": "Related spaces: https://huggingface.co/spaces/gradio/Model3D, https://huggingface.co/spaces/gradio/PIFu-Clothed-Human-Digitization, https://huggingface.co/spaces/gradio/dpt-depth-estimation-3d-obj\nTags: VISION, IMAGE" }, { "id": 269, "parent": 268, "path": "10_other-tutorials/how-to-use-3D-model-component.md", "level": 2, "title": "Introduction", "content": "3D models are becoming more popular in machine learning and make for some of the most fun demos to experiment with. Using `gradio`, you can easily build a demo of your 3D image model and share it with anyone. The Gradio 3D Model component accepts 3 file types including: _.obj_, _.glb_, & _.gltf_.\n\nThis guide will show you how to build a demo for your 3D image model in a few lines of code; like the one below. Play around with 3D object by clicking around, dragging and zooming:\n\n " }, { "id": 270, "parent": 269, "path": "10_other-tutorials/how-to-use-3D-model-component.md", "level": 3, "title": "Prerequisites", "content": "Make sure you have the `gradio` Python package already [installed](https://gradio.app/guides/quickstart)." }, { "id": 271, "parent": 268, "path": "10_other-tutorials/how-to-use-3D-model-component.md", "level": 2, "title": "Taking a Look at the Code", "content": "Let's take a look at how to create the minimal interface above. The prediction function in this case will just return the original 3D model mesh, but you can change this function to run inference on your machine learning model. We'll take a look at more complex examples below.\n\n```python\nimport gradio as gr\nimport os\n\n\ndef load_mesh(mesh_file_name):\n return mesh_file_name\n\n\ndemo = gr.Interface(\n fn=load_mesh,\n inputs=gr.Model3D(),\n outputs=gr.Model3D(\n clear_color=[0.0, 0.0, 0.0, 0.0], label=\"3D Model\"),\n examples=[\n [os.path.join(os.path.dirname(__file__), \"files/Bunny.obj\")],\n [os.path.join(os.path.dirname(__file__), \"files/Duck.glb\")],\n [os.path.join(os.path.dirname(__file__), \"files/Fox.gltf\")],\n [os.path.join(os.path.dirname(__file__), \"files/face.obj\")],\n ],\n)\n\nif __name__ == \"__main__\":\n demo.launch()\n```\n\nLet's break down the code above:\n\n`load_mesh`: This is our 'prediction' function and for simplicity, this function will take in the 3D model mesh and return it.\n\nCreating the Interface:\n\n- `fn`: the prediction function that is used when the user clicks submit. In our case this is the `load_mesh` function.\n- `inputs`: create a model3D input component. The input expects an uploaded file as a {str} filepath.\n- `outputs`: create a model3D output component. The output component also expects a file as a {str} filepath.\n - `clear_color`: this is the background color of the 3D model canvas. Expects RGBa values.\n - `label`: the label that appears on the top left of the component.\n- `examples`: list of 3D model files. The 3D model component can accept _.obj_, _.glb_, & _.gltf_ file types.\n- `cache_examples`: saves the predicted output for the examples, to save time on inference." }, { "id": 272, "parent": 268, "path": "10_other-tutorials/how-to-use-3D-model-component.md", "level": 2, "title": "Exploring a more complex Model3D Demo:", "content": "Below is a demo that uses the DPT model to predict the depth of an image and then uses 3D Point Cloud to create a 3D object. Take a look at the [app.py](https://huggingface.co/spaces/gradio/dpt-depth-estimation-3d-obj/blob/main/app.py) file for a peek into the code and the model prediction function.\n \n\n---\n\nAnd you're done! That's all the code you need to build an interface for your Model3D model. Here are some references that you may find useful:\n\n- Gradio's [\"Getting Started\" guide](https://gradio.app/getting_started/)\n- The first [3D Model Demo](https://huggingface.co/spaces/gradio/Model3D) and [complete code](https://huggingface.co/spaces/gradio/Model3D/tree/main) (on Hugging Face Spaces)" }, { "id": 273, "parent": null, "path": "10_other-tutorials/Gradio-and-ONNX-on-Hugging-Face.md", "level": 1, "title": "Gradio and ONNX on Hugging Face", "content": "Related spaces: https://huggingface.co/spaces/onnx/EfficientNet-Lite4\nTags: ONNX, SPACES\nContributed by Gradio and the ONNX team" }, { "id": 274, "parent": 273, "path": "10_other-tutorials/Gradio-and-ONNX-on-Hugging-Face.md", "level": 2, "title": "Introduction", "content": "In this Guide, we'll walk you through:\n\n- Introduction of ONNX, ONNX model zoo, Gradio, and Hugging Face Spaces\n- How to setup a Gradio demo for EfficientNet-Lite4\n- How to contribute your own Gradio demos for the ONNX organization on Hugging Face\n\nHere's an [example](https://onnx-efficientnet-lite4.hf.space/) of an ONNX model." }, { "id": 275, "parent": 273, "path": "10_other-tutorials/Gradio-and-ONNX-on-Hugging-Face.md", "level": 2, "title": "What is the ONNX Model Zoo?", "content": "Open Neural Network Exchange ([ONNX](https://onnx.ai/)) is an open standard format for representing machine learning models. ONNX is supported by a community of partners who have implemented it in many frameworks and tools. For example, if you have trained a model in TensorFlow or PyTorch, you can convert it to ONNX easily, and from there run it on a variety of devices using an engine/compiler like ONNX Runtime.\n\nThe [ONNX Model Zoo](https://github.com/onnx/models) is a collection of pre-trained, state-of-the-art models in the ONNX format contributed by community members. Accompanying each model are Jupyter notebooks for model training and running inference with the trained model. The notebooks are written in Python and include links to the training dataset as well as references to the original paper that describes the model architecture." }, { "id": 276, "parent": 273, "path": "10_other-tutorials/Gradio-and-ONNX-on-Hugging-Face.md", "level": 2, "title": "What are Hugging Face Spaces & Gradio?", "content": "" }, { "id": 277, "parent": 276, "path": "10_other-tutorials/Gradio-and-ONNX-on-Hugging-Face.md", "level": 3, "title": "Gradio", "content": "Gradio lets users demo their machine learning models as a web app all in python code. Gradio wraps a python function into a user interface and the demos can be launched inside jupyter notebooks, colab notebooks, as well as embedded in your own website and hosted on Hugging Face Spaces for free.\n\nGet started [here](https://gradio.app/getting_started)" }, { "id": 278, "parent": 276, "path": "10_other-tutorials/Gradio-and-ONNX-on-Hugging-Face.md", "level": 3, "title": "Hugging Face Spaces", "content": "Hugging Face Spaces is a free hosting option for Gradio demos. Spaces comes with 3 SDK options: Gradio, Streamlit and Static HTML demos. Spaces can be public or private and the workflow is similar to github repos. There are over 2000+ spaces currently on Hugging Face. Learn more about spaces [here](https://huggingface.co/spaces/launch)." }, { "id": 279, "parent": 276, "path": "10_other-tutorials/Gradio-and-ONNX-on-Hugging-Face.md", "level": 3, "title": "Hugging Face Models", "content": "Hugging Face Model Hub also supports ONNX models and ONNX models can be filtered through the [ONNX tag](https://huggingface.co/models?library=onnx&sort=downloads)" }, { "id": 280, "parent": 273, "path": "10_other-tutorials/Gradio-and-ONNX-on-Hugging-Face.md", "level": 2, "title": "How did Hugging Face help the ONNX Model Zoo?", "content": "There are a lot of Jupyter notebooks in the ONNX Model Zoo for users to test models. Previously, users needed to download the models themselves and run those notebooks locally for testing. With Hugging Face, the testing process can be much simpler and more user-friendly. Users can easily try certain ONNX Model Zoo model on Hugging Face Spaces and run a quick demo powered by Gradio with ONNX Runtime, all on cloud without downloading anything locally. Note, there are various runtimes for ONNX, e.g., [ONNX Runtime](https://github.com/microsoft/onnxruntime), [MXNet](https://github.com/apache/incubator-mxnet)." }, { "id": 281, "parent": 273, "path": "10_other-tutorials/Gradio-and-ONNX-on-Hugging-Face.md", "level": 2, "title": "What is the role of ONNX Runtime?", "content": "ONNX Runtime is a cross-platform inference and training machine-learning accelerator. It makes live Gradio demos with ONNX Model Zoo model on Hugging Face possible.\n\nONNX Runtime inference can enable faster customer experiences and lower costs, supporting models from deep learning frameworks such as PyTorch and TensorFlow/Keras as well as classical machine learning libraries such as scikit-learn, LightGBM, XGBoost, etc. ONNX Runtime is compatible with different hardware, drivers, and operating systems, and provides optimal performance by leveraging hardware accelerators where applicable alongside graph optimizations and transforms. For more information please see the [official website](https://onnxruntime.ai/)." }, { "id": 282, "parent": 273, "path": "10_other-tutorials/Gradio-and-ONNX-on-Hugging-Face.md", "level": 2, "title": "Setting up a Gradio Demo for EfficientNet-Lite4", "content": "EfficientNet-Lite 4 is the largest variant and most accurate of the set of EfficientNet-Lite models. It is an integer-only quantized model that produces the highest accuracy of all of the EfficientNet models. It achieves 80.4% ImageNet top-1 accuracy, while still running in real-time (e.g. 30ms/image) on a Pixel 4 CPU. To learn more read the [model card](https://github.com/onnx/models/tree/main/vision/classification/efficientnet-lite4)\n\nHere we walk through setting up a example demo for EfficientNet-Lite4 using Gradio\n\nFirst we import our dependencies and download and load the efficientnet-lite4 model from the onnx model zoo. Then load the labels from the labels_map.txt file. We then setup our preprocessing functions, load the model for inference, and setup the inference function. Finally, the inference function is wrapped into a gradio interface for a user to interact with. See the full code below.\n\n```python\nimport numpy as np\nimport math\nimport matplotlib.pyplot as plt\nimport cv2\nimport json\nimport gradio as gr\nfrom huggingface_hub import hf_hub_download\nfrom onnx import hub\nimport onnxruntime as ort" }, { "id": 283, "parent": null, "path": "10_other-tutorials/Gradio-and-ONNX-on-Hugging-Face.md", "level": 1, "title": "loads ONNX model from ONNX Model Zoo", "content": "model = hub.load(\"efficientnet-lite4\")" }, { "id": 284, "parent": null, "path": "10_other-tutorials/Gradio-and-ONNX-on-Hugging-Face.md", "level": 1, "title": "loads the labels text file", "content": "labels = json.load(open(\"labels_map.txt\", \"r\"))" }, { "id": 285, "parent": null, "path": "10_other-tutorials/Gradio-and-ONNX-on-Hugging-Face.md", "level": 1, "title": "sets image file dimensions to 224x224 by resizing and cropping image from center", "content": "def pre_process_edgetpu(img, dims):\n output_height, output_width, _ = dims\n img = resize_with_aspectratio(img, output_height, output_width, inter_pol=cv2.INTER_LINEAR)\n img = center_crop(img, output_height, output_width)\n img = np.asarray(img, dtype='float32')\n # converts jpg pixel value from [0 - 255] to float array [-1.0 - 1.0]\n img -= [127.0, 127.0, 127.0]\n img /= [128.0, 128.0, 128.0]\n return img" }, { "id": 286, "parent": null, "path": "10_other-tutorials/Gradio-and-ONNX-on-Hugging-Face.md", "level": 1, "title": "resizes the image with a proportional scale", "content": "def resize_with_aspectratio(img, out_height, out_width, scale=87.5, inter_pol=cv2.INTER_LINEAR):\n height, width, _ = img.shape\n new_height = int(100. * out_height / scale)\n new_width = int(100. * out_width / scale)\n if height > width:\n w = new_width\n h = int(new_height * height / width)\n else:\n h = new_height\n w = int(new_width * width / height)\n img = cv2.resize(img, (w, h), interpolation=inter_pol)\n return img" }, { "id": 287, "parent": null, "path": "10_other-tutorials/Gradio-and-ONNX-on-Hugging-Face.md", "level": 1, "title": "crops the image around the center based on given height and width", "content": "def center_crop(img, out_height, out_width):\n height, width, _ = img.shape\n left = int((width - out_width) / 2)\n right = int((width + out_width) / 2)\n top = int((height - out_height) / 2)\n bottom = int((height + out_height) / 2)\n img = img[top:bottom, left:right]\n return img\n\n\nsess = ort.InferenceSession(model)\n\ndef inference(img):\n img = cv2.imread(img)\n img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n\n img = pre_process_edgetpu(img, (224, 224, 3))\n\n img_batch = np.expand_dims(img, axis=0)\n\n results = sess.run([\"Softmax:0\"], {\"images:0\": img_batch})[0]\n result = reversed(results[0].argsort()[-5:])\n resultdic = {}\n for r in result:\n resultdic[labels[str(r)]] = float(results[0][r])\n return resultdic\n\ntitle = \"EfficientNet-Lite4\"\ndescription = \"EfficientNet-Lite 4 is the largest variant and most accurate of the set of EfficientNet-Lite model. It is an integer-only quantized model that produces the highest accuracy of all of the EfficientNet models. It achieves 80.4% ImageNet top-1 accuracy, while still running in real-time (e.g. 30ms/image) on a Pixel 4 CPU.\"\nexamples = [['catonnx.jpg']]\ngr.Interface(inference, gr.Image(type=\"filepath\"), \"label\", title=title, description=description, examples=examples).launch()\n```" }, { "id": 288, "parent": 287, "path": "10_other-tutorials/Gradio-and-ONNX-on-Hugging-Face.md", "level": 2, "title": "How to contribute Gradio demos on HF spaces using ONNX models", "content": "- Add model to the [onnx model zoo](https://github.com/onnx/models/blob/main/.github/PULL_REQUEST_TEMPLATE.md)\n- Create an account on Hugging Face [here](https://huggingface.co/join).\n- See list of models left to add to ONNX organization, please refer to the table with the [Models list](https://github.com/onnx/models#models)\n- Add Gradio Demo under your username, see this [blog post](https://huggingface.co/blog/gradio-spaces) for setting up Gradio Demo on Hugging Face.\n- Request to join ONNX Organization [here](https://huggingface.co/onnx).\n- Once approved transfer model from your username to ONNX organization\n- Add a badge for model in model table, see examples in [Models list](https://github.com/onnx/models#models)" }, { "id": 289, "parent": null, "path": "10_other-tutorials/plot-component-for-maps.md", "level": 1, "title": "How to Use the Plot Component for Maps", "content": "Tags: PLOTS, MAPS" }, { "id": 290, "parent": 289, "path": "10_other-tutorials/plot-component-for-maps.md", "level": 2, "title": "Introduction", "content": "This guide explains how you can use Gradio to plot geographical data on a map using the `gradio.Plot` component. The Gradio `Plot` component works with Matplotlib, Bokeh and Plotly. Plotly is what we will be working with in this guide. Plotly allows developers to easily create all sorts of maps with their geographical data. Take a look [here](https://plotly.com/python/maps/) for some examples." }, { "id": 291, "parent": 289, "path": "10_other-tutorials/plot-component-for-maps.md", "level": 2, "title": "Overview", "content": "We will be using the New York City Airbnb dataset, which is hosted on kaggle [here](https://www.kaggle.com/datasets/dgomonov/new-york-city-airbnb-open-data). I've uploaded it to the Hugging Face Hub as a dataset [here](https://huggingface.co/datasets/gradio/NYC-Airbnb-Open-Data) for easier use and download. Using this data we will plot Airbnb locations on a map output and allow filtering based on price and location. Below is the demo that we will be building. ⚡️\n\n$demo_map_airbnb" }, { "id": 292, "parent": 289, "path": "10_other-tutorials/plot-component-for-maps.md", "level": 2, "title": "Step 1 - Loading CSV data 💾", "content": "Let's start by loading the Airbnb NYC data from the Hugging Face Hub.\n\n```python\nfrom datasets import load_dataset\n\ndataset = load_dataset(\"gradio/NYC-Airbnb-Open-Data\", split=\"train\")\ndf = dataset.to_pandas()\n\ndef filter_map(min_price, max_price, boroughs):\n new_df = df[(df['neighbourhood_group'].isin(boroughs)) &\n (df['price'] > min_price) & (df['price'] < max_price)]\n names = new_df[\"name\"].tolist()\n prices = new_df[\"price\"].tolist()\n text_list = [(names[i], prices[i]) for i in range(0, len(names))]\n```\n\nIn the code above, we first load the csv data into a pandas dataframe. Let's begin by defining a function that we will use as the prediction function for the gradio app. This function will accept the minimum price and maximum price range as well as the list of boroughs to filter the resulting map. We can use the passed in values (`min_price`, `max_price`, and list of `boroughs`) to filter the dataframe and create `new_df`. Next we will create `text_list` of the names and prices of each Airbnb to use as labels on the map." }, { "id": 293, "parent": 289, "path": "10_other-tutorials/plot-component-for-maps.md", "level": 2, "title": "Step 2 - Map Figure 🌐", "content": "Plotly makes it easy to work with maps. Let's take a look below how we can create a map figure.\n\n```python\nimport plotly.graph_objects as go\n\nfig = go.Figure(go.Scattermapbox(\n customdata=text_list,\n lat=new_df['latitude'].tolist(),\n lon=new_df['longitude'].tolist(),\n mode='markers',\n marker=go.scattermapbox.Marker(\n size=6\n ),\n hoverinfo=\"text\",\n hovertemplate='Name: %{customdata[0]}
Price: $%{customdata[1]}'\n ))\n\nfig.update_layout(\n mapbox_style=\"open-street-map\",\n hovermode='closest',\n mapbox=dict(\n bearing=0,\n center=go.layout.mapbox.Center(\n lat=40.67,\n lon=-73.90\n ),\n pitch=0,\n zoom=9\n ),\n)\n```\n\nAbove, we create a scatter plot on mapbox by passing it our list of latitudes and longitudes to plot markers. We also pass in our custom data of names and prices for additional info to appear on every marker we hover over. Next we use `update_layout` to specify other map settings such as zoom, and centering.\n\nMore info [here](https://plotly.com/python/scattermapbox/) on scatter plots using Mapbox and Plotly." }, { "id": 294, "parent": 289, "path": "10_other-tutorials/plot-component-for-maps.md", "level": 2, "title": "Step 3 - Gradio App ⚡️", "content": "We will use two `gr.Number` components and a `gr.CheckboxGroup` to allow users of our app to specify price ranges and borough locations. We will then use the `gr.Plot` component as an output for our Plotly + Mapbox map we created earlier.\n\n```python\nwith gr.Blocks() as demo:\n with gr.Column():\n with gr.Row():\n min_price = gr.Number(value=250, label=\"Minimum Price\")\n max_price = gr.Number(value=1000, label=\"Maximum Price\")\n boroughs = gr.CheckboxGroup(choices=[\"Queens\", \"Brooklyn\", \"Manhattan\", \"Bronx\", \"Staten Island\"], value=[\"Queens\", \"Brooklyn\"], label=\"Select Boroughs:\")\n btn = gr.Button(value=\"Update Filter\")\n map = gr.Plot()\n demo.load(filter_map, [min_price, max_price, boroughs], map)\n btn.click(filter_map, [min_price, max_price, boroughs], map)\n```\n\nWe layout these components using the `gr.Column` and `gr.Row` and we'll also add event triggers for when the demo first loads and when our \"Update Filter\" button is clicked in order to trigger the map to update with our new filters.\n\nThis is what the full demo code looks like:\n\n```py\n# type: ignore\nimport gradio as gr\nimport plotly.graph_objects as go\nfrom datasets import load_dataset\n\ndataset = load_dataset(\"gradio/NYC-Airbnb-Open-Data\", split=\"train\")\ndf = dataset.to_pandas()\n\ndef filter_map(min_price, max_price, boroughs):\n\n filtered_df = df[(df['neighbourhood_group'].isin(boroughs)) &\n (df['price'] > min_price) & (df['price'] < max_price)]\n names = filtered_df[\"name\"].tolist()\n prices = filtered_df[\"price\"].tolist()\n text_list = [(names[i], prices[i]) for i in range(0, len(names))]\n fig = go.Figure(go.Scattermapbox(\n customdata=text_list,\n lat=filtered_df['latitude'].tolist(),\n lon=filtered_df['longitude'].tolist(),\n mode='markers',\n marker=go.scattermapbox.Marker(\n size=6\n ),\n hoverinfo=\"text\",\n hovertemplate='Name: %{customdata[0]}
Price: $%{customdata[1]}'\n ))\n\n fig.update_layout(\n mapbox_style=\"open-street-map\",\n hovermode='closest',\n mapbox=dict(\n bearing=0,\n center=go.layout.mapbox.Center(\n lat=40.67,\n lon=-73.90\n ),\n pitch=0,\n zoom=9\n ),\n )\n\n return fig\n\nwith gr.Blocks() as demo:\n with gr.Column():\n with gr.Row():\n min_price = gr.Number(value=250, label=\"Minimum Price\")\n max_price = gr.Number(value=1000, label=\"Maximum Price\")\n boroughs = gr.CheckboxGroup(choices=[\"Queens\", \"Brooklyn\", \"Manhattan\", \"Bronx\", \"Staten Island\"], value=[\"Queens\", \"Brooklyn\"], label=\"Select Boroughs:\")\n btn = gr.Button(value=\"Update Filter\")\n map = gr.Plot()\n demo.load(filter_map, [min_price, max_price, boroughs], map)\n btn.click(filter_map, [min_price, max_price, boroughs], map)\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```" }, { "id": 295, "parent": 289, "path": "10_other-tutorials/plot-component-for-maps.md", "level": 2, "title": "Step 4 - Deployment 🤗", "content": "If you run the code above, your app will start running locally.\nYou can even get a temporary shareable link by passing the `share=True` parameter to `launch`.\n\nBut what if you want to a permanent deployment solution?\nLet's deploy our Gradio app to the free HuggingFace Spaces platform.\n\nIf you haven't used Spaces before, follow the previous guide [here](/using_hugging_face_integrations)." }, { "id": 296, "parent": 289, "path": "10_other-tutorials/plot-component-for-maps.md", "level": 2, "title": "Conclusion 🎉", "content": "And you're all done! That's all the code you need to build a map demo.\n\nHere's a link to the demo [Map demo](https://huggingface.co/spaces/gradio/map_airbnb) and [complete code](https://huggingface.co/spaces/gradio/map_airbnb/blob/main/run.py) (on Hugging Face Spaces)" }, { "id": 297, "parent": null, "path": "10_other-tutorials/image-classification-with-vision-transformers.md", "level": 1, "title": "Image Classification with Vision Transformers", "content": "Related spaces: https://huggingface.co/spaces/abidlabs/vision-transformer\nTags: VISION, TRANSFORMERS, HUB" }, { "id": 298, "parent": 297, "path": "10_other-tutorials/image-classification-with-vision-transformers.md", "level": 2, "title": "Introduction", "content": "Image classification is a central task in computer vision. Building better classifiers to classify what object is present in a picture is an active area of research, as it has applications stretching from facial recognition to manufacturing quality control.\n\nState-of-the-art image classifiers are based on the _transformers_ architectures, originally popularized for NLP tasks. Such architectures are typically called vision transformers (ViT). Such models are perfect to use with Gradio's _image_ input component, so in this tutorial we will build a web demo to classify images using Gradio. We will be able to build the whole web application in a **single line of Python**, and it will look like the demo on the bottom of the page.\n\nLet's get started!" }, { "id": 299, "parent": 298, "path": "10_other-tutorials/image-classification-with-vision-transformers.md", "level": 3, "title": "Prerequisites", "content": "Make sure you have the `gradio` Python package already [installed](/getting_started)." }, { "id": 300, "parent": 297, "path": "10_other-tutorials/image-classification-with-vision-transformers.md", "level": 2, "title": "Step 1 — Choosing a Vision Image Classification Model", "content": "First, we will need an image classification model. For this tutorial, we will use a model from the [Hugging Face Model Hub](https://huggingface.co/models?pipeline_tag=image-classification). The Hub contains thousands of models covering dozens of different machine learning tasks.\n\nExpand the Tasks category on the left sidebar and select \"Image Classification\" as our task of interest. You will then see all of the models on the Hub that are designed to classify images.\n\nAt the time of writing, the most popular one is `google/vit-base-patch16-224`, which has been trained on ImageNet images at a resolution of 224x224 pixels. We will use this model for our demo." }, { "id": 301, "parent": 297, "path": "10_other-tutorials/image-classification-with-vision-transformers.md", "level": 2, "title": "Step 2 — Loading the Vision Transformer Model with Gradio", "content": "When using a model from the Hugging Face Hub, we do not need to define the input or output components for the demo. Similarly, we do not need to be concerned with the details of preprocessing or postprocessing.\nAll of these are automatically inferred from the model tags.\n\nBesides the import statement, it only takes a single line of Python to load and launch the demo.\n\nWe use the `gr.Interface.load()` method and pass in the path to the model including the `huggingface/` to designate that it is from the Hugging Face Hub.\n\n```python\nimport gradio as gr\n\ngr.Interface.load(\n \"huggingface/google/vit-base-patch16-224\",\n examples=[\"alligator.jpg\", \"laptop.jpg\"]).launch()\n```\n\nNotice that we have added one more parameter, the `examples`, which allows us to prepopulate our interfaces with a few predefined examples.\n\nThis produces the following interface, which you can try right here in your browser. When you input an image, it is automatically preprocessed and sent to the Hugging Face Hub API, where it is passed through the model and returned as a human-interpretable prediction. Try uploading your own image!\n\n\n\n---\n\nAnd you're done! In one line of code, you have built a web demo for an image classifier. If you'd like to share with others, try setting `share=True` when you `launch()` the Interface!" }, { "id": 302, "parent": null, "path": "10_other-tutorials/Gradio-and-Wandb-Integration.md", "level": 1, "title": "Gradio and W&B Integration", "content": "Related spaces: https://huggingface.co/spaces/akhaliq/JoJoGAN\nTags: WANDB, SPACES\nContributed by Gradio team" }, { "id": 303, "parent": 302, "path": "10_other-tutorials/Gradio-and-Wandb-Integration.md", "level": 2, "title": "Introduction", "content": "In this Guide, we'll walk you through:\n\n- Introduction of Gradio, and Hugging Face Spaces, and Wandb\n- How to setup a Gradio demo using the Wandb integration for JoJoGAN\n- How to contribute your own Gradio demos after tracking your experiments on wandb to the Wandb organization on Hugging Face" }, { "id": 304, "parent": 302, "path": "10_other-tutorials/Gradio-and-Wandb-Integration.md", "level": 2, "title": "What is Wandb?", "content": "Weights and Biases (W&B) allows data scientists and machine learning scientists to track their machine learning experiments at every stage, from training to production. Any metric can be aggregated over samples and shown in panels in a customizable and searchable dashboard, like below:\n\n\"Screen" }, { "id": 305, "parent": 302, "path": "10_other-tutorials/Gradio-and-Wandb-Integration.md", "level": 2, "title": "What are Hugging Face Spaces & Gradio?", "content": "" }, { "id": 306, "parent": 305, "path": "10_other-tutorials/Gradio-and-Wandb-Integration.md", "level": 3, "title": "Gradio", "content": "Gradio lets users demo their machine learning models as a web app, all in a few lines of Python. Gradio wraps any Python function (such as a machine learning model's inference function) into a user interface and the demos can be launched inside jupyter notebooks, colab notebooks, as well as embedded in your own website and hosted on Hugging Face Spaces for free.\n\nGet started [here](https://gradio.app/getting_started)" }, { "id": 307, "parent": 305, "path": "10_other-tutorials/Gradio-and-Wandb-Integration.md", "level": 3, "title": "Hugging Face Spaces", "content": "Hugging Face Spaces is a free hosting option for Gradio demos. Spaces comes with 3 SDK options: Gradio, Streamlit and Static HTML demos. Spaces can be public or private and the workflow is similar to github repos. There are over 2000+ spaces currently on Hugging Face. Learn more about spaces [here](https://huggingface.co/spaces/launch)." }, { "id": 308, "parent": 302, "path": "10_other-tutorials/Gradio-and-Wandb-Integration.md", "level": 2, "title": "Setting up a Gradio Demo for JoJoGAN", "content": "Now, let's walk you through how to do this on your own. We'll make the assumption that you're new to W&B and Gradio for the purposes of this tutorial.\n\nLet's get started!\n\n1. Create a W&B account\n\n Follow [these quick instructions](https://app.wandb.ai/login) to create your free account if you don’t have one already. It shouldn't take more than a couple minutes. Once you're done (or if you've already got an account), next, we'll run a quick colab.\n\n2. Open Colab Install Gradio and W&B\n\n We'll be following along with the colab provided in the JoJoGAN repo with some minor modifications to use Wandb and Gradio more effectively.\n\n [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/mchong6/JoJoGAN/blob/main/stylize.ipynb)\n\n Install Gradio and Wandb at the top:\n\n ```sh\n pip install gradio wandb\n ```\n\n3. Finetune StyleGAN and W&B experiment tracking\n\n This next step will open a W&B dashboard to track your experiments and a gradio panel showing pretrained models to choose from a drop down menu from a Gradio Demo hosted on Huggingface Spaces. Here's the code you need for that:\n\n ```python\n alpha = 1.0\n alpha = 1-alpha\n\n preserve_color = True\n num_iter = 100\n log_interval = 50\n\n samples = []\n column_names = [\"Reference (y)\", \"Style Code(w)\", \"Real Face Image(x)\"]\n\n wandb.init(project=\"JoJoGAN\")\n config = wandb.config\n config.num_iter = num_iter\n config.preserve_color = preserve_color\n wandb.log(\n {\"Style reference\": [wandb.Image(transforms.ToPILImage()(target_im))]},\n step=0)\n\n # load discriminator for perceptual loss\n discriminator = Discriminator(1024, 2).eval().to(device)\n ckpt = torch.load('models/stylegan2-ffhq-config-f.pt', map_location=lambda storage, loc: storage)\n discriminator.load_state_dict(ckpt[\"d\"], strict=False)\n\n # reset generator\n del generator\n generator = deepcopy(original_generator)\n\n g_optim = optim.Adam(generator.parameters(), lr=2e-3, betas=(0, 0.99))\n\n # Which layers to swap for generating a family of plausible real images -> fake image\n if preserve_color:\n id_swap = [9,11,15,16,17]\n else:\n id_swap = list(range(7, generator.n_latent))\n\n for idx in tqdm(range(num_iter)):\n mean_w = generator.get_latent(torch.randn([latents.size(0), latent_dim]).to(device)).unsqueeze(1).repeat(1, generator.n_latent, 1)\n in_latent = latents.clone()\n in_latent[:, id_swap] = alpha*latents[:, id_swap] + (1-alpha)*mean_w[:, id_swap]\n\n img = generator(in_latent, input_is_latent=True)\n\n with torch.no_grad():\n real_feat = discriminator(targets)\n fake_feat = discriminator(img)\n\n loss = sum([F.l1_loss(a, b) for a, b in zip(fake_feat, real_feat)])/len(fake_feat)\n\n wandb.log({\"loss\": loss}, step=idx)\n if idx % log_interval == 0:\n generator.eval()\n my_sample = generator(my_w, input_is_latent=True)\n generator.train()\n my_sample = transforms.ToPILImage()(utils.make_grid(my_sample, normalize=True, range=(-1, 1)))\n wandb.log(\n {\"Current stylization\": [wandb.Image(my_sample)]},\n step=idx)\n table_data = [\n wandb.Image(transforms.ToPILImage()(target_im)),\n wandb.Image(img),\n wandb.Image(my_sample),\n ]\n samples.append(table_data)\n\n g_optim.zero_grad()\n loss.backward()\n g_optim.step()\n\n out_table = wandb.Table(data=samples, columns=column_names)\n wandb.log({\"Current Samples\": out_table})\n ```\n4. Save, Download, and Load Model\n\n Here's how to save and download your model.\n\n ```python\n from PIL import Image\n import torch\n torch.backends.cudnn.benchmark = True\n from torchvision import transforms, utils\n from util import *\n import math\n import random\n import numpy as np\n from torch import nn, autograd, optim\n from torch.nn import functional as F\n from tqdm import tqdm\n import lpips\n from model import *\n from e4e_projection import projection as e4e_projection\n \n from copy import deepcopy\n import imageio\n \n import os\n import sys\n import torchvision.transforms as transforms\n from argparse import Namespace\n from e4e.models.psp import pSp\n from util import *\n from huggingface_hub import hf_hub_download\n from google.colab import files\n \n torch.save({\"g\": generator.state_dict()}, \"your-model-name.pt\")\n \n files.download('your-model-name.pt')\n \n latent_dim = 512\n device=\"cuda\"\n model_path_s = hf_hub_download(repo_id=\"akhaliq/jojogan-stylegan2-ffhq-config-f\", filename=\"stylegan2-ffhq-config-f.pt\")\n original_generator = Generator(1024, latent_dim, 8, 2).to(device)\n ckpt = torch.load(model_path_s, map_location=lambda storage, loc: storage)\n original_generator.load_state_dict(ckpt[\"g_ema\"], strict=False)\n mean_latent = original_generator.mean_latent(10000)\n \n generator = deepcopy(original_generator)\n \n ckpt = torch.load(\"/content/JoJoGAN/your-model-name.pt\", map_location=lambda storage, loc: storage)\n generator.load_state_dict(ckpt[\"g\"], strict=False)\n generator.eval()\n \n plt.rcParams['figure.dpi'] = 150\n \n transform = transforms.Compose(\n [\n transforms.Resize((1024, 1024)),\n transforms.ToTensor(),\n transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)),\n ]\n )\n \n def inference(img):\n img.save('out.jpg')\n aligned_face = align_face('out.jpg')\n \n my_w = e4e_projection(aligned_face, \"out.pt\", device).unsqueeze(0)\n with torch.no_grad():\n my_sample = generator(my_w, input_is_latent=True)\n \n npimage = my_sample[0].cpu().permute(1, 2, 0).detach().numpy()\n imageio.imwrite('filename.jpeg', npimage)\n return 'filename.jpeg'\n ````\n\n5. Build a Gradio Demo\n\n ```python\n import gradio as gr\n \n title = \"JoJoGAN\"\n description = \"Gradio Demo for JoJoGAN: One Shot Face Stylization. To use it, simply upload your image, or click one of the examples to load them. Read more at the links below.\"\n \n demo = gr.Interface(\n inference,\n gr.Image(type=\"pil\"),\n gr.Image(type=\"file\"),\n title=title,\n description=description\n )\n \n demo.launch(share=True)\n ```\n\n6. Integrate Gradio into your W&B Dashboard\n\n The last step—integrating your Gradio demo with your W&B dashboard—is just one extra line:\n\n ```python\n demo.integrate(wandb=wandb)\n ```\n\n Once you call integrate, a demo will be created and you can integrate it into your dashboard or report.\n\n Outside of W&B with Web components, using the `gradio-app` tags, anyone can embed Gradio demos on HF spaces directly into their blogs, websites, documentation, etc.:\n \n ```html\n \n ```\n\n7. (Optional) Embed W&B plots in your Gradio App\n\n It's also possible to embed W&B plots within Gradio apps. To do so, you can create a W&B Report of your plots and\n embed them within your Gradio app within a `gr.HTML` block.\n\n The Report will need to be public and you will need to wrap the URL within an iFrame like this:\n\n ```python\n import gradio as gr\n \n def wandb_report(url):\n iframe = f'\n\nIf you are permanently hosting your Gradio application, you can embed the UI using the Gradio Panel Extended custom Panel.\n\nGo to your Comet Project page, and head over to the Panels tab. Click the `+ Add` button to bring up the Panels search page.\n\n\"adding-panels\"\n\nNext, search for Gradio Panel Extended in the Public Panels section and click `Add`.\n\n\"gradio-panel-extended\"\n\nOnce you have added your Panel, click `Edit` to access to the Panel Options page and paste in the URL of your Gradio application.\n\n![Edit-Gradio-Panel-Options](https://user-images.githubusercontent.com/7529846/214573001-23814b5a-ca65-4ace-a8a5-b27cdda70f7a.gif)\n\n\"Edit-Gradio-Panel-URL\"" }, { "id": 339, "parent": 337, "path": "10_other-tutorials/Gradio-and-Comet.md", "level": 2, "title": "3. Embedding Hugging Face Spaces directly into your Comet Projects", "content": "\n\nYou can also embed Gradio Applications that are hosted on Hugging Faces Spaces into your Comet Projects using the Hugging Face Spaces Panel.\n\nGo to your Comet Project page, and head over to the Panels tab. Click the `+ Add` button to bring up the Panels search page. Next, search for the Hugging Face Spaces Panel in the Public Panels section and click `Add`.\n\n\"huggingface-spaces-panel\"\n\nOnce you have added your Panel, click Edit to access to the Panel Options page and paste in the path of your Hugging Face Space e.g. `pytorch/ResNet`\n\n\"Edit-HF-Space\"" }, { "id": 340, "parent": 337, "path": "10_other-tutorials/Gradio-and-Comet.md", "level": 2, "title": "4. Logging Model Inferences to Comet", "content": "\n\n[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/comet-ml/comet-examples/blob/master/integrations/model-evaluation/gradio/notebooks/Logging_Model_Inferences_with_Comet_and_Gradio.ipynb)\n\nIn the previous examples, we demonstrated the various ways in which you can interact with a Gradio application through the Comet UI. Additionally, you can also log model inferences, such as SHAP plots, from your Gradio application to Comet.\n\nIn the following snippet, we're going to log inferences from a Text Generation model. We can persist an Experiment across multiple inference calls using Gradio's [State](https://www.gradio.app/docs/#state) object. This will allow you to log multiple inferences from a model to a single Experiment.\n\n```python\nimport comet_ml\nimport gradio as gr\nimport shap\nimport torch\nfrom transformers import AutoModelForCausalLM, AutoTokenizer\n\nif torch.cuda.is_available():\n device = \"cuda\"\nelse:\n device = \"cpu\"\n\nMODEL_NAME = \"gpt2\"\n\nmodel = AutoModelForCausalLM.from_pretrained(MODEL_NAME)" }, { "id": 341, "parent": null, "path": "10_other-tutorials/Gradio-and-Comet.md", "level": 1, "title": "set model decoder to true", "content": "model.config.is_decoder = True" }, { "id": 342, "parent": null, "path": "10_other-tutorials/Gradio-and-Comet.md", "level": 1, "title": "set text-generation params under task_specific_params", "content": "model.config.task_specific_params[\"text-generation\"] = {\n \"do_sample\": True,\n \"max_length\": 50,\n \"temperature\": 0.7,\n \"top_k\": 50,\n \"no_repeat_ngram_size\": 2,\n}\nmodel = model.to(device)\n\ntokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)\nexplainer = shap.Explainer(model, tokenizer)\n\n\ndef start_experiment():\n \"\"\"Returns an APIExperiment object that is thread safe\n and can be used to log inferences to a single Experiment\n \"\"\"\n try:\n api = comet_ml.API()\n workspace = api.get_default_workspace()\n project_name = comet_ml.config.get_config()[\"comet.project_name\"]\n\n experiment = comet_ml.APIExperiment(\n workspace=workspace, project_name=project_name\n )\n experiment.log_other(\"Created from\", \"gradio-inference\")\n\n message = f\"Started Experiment: [{experiment.name}]({experiment.url})\"\n\n return (experiment, message)\n\n except Exception as e:\n return None, None\n\n\ndef predict(text, state, message):\n experiment = state\n\n shap_values = explainer([text])\n plot = shap.plots.text(shap_values, display=False)\n\n if experiment is not None:\n experiment.log_other(\"message\", message)\n experiment.log_html(plot)\n\n return plot\n\n\nwith gr.Blocks() as demo:\n start_experiment_btn = gr.Button(\"Start New Experiment\")\n experiment_status = gr.Markdown()\n\n # Log a message to the Experiment to provide more context\n experiment_message = gr.Textbox(label=\"Experiment Message\")\n experiment = gr.State()\n\n input_text = gr.Textbox(label=\"Input Text\", lines=5, interactive=True)\n submit_btn = gr.Button(\"Submit\")\n\n output = gr.HTML(interactive=True)\n\n start_experiment_btn.click(\n start_experiment, outputs=[experiment, experiment_status]\n )\n submit_btn.click(\n predict, inputs=[input_text, experiment, experiment_message], outputs=[output]\n )\n```\n\nInferences from this snippet will be saved in the HTML tab of your experiment.\n\n" }, { "id": 343, "parent": 342, "path": "10_other-tutorials/Gradio-and-Comet.md", "level": 2, "title": "Conclusion", "content": "We hope you found this guide useful and that it provides some inspiration to help you build awesome model evaluation workflows with Comet and Gradio." }, { "id": 344, "parent": 342, "path": "10_other-tutorials/Gradio-and-Comet.md", "level": 2, "title": "How to contribute Gradio demos on HF spaces on the Comet organization", "content": "- Create an account on Hugging Face [here](https://huggingface.co/join).\n- Add Gradio Demo under your username, see this [course](https://huggingface.co/course/chapter9/4?fw=pt) for setting up Gradio Demo on Hugging Face.\n- Request to join the Comet organization [here](https://huggingface.co/Comet)." }, { "id": 345, "parent": 342, "path": "10_other-tutorials/Gradio-and-Comet.md", "level": 2, "title": "Additional Resources", "content": "- [Comet Documentation](https://www.comet.com/docs/v2/?utm_source=gradio&utm_medium=referral&utm_campaign=gradio-integration&utm_content=gradio-docs)" }, { "id": 346, "parent": null, "path": "10_other-tutorials/using-gradio-for-tabular-workflows.md", "level": 1, "title": "Using Gradio for Tabular Data Science Workflows", "content": "Related spaces: https://huggingface.co/spaces/scikit-learn/gradio-skops-integration, https://huggingface.co/spaces/scikit-learn/tabular-playground, https://huggingface.co/spaces/merve/gradio-analysis-dashboard" }, { "id": 347, "parent": 346, "path": "10_other-tutorials/using-gradio-for-tabular-workflows.md", "level": 2, "title": "Introduction", "content": "Tabular data science is the most widely used domain of machine learning, with problems ranging from customer segmentation to churn prediction. Throughout various stages of the tabular data science workflow, communicating your work to stakeholders or clients can be cumbersome; which prevents data scientists from focusing on what matters, such as data analysis and model building. Data scientists can end up spending hours building a dashboard that takes in dataframe and returning plots, or returning a prediction or plot of clusters in a dataset. In this guide, we'll go through how to use `gradio` to improve your data science workflows. We will also talk about how to use `gradio` and [skops](https://skops.readthedocs.io/en/stable/) to build interfaces with only one line of code!" }, { "id": 348, "parent": 347, "path": "10_other-tutorials/using-gradio-for-tabular-workflows.md", "level": 3, "title": "Prerequisites", "content": "Make sure you have the `gradio` Python package already [installed](/getting_started)." }, { "id": 349, "parent": 346, "path": "10_other-tutorials/using-gradio-for-tabular-workflows.md", "level": 2, "title": "Let's Create a Simple Interface!", "content": "We will take a look at how we can create a simple UI that predicts failures based on product information.\n\n```python\nimport gradio as gr\nimport pandas as pd\nimport joblib\nimport datasets\n\n\ninputs = [gr.Dataframe(row_count = (2, \"dynamic\"), col_count=(4,\"dynamic\"), label=\"Input Data\", interactive=1)]\n\noutputs = [gr.Dataframe(row_count = (2, \"dynamic\"), col_count=(1, \"fixed\"), label=\"Predictions\", headers=[\"Failures\"])]\n\nmodel = joblib.load(\"model.pkl\")" }, { "id": 350, "parent": null, "path": "10_other-tutorials/using-gradio-for-tabular-workflows.md", "level": 1, "title": "we will give our dataframe as example", "content": "df = datasets.load_dataset(\"merve/supersoaker-failures\")\ndf = df[\"train\"].to_pandas()\n\ndef infer(input_dataframe):\n return pd.DataFrame(model.predict(input_dataframe))\n\ngr.Interface(fn = infer, inputs = inputs, outputs = outputs, examples = [[df.head(2)]]).launch()\n```\n\nLet's break down above code.\n\n- `fn`: the inference function that takes input dataframe and returns predictions.\n- `inputs`: the component we take our input with. We define our input as dataframe with 2 rows and 4 columns, which initially will look like an empty dataframe with the aforementioned shape. When the `row_count` is set to `dynamic`, you don't have to rely on the dataset you're inputting to pre-defined component.\n- `outputs`: The dataframe component that stores outputs. This UI can take single or multiple samples to infer, and returns 0 or 1 for each sample in one column, so we give `row_count` as 2 and `col_count` as 1 above. `headers` is a list made of header names for dataframe.\n- `examples`: You can either pass the input by dragging and dropping a CSV file, or a pandas DataFrame through examples, which headers will be automatically taken by the interface.\n\nWe will now create an example for a minimal data visualization dashboard. You can find a more comprehensive version in the related Spaces.\n\n\n\n```python\nimport gradio as gr\nimport pandas as pd\nimport datasets\nimport seaborn as sns\nimport matplotlib.pyplot as plt\n\ndf = datasets.load_dataset(\"merve/supersoaker-failures\")\ndf = df[\"train\"].to_pandas()\ndf.dropna(axis=0, inplace=True)\n\ndef plot(df):\n plt.scatter(df.measurement_13, df.measurement_15, c = df.loading,alpha=0.5)\n plt.savefig(\"scatter.png\")\n df['failure'].value_counts().plot(kind='bar')\n plt.savefig(\"bar.png\")\n sns.heatmap(df.select_dtypes(include=\"number\").corr())\n plt.savefig(\"corr.png\")\n plots = [\"corr.png\",\"scatter.png\", \"bar.png\"]\n return plots\n\ninputs = [gr.Dataframe(label=\"Supersoaker Production Data\")]\noutputs = [gr.Gallery(label=\"Profiling Dashboard\", columns=(1,3))]\n\ngr.Interface(plot, inputs=inputs, outputs=outputs, examples=[df.head(100)], title=\"Supersoaker Failures Analysis Dashboard\").launch()\n```\n\n\n\nWe will use the same dataset we used to train our model, but we will make a dashboard to visualize it this time.\n\n- `fn`: The function that will create plots based on data.\n- `inputs`: We use the same `Dataframe` component we used above.\n- `outputs`: The `Gallery` component is used to keep our visualizations.\n- `examples`: We will have the dataset itself as the example." }, { "id": 351, "parent": 350, "path": "10_other-tutorials/using-gradio-for-tabular-workflows.md", "level": 2, "title": "Easily load tabular data interfaces with one line of code using skops", "content": "`skops` is a library built on top of `huggingface_hub` and `sklearn`. With the recent `gradio` integration of `skops`, you can build tabular data interfaces with one line of code!\n\n```python\nimport gradio as gr" }, { "id": 352, "parent": null, "path": "10_other-tutorials/using-gradio-for-tabular-workflows.md", "level": 1, "title": "title and description are optional", "content": "title = \"Supersoaker Defective Product Prediction\"\ndescription = \"This model predicts Supersoaker production line failures. Drag and drop any slice from dataset or edit values as you wish in below dataframe component.\"\n\ngr.load(\"huggingface/scikit-learn/tabular-playground\", title=title, description=description).launch()\n```\n\n\n\n`sklearn` models pushed to Hugging Face Hub using `skops` include a `config.json` file that contains an example input with column names, the task being solved (that can either be `tabular-classification` or `tabular-regression`). From the task type, `gradio` constructs the `Interface` and consumes column names and the example input to build it. You can [refer to skops documentation on hosting models on Hub](https://skops.readthedocs.io/en/latest/auto_examples/plot_hf_hub.html#sphx-glr-auto-examples-plot-hf-hub-py) to learn how to push your models to Hub using `skops`." }, { "id": 353, "parent": null, "path": "10_other-tutorials/running-background-tasks.md", "level": 1, "title": "Running Background Tasks", "content": "Related spaces: https://huggingface.co/spaces/freddyaboulton/gradio-google-forms\nTags: TASKS, SCHEDULED, TABULAR, DATA" }, { "id": 354, "parent": 353, "path": "10_other-tutorials/running-background-tasks.md", "level": 2, "title": "Introduction", "content": "This guide explains how you can run background tasks from your gradio app.\nBackground tasks are operations that you'd like to perform outside the request-response\nlifecycle of your app either once or on a periodic schedule.\nExamples of background tasks include periodically synchronizing data to an external database or\nsending a report of model predictions via email." }, { "id": 355, "parent": 353, "path": "10_other-tutorials/running-background-tasks.md", "level": 2, "title": "Overview", "content": "We will be creating a simple \"Google-forms-style\" application to gather feedback from users of the gradio library.\nWe will use a local sqlite database to store our data, but we will periodically synchronize the state of the database\nwith a [HuggingFace Dataset](https://huggingface.co/datasets) so that our user reviews are always backed up.\nThe synchronization will happen in a background task running every 60 seconds.\n\nAt the end of the demo, you'll have a fully working application like this one:\n\n " }, { "id": 356, "parent": 353, "path": "10_other-tutorials/running-background-tasks.md", "level": 2, "title": "Step 1 - Write your database logic 💾", "content": "Our application will store the name of the reviewer, their rating of gradio on a scale of 1 to 5, as well as\nany comments they want to share about the library. Let's write some code that creates a database table to\nstore this data. We'll also write some functions to insert a review into that table and fetch the latest 10 reviews.\n\nWe're going to use the `sqlite3` library to connect to our sqlite database but gradio will work with any library.\n\nThe code will look like this:\n\n```python\nDB_FILE = \"./reviews.db\"\ndb = sqlite3.connect(DB_FILE)" }, { "id": 357, "parent": null, "path": "10_other-tutorials/running-background-tasks.md", "level": 1, "title": "Create table if it doesn't already exist", "content": "try:\n db.execute(\"SELECT * FROM reviews\").fetchall()\n db.close()\nexcept sqlite3.OperationalError:\n db.execute(\n '''\n CREATE TABLE reviews (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,\n name TEXT, review INTEGER, comments TEXT)\n ''')\n db.commit()\n db.close()\n\ndef get_latest_reviews(db: sqlite3.Connection):\n reviews = db.execute(\"SELECT * FROM reviews ORDER BY id DESC limit 10\").fetchall()\n total_reviews = db.execute(\"Select COUNT(id) from reviews\").fetchone()[0]\n reviews = pd.DataFrame(reviews, columns=[\"id\", \"date_created\", \"name\", \"review\", \"comments\"])\n return reviews, total_reviews\n\n\ndef add_review(name: str, review: int, comments: str):\n db = sqlite3.connect(DB_FILE)\n cursor = db.cursor()\n cursor.execute(\"INSERT INTO reviews(name, review, comments) VALUES(?,?,?)\", [name, review, comments])\n db.commit()\n reviews, total_reviews = get_latest_reviews(db)\n db.close()\n return reviews, total_reviews\n```\n\nLet's also write a function to load the latest reviews when the gradio application loads:\n\n```python\ndef load_data():\n db = sqlite3.connect(DB_FILE)\n reviews, total_reviews = get_latest_reviews(db)\n db.close()\n return reviews, total_reviews\n```" }, { "id": 358, "parent": 357, "path": "10_other-tutorials/running-background-tasks.md", "level": 2, "title": "Step 2 - Create a gradio app ⚡", "content": "Now that we have our database logic defined, we can use gradio create a dynamic web page to ask our users for feedback!\n\n```python\nwith gr.Blocks() as demo:\n with gr.Row():\n with gr.Column():\n name = gr.Textbox(label=\"Name\", placeholder=\"What is your name?\")\n review = gr.Radio(label=\"How satisfied are you with using gradio?\", choices=[1, 2, 3, 4, 5])\n comments = gr.Textbox(label=\"Comments\", lines=10, placeholder=\"Do you have any feedback on gradio?\")\n submit = gr.Button(value=\"Submit Feedback\")\n with gr.Column():\n data = gr.Dataframe(label=\"Most recently created 10 rows\")\n count = gr.Number(label=\"Total number of reviews\")\n submit.click(add_review, [name, review, comments], [data, count])\n demo.load(load_data, None, [data, count])\n```" }, { "id": 359, "parent": 357, "path": "10_other-tutorials/running-background-tasks.md", "level": 2, "title": "Step 3 - Synchronize with HuggingFace Datasets 🤗", "content": "We could call `demo.launch()` after step 2 and have a fully functioning application. However,\nour data would be stored locally on our machine. If the sqlite file were accidentally deleted, we'd lose all of our reviews!\nLet's back up our data to a dataset on the HuggingFace hub.\n\nCreate a dataset [here](https://huggingface.co/datasets) before proceeding.\n\nNow at the **top** of our script, we'll use the [huggingface hub client library](https://huggingface.co/docs/huggingface_hub/index)\nto connect to our dataset and pull the latest backup.\n\n```python\nTOKEN = os.environ.get('HUB_TOKEN')\nrepo = huggingface_hub.Repository(\n local_dir=\"data\",\n repo_type=\"dataset\",\n clone_from=\"\",\n use_auth_token=TOKEN\n)\nrepo.git_pull()\n\nshutil.copyfile(\"./data/reviews.db\", DB_FILE)\n```\n\nNote that you'll have to get an access token from the \"Settings\" tab of your HuggingFace for the above code to work.\nIn the script, the token is securely accessed via an environment variable.\n\n![access_token](https://github.com/gradio-app/gradio/blob/main/guides/assets/access_token.png?raw=true)\n\nNow we will create a background task to synch our local database to the dataset hub every 60 seconds.\nWe will use the [AdvancedPythonScheduler](https://apscheduler.readthedocs.io/en/3.x/) to handle the scheduling.\nHowever, this is not the only task scheduling library available. Feel free to use whatever you are comfortable with.\n\nThe function to back up our data will look like this:\n\n```python\nfrom apscheduler.schedulers.background import BackgroundScheduler\n\ndef backup_db():\n shutil.copyfile(DB_FILE, \"./data/reviews.db\")\n db = sqlite3.connect(DB_FILE)\n reviews = db.execute(\"SELECT * FROM reviews\").fetchall()\n pd.DataFrame(reviews).to_csv(\"./data/reviews.csv\", index=False)\n print(\"updating db\")\n repo.push_to_hub(blocking=False, commit_message=f\"Updating data at {datetime.datetime.now()}\")\n\n\nscheduler = BackgroundScheduler()\nscheduler.add_job(func=backup_db, trigger=\"interval\", seconds=60)\nscheduler.start()\n```" }, { "id": 360, "parent": 357, "path": "10_other-tutorials/running-background-tasks.md", "level": 2, "title": "Step 4 (Bonus) - Deployment to HuggingFace Spaces", "content": "You can use the HuggingFace [Spaces](https://huggingface.co/spaces) platform to deploy this application for free ✨\n\nIf you haven't used Spaces before, follow the previous guide [here](/using_hugging_face_integrations).\nYou will have to use the `HUB_TOKEN` environment variable as a secret in the Guides." }, { "id": 361, "parent": 357, "path": "10_other-tutorials/running-background-tasks.md", "level": 2, "title": "Conclusion", "content": "Congratulations! You know how to run background tasks from your gradio app on a schedule ⏲️.\n\nCheckout the application running on Spaces [here](https://huggingface.co/spaces/freddyaboulton/gradio-google-forms).\nThe complete code is [here](https://huggingface.co/spaces/freddyaboulton/gradio-google-forms/blob/main/app.py)" }, { "id": 362, "parent": null, "path": "10_other-tutorials/using-gradio-in-other-programming-languages.md", "level": 1, "title": "Using Gradio in Other Programming Languages", "content": "The core `gradio` library is a Python library. But you can also use `gradio` to create UIs around programs written in other languages, thanks to Python's ability to interface with external processes. Using Python's `subprocess` module, you can call programs written in C++, Rust, or virtually any other language, allowing `gradio` to become a flexible UI layer for non-Python applications.\n\nIn this post, we'll walk through how to integrate `gradio` with C++ and Rust, using Python's `subprocess` module to invoke code written in these languages. We'll also discuss how to use Gradio with R, which is even easier, thanks to the [reticulate](https://rstudio.github.io/reticulate/) R package, which makes it possible to install and import Python modules in R." }, { "id": 363, "parent": 362, "path": "10_other-tutorials/using-gradio-in-other-programming-languages.md", "level": 2, "title": "Using Gradio with C++", "content": "Let’s start with a simple example of integrating a C++ program into a Gradio app. Suppose we have the following C++ program that adds two numbers:\n\n```cpp\n// add.cpp\n#include \n\nint main() {\n double a, b;\n std::cin >> a >> b;\n std::cout << a + b << std::endl;\n return 0;\n}\n```\n\nThis program reads two numbers from standard input, adds them, and outputs the result.\n\nWe can build a Gradio interface around this C++ program using Python's `subprocess` module. Here’s the corresponding Python code:\n\n```python\nimport gradio as gr\nimport subprocess\n\ndef add_numbers(a, b):\n process = subprocess.Popen(\n ['./add'], \n stdin=subprocess.PIPE, \n stdout=subprocess.PIPE, \n stderr=subprocess.PIPE\n )\n output, error = process.communicate(input=f\"{a} {b}\\n\".encode())\n \n if error:\n return f\"Error: {error.decode()}\"\n return float(output.decode().strip())\n\ndemo = gr.Interface(\n fn=add_numbers, \n inputs=[gr.Number(label=\"Number 1\"), gr.Number(label=\"Number 2\")], \n outputs=gr.Textbox(label=\"Result\")\n)\n\ndemo.launch()\n```\n\nHere, `subprocess.Popen` is used to execute the compiled C++ program (`add`), pass the input values, and capture the output. You can compile the C++ program by running:\n\n```bash\ng++ -o add add.cpp\n```\n\nThis example shows how easy it is to call C++ from Python using `subprocess` and build a Gradio interface around it." }, { "id": 364, "parent": 362, "path": "10_other-tutorials/using-gradio-in-other-programming-languages.md", "level": 2, "title": "Using Gradio with Rust", "content": "Now, let’s move to another example: calling a Rust program to apply a sepia filter to an image. The Rust code could look something like this:\n\n```rust\n// sepia.rs\nextern crate image;\n\nuse image::{GenericImageView, ImageBuffer, Rgba};\n\nfn sepia_filter(input: &str, output: &str) {\n let img = image::open(input).unwrap();\n let (width, height) = img.dimensions();\n let mut img_buf = ImageBuffer::new(width, height);\n\n for (x, y, pixel) in img.pixels() {\n let (r, g, b, a) = (pixel[0] as f32, pixel[1] as f32, pixel[2] as f32, pixel[3]);\n let tr = (0.393 * r + 0.769 * g + 0.189 * b).min(255.0);\n let tg = (0.349 * r + 0.686 * g + 0.168 * b).min(255.0);\n let tb = (0.272 * r + 0.534 * g + 0.131 * b).min(255.0);\n img_buf.put_pixel(x, y, Rgba([tr as u8, tg as u8, tb as u8, a]));\n }\n\n img_buf.save(output).unwrap();\n}\n\nfn main() {\n let args: Vec = std::env::args().collect();\n if args.len() != 3 {\n eprintln!(\"Usage: sepia \");\n return;\n }\n sepia_filter(&args[1], &args[2]);\n}\n```\n\nThis Rust program applies a sepia filter to an image. It takes two command-line arguments: the input image path and the output image path. You can compile this program using:\n\n```bash\ncargo build --release\n```\n\nNow, we can call this Rust program from Python and use Gradio to build the interface:\n\n```python\nimport gradio as gr\nimport subprocess\n\ndef apply_sepia(input_path):\n output_path = \"output.png\"\n \n process = subprocess.Popen(\n ['./target/release/sepia', input_path, output_path], \n stdout=subprocess.PIPE, \n stderr=subprocess.PIPE\n )\n process.wait()\n \n return output_path\n\ndemo = gr.Interface(\n fn=apply_sepia, \n inputs=gr.Image(type=\"filepath\", label=\"Input Image\"), \n outputs=gr.Image(label=\"Sepia Image\")\n)\n\ndemo.launch()\n```\n\nHere, when a user uploads an image and clicks submit, Gradio calls the Rust binary (`sepia`) to process the image, and returns the sepia-filtered output to Gradio.\n\nThis setup showcases how you can integrate performance-critical or specialized code written in Rust into a Gradio interface." }, { "id": 365, "parent": 362, "path": "10_other-tutorials/using-gradio-in-other-programming-languages.md", "level": 2, "title": "Using Gradio with R (via `reticulate`)", "content": "Integrating Gradio with R is particularly straightforward thanks to the `reticulate` package, which allows you to run Python code directly in R. Let’s walk through an example of using Gradio in R. \n\n**Installation**\n\nFirst, you need to install the `reticulate` package in R:\n\n```r\ninstall.packages(\"reticulate\")\n```\n\n\nOnce installed, you can use the package to run Gradio directly from within an R script.\n\n\n```r\nlibrary(reticulate)\n\npy_install(\"gradio\", pip = TRUE)\n\ngr <- import(\"gradio\") # import gradio as gr\n```\n\n**Building a Gradio Application**\n\nWith gradio installed and imported, we now have access to gradio's app building methods. Let's build a simple app for an R function that returns a greeting\n\n```r\ngreeting <- \\(name) paste(\"Hello\", name)\n\napp <- gr$Interface(\n fn = greeting,\n inputs = gr$Text(label = \"Name\"),\n outputs = gr$Text(label = \"Greeting\"),\n title = \"Hello! 😃 👋\"\n)\n\napp$launch(server_name = \"localhost\", \n server_port = as.integer(3000))\n```\n\nCredit to [@IfeanyiIdiaye](https://github.com/Ifeanyi55) for contributing this section. You can see more examples [here](https://github.com/Ifeanyi55/Gradio-in-R/tree/main/Code), including using Gradio Blocks to build a machine learning application in R." }, { "id": 366, "parent": null, "path": "02_building-interfaces/00_the-interface-class.md", "level": 1, "title": "The `Interface` class", "content": "As mentioned in the [Quickstart](/main/guides/quickstart), the `gr.Interface` class is a high-level abstraction in Gradio that allows you to quickly create a demo for any Python function simply by specifying the input types and the output types. Revisiting our first demo:\n\n```py\nimport gradio as gr\n\ndef greet(name, intensity):\n return \"Hello, \" + name + \"!\" * int(intensity)\n\ndemo = gr.Interface(\n fn=greet,\n inputs=[\"text\", \"slider\"],\n outputs=[\"text\"],\n)\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n\n\nWe see that the `Interface` class is initialized with three required parameters:\n\n- `fn`: the function to wrap a user interface (UI) around\n- `inputs`: which Gradio component(s) to use for the input. The number of components should match the number of arguments in your function.\n- `outputs`: which Gradio component(s) to use for the output. The number of components should match the number of return values from your function.\n\nIn this Guide, we'll dive into `gr.Interface` and the various ways it can be customized, but before we do that, let's get a better understanding of Gradio components." }, { "id": 367, "parent": 366, "path": "02_building-interfaces/00_the-interface-class.md", "level": 2, "title": "Gradio Components", "content": "Gradio includes more than 30 pre-built components (as well as many [community-built _custom components_](https://www.gradio.app/custom-components/gallery)) that can be used as inputs or outputs in your demo. These components correspond to common data types in machine learning and data science, e.g. the `gr.Image` component is designed to handle input or output images, the `gr.Label` component displays classification labels and probabilities, the `gr.LinePlot` component displays line plots, and so on." }, { "id": 368, "parent": 366, "path": "02_building-interfaces/00_the-interface-class.md", "level": 2, "title": "Components Attributes", "content": "We used the default versions of the `gr.Textbox` and `gr.Slider`, but what if you want to change how the UI components look or behave?\n\nLet's say you want to customize the slider to have values from 1 to 10, with a default of 2. And you wanted to customize the output text field — you want it to be larger and have a label.\n\nIf you use the actual classes for `gr.Textbox` and `gr.Slider` instead of the string shortcuts, you have access to much more customizability through component attributes.\n\n```py\nimport gradio as gr\n\ndef greet(name, intensity):\n return \"Hello, \" + name + \"!\" * intensity\n\ndemo = gr.Interface(\n fn=greet,\n inputs=[\"text\", gr.Slider(value=2, minimum=1, maximum=10, step=1)],\n outputs=[gr.Textbox(label=\"greeting\", lines=3)],\n)\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n$demo_hello_world_2" }, { "id": 369, "parent": 366, "path": "02_building-interfaces/00_the-interface-class.md", "level": 2, "title": "Multiple Input and Output Components", "content": "Suppose you had a more complex function, with multiple outputs as well. In the example below, we define a function that takes a string, boolean, and number, and returns a string and number. \n\n```py\nimport gradio as gr\n\ndef greet(name, is_morning, temperature):\n salutation = \"Good morning\" if is_morning else \"Good evening\"\n greeting = f\"{salutation} {name}. It is {temperature} degrees today\"\n celsius = (temperature - 32) * 5 / 9\n return greeting, round(celsius, 2)\n\ndemo = gr.Interface(\n fn=greet,\n inputs=[\"text\", \"checkbox\", gr.Slider(0, 100)],\n outputs=[\"text\", \"number\"],\n)\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n$demo_hello_world_3\n\nJust as each component in the `inputs` list corresponds to one of the parameters of the function, in order, each component in the `outputs` list corresponds to one of the values returned by the function, in order." }, { "id": 370, "parent": 366, "path": "02_building-interfaces/00_the-interface-class.md", "level": 2, "title": "An Image Example", "content": "Gradio supports many types of components, such as `Image`, `DataFrame`, `Video`, or `Label`. Let's try an image-to-image function to get a feel for these!\n\n```py\nimport numpy as np\nimport gradio as gr\n\ndef sepia(input_img):\n sepia_filter = np.array([\n [0.393, 0.769, 0.189],\n [0.349, 0.686, 0.168],\n [0.272, 0.534, 0.131]\n ])\n sepia_img = input_img.dot(sepia_filter.T)\n sepia_img /= sepia_img.max()\n return sepia_img\n\ndemo = gr.Interface(sepia, gr.Image(), \"image\")\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n$demo_sepia_filter\n\nWhen using the `Image` component as input, your function will receive a NumPy array with the shape `(height, width, 3)`, where the last dimension represents the RGB values. We'll return an image as well in the form of a NumPy array. \n\nGradio handles the preprocessing and postprocessing to convert images to NumPy arrays and vice versa. You can also control the preprocessing performed with the `type=` keyword argument. For example, if you wanted your function to take a file path to an image instead of a NumPy array, the input `Image` component could be written as:\n\n```python\ngr.Image(type=\"filepath\")\n```\n\nYou can read more about the built-in Gradio components and how to customize them in the [Gradio docs](https://gradio.app/docs)." }, { "id": 371, "parent": 366, "path": "02_building-interfaces/00_the-interface-class.md", "level": 2, "title": "Example Inputs", "content": "You can provide example data that a user can easily load into `Interface`. This can be helpful to demonstrate the types of inputs the model expects, as well as to provide a way to explore your dataset in conjunction with your model. To load example data, you can provide a **nested list** to the `examples=` keyword argument of the Interface constructor. Each sublist within the outer list represents a data sample, and each element within the sublist represents an input for each input component. The format of example data for each component is specified in the [Docs](https://gradio.app/docs#components).\n\n```py\nimport gradio as gr\n\ndef calculator(num1, operation, num2):\n if operation == \"add\":\n return num1 + num2\n elif operation == \"subtract\":\n return num1 - num2\n elif operation == \"multiply\":\n return num1 * num2\n elif operation == \"divide\":\n if num2 == 0:\n raise gr.Error(\"Cannot divide by zero!\")\n return num1 / num2\n\ndemo = gr.Interface(\n calculator,\n [\n \"number\",\n gr.Radio([\"add\", \"subtract\", \"multiply\", \"divide\"]),\n \"number\"\n ],\n \"number\",\n examples=[\n [45, \"add\", 3],\n [3.14, \"divide\", 2],\n [144, \"multiply\", 2.5],\n [0, \"subtract\", 1.2],\n ],\n title=\"Toy Calculator\",\n description=\"Here's a sample toy calculator.\",\n)\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n$demo_calculator\n\nYou can load a large dataset into the examples to browse and interact with the dataset through Gradio. The examples will be automatically paginated (you can configure this through the `examples_per_page` argument of `Interface`).\n\nContinue learning about examples in the [More On Examples](https://gradio.app/guides/more-on-examples) guide." }, { "id": 372, "parent": 366, "path": "02_building-interfaces/00_the-interface-class.md", "level": 2, "title": "Descriptive Content", "content": "In the previous example, you may have noticed the `title=` and `description=` keyword arguments in the `Interface` constructor that helps users understand your app.\n\nThere are three arguments in the `Interface` constructor to specify where this content should go:\n\n- `title`: which accepts text and can display it at the very top of interface, and also becomes the page title.\n- `description`: which accepts text, markdown or HTML and places it right under the title.\n- `article`: which also accepts text, markdown or HTML and places it below the interface.\n\n![annotated](https://github.com/gradio-app/gradio/blob/main/guides/assets/annotated.png?raw=true)\n\nAnother useful keyword argument is `label=`, which is present in every `Component`. This modifies the label text at the top of each `Component`. You can also add the `info=` keyword argument to form elements like `Textbox` or `Radio` to provide further information on their usage.\n\n```python\ngr.Number(label='Age', info='In years, must be greater than 0')\n```" }, { "id": 373, "parent": 366, "path": "02_building-interfaces/00_the-interface-class.md", "level": 2, "title": "Additional Inputs within an Accordion", "content": "If your prediction function takes many inputs, you may want to hide some of them within a collapsed accordion to avoid cluttering the UI. The `Interface` class takes an `additional_inputs` argument which is similar to `inputs` but any input components included here are not visible by default. The user must click on the accordion to show these components. The additional inputs are passed into the prediction function, in order, after the standard inputs.\n\nYou can customize the appearance of the accordion by using the optional `additional_inputs_accordion` argument, which accepts a string (in which case, it becomes the label of the accordion), or an instance of the `gr.Accordion()` class (e.g. this lets you control whether the accordion is open or closed by default).\n\nHere's an example:\n\n```py\nimport gradio as gr\n\ndef generate_fake_image(prompt, seed, initial_image=None):\n return f\"Used seed: {seed}\", \"https://dummyimage.com/300/09f.png\"\n\ndemo = gr.Interface(\n generate_fake_image,\n inputs=[\"textbox\"],\n outputs=[\"textbox\", \"image\"],\n additional_inputs=[\n gr.Slider(0, 1000),\n \"image\"\n ]\n)\n\nif __name__ == \"__main__\":\n demo.launch()\n\n\n```\n$demo_interface_with_additional_inputs" }, { "id": 374, "parent": null, "path": "02_building-interfaces/03_interface-state.md", "level": 1, "title": "Interface State", "content": "So far, we've assumed that your demos are *stateless*: that they do not persist information beyond a single function call. What if you want to modify the behavior of your demo based on previous interactions with the demo? There are two approaches in Gradio: *global state* and *session state*." }, { "id": 375, "parent": 374, "path": "02_building-interfaces/03_interface-state.md", "level": 2, "title": "Global State", "content": "If the state is something that should be accessible to all function calls and all users, you can create a variable outside the function call and access it inside the function. For example, you may load a large model outside the function and use it inside the function so that every function call does not need to reload the model.\n\n```py\nimport gradio as gr\n\nscores = []\n\ndef track_score(score):\n scores.append(score)\n top_scores = sorted(scores, reverse=True)[:3]\n return top_scores\n\ndemo = gr.Interface(\n track_score,\n gr.Number(label=\"Score\"),\n gr.JSON(label=\"Top Scores\")\n)\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n\nIn the code above, the `scores` array is shared between all users. If multiple users are accessing this demo, their scores will all be added to the same list, and the returned top 3 scores will be collected from this shared reference." }, { "id": 376, "parent": 374, "path": "02_building-interfaces/03_interface-state.md", "level": 2, "title": "Session State", "content": "Another type of data persistence Gradio supports is session state, where data persists across multiple submits within a page session. However, data is _not_ shared between different users of your model. To store data in a session state, you need to do three things:\n\n1. Pass in an extra parameter into your function, which represents the state of the interface.\n2. At the end of the function, return the updated value of the state as an extra return value.\n3. Add the `'state'` input and `'state'` output components when creating your `Interface`\n\nHere's a simple app to illustrate session state - this app simply stores users previous submissions and displays them back to the user:\n\n\n```py\nimport gradio as gr\n\ndef store_message(message: str, history: list[str]): # type: ignore\n output = {\n \"Current messages\": message,\n \"Previous messages\": history[::-1]\n }\n history.append(message)\n return output, history\n\ndemo = gr.Interface(fn=store_message,\n inputs=[\"textbox\", gr.State(value=[])],\n outputs=[\"json\", gr.State()])\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n$demo_interface_state\n\n\nNotice how the state persists across submits within each page, but if you load this demo in another tab (or refresh the page), the demos will not share chat history. Here, we could not store the submission history in a global variable, otherwise the submission history would then get jumbled between different users.\n\nThe initial value of the `State` is `None` by default. If you pass a parameter to the `value` argument of `gr.State()`, it is used as the default value of the state instead. \n\nNote: the `Interface` class only supports a single session state variable (though it can be a list with multiple elements). For more complex use cases, you can use Blocks, [which supports multiple `State` variables](/guides/state-in-blocks/). Alternatively, if you are building a chatbot that maintains user state, consider using the `ChatInterface` abstraction, [which manages state automatically](/guides/creating-a-chatbot-fast)." }, { "id": 377, "parent": null, "path": "02_building-interfaces/04_reactive-interfaces.md", "level": 1, "title": "Reactive Interfaces", "content": "Finally, we cover how to get Gradio demos to refresh automatically or continuously stream data." }, { "id": 378, "parent": 377, "path": "02_building-interfaces/04_reactive-interfaces.md", "level": 2, "title": "Live Interfaces", "content": "You can make interfaces automatically refresh by setting `live=True` in the interface. Now the interface will recalculate as soon as the user input changes.\n\n```py\nimport gradio as gr\n\ndef calculator(num1, operation, num2):\n if operation == \"add\":\n return num1 + num2\n elif operation == \"subtract\":\n return num1 - num2\n elif operation == \"multiply\":\n return num1 * num2\n elif operation == \"divide\":\n return num1 / num2\n\ndemo = gr.Interface(\n calculator,\n [\n \"number\",\n gr.Radio([\"add\", \"subtract\", \"multiply\", \"divide\"]),\n \"number\"\n ],\n \"number\",\n live=True,\n)\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n$demo_calculator_live\n\nNote there is no submit button, because the interface resubmits automatically on change." }, { "id": 379, "parent": 377, "path": "02_building-interfaces/04_reactive-interfaces.md", "level": 2, "title": "Streaming Components", "content": "Some components have a \"streaming\" mode, such as `Audio` component in microphone mode, or the `Image` component in webcam mode. Streaming means data is sent continuously to the backend and the `Interface` function is continuously being rerun.\n\nThe difference between `gr.Audio(source='microphone')` and `gr.Audio(source='microphone', streaming=True)`, when both are used in `gr.Interface(live=True)`, is that the first `Component` will automatically submit data and run the `Interface` function when the user stops recording, whereas the second `Component` will continuously send data and run the `Interface` function _during_ recording.\n\nHere is example code of streaming images from the webcam.\n\n```py\nimport gradio as gr\nimport numpy as np\n\ndef flip(im):\n return np.flipud(im)\n\ndemo = gr.Interface(\n flip,\n gr.Image(sources=[\"webcam\"], streaming=True),\n \"image\",\n live=True\n)\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n\nStreaming can also be done in an output component. A `gr.Audio(streaming=True)` output component can take a stream of audio data yielded piece-wise by a generator function and combines them into a single audio file. For a detailed example, see our guide on performing [automatic speech recognition](/guides/real-time-speech-recognition) with Gradio." }, { "id": 380, "parent": null, "path": "02_building-interfaces/05_four-kinds-of-interfaces.md", "level": 1, "title": "The 4 Kinds of Gradio Interfaces", "content": "So far, we've always assumed that in order to build an Gradio demo, you need both inputs and outputs. But this isn't always the case for machine learning demos: for example, _unconditional image generation models_ don't take any input but produce an image as the output.\n\nIt turns out that the `gradio.Interface` class can actually handle 4 different kinds of demos:\n\n1. **Standard demos**: which have both separate inputs and outputs (e.g. an image classifier or speech-to-text model)\n2. **Output-only demos**: which don't take any input but produce on output (e.g. an unconditional image generation model)\n3. **Input-only demos**: which don't produce any output but do take in some sort of input (e.g. a demo that saves images that you upload to a persistent external database)\n4. **Unified demos**: which have both input and output components, but the input and output components _are the same_. This means that the output produced overrides the input (e.g. a text autocomplete model)\n\nDepending on the kind of demo, the user interface (UI) looks slightly different:\n\n![](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/gradio-guides/interfaces4.png)\n\nLet's see how to build each kind of demo using the `Interface` class, along with examples:" }, { "id": 381, "parent": 380, "path": "02_building-interfaces/05_four-kinds-of-interfaces.md", "level": 2, "title": "Standard demos", "content": "To create a demo that has both the input and the output components, you simply need to set the values of the `inputs` and `outputs` parameter in `Interface()`. Here's an example demo of a simple image filter:\n\n```py\nimport numpy as np\nimport gradio as gr\n\ndef sepia(input_img):\n sepia_filter = np.array([\n [0.393, 0.769, 0.189],\n [0.349, 0.686, 0.168],\n [0.272, 0.534, 0.131]\n ])\n sepia_img = input_img.dot(sepia_filter.T)\n sepia_img /= sepia_img.max()\n return sepia_img\n\ndemo = gr.Interface(sepia, gr.Image(), \"image\")\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n$demo_sepia_filter" }, { "id": 382, "parent": 380, "path": "02_building-interfaces/05_four-kinds-of-interfaces.md", "level": 2, "title": "Output-only demos", "content": "What about demos that only contain outputs? In order to build such a demo, you simply set the value of the `inputs` parameter in `Interface()` to `None`. Here's an example demo of a mock image generation model:\n\n```py\nimport time\n\nimport gradio as gr\n\ndef fake_gan():\n time.sleep(1)\n images = [\n \"https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=387&q=80\",\n \"https://images.unsplash.com/photo-1554151228-14d9def656e4?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=386&q=80\",\n \"https://images.unsplash.com/photo-1542909168-82c3e7fdca5c?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MXx8aHVtYW4lMjBmYWNlfGVufDB8fDB8fA%3D%3D&w=1000&q=80\",\n ]\n return images\n\ndemo = gr.Interface(\n fn=fake_gan,\n inputs=None,\n outputs=gr.Gallery(label=\"Generated Images\", columns=[2]),\n title=\"FD-GAN\",\n description=\"This is a fake demo of a GAN. In reality, the images are randomly chosen from Unsplash.\",\n)\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n$demo_fake_gan_no_input" }, { "id": 383, "parent": 380, "path": "02_building-interfaces/05_four-kinds-of-interfaces.md", "level": 2, "title": "Input-only demos", "content": "Similarly, to create a demo that only contains inputs, set the value of `outputs` parameter in `Interface()` to be `None`. Here's an example demo that saves any uploaded image to disk:\n\n```py\nimport random\nimport string\nimport gradio as gr\n\ndef save_image_random_name(image):\n random_string = ''.join(random.choices(string.ascii_letters, k=20)) + '.png'\n image.save(random_string)\n print(f\"Saved image to {random_string}!\")\n\ndemo = gr.Interface(\n fn=save_image_random_name,\n inputs=gr.Image(type=\"pil\"),\n outputs=None,\n)\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n$demo_save_file_no_output" }, { "id": 384, "parent": 380, "path": "02_building-interfaces/05_four-kinds-of-interfaces.md", "level": 2, "title": "Unified demos", "content": "A demo that has a single component as both the input and the output. It can simply be created by setting the values of the `inputs` and `outputs` parameter as the same component. Here's an example demo of a text generation model:\n\n```py\nimport gradio as gr\nfrom transformers import pipeline\n\ngenerator = pipeline('text-generation', model = 'gpt2')\n\ndef generate_text(text_prompt):\n response = generator(text_prompt, max_length = 30, num_return_sequences=5)\n return response[0]['generated_text'] # type: ignore\n\ntextbox = gr.Textbox()\n\ndemo = gr.Interface(generate_text, textbox, textbox)\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n$demo_unified_demo_text_generation\n\nIt may be the case that none of the 4 cases fulfill your exact needs. In this case, you need to use the `gr.Blocks()` approach!" }, { "id": 385, "parent": null, "path": "02_building-interfaces/02_flagging.md", "level": 1, "title": "Flagging", "content": "You may have noticed the \"Flag\" button that appears by default in your `Interface`. When a user using your demo sees input with interesting output, such as erroneous or unexpected model behaviour, they can flag the input for you to review. Within the directory provided by the `flagging_dir=` argument to the `Interface` constructor, a CSV file will log the flagged inputs. If the interface involves file data, such as for Image and Audio components, folders will be created to store those flagged data as well.\n\nFor example, with the calculator interface shown above, we would have the flagged data stored in the flagged directory shown below:\n\n```directory\n+-- calculator.py\n+-- flagged/\n| +-- logs.csv\n```\n\n_flagged/logs.csv_\n\n```csv\nnum1,operation,num2,Output\n5,add,7,12\n6,subtract,1.5,4.5\n```\n\nWith the sepia interface shown earlier, we would have the flagged data stored in the flagged directory shown below:\n\n```directory\n+-- sepia.py\n+-- flagged/\n| +-- logs.csv\n| +-- im/\n| | +-- 0.png\n| | +-- 1.png\n| +-- Output/\n| | +-- 0.png\n| | +-- 1.png\n```\n\n_flagged/logs.csv_\n\n```csv\nim,Output\nim/0.png,Output/0.png\nim/1.png,Output/1.png\n```\n\nIf you wish for the user to provide a reason for flagging, you can pass a list of strings to the `flagging_options` argument of Interface. Users will have to select one of the strings when flagging, which will be saved as an additional column to the CSV." }, { "id": 386, "parent": null, "path": "02_building-interfaces/01_more-on-examples.md", "level": 1, "title": "More on Examples", "content": "In the [previous Guide](/main/guides/the-interface-class), we discussed how to provide example inputs for your demo to make it easier for users to try it out. Here, we dive into more details." }, { "id": 387, "parent": 386, "path": "02_building-interfaces/01_more-on-examples.md", "level": 2, "title": "Providing Examples", "content": "Adding examples to an Interface is as easy as providing a list of lists to the `examples`\nkeyword argument.\nEach sublist is a data sample, where each element corresponds to an input of the prediction function.\nThe inputs must be ordered in the same order as the prediction function expects them.\n\nIf your interface only has one input component, then you can provide your examples as a regular list instead of a list of lists." }, { "id": 388, "parent": 387, "path": "02_building-interfaces/01_more-on-examples.md", "level": 3, "title": "Loading Examples from a Directory", "content": "You can also specify a path to a directory containing your examples. If your Interface takes only a single file-type input, e.g. an image classifier, you can simply pass a directory filepath to the `examples=` argument, and the `Interface` will load the images in the directory as examples.\nIn the case of multiple inputs, this directory must\ncontain a log.csv file with the example values.\nIn the context of the calculator demo, we can set `examples='/demo/calculator/examples'` and in that directory we include the following `log.csv` file:\n\n```csv\nnum,operation,num2\n5,\"add\",3\n4,\"divide\",2\n5,\"multiply\",3\n```\n\nThis can be helpful when browsing flagged data. Simply point to the flagged directory and the `Interface` will load the examples from the flagged data." }, { "id": 389, "parent": 387, "path": "02_building-interfaces/01_more-on-examples.md", "level": 3, "title": "Providing Partial Examples", "content": "Sometimes your app has many input components, but you would only like to provide examples for a subset of them. In order to exclude some inputs from the examples, pass `None` for all data samples corresponding to those particular components." }, { "id": 390, "parent": 386, "path": "02_building-interfaces/01_more-on-examples.md", "level": 2, "title": "Caching examples", "content": "You may wish to provide some cached examples of your model for users to quickly try out, in case your model takes a while to run normally.\nIf `cache_examples=True`, your Gradio app will run all of the examples and save the outputs when you call the `launch()` method. This data will be saved in a directory called `gradio_cached_examples` in your working directory by default. You can also set this directory with the `GRADIO_EXAMPLES_CACHE` environment variable, which can be either an absolute path or a relative path to your working directory.\n\nWhenever a user clicks on an example, the output will automatically be populated in the app now, using data from this cached directory instead of actually running the function. This is useful so users can quickly try out your model without adding any load!\n\nAlternatively, you can set `cache_examples=\"lazy\"`. This means that each particular example will only get cached after it is first used (by any user) in the Gradio app. This is helpful if your prediction function is long-running and you do not want to wait a long time for your Gradio app to start.\n\nKeep in mind once the cache is generated, it will not be updated automatically in future launches. If the examples or function logic change, delete the cache folder to clear the cache and rebuild it with another `launch()`." }, { "id": 391, "parent": null, "path": "01_getting-started/01_quickstart.md", "level": 1, "title": "Quickstart", "content": "Gradio is an open-source Python package that allows you to quickly **build** a demo or web application for your machine learning model, API, or any arbitrary Python function. You can then **share** a link to your demo or web application in just a few seconds using Gradio's built-in sharing features. *No JavaScript, CSS, or web hosting experience needed!*\n\n\n\nIt just takes a few lines of Python to create your own demo, so let's get started 💫" }, { "id": 392, "parent": 391, "path": "01_getting-started/01_quickstart.md", "level": 2, "title": "Installation", "content": "**Prerequisite**: Gradio requires [Python 3.10 or higher](https://www.python.org/downloads/).\n\n\nWe recommend installing Gradio using `pip`, which is included by default in Python. Run this in your terminal or command prompt:\n\n```bash\npip install --upgrade gradio\n```\n\n\nTip: It is best to install Gradio in a virtual environment. Detailed installation instructions for all common operating systems are provided here." }, { "id": 393, "parent": 391, "path": "01_getting-started/01_quickstart.md", "level": 2, "title": "Building Your First Demo", "content": "You can run Gradio in your favorite code editor, Jupyter notebook, Google Colab, or anywhere else you write Python. Let's write your first Gradio app:\n\n\n```py\nimport gradio as gr\n\ndef greet(name, intensity):\n return \"Hello, \" + name + \"!\" * int(intensity)\n\ndemo = gr.Interface(\n fn=greet,\n inputs=[\"text\", \"slider\"],\n outputs=[\"text\"],\n)\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n\n\nTip: We shorten the imported name from gradio to gr. This is a widely adopted convention for better readability of code. \n\nNow, run your code. If you've written the Python code in a file named `app.py`, then you would run `python app.py` from the terminal.\n\nThe demo below will open in a browser on [http://localhost:7860](http://localhost:7860) if running from a file. If you are running within a notebook, the demo will appear embedded within the notebook.\n\n$demo_hello_world_4\n\nType your name in the textbox on the left, drag the slider, and then press the Submit button. You should see a friendly greeting on the right.\n\nTip: When developing locally, you can run your Gradio app in hot reload mode, which automatically reloads the Gradio app whenever you make changes to the file. To do this, simply type in gradio before the name of the file instead of python. In the example above, you would type: `gradio app.py` in your terminal. Learn more in the Hot Reloading Guide.\n\n\n**Understanding the `Interface` Class**\n\nYou'll notice that in order to make your first demo, you created an instance of the `gr.Interface` class. The `Interface` class is designed to create demos for machine learning models which accept one or more inputs, and return one or more outputs. \n\nThe `Interface` class has three core arguments:\n\n- `fn`: the function to wrap a user interface (UI) around\n- `inputs`: the Gradio component(s) to use for the input. The number of components should match the number of arguments in your function.\n- `outputs`: the Gradio component(s) to use for the output. The number of components should match the number of return values from your function.\n\nThe `fn` argument is very flexible -- you can pass *any* Python function that you want to wrap with a UI. In the example above, we saw a relatively simple function, but the function could be anything from a music generator to a tax calculator to the prediction function of a pretrained machine learning model.\n\nThe `inputs` and `outputs` arguments take one or more Gradio components. As we'll see, Gradio includes more than [30 built-in components](https://www.gradio.app/docs/gradio/introduction) (such as the `gr.Textbox()`, `gr.Image()`, and `gr.HTML()` components) that are designed for machine learning applications. \n\nTip: For the `inputs` and `outputs` arguments, you can pass in the name of these components as a string (`\"textbox\"`) or an instance of the class (`gr.Textbox()`).\n\nIf your function accepts more than one argument, as is the case above, pass a list of input components to `inputs`, with each input component corresponding to one of the arguments of the function, in order. The same holds true if your function returns more than one value: simply pass in a list of components to `outputs`. This flexibility makes the `Interface` class a very powerful way to create demos.\n\nWe'll dive deeper into the `gr.Interface` on our series on [building Interfaces](https://www.gradio.app/main/guides/the-interface-class)." }, { "id": 394, "parent": 391, "path": "01_getting-started/01_quickstart.md", "level": 2, "title": "Sharing Your Demo", "content": "What good is a beautiful demo if you can't share it? Gradio lets you easily share a machine learning demo without having to worry about the hassle of hosting on a web server. Simply set `share=True` in `launch()`, and a publicly accessible URL will be created for your demo. Let's revisit our example demo, but change the last line as follows:\n\n```python\nimport gradio as gr\n\ndef greet(name):\n return \"Hello \" + name + \"!\"\n\ndemo = gr.Interface(fn=greet, inputs=\"textbox\", outputs=\"textbox\")\n \ndemo.launch(share=True) # Share your demo with just 1 extra parameter 🚀\n```\n\nWhen you run this code, a public URL will be generated for your demo in a matter of seconds, something like:\n\n👉   `https://a23dsf231adb.gradio.live`\n\nNow, anyone around the world can try your Gradio demo from their browser, while the machine learning model and all computation continues to run locally on your computer.\n\nTo learn more about sharing your demo, read our dedicated guide on [sharing your Gradio application](https://www.gradio.app/guides/sharing-your-app)." }, { "id": 395, "parent": 391, "path": "01_getting-started/01_quickstart.md", "level": 2, "title": "An Overview of Gradio", "content": "So far, we've been discussing the `Interface` class, which is a high-level class that lets to build demos quickly with Gradio. But what else does Gradio include?" }, { "id": 396, "parent": 395, "path": "01_getting-started/01_quickstart.md", "level": 3, "title": "Custom Demos with `gr.Blocks`", "content": "Gradio offers a low-level approach for designing web apps with more customizable layouts and data flows with the `gr.Blocks` class. Blocks supports things like controlling where components appear on the page, handling multiple data flows and more complex interactions (e.g. outputs can serve as inputs to other functions), and updating properties/visibility of components based on user interaction — still all in Python. \n\nYou can build very custom and complex applications using `gr.Blocks()`. For example, the popular image generation [Automatic1111 Web UI](https://github.com/AUTOMATIC1111/stable-diffusion-webui) is built using Gradio Blocks. We dive deeper into the `gr.Blocks` on our series on [building with Blocks](https://www.gradio.app/guides/blocks-and-event-listeners)." }, { "id": 397, "parent": 395, "path": "01_getting-started/01_quickstart.md", "level": 3, "title": "Chatbots with `gr.ChatInterface`", "content": "Gradio includes another high-level class, `gr.ChatInterface`, which is specifically designed to create Chatbot UIs. Similar to `Interface`, you supply a function and Gradio creates a fully working Chatbot UI. If you're interested in creating a chatbot, you can jump straight to [our dedicated guide on `gr.ChatInterface`](https://www.gradio.app/guides/creating-a-chatbot-fast)." }, { "id": 398, "parent": 395, "path": "01_getting-started/01_quickstart.md", "level": 3, "title": "The Gradio Python & JavaScript Ecosystem", "content": "That's the gist of the core `gradio` Python library, but Gradio is actually so much more! It's an entire ecosystem of Python and JavaScript libraries that let you build machine learning applications, or query them programmatically, in Python or JavaScript. Here are other related parts of the Gradio ecosystem:\n\n* [Gradio Python Client](https://www.gradio.app/guides/getting-started-with-the-python-client) (`gradio_client`): query any Gradio app programmatically in Python.\n* [Gradio JavaScript Client](https://www.gradio.app/guides/getting-started-with-the-js-client) (`@gradio/client`): query any Gradio app programmatically in JavaScript.\n* [Gradio-Lite](https://www.gradio.app/guides/gradio-lite) (`@gradio/lite`): write Gradio apps in Python that run entirely in the browser (no server needed!), thanks to Pyodide. \n* [Hugging Face Spaces](https://huggingface.co/spaces): the most popular place to host Gradio applications — for free!" }, { "id": 399, "parent": 391, "path": "01_getting-started/01_quickstart.md", "level": 2, "title": "What's Next?", "content": "Keep learning about Gradio sequentially using the Gradio Guides, which include explanations as well as example code and embedded interactive demos. Next up: [let's dive deeper into the Interface class](https://www.gradio.app/guides/the-interface-class).\n\nOr, if you already know the basics and are looking for something specific, you can search the more [technical API documentation](https://www.gradio.app/docs/)." }, { "id": 400, "parent": null, "path": "09_gradio-clients-and-lite/05_gradio-lite.md", "level": 1, "title": "Gradio-Lite: Serverless Gradio Running Entirely in Your Browser", "content": "Tags: SERVERLESS, BROWSER, PYODIDE\n\nGradio is a popular Python library for creating interactive machine learning apps. Traditionally, Gradio applications have relied on server-side infrastructure to run, which can be a hurdle for developers who need to host their applications.\n\nEnter Gradio-lite (`@gradio/lite`): a library that leverages [Pyodide](https://pyodide.org/en/stable/) to bring Gradio directly to your browser. In this blog post, we'll explore what `@gradio/lite` is, go over example code, and discuss the benefits it offers for running Gradio applications." }, { "id": 401, "parent": 400, "path": "09_gradio-clients-and-lite/05_gradio-lite.md", "level": 2, "title": "What is `@gradio/lite`?", "content": "`@gradio/lite` is a JavaScript library that enables you to run Gradio applications directly within your web browser. It achieves this by utilizing Pyodide, a Python runtime for WebAssembly, which allows Python code to be executed in the browser environment. With `@gradio/lite`, you can **write regular Python code for your Gradio applications**, and they will **run seamlessly in the browser** without the need for server-side infrastructure." }, { "id": 402, "parent": 400, "path": "09_gradio-clients-and-lite/05_gradio-lite.md", "level": 2, "title": "Getting Started", "content": "Let's build a \"Hello World\" Gradio app in `@gradio/lite`" }, { "id": 403, "parent": 402, "path": "09_gradio-clients-and-lite/05_gradio-lite.md", "level": 3, "title": "1. Import JS and CSS", "content": "Start by creating a new HTML file, if you don't have one already. Importing the JavaScript and CSS corresponding to the `@gradio/lite` package by using the following code:\n\n\n```html\n\n\t\n\t\t\n\t\t\n\t\n\n```\n\nNote that you should generally use the latest version of `@gradio/lite` that is available. You can see the [versions available here](https://www.jsdelivr.com/package/npm/@gradio/lite?tab=files)." }, { "id": 404, "parent": 402, "path": "09_gradio-clients-and-lite/05_gradio-lite.md", "level": 3, "title": "2. Create the `` tags", "content": "Somewhere in the body of your HTML page (wherever you'd like the Gradio app to be rendered), create opening and closing `` tags.\n\n```html\n\n\t\n\t\t\n\t\t\n\t\n\t\n\t\t\n\t\t\n\t\n\n```\n\nNote: you can add the `theme` attribute to the `` tag to force the theme to be dark or light (by default, it respects the system theme). E.g.\n\n```html\n\n...\n\n```" }, { "id": 405, "parent": 402, "path": "09_gradio-clients-and-lite/05_gradio-lite.md", "level": 3, "title": "3. Write your Gradio app inside of the tags", "content": "Now, write your Gradio app as you would normally, in Python! Keep in mind that since this is Python, whitespace and indentations matter.\n\n```html\n\n\t\n\t\t\n\t\t\n\t\n\t\n\t\t\n\t\timport gradio as gr\n\n\t\tdef greet(name):\n\t\t\treturn \"Hello, \" + name + \"!\"\n\n\t\tgr.Interface(greet, \"textbox\", \"textbox\").launch()\n\t\t\n\t\n\n```\n\nAnd that's it! You should now be able to open your HTML page in the browser and see the Gradio app rendered! Note that it may take a little while for the Gradio app to load initially since Pyodide can take a while to install in your browser.\n\n**Note on debugging**: to see any errors in your Gradio-lite application, open the inspector in your web browser. All errors (including Python errors) will be printed there." }, { "id": 406, "parent": 400, "path": "09_gradio-clients-and-lite/05_gradio-lite.md", "level": 2, "title": "More Examples: Adding Additional Files and Requirements", "content": "What if you want to create a Gradio app that spans multiple files? Or that has custom Python requirements? Both are possible with `@gradio/lite`!" }, { "id": 407, "parent": 406, "path": "09_gradio-clients-and-lite/05_gradio-lite.md", "level": 3, "title": "Multiple Files", "content": "Adding multiple files within a `@gradio/lite` app is very straightforward: use the `` tag. You can have as many `` tags as you want, but each one needs to have a `name` attribute and the entry point to your Gradio app should have the `entrypoint` attribute.\n\nHere's an example:\n\n```html\n\n\n\nimport gradio as gr\nfrom utils import add\n\ndemo = gr.Interface(fn=add, inputs=[\"number\", \"number\"], outputs=\"number\")\n\ndemo.launch()\n\n\n\ndef add(a, b):\n\treturn a + b\n\n\n\n\n```" }, { "id": 408, "parent": 406, "path": "09_gradio-clients-and-lite/05_gradio-lite.md", "level": 3, "title": "Additional Requirements", "content": "If your Gradio app has additional requirements, it is usually possible to [install them in the browser using micropip](https://pyodide.org/en/stable/usage/loading-packages.html#loading-packages). We've created a wrapper to make this paticularly convenient: simply list your requirements in the same syntax as a `requirements.txt` and enclose them with `` tags.\n\nHere, we install `transformers_js_py` to run a text classification model directly in the browser!\n\n```html\n\n\n\ntransformers_js_py\n\n\n\nfrom transformers_js import import_transformers_js\nimport gradio as gr\n\ntransformers = await import_transformers_js()\npipeline = transformers.pipeline\npipe = await pipeline('sentiment-analysis')\n\nasync def classify(text):\n\treturn await pipe(text)\n\ndemo = gr.Interface(classify, \"textbox\", \"json\")\ndemo.launch()\n\n\n\n\n```\n\n**Try it out**: You can see this example running in [this Hugging Face Static Space](https://huggingface.co/spaces/abidlabs/gradio-lite-classify), which lets you host static (serverless) web applications for free. Visit the page and you'll be able to run a machine learning model without internet access!" }, { "id": 409, "parent": 406, "path": "09_gradio-clients-and-lite/05_gradio-lite.md", "level": 3, "title": "SharedWorker mode", "content": "By default, Gradio-Lite executes Python code in a [Web Worker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API) with [Pyodide](https://pyodide.org/) runtime, and each Gradio-Lite app has its own worker.\nIt has some benefits such as environment isolation.\n\nHowever, when there are many Gradio-Lite apps in the same page, it may cause performance issues such as high memory usage because each app has its own worker and Pyodide runtime.\nIn such cases, you can use the **SharedWorker mode** to share a single Pyodide runtime in a [SharedWorker](https://developer.mozilla.org/en-US/docs/Web/API/SharedWorker) among multiple Gradio-Lite apps. To enable the SharedWorker mode, set the `shared-worker` attribute to the `` tag.\n\n```html\n\n\n\nimport gradio as gr" }, { "id": 410, "parent": null, "path": "09_gradio-clients-and-lite/05_gradio-lite.md", "level": 1, "title": "...", "content": "\n\n\nimport gradio as gr" }, { "id": 411, "parent": null, "path": "09_gradio-clients-and-lite/05_gradio-lite.md", "level": 1, "title": "...", "content": "\n```\n\nWhen using the SharedWorker mode, you should be aware of the following points:\n* The apps share the same Python environment, which means that they can access the same modules and objects. If, for example, one app makes changes to some modules, the changes will be visible to other apps.\n* The file system is shared among the apps, while each app's files are mounted in each home directory, so each app can access the files of other apps." }, { "id": 412, "parent": 411, "path": "09_gradio-clients-and-lite/05_gradio-lite.md", "level": 3, "title": "Code and Demo Playground", "content": "If you'd like to see the code side-by-side with the demo just pass in the `playground` attribute to the gradio-lite element. This will create an interactive playground that allows you to change the code and update the demo! If you're using playground, you can also set layout to either 'vertical' or 'horizontal' which will determine if the code editor and preview are side-by-side or on top of each other (by default it's reposnsive with the width of the page).\n\n```html\n\nimport gradio as gr\n\ngr.Interface(fn=lambda x: x,\n\t\t\tinputs=gr.Textbox(),\n\t\t\toutputs=gr.Textbox()\n\t\t).launch()\n\n```" }, { "id": 413, "parent": 411, "path": "09_gradio-clients-and-lite/05_gradio-lite.md", "level": 2, "title": "Benefits of Using `@gradio/lite`", "content": "" }, { "id": 414, "parent": 413, "path": "09_gradio-clients-and-lite/05_gradio-lite.md", "level": 3, "title": "1. Serverless Deployment", "content": "The primary advantage of @gradio/lite is that it eliminates the need for server infrastructure. This simplifies deployment, reduces server-related costs, and makes it easier to share your Gradio applications with others." }, { "id": 415, "parent": 413, "path": "09_gradio-clients-and-lite/05_gradio-lite.md", "level": 3, "title": "2. Low Latency", "content": "By running in the browser, @gradio/lite offers low-latency interactions for users. There's no need for data to travel to and from a server, resulting in faster responses and a smoother user experience." }, { "id": 416, "parent": 413, "path": "09_gradio-clients-and-lite/05_gradio-lite.md", "level": 3, "title": "3. Privacy and Security", "content": "Since all processing occurs within the user's browser, `@gradio/lite` enhances privacy and security. User data remains on their device, providing peace of mind regarding data handling." }, { "id": 417, "parent": 413, "path": "09_gradio-clients-and-lite/05_gradio-lite.md", "level": 3, "title": "Limitations", "content": "* Currently, the biggest limitation in using `@gradio/lite` is that your Gradio apps will generally take more time (usually 5-15 seconds) to load initially in the browser. This is because the browser needs to load the Pyodide runtime before it can render Python code.\n\n* Not every Python package is supported by Pyodide. While `gradio` and many other popular packages (including `numpy`, `scikit-learn`, and `transformers-js`) can be installed in Pyodide, if your app has many dependencies, its worth checking whether whether the dependencies are included in Pyodide, or can be [installed with `micropip`](https://micropip.pyodide.org/en/v0.2.2/project/api.html#micropip.install)." }, { "id": 418, "parent": 411, "path": "09_gradio-clients-and-lite/05_gradio-lite.md", "level": 2, "title": "Try it out!", "content": "You can immediately try out `@gradio/lite` by copying and pasting this code in a local `index.html` file and opening it with your browser:\n\n```html\n\n\t\n\t\t\n\t\t\n\t\n\t\n\t\t\n\t\timport gradio as gr\n\n\t\tdef greet(name):\n\t\t\treturn \"Hello, \" + name + \"!\"\n\n\t\tgr.Interface(greet, \"textbox\", \"textbox\").launch()\n\t\t\n\t\n\n```\n\n\nWe've also created a playground on the Gradio website that allows you to interactively edit code and see the results immediately!\n\nPlayground: https://www.gradio.app/playground" }, { "id": 419, "parent": null, "path": "09_gradio-clients-and-lite/02_getting-started-with-the-js-client.md", "level": 1, "title": "Getting Started with the Gradio JavaScript Client", "content": "Tags: CLIENT, API, SPACES\n\nThe Gradio JavaScript Client makes it very easy to use any Gradio app as an API. As an example, consider this [Hugging Face Space that transcribes audio files](https://huggingface.co/spaces/abidlabs/whisper) that are recorded from the microphone.\n\n![](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/gradio-guides/whisper-screenshot.jpg)\n\nUsing the `@gradio/client` library, we can easily use the Gradio as an API to transcribe audio files programmatically.\n\nHere's the entire code to do it:\n\n```js\nimport { Client, handle_file } from \"@gradio/client\";\n\nconst response = await fetch(\n\t\"https://github.com/audio-samples/audio-samples.github.io/raw/master/samples/wav/ted_speakers/SalmanKhan/sample-1.wav\"\n);\nconst audio_file = await response.blob();\n\nconst app = await Client.connect(\"abidlabs/whisper\");\nconst transcription = await app.predict(\"/predict\", [handle_file(audio_file)]);\n\nconsole.log(transcription.data);\n// [ \"I said the same phrase 30 times.\" ]\n```\n\nThe Gradio Client works with any hosted Gradio app, whether it be an image generator, a text summarizer, a stateful chatbot, a tax calculator, or anything else! The Gradio Client is mostly used with apps hosted on [Hugging Face Spaces](https://hf.space), but your app can be hosted anywhere, such as your own server.\n\n**Prequisites**: To use the Gradio client, you do _not_ need to know the `gradio` library in great detail. However, it is helpful to have general familiarity with Gradio's concepts of input and output components." }, { "id": 420, "parent": 419, "path": "09_gradio-clients-and-lite/02_getting-started-with-the-js-client.md", "level": 2, "title": "Installation via npm", "content": "Install the @gradio/client package to interact with Gradio APIs using Node.js version >=18.0.0 or in browser-based projects. Use npm or any compatible package manager:\n\n```bash\nnpm i @gradio/client\n```\n\nThis command adds @gradio/client to your project dependencies, allowing you to import it in your JavaScript or TypeScript files." }, { "id": 421, "parent": 419, "path": "09_gradio-clients-and-lite/02_getting-started-with-the-js-client.md", "level": 2, "title": "Installation via CDN", "content": "For quick addition to your web project, you can use the jsDelivr CDN to load the latest version of @gradio/client directly into your HTML:\n\n```bash\n\n```\n\nBe sure to add this to the `` of your HTML. This will install the latest version but we advise hardcoding the version in production. You can find all available versions [here](https://www.jsdelivr.com/package/npm/@gradio/client). This approach is ideal for experimental or prototying purposes, though has some limitations." }, { "id": 422, "parent": 419, "path": "09_gradio-clients-and-lite/02_getting-started-with-the-js-client.md", "level": 2, "title": "Connecting to a running Gradio App", "content": "Start by connecting instantiating a `client` instance and connecting it to a Gradio app that is running on Hugging Face Spaces or generally anywhere on the web." }, { "id": 423, "parent": 419, "path": "09_gradio-clients-and-lite/02_getting-started-with-the-js-client.md", "level": 2, "title": "Connecting to a Hugging Face Space", "content": "```js\nimport { Client } from \"@gradio/client\";\n\nconst app = await Client.connect(\"abidlabs/en2fr\"); // a Space that translates from English to French\n```\n\nYou can also connect to private Spaces by passing in your HF token with the `hf_token` property of the options parameter. You can get your HF token here: https://huggingface.co/settings/tokens\n\n```js\nimport { Client } from \"@gradio/client\";\n\nconst app = await Client.connect(\"abidlabs/my-private-space\", { hf_token: \"hf_...\" })\n```" }, { "id": 424, "parent": 419, "path": "09_gradio-clients-and-lite/02_getting-started-with-the-js-client.md", "level": 2, "title": "Duplicating a Space for private use", "content": "While you can use any public Space as an API, you may get rate limited by Hugging Face if you make too many requests. For unlimited usage of a Space, simply duplicate the Space to create a private Space, and then use it to make as many requests as you'd like! You'll need to pass in your [Hugging Face token](https://huggingface.co/settings/tokens)).\n\n`Client.duplicate` is almost identical to `Client.connect`, the only difference is under the hood:\n\n```js\nimport { Client, handle_file } from \"@gradio/client\";\n\nconst response = await fetch(\n\t\"https://audio-samples.github.io/samples/mp3/blizzard_unconditional/sample-0.mp3\"\n);\nconst audio_file = await response.blob();\n\nconst app = await Client.duplicate(\"abidlabs/whisper\", { hf_token: \"hf_...\" });\nconst transcription = await app.predict(\"/predict\", [handle_file(audio_file)]);\n```\n\nIf you have previously duplicated a Space, re-running `Client.duplicate` will _not_ create a new Space. Instead, the client will attach to the previously-created Space. So it is safe to re-run the `Client.duplicate` method multiple times with the same space.\n\n**Note:** if the original Space uses GPUs, your private Space will as well, and your Hugging Face account will get billed based on the price of the GPU. To minimize charges, your Space will automatically go to sleep after 5 minutes of inactivity. You can also set the hardware using the `hardware` and `timeout` properties of `duplicate`'s options object like this:\n\n```js\nimport { Client } from \"@gradio/client\";\n\nconst app = await Client.duplicate(\"abidlabs/whisper\", {\n\thf_token: \"hf_...\",\n\ttimeout: 60,\n\thardware: \"a10g-small\"\n});\n```" }, { "id": 425, "parent": 419, "path": "09_gradio-clients-and-lite/02_getting-started-with-the-js-client.md", "level": 2, "title": "Connecting a general Gradio app", "content": "If your app is running somewhere else, just provide the full URL instead, including the \"http://\" or \"https://\". Here's an example of making predictions to a Gradio app that is running on a share URL:\n\n```js\nimport { Client } from \"@gradio/client\";\n\nconst app = Client.connect(\"https://bec81a83-5b5c-471e.gradio.live\");\n```" }, { "id": 426, "parent": 419, "path": "09_gradio-clients-and-lite/02_getting-started-with-the-js-client.md", "level": 2, "title": "Connecting to a Gradio app with auth", "content": "If the Gradio application you are connecting to [requires a username and password](/guides/sharing-your-app#authentication), then provide them as a tuple to the `auth` argument of the `Client` class:\n\n```js\nimport { Client } from \"@gradio/client\";\n\nClient.connect(\n space_name,\n { auth: [username, password] }\n)\n```" }, { "id": 427, "parent": 419, "path": "09_gradio-clients-and-lite/02_getting-started-with-the-js-client.md", "level": 2, "title": "Inspecting the API endpoints", "content": "Once you have connected to a Gradio app, you can view the APIs that are available to you by calling the `Client`'s `view_api` method.\n\nFor the Whisper Space, we can do this:\n\n```js\nimport { Client } from \"@gradio/client\";\n\nconst app = await Client.connect(\"abidlabs/whisper\");\n\nconst app_info = await app.view_api();\n\nconsole.log(app_info);\n```\n\nAnd we will see the following:\n\n```json\n{\n\t\"named_endpoints\": {\n\t\t\"/predict\": {\n\t\t\t\"parameters\": [\n\t\t\t\t{\n\t\t\t\t\t\"label\": \"text\",\n\t\t\t\t\t\"component\": \"Textbox\",\n\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"returns\": [\n\t\t\t\t{\n\t\t\t\t\t\"label\": \"output\",\n\t\t\t\t\t\"component\": \"Textbox\",\n\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t},\n\t\"unnamed_endpoints\": {}\n}\n```\n\nThis shows us that we have 1 API endpoint in this space, and shows us how to use the API endpoint to make a prediction: we should call the `.predict()` method (which we will explore below), providing a parameter `input_audio` of type `string`, which is a url to a file.\n\nWe should also provide the `api_name='/predict'` argument to the `predict()` method. Although this isn't necessary if a Gradio app has only 1 named endpoint, it does allow us to call different endpoints in a single app if they are available. If an app has unnamed API endpoints, these can also be displayed by running `.view_api(all_endpoints=True)`." }, { "id": 428, "parent": 419, "path": "09_gradio-clients-and-lite/02_getting-started-with-the-js-client.md", "level": 2, "title": "The \"View API\" Page", "content": "As an alternative to running the `.view_api()` method, you can click on the \"Use via API\" link in the footer of the Gradio app, which shows us the same information, along with example usage. \n\n![](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/gradio-guides/view-api.png)\n\nThe View API page also includes an \"API Recorder\" that lets you interact with the Gradio UI normally and converts your interactions into the corresponding code to run with the JS Client." }, { "id": 429, "parent": 419, "path": "09_gradio-clients-and-lite/02_getting-started-with-the-js-client.md", "level": 2, "title": "Making a prediction", "content": "The simplest way to make a prediction is simply to call the `.predict()` method with the appropriate arguments:\n\n```js\nimport { Client } from \"@gradio/client\";\n\nconst app = await Client.connect(\"abidlabs/en2fr\");\nconst result = await app.predict(\"/predict\", [\"Hello\"]);\n```\n\nIf there are multiple parameters, then you should pass them as an array to `.predict()`, like this:\n\n```js\nimport { Client } from \"@gradio/client\";\n\nconst app = await Client.connect(\"gradio/calculator\");\nconst result = await app.predict(\"/predict\", [4, \"add\", 5]);\n```\n\nFor certain inputs, such as images, you should pass in a `Buffer`, `Blob` or `File` depending on what is most convenient. In node, this would be a `Buffer` or `Blob`; in a browser environment, this would be a `Blob` or `File`.\n\n```js\nimport { Client, handle_file } from \"@gradio/client\";\n\nconst response = await fetch(\n\t\"https://audio-samples.github.io/samples/mp3/blizzard_unconditional/sample-0.mp3\"\n);\nconst audio_file = await response.blob();\n\nconst app = await Client.connect(\"abidlabs/whisper\");\nconst result = await app.predict(\"/predict\", [handle_file(audio_file)]);\n```" }, { "id": 430, "parent": 419, "path": "09_gradio-clients-and-lite/02_getting-started-with-the-js-client.md", "level": 2, "title": "Using events", "content": "If the API you are working with can return results over time, or you wish to access information about the status of a job, you can use the iterable interface for more flexibility. This is especially useful for iterative endpoints or generator endpoints that will produce a series of values over time as discrete responses.\n\n```js\nimport { Client } from \"@gradio/client\";\n\nfunction log_result(payload) {\n\tconst {\n\t\tdata: [translation]\n\t} = payload;\n\n\tconsole.log(`The translated result is: ${translation}`);\n}\n\nconst app = await Client.connect(\"abidlabs/en2fr\");\nconst job = app.submit(\"/predict\", [\"Hello\"]);\n\nfor await (const message of job) {\n\tlog_result(message);\n}\n```" }, { "id": 431, "parent": 419, "path": "09_gradio-clients-and-lite/02_getting-started-with-the-js-client.md", "level": 2, "title": "Status", "content": "The event interface also allows you to get the status of the running job by instantiating the client with the `events` options passing `status` and `data` as an array:\n\n\n```ts\nimport { Client } from \"@gradio/client\";\n\nconst app = await Client.connect(\"abidlabs/en2fr\", {\n\tevents: [\"status\", \"data\"]\n});\n```\n\nThis ensures that status messages are also reported to the client.\n\n`status`es are returned as an object with the following attributes: `status` (a human readbale status of the current job, `\"pending\" | \"generating\" | \"complete\" | \"error\"`), `code` (the detailed gradio code for the job), `position` (the current position of this job in the queue), `queue_size` (the total queue size), `eta` (estimated time this job will complete), `success` (a boolean representing whether the job completed successfully), and `time` ( as `Date` object detailing the time that the status was generated).\n\n```js\nimport { Client } from \"@gradio/client\";\n\nfunction log_status(status) {\n\tconsole.log(\n\t\t`The current status for this job is: ${JSON.stringify(status, null, 2)}.`\n\t);\n}\n\nconst app = await Client.connect(\"abidlabs/en2fr\", {\n\tevents: [\"status\", \"data\"]\n});\nconst job = app.submit(\"/predict\", [\"Hello\"]);\n\nfor await (const message of job) {\n\tif (message.type === \"status\") {\n\t\tlog_status(message);\n\t}\n}\n```" }, { "id": 432, "parent": 419, "path": "09_gradio-clients-and-lite/02_getting-started-with-the-js-client.md", "level": 2, "title": "Cancelling Jobs", "content": "The job instance also has a `.cancel()` method that cancels jobs that have been queued but not started. For example, if you run:\n\n```js\nimport { Client } from \"@gradio/client\";\n\nconst app = await Client.connect(\"abidlabs/en2fr\");\nconst job_one = app.submit(\"/predict\", [\"Hello\"]);\nconst job_two = app.submit(\"/predict\", [\"Friends\"]);\n\njob_one.cancel();\njob_two.cancel();\n```\n\nIf the first job has started processing, then it will not be canceled but the client will no longer listen for updates (throwing away the job). If the second job has not yet started, it will be successfully canceled and removed from the queue." }, { "id": 433, "parent": 419, "path": "09_gradio-clients-and-lite/02_getting-started-with-the-js-client.md", "level": 2, "title": "Generator Endpoints", "content": "Some Gradio API endpoints do not return a single value, rather they return a series of values. You can listen for these values in real time using the iterable interface:\n\n```js\nimport { Client } from \"@gradio/client\";\n\nconst app = await Client.connect(\"gradio/count_generator\");\nconst job = app.submit(0, [9]);\n\nfor await (const message of job) {\n\tconsole.log(message.data);\n}\n```\n\nThis will log out the values as they are generated by the endpoint.\n\nYou can also cancel jobs that that have iterative outputs, in which case the job will finish immediately.\n\n```js\nimport { Client } from \"@gradio/client\";\n\nconst app = await Client.connect(\"gradio/count_generator\");\nconst job = app.submit(0, [9]);\n\nfor await (const message of job) {\n\tconsole.log(message.data);\n}\n\nsetTimeout(() => {\n\tjob.cancel();\n}, 3000);\n```" }, { "id": 434, "parent": null, "path": "09_gradio-clients-and-lite/07_fastapi-app-with-the-gradio-client.md", "level": 1, "title": "Building a Web App with the Gradio Python Client", "content": "Tags: CLIENT, API, WEB APP\n\nIn this blog post, we will demonstrate how to use the `gradio_client` [Python library](getting-started-with-the-python-client/), which enables developers to make requests to a Gradio app programmatically, by creating an end-to-end example web app using FastAPI. The web app we will be building is called \"Acapellify,\" and it will allow users to upload video files as input and return a version of that video without instrumental music. It will also display a gallery of generated videos.\n\n**Prerequisites**\n\nBefore we begin, make sure you are running Python 3.9 or later, and have the following libraries installed:\n\n- `gradio_client`\n- `fastapi`\n- `uvicorn`\n\nYou can install these libraries from `pip`:\n\n```bash\n$ pip install gradio_client fastapi uvicorn\n```\n\nYou will also need to have ffmpeg installed. You can check to see if you already have ffmpeg by running in your terminal:\n\n```bash\n$ ffmpeg version\n```\n\nOtherwise, install ffmpeg [by following these instructions](https://www.hostinger.com/tutorials/how-to-install-ffmpeg)." }, { "id": 435, "parent": 434, "path": "09_gradio-clients-and-lite/07_fastapi-app-with-the-gradio-client.md", "level": 2, "title": "Step 1: Write the Video Processing Function", "content": "Let's start with what seems like the most complex bit -- using machine learning to remove the music from a video.\n\nLuckily for us, there's an existing Space we can use to make this process easier: [https://huggingface.co/spaces/abidlabs/music-separation](https://huggingface.co/spaces/abidlabs/music-separation). This Space takes an audio file and produces two separate audio files: one with the instrumental music and one with all other sounds in the original clip. Perfect to use with our client!\n\nOpen a new Python file, say `main.py`, and start by importing the `Client` class from `gradio_client` and connecting it to this Space:\n\n```py\nfrom gradio_client import Client, handle_file\n\nclient = Client(\"abidlabs/music-separation\")\n\ndef acapellify(audio_path):\n result = client.predict(handle_file(audio_path), api_name=\"/predict\")\n return result[0]\n```\n\nThat's all the code that's needed -- notice that the API endpoints returns two audio files (one without the music, and one with just the music) in a list, and so we just return the first element of the list.\n\n---\n\n**Note**: since this is a public Space, there might be other users using this Space as well, which might result in a slow experience. You can duplicate this Space with your own [Hugging Face token](https://huggingface.co/settings/tokens) and create a private Space that only you have will have access to and bypass the queue. To do that, simply replace the first two lines above with:\n\n```py\nfrom gradio_client import Client\n\nclient = Client.duplicate(\"abidlabs/music-separation\", hf_token=YOUR_HF_TOKEN)\n```\n\nEverything else remains the same!\n\n---\n\nNow, of course, we are working with video files, so we first need to extract the audio from the video files. For this, we will be using the `ffmpeg` library, which does a lot of heavy lifting when it comes to working with audio and video files. The most common way to use `ffmpeg` is through the command line, which we'll call via Python's `subprocess` module:\n\nOur video processing workflow will consist of three steps:\n\n1. First, we start by taking in a video filepath and extracting the audio using `ffmpeg`.\n2. Then, we pass in the audio file through the `acapellify()` function above.\n3. Finally, we combine the new audio with the original video to produce a final acapellified video.\n\nHere's the complete code in Python, which you can add to your `main.py` file:\n\n```python\nimport subprocess\n\ndef process_video(video_path):\n old_audio = os.path.basename(video_path).split(\".\")[0] + \".m4a\"\n subprocess.run(['ffmpeg', '-y', '-i', video_path, '-vn', '-acodec', 'copy', old_audio])\n\n new_audio = acapellify(old_audio)\n\n new_video = f\"acap_{video_path}\"\n subprocess.call(['ffmpeg', '-y', '-i', video_path, '-i', new_audio, '-map', '0:v', '-map', '1:a', '-c:v', 'copy', '-c:a', 'aac', '-strict', 'experimental', f\"static/{new_video}\"])\n return new_video\n```\n\nYou can read up on [ffmpeg documentation](https://ffmpeg.org/ffmpeg.html) if you'd like to understand all of the command line parameters, as they are beyond the scope of this tutorial." }, { "id": 436, "parent": 434, "path": "09_gradio-clients-and-lite/07_fastapi-app-with-the-gradio-client.md", "level": 2, "title": "Step 2: Create a FastAPI app (Backend Routes)", "content": "Next up, we'll create a simple FastAPI app. If you haven't used FastAPI before, check out [the great FastAPI docs](https://fastapi.tiangolo.com/). Otherwise, this basic template, which we add to `main.py`, will look pretty familiar:\n\n```python\nimport os\nfrom fastapi import FastAPI, File, UploadFile, Request\nfrom fastapi.responses import HTMLResponse, RedirectResponse\nfrom fastapi.staticfiles import StaticFiles\nfrom fastapi.templating import Jinja2Templates\n\napp = FastAPI()\nos.makedirs(\"static\", exist_ok=True)\napp.mount(\"/static\", StaticFiles(directory=\"static\"), name=\"static\")\ntemplates = Jinja2Templates(directory=\"templates\")\n\nvideos = []\n\n@app.get(\"/\", response_class=HTMLResponse)\nasync def home(request: Request):\n return templates.TemplateResponse(\n \"home.html\", {\"request\": request, \"videos\": videos})\n\n@app.post(\"/uploadvideo/\")\nasync def upload_video(video: UploadFile = File(...)):\n video_path = video.filename\n with open(video_path, \"wb+\") as fp:\n fp.write(video.file.read())\n\n new_video = process_video(video.filename)\n videos.append(new_video)\n return RedirectResponse(url='/', status_code=303)\n```\n\nIn this example, the FastAPI app has two routes: `/` and `/uploadvideo/`.\n\nThe `/` route returns an HTML template that displays a gallery of all uploaded videos.\n\nThe `/uploadvideo/` route accepts a `POST` request with an `UploadFile` object, which represents the uploaded video file. The video file is \"acapellified\" via the `process_video()` method, and the output video is stored in a list which stores all of the uploaded videos in memory.\n\nNote that this is a very basic example and if this were a production app, you will need to add more logic to handle file storage, user authentication, and security considerations." }, { "id": 437, "parent": 434, "path": "09_gradio-clients-and-lite/07_fastapi-app-with-the-gradio-client.md", "level": 2, "title": "Step 3: Create a FastAPI app (Frontend Template)", "content": "Finally, we create the frontend of our web application. First, we create a folder called `templates` in the same directory as `main.py`. We then create a template, `home.html` inside the `templates` folder. Here is the resulting file structure:\n\n```csv\n├── main.py\n├── templates\n│ └── home.html\n```\n\nWrite the following as the contents of `home.html`:\n\n```html\n<!DOCTYPE html> <html> <head> <title>Video Gallery</title>\n<style> body { font-family: sans-serif; margin: 0; padding: 0;\nbackground-color: #f5f5f5; } h1 { text-align: center; margin-top: 30px;\nmargin-bottom: 20px; } .gallery { display: flex; flex-wrap: wrap;\njustify-content: center; gap: 20px; padding: 20px; } .video { border: 2px solid\n#ccc; box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.2); border-radius: 5px; overflow:\nhidden; width: 300px; margin-bottom: 20px; } .video video { width: 100%; height:\n200px; } .video p { text-align: center; margin: 10px 0; } form { margin-top:\n20px; text-align: center; } input[type=\"file\"] { display: none; } .upload-btn {\ndisplay: inline-block; background-color: #3498db; color: #fff; padding: 10px\n20px; font-size: 16px; border: none; border-radius: 5px; cursor: pointer; }\n.upload-btn:hover { background-color: #2980b9; } .file-name { margin-left: 10px;\n} </style> </head> <body> <h1>Video Gallery</h1> {% if videos %}\n<div class=\"gallery\"> {% for video in videos %} <div class=\"video\">\n<video controls> <source src=\"{{ url_for('static', path=video) }}\"\ntype=\"video/mp4\"> Your browser does not support the video tag. </video>\n<p>{{ video }}</p> </div> {% endfor %} </div> {% else %} <p>No\nvideos uploaded yet.</p> {% endif %} <form action=\"/uploadvideo/\"\nmethod=\"post\" enctype=\"multipart/form-data\"> <label for=\"video-upload\"\nclass=\"upload-btn\">Choose video file</label> <input type=\"file\"\nname=\"video\" id=\"video-upload\"> <span class=\"file-name\"></span> <button\ntype=\"submit\" class=\"upload-btn\">Upload</button> </form> <script> //\nDisplay selected file name in the form const fileUpload =\ndocument.getElementById(\"video-upload\"); const fileName =\ndocument.querySelector(\".file-name\"); fileUpload.addEventListener(\"change\", (e)\n=> { fileName.textContent = e.target.files[0].name; }); </script> </body>\n</html>\n```" }, { "id": 438, "parent": 434, "path": "09_gradio-clients-and-lite/07_fastapi-app-with-the-gradio-client.md", "level": 2, "title": "Step 4: Run your FastAPI app", "content": "Finally, we are ready to run our FastAPI app, powered by the Gradio Python Client!\n\nOpen up a terminal and navigate to the directory containing `main.py`. Then run the following command in the terminal:\n\n```bash\n$ uvicorn main:app\n```\n\nYou should see an output that looks like this:\n\n```csv\nLoaded as API: https://abidlabs-music-separation.hf.space ✔\nINFO: Started server process [1360]\nINFO: Waiting for application startup.\nINFO: Application startup complete.\nINFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)\n```\n\nAnd that's it! Start uploading videos and you'll get some \"acapellified\" videos in response (might take seconds to minutes to process depending on the length of your videos). Here's how the UI looks after uploading two videos:\n\n![](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/gradio-guides/acapellify.png)\n\nIf you'd like to learn more about how to use the Gradio Python Client in your projects, [read the dedicated Guide](/guides/getting-started-with-the-python-client/)." }, { "id": 439, "parent": null, "path": "09_gradio-clients-and-lite/04_gradio-and-llm-agents.md", "level": 1, "title": "Gradio & LLM Agents 🤝", "content": "Large Language Models (LLMs) are very impressive but they can be made even more powerful if we could give them skills to accomplish specialized tasks.\n\nThe [gradio_tools](https://github.com/freddyaboulton/gradio-tools) library can turn any [Gradio](https://github.com/gradio-app/gradio) application into a [tool](https://python.langchain.com/en/latest/modules/agents/tools.html) that an [agent](https://docs.langchain.com/docs/components/agents/agent) can use to complete its task. For example, an LLM could use a Gradio tool to transcribe a voice recording it finds online and then summarize it for you. Or it could use a different Gradio tool to apply OCR to a document on your Google Drive and then answer questions about it.\n\nThis guide will show how you can use `gradio_tools` to grant your LLM Agent access to the cutting edge Gradio applications hosted in the world. Although `gradio_tools` are compatible with more than one agent framework, we will focus on [Langchain Agents](https://docs.langchain.com/docs/components/agents/) in this guide." }, { "id": 440, "parent": 439, "path": "09_gradio-clients-and-lite/04_gradio-and-llm-agents.md", "level": 2, "title": "Some background", "content": "" }, { "id": 441, "parent": 440, "path": "09_gradio-clients-and-lite/04_gradio-and-llm-agents.md", "level": 3, "title": "What are agents?", "content": "A [LangChain agent](https://docs.langchain.com/docs/components/agents/agent) is a Large Language Model (LLM) that takes user input and reports an output based on using one of many tools at its disposal." }, { "id": 442, "parent": 440, "path": "09_gradio-clients-and-lite/04_gradio-and-llm-agents.md", "level": 3, "title": "What is Gradio?", "content": "[Gradio](https://github.com/gradio-app/gradio) is the defacto standard framework for building Machine Learning Web Applications and sharing them with the world - all with just python! 🐍" }, { "id": 443, "parent": 439, "path": "09_gradio-clients-and-lite/04_gradio-and-llm-agents.md", "level": 2, "title": "gradio_tools - An end-to-end example", "content": "To get started with `gradio_tools`, all you need to do is import and initialize your tools and pass them to the langchain agent!\n\nIn the following example, we import the `StableDiffusionPromptGeneratorTool` to create a good prompt for stable diffusion, the\n`StableDiffusionTool` to create an image with our improved prompt, the `ImageCaptioningTool` to caption the generated image, and\nthe `TextToVideoTool` to create a video from a prompt.\n\nWe then tell our agent to create an image of a dog riding a skateboard, but to please improve our prompt ahead of time. We also ask\nit to caption the generated image and create a video for it. The agent can decide which tool to use without us explicitly telling it.\n\n```python\nimport os\n\nif not os.getenv(\"OPENAI_API_KEY\"):\n raise ValueError(\"OPENAI_API_KEY must be set\")\n\nfrom langchain.agents import initialize_agent\nfrom langchain.llms import OpenAI\nfrom gradio_tools import (StableDiffusionTool, ImageCaptioningTool, StableDiffusionPromptGeneratorTool,\n TextToVideoTool)\n\nfrom langchain.memory import ConversationBufferMemory\n\nllm = OpenAI(temperature=0)\nmemory = ConversationBufferMemory(memory_key=\"chat_history\")\ntools = [StableDiffusionTool().langchain, ImageCaptioningTool().langchain,\n StableDiffusionPromptGeneratorTool().langchain, TextToVideoTool().langchain]\n\n\nagent = initialize_agent(tools, llm, memory=memory, agent=\"conversational-react-description\", verbose=True)\noutput = agent.run(input=(\"Please create a photo of a dog riding a skateboard \"\n \"but improve my prompt prior to using an image generator.\"\n \"Please caption the generated image and create a video for it using the improved prompt.\"))\n```\n\nYou'll note that we are using some pre-built tools that come with `gradio_tools`. Please see this [doc](https://github.com/freddyaboulton/gradio-tools#gradio-tools-gradio--llm-agents) for a complete list of the tools that come with `gradio_tools`.\nIf you would like to use a tool that's not currently in `gradio_tools`, it is very easy to add your own. That's what the next section will cover." }, { "id": 444, "parent": 439, "path": "09_gradio-clients-and-lite/04_gradio-and-llm-agents.md", "level": 2, "title": "gradio_tools - creating your own tool", "content": "The core abstraction is the `GradioTool`, which lets you define a new tool for your LLM as long as you implement a standard interface:\n\n```python\nclass GradioTool(BaseTool):\n\n def __init__(self, name: str, description: str, src: str) -> None:\n\n @abstractmethod\n def create_job(self, query: str) -> Job:\n pass\n\n @abstractmethod\n def postprocess(self, output: Tuple[Any] | Any) -> str:\n pass\n```\n\nThe requirements are:\n\n1. The name for your tool\n2. The description for your tool. This is crucial! Agents decide which tool to use based on their description. Be precise and be sure to include example of what the input and the output of the tool should look like.\n3. The url or space id, e.g. `freddyaboulton/calculator`, of the Gradio application. Based on this value, `gradio_tool` will create a [gradio client](https://github.com/gradio-app/gradio/blob/main/client/python/README.md) instance to query the upstream application via API. Be sure to click the link and learn more about the gradio client library if you are not familiar with it.\n4. create_job - Given a string, this method should parse that string and return a job from the client. Most times, this is as simple as passing the string to the `submit` function of the client. More info on creating jobs [here](https://github.com/gradio-app/gradio/blob/main/client/python/README.md#making-a-prediction)\n5. postprocess - Given the result of the job, convert it to a string the LLM can display to the user.\n6. _Optional_ - Some libraries, e.g. [MiniChain](https://github.com/srush/MiniChain/tree/main), may need some info about the underlying gradio input and output types used by the tool. By default, this will return gr.Textbox() but\n if you'd like to provide more accurate info, implement the `_block_input(self, gr)` and `_block_output(self, gr)` methods of the tool. The `gr` variable is the gradio module (the result of `import gradio as gr`). It will be\n automatically imported by the `GradiTool` parent class and passed to the `_block_input` and `_block_output` methods.\n\nAnd that's it!\n\nOnce you have created your tool, open a pull request to the `gradio_tools` repo! We welcome all contributions." }, { "id": 445, "parent": 439, "path": "09_gradio-clients-and-lite/04_gradio-and-llm-agents.md", "level": 2, "title": "Example tool - Stable Diffusion", "content": "Here is the code for the StableDiffusion tool as an example:\n\n```python\nfrom gradio_tool import GradioTool\nimport os\n\nclass StableDiffusionTool(GradioTool):\n \"\"\"Tool for calling stable diffusion from llm\"\"\"\n\n def __init__(\n self,\n name=\"StableDiffusion\",\n description=(\n \"An image generator. Use this to generate images based on \"\n \"text input. Input should be a description of what the image should \"\n \"look like. The output will be a path to an image file.\"\n ),\n src=\"gradio-client-demos/stable-diffusion\",\n hf_token=None,\n ) -> None:\n super().__init__(name, description, src, hf_token)\n\n def create_job(self, query: str) -> Job:\n return self.client.submit(query, \"\", 9, fn_index=1)\n\n def postprocess(self, output: str) -> str:\n return [os.path.join(output, i) for i in os.listdir(output) if not i.endswith(\"json\")][0]\n\n def _block_input(self, gr) -> \"gr.components.Component\":\n return gr.Textbox()\n\n def _block_output(self, gr) -> \"gr.components.Component\":\n return gr.Image()\n```\n\nSome notes on this implementation:\n\n1. All instances of `GradioTool` have an attribute called `client` that is a pointed to the underlying [gradio client](https://github.com/gradio-app/gradio/tree/main/client/python#gradio_client-use-a-gradio-app-as-an-api----in-3-lines-of-python). That is what you should use\n in the `create_job` method.\n2. `create_job` just passes the query string to the `submit` function of the client with some other parameters hardcoded, i.e. the negative prompt string and the guidance scale. We could modify our tool to also accept these values from the input string in a subsequent version.\n3. The `postprocess` method simply returns the first image from the gallery of images created by the stable diffusion space. We use the `os` module to get the full path of the image." }, { "id": 446, "parent": 439, "path": "09_gradio-clients-and-lite/04_gradio-and-llm-agents.md", "level": 2, "title": "Conclusion", "content": "You now know how to extend the abilities of your LLM with the 1000s of gradio spaces running in the wild!\nAgain, we welcome any contributions to the [gradio_tools](https://github.com/freddyaboulton/gradio-tools) library.\nWe're excited to see the tools you all build!" }, { "id": 447, "parent": null, "path": "09_gradio-clients-and-lite/03_querying-gradio-apps-with-curl.md", "level": 1, "title": "Querying Gradio Apps with Curl", "content": "Tags: CURL, API, SPACES\n\nIt is possible to use any Gradio app as an API using cURL, the command-line tool that is pre-installed on many operating systems. This is particularly useful if you are trying to query a Gradio app from an environment other than Python or Javascript (since specialized Gradio clients exist for both [Python](/guides/getting-started-with-the-python-client) and [Javascript](/guides/getting-started-with-the-js-client)).\n\nAs an example, consider this Gradio demo that translates text from English to French: https://abidlabs-en2fr.hf.space/.\n\nUsing `curl`, we can translate text programmatically.\n\nHere's the code to do it:\n\n```bash\n$ curl -X POST https://abidlabs-en2fr.hf.space/call/predict -H \"Content-Type: application/json\" -d '{\n \"data\": [\"Hello, my friend.\"] \n}'\n\n>> {\"event_id\": $EVENT_ID} \n```\n\n```bash\n$ curl -N https://abidlabs-en2fr.hf.space/call/predict/$EVENT_ID\n\n>> event: complete\n>> data: [\"Bonjour, mon ami.\"]\n```\n\n\nNote: making a prediction and getting a result requires two `curl` requests: a `POST` and a `GET`. The `POST` request returns an `EVENT_ID` and prints it to the console, which is used in the second `GET` request to fetch the results. You can combine these into a single command using `awk` and `read` to parse the results of the first command and pipe into the second, like this:\n\n```bash\n$ curl -X POST https://abidlabs-en2fr.hf.space/call/predict -H \"Content-Type: application/json\" -d '{\n \"data\": [\"Hello, my friend.\"] \n}' \\\n | awk -F'\"' '{ print $4}' \\\n | read EVENT_ID; curl -N https://abidlabs-en2fr.hf.space/call/predict/$EVENT_ID\n\n>> event: complete\n>> data: [\"Bonjour, mon ami.\"]\n```\n\nIn the rest of this Guide, we'll explain these two steps in more detail and provide additional examples of querying Gradio apps with `curl`.\n\n\n**Prerequisites**: For this Guide, you do _not_ need to know how to build Gradio apps in great detail. However, it is helpful to have general familiarity with Gradio's concepts of input and output components." }, { "id": 448, "parent": 447, "path": "09_gradio-clients-and-lite/03_querying-gradio-apps-with-curl.md", "level": 2, "title": "Installation", "content": "You generally don't need to install cURL, as it comes pre-installed on many operating systems. Run:\n\n```bash\ncurl --version\n```\n\nto confirm that `curl` is installed. If it is not already installed, you can install it by visiting https://curl.se/download.html." }, { "id": 449, "parent": 447, "path": "09_gradio-clients-and-lite/03_querying-gradio-apps-with-curl.md", "level": 2, "title": "Step 0: Get the URL for your Gradio App ", "content": "To query a Gradio app, you'll need its full URL. This is usually just the URL that the Gradio app is hosted on, for example: https://bec81a83-5b5c-471e.gradio.live\n\n\n**Hugging Face Spaces**\n\nHowever, if you are querying a Gradio on Hugging Face Spaces, you will need to use the URL of the embedded Gradio app, not the URL of the Space webpage. For example:\n\n```bash\n❌ Space URL: https://huggingface.co/spaces/abidlabs/en2fr\n✅ Gradio app URL: https://abidlabs-en2fr.hf.space/\n```\n\nYou can get the Gradio app URL by clicking the \"view API\" link at the bottom of the page. Or, you can right-click on the page and then click on \"View Frame Source\" or the equivalent in your browser to view the URL of the embedded Gradio app.\n\nWhile you can use any public Space as an API, you may get rate limited by Hugging Face if you make too many requests. For unlimited usage of a Space, simply duplicate the Space to create a private Space,\nand then use it to make as many requests as you'd like!\n\nNote: to query private Spaces, you will need to pass in your Hugging Face (HF) token. You can get your HF token here: https://huggingface.co/settings/tokens. In this case, you will need to include an additional header in both of your `curl` calls that we'll discuss below:\n\n```bash\n-H \"Authorization: Bearer $HF_TOKEN\"\n```\n\nNow, we are ready to make the two `curl` requests." }, { "id": 450, "parent": 447, "path": "09_gradio-clients-and-lite/03_querying-gradio-apps-with-curl.md", "level": 2, "title": "Step 1: Make a Prediction (POST)", "content": "The first of the two `curl` requests is `POST` request that submits the input payload to the Gradio app. \n\nThe syntax of the `POST` request is as follows:\n\n```bash\n$ curl -X POST $URL/call/$API_NAME -H \"Content-Type: application/json\" -d '{\n \"data\": $PAYLOAD\n}'\n```\n\nHere:\n\n* `$URL` is the URL of the Gradio app as obtained in Step 0\n* `$API_NAME` is the name of the API endpoint for the event that you are running. You can get the API endpoint names by clicking the \"view API\" link at the bottom of the page.\n* `$PAYLOAD` is a valid JSON data list containing the input payload, one element for each input component.\n\nWhen you make this `POST` request successfully, you will get an event id that is printed to the terminal in this format:\n\n```bash\n>> {\"event_id\": $EVENT_ID} \n```\n\nThis `EVENT_ID` will be needed in the subsequent `curl` request to fetch the results of the prediction. \n\nHere are some examples of how to make the `POST` request\n\n**Basic Example**\n\nRevisiting the example at the beginning of the page, here is how to make the `POST` request for a simple Gradio application that takes in a single input text component:\n\n```bash\n$ curl -X POST https://abidlabs-en2fr.hf.space/call/predict -H \"Content-Type: application/json\" -d '{\n \"data\": [\"Hello, my friend.\"] \n}'\n```\n\n**Multiple Input Components**\n\nThis [Gradio demo](https://huggingface.co/spaces/gradio/hello_world_3) accepts three inputs: a string corresponding to the `gr.Textbox`, a boolean value corresponding to the `gr.Checkbox`, and a numerical value corresponding to the `gr.Slider`. Here is the `POST` request:\n\n```bash\ncurl -X POST https://gradio-hello-world-3.hf.space/call/predict -H \"Content-Type: application/json\" -d '{\n \"data\": [\"Hello\", true, 5]\n}'\n```\n\n**Private Spaces**\n\nAs mentioned earlier, if you are making a request to a private Space, you will need to pass in a [Hugging Face token](https://huggingface.co/settings/tokens) that has read access to the Space. The request will look like this:\n\n```bash\n$ curl -X POST https://private-space.hf.space/call/predict -H \"Content-Type: application/json\" -H \"Authorization: Bearer $HF_TOKEN\" -d '{\n \"data\": [\"Hello, my friend.\"] \n}'\n```\n\n**Files**\n\nIf you are using `curl` to query a Gradio application that requires file inputs, the files *need* to be provided as URLs, and The URL needs to be enclosed in a dictionary in this format:\n\n```bash\n{\"path\": $URL}\n```\n\nHere is an example `POST` request:\n\n```bash\n$ curl -X POST https://gradio-image-mod.hf.space/call/predict -H \"Content-Type: application/json\" -d '{\n \"data\": [{\"path\": \"https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png\"}] \n}'\n```\n\n\n**Stateful Demos**\n\nIf your Gradio demo [persists user state](/guides/interface-state) across multiple interactions (e.g. is a chatbot), you can pass in a `session_hash` alongside the `data`. Requests with the same `session_hash` are assumed to be part of the same user session. Here's how that might look:\n\n```bash" }, { "id": 451, "parent": null, "path": "09_gradio-clients-and-lite/03_querying-gradio-apps-with-curl.md", "level": 1, "title": "These two requests will share a session", "content": "curl -X POST https://gradio-chatinterface-random-response.hf.space/call/chat -H \"Content-Type: application/json\" -d '{\n \"data\": [\"Are you sentient?\"],\n \"session_hash\": \"randomsequence1234\"\n}'\n\ncurl -X POST https://gradio-chatinterface-random-response.hf.space/call/chat -H \"Content-Type: application/json\" -d '{\n \"data\": [\"Really?\"],\n \"session_hash\": \"randomsequence1234\"\n}'" }, { "id": 452, "parent": null, "path": "09_gradio-clients-and-lite/03_querying-gradio-apps-with-curl.md", "level": 1, "title": "This request will be treated as a new session", "content": "curl -X POST https://gradio-chatinterface-random-response.hf.space/call/chat -H \"Content-Type: application/json\" -d '{\n \"data\": [\"Are you sentient?\"],\n \"session_hash\": \"newsequence5678\"\n}'\n```" }, { "id": 453, "parent": 452, "path": "09_gradio-clients-and-lite/03_querying-gradio-apps-with-curl.md", "level": 2, "title": "Step 2: GET the result", "content": "Once you have received the `EVENT_ID` corresponding to your prediction, you can stream the results. Gradio stores these results in a least-recently-used cache in the Gradio app. By default, the cache can store 2,000 results (across all users and endpoints of the app). \n\nTo stream the results for your prediction, make a `GET` request with the following syntax:\n\n```bash\n$ curl -N $URL/call/$API_NAME/$EVENT_ID\n```\n\n\nTip: If you are fetching results from a private Space, include a header with your HF token like this: `-H \"Authorization: Bearer $HF_TOKEN\"` in the `GET` request.\n\nThis should produce a stream of responses in this format:\n\n```bash\nevent: ... \ndata: ...\nevent: ... \ndata: ...\n...\n```\n\nHere: `event` can be one of the following:\n* `generating`: indicating an intermediate result\n* `complete`: indicating that the prediction is complete and the final result \n* `error`: indicating that the prediction was not completed successfully\n* `heartbeat`: sent every 15 seconds to keep the request alive\n\nThe `data` is in the same format as the input payload: valid JSON data list containing the output result, one element for each output component.\n\nHere are some examples of what results you should expect if a request is completed successfully:\n\n**Basic Example**\n\nRevisiting the example at the beginning of the page, we would expect the result to look like this:\n\n```bash\nevent: complete\ndata: [\"Bonjour, mon ami.\"]\n```\n\n**Multiple Outputs**\n\nIf your endpoint returns multiple values, they will appear as elements of the `data` list:\n\n```bash\nevent: complete\ndata: [\"Good morning Hello. It is 5 degrees today\", -15.0]\n```\n\n**Streaming Example**\n\nIf your Gradio app [streams a sequence of values](/guides/streaming-outputs), then they will be streamed directly to your terminal, like this:\n\n```bash\nevent: generating\ndata: [\"Hello, w!\"]\nevent: generating\ndata: [\"Hello, wo!\"]\nevent: generating\ndata: [\"Hello, wor!\"]\nevent: generating\ndata: [\"Hello, worl!\"]\nevent: generating\ndata: [\"Hello, world!\"]\nevent: complete\ndata: [\"Hello, world!\"]\n```\n\n**File Example**\n\nIf your Gradio app returns a file, the file will be represented as a dictionary in this format (including potentially some additional keys):\n\n```python\n{\n \"orig_name\": \"example.jpg\",\n \"path\": \"/path/in/server.jpg\",\n \"url\": \"https:/example.com/example.jpg\",\n \"meta\": {\"_type\": \"gradio.FileData\"}\n}\n```\n\nIn your terminal, it may appear like this:\n\n```bash\nevent: complete\ndata: [{\"path\": \"/tmp/gradio/359933dc8d6cfe1b022f35e2c639e6e42c97a003/image.webp\", \"url\": \"https://gradio-image-mod.hf.space/c/file=/tmp/gradio/359933dc8d6cfe1b022f35e2c639e6e42c97a003/image.webp\", \"size\": null, \"orig_name\": \"image.webp\", \"mime_type\": null, \"is_stream\": false, \"meta\": {\"_type\": \"gradio.FileData\"}}]\n```" }, { "id": 454, "parent": 452, "path": "09_gradio-clients-and-lite/03_querying-gradio-apps-with-curl.md", "level": 2, "title": "Authentication", "content": "What if your Gradio application has [authentication enabled](/guides/sharing-your-app#authentication)? In that case, you'll need to make an additional `POST` request with cURL to authenticate yourself before you make any queries. Here are the complete steps:\n\nFirst, login with a `POST` request supplying a valid username and password:\n\n```bash\ncurl -X POST $URL/login \\\n -d \"username=$USERNAME&password=$PASSWORD\" \\\n -c cookies.txt\n```\n\nIf the credentials are correct, you'll get `{\"success\":true}` in response and the cookies will be saved in `cookies.txt`.\n\nNext, you'll need to include these cookies when you make the original `POST` request, like this:\n\n```bash\n$ curl -X POST $URL/call/$API_NAME -b cookies.txt -H \"Content-Type: application/json\" -d '{\n \"data\": $PAYLOAD\n}'\n```\n\nFinally, you'll need to `GET` the results, again supplying the cookies from the file:\n\n```bash\ncurl -N $URL/call/$API_NAME/$EVENT_ID -b cookies.txt\n```" }, { "id": 455, "parent": null, "path": "09_gradio-clients-and-lite/06_gradio-lite-and-transformers-js.md", "level": 1, "title": "Building Serverless Machine Learning Apps with Gradio-Lite and Transformers.js", "content": "Tags: SERVERLESS, BROWSER, PYODIDE, TRANSFORMERS\n\nGradio and [Transformers](https://huggingface.co/docs/transformers/index) are a powerful combination for building machine learning apps with a web interface. Both libraries have serverless versions that can run entirely in the browser: [Gradio-Lite](./gradio-lite) and [Transformers.js](https://huggingface.co/docs/transformers.js/index).\nIn this document, we will introduce how to create a serverless machine learning application using Gradio-Lite and Transformers.js.\nYou will just write Python code within a static HTML file and host it without setting up a server-side Python runtime." }, { "id": 456, "parent": 455, "path": "09_gradio-clients-and-lite/06_gradio-lite-and-transformers-js.md", "level": 2, "title": "Libraries Used", "content": "" }, { "id": 457, "parent": 456, "path": "09_gradio-clients-and-lite/06_gradio-lite-and-transformers-js.md", "level": 3, "title": "Gradio-Lite", "content": "Gradio-Lite is the serverless version of Gradio, allowing you to build serverless web UI applications by embedding Python code within HTML. For a detailed introduction to Gradio-Lite itself, please read [this Guide](./gradio-lite)." }, { "id": 458, "parent": 456, "path": "09_gradio-clients-and-lite/06_gradio-lite-and-transformers-js.md", "level": 3, "title": "Transformers.js and Transformers.js.py", "content": "Transformers.js is the JavaScript version of the Transformers library that allows you to run machine learning models entirely in the browser.\nSince Transformers.js is a JavaScript library, it cannot be directly used from the Python code of Gradio-Lite applications. To address this, we use a wrapper library called [Transformers.js.py](https://github.com/whitphx/transformers.js.py).\nThe name Transformers.js.py may sound unusual, but it represents the necessary technology stack for using Transformers.js from Python code within a browser environment. The regular Transformers library is not compatible with browser environments." }, { "id": 459, "parent": 455, "path": "09_gradio-clients-and-lite/06_gradio-lite-and-transformers-js.md", "level": 2, "title": "Sample Code", "content": "Here's an example of how to use Gradio-Lite and Transformers.js together.\nPlease create an HTML file and paste the following code:\n\n```html\n\n\t\n\t\t\n\t\t\n\t\n\t\n\t\t\nimport gradio as gr\nfrom transformers_js_py import pipeline\n\npipe = await pipeline('sentiment-analysis')\n\ndemo = gr.Interface.from_pipeline(pipe)\n\ndemo.launch()\n\n\t\t\t\ntransformers-js-py\n\t\t\t\n\t\t\n\t\n\n```\n\nHere is a running example of the code above (after the app has loaded, you could disconnect your Internet connection and the app will still work since its running entirely in your browser):\n\n\nimport gradio as gr\nfrom transformers_js_py import pipeline\n\npipe = await pipeline('sentiment-analysis')\n\ndemo = gr.Interface.from_pipeline(pipe)\n\ndemo.launch()\n\ntransformers-js-py\n\n\n\nAnd you you can open your HTML file in a browser to see the Gradio app running!\n\nThe Python code inside the `` tag is the Gradio application code. For more details on this part, please refer to [this article](./gradio-lite).\nThe `` tag is used to specify packages to be installed in addition to Gradio-Lite and its dependencies. In this case, we are using Transformers.js.py (`transformers-js-py`), so it is specified here.\n\nLet's break down the code:\n\n`pipe = await pipeline('sentiment-analysis')` creates a Transformers.js pipeline.\nIn this example, we create a sentiment analysis pipeline.\nFor more information on the available pipeline types and usage, please refer to the [Transformers.js documentation](https://huggingface.co/docs/transformers.js/index).\n\n`demo = gr.Interface.from_pipeline(pipe)` creates a Gradio app instance. By passing the Transformers.js.py pipeline to `gr.Interface.from_pipeline()`, we can create an interface that utilizes that pipeline with predefined input and output components.\n\nFinally, `demo.launch()` launches the created app." }, { "id": 460, "parent": 455, "path": "09_gradio-clients-and-lite/06_gradio-lite-and-transformers-js.md", "level": 2, "title": "Customizing the Model or Pipeline", "content": "You can modify the line `pipe = await pipeline('sentiment-analysis')` in the sample above to try different models or tasks.\n\nFor example, if you change it to `pipe = await pipeline('sentiment-analysis', 'Xenova/bert-base-multilingual-uncased-sentiment')`, you can test the same sentiment analysis task but with a different model. The second argument of the `pipeline` function specifies the model name.\nIf it's not specified like in the first example, the default model is used. For more details on these specs, refer to the [Transformers.js documentation](https://huggingface.co/docs/transformers.js/index).\n\n\nimport gradio as gr\nfrom transformers_js_py import pipeline\n\npipe = await pipeline('sentiment-analysis', 'Xenova/bert-base-multilingual-uncased-sentiment')\n\ndemo = gr.Interface.from_pipeline(pipe)\n\ndemo.launch()\n\ntransformers-js-py\n\n\n\nAs another example, changing it to `pipe = await pipeline('image-classification')` creates a pipeline for image classification instead of sentiment analysis.\nIn this case, the interface created with `demo = gr.Interface.from_pipeline(pipe)` will have a UI for uploading an image and displaying the classification result. The `gr.Interface.from_pipeline` function automatically creates an appropriate UI based on the type of pipeline.\n\n\nimport gradio as gr\nfrom transformers_js_py import pipeline\n\npipe = await pipeline('image-classification')\n\ndemo = gr.Interface.from_pipeline(pipe)\n\ndemo.launch()\n\ntransformers-js-py\n\n\n\n
\n\n**Note**: If you use an audio pipeline, such as `automatic-speech-recognition`, you will need to put `transformers-js-py[audio]` in your `` as there are additional requirements needed to process audio files." }, { "id": 461, "parent": 455, "path": "09_gradio-clients-and-lite/06_gradio-lite-and-transformers-js.md", "level": 2, "title": "Customizing the UI", "content": "Instead of using `gr.Interface.from_pipeline()`, you can define the user interface using Gradio's regular API.\nHere's an example where the Python code inside the `` tag has been modified from the previous sample:\n\n```html\n\n\t\n\t\t\n\t\t\n\t\n\t\n\t\t\nimport gradio as gr\nfrom transformers_js_py import pipeline\n\npipe = await pipeline('sentiment-analysis')\n\nasync def fn(text):\n\tresult = await pipe(text)\n\treturn result\n\ndemo = gr.Interface(\n\tfn=fn,\n\tinputs=gr.Textbox(),\n\toutputs=gr.JSON(),\n)\n\ndemo.launch()\n\n\t\t\t\ntransformers-js-py\n\t\t\t\n\t\t\n\t\n\n```\n\nIn this example, we modified the code to construct the Gradio user interface manually so that we could output the result as JSON.\n\n\nimport gradio as gr\nfrom transformers_js_py import pipeline\n\npipe = await pipeline('sentiment-analysis')\n\nasync def fn(text):\n\tresult = await pipe(text)\n\treturn result\n\ndemo = gr.Interface(\n\tfn=fn,\n\tinputs=gr.Textbox(),\n\toutputs=gr.JSON(),\n)\n\ndemo.launch()\n\ntransformers-js-py\n\n" }, { "id": 462, "parent": 455, "path": "09_gradio-clients-and-lite/06_gradio-lite-and-transformers-js.md", "level": 2, "title": "Conclusion", "content": "By combining Gradio-Lite and Transformers.js (and Transformers.js.py), you can create serverless machine learning applications that run entirely in the browser.\n\nGradio-Lite provides a convenient method to create an interface for a given Transformers.js pipeline, `gr.Interface.from_pipeline()`.\nThis method automatically constructs the interface based on the pipeline's task type.\n\nAlternatively, you can define the interface manually using Gradio's regular API, as shown in the second example.\n\nBy using these libraries, you can build and deploy machine learning applications without the need for server-side Python setup or external dependencies." }, { "id": 463, "parent": null, "path": "09_gradio-clients-and-lite/01_getting-started-with-the-python-client.md", "level": 1, "title": "Getting Started with the Gradio Python client", "content": "Tags: CLIENT, API, SPACES\n\nThe Gradio Python client makes it very easy to use any Gradio app as an API. As an example, consider this [Hugging Face Space that transcribes audio files](https://huggingface.co/spaces/abidlabs/whisper) that are recorded from the microphone.\n\n![](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/gradio-guides/whisper-screenshot.jpg)\n\nUsing the `gradio_client` library, we can easily use the Gradio as an API to transcribe audio files programmatically.\n\nHere's the entire code to do it:\n\n```python\nfrom gradio_client import Client, handle_file\n\nclient = Client(\"abidlabs/whisper\")\n\nclient.predict(\n audio=handle_file(\"audio_sample.wav\")\n)\n\n>> \"This is a test of the whisper speech recognition model.\"\n```\n\nThe Gradio client works with any hosted Gradio app! Although the Client is mostly used with apps hosted on [Hugging Face Spaces](https://hf.space), your app can be hosted anywhere, such as your own server.\n\n**Prerequisites**: To use the Gradio client, you do _not_ need to know the `gradio` library in great detail. However, it is helpful to have general familiarity with Gradio's concepts of input and output components." }, { "id": 464, "parent": 463, "path": "09_gradio-clients-and-lite/01_getting-started-with-the-python-client.md", "level": 2, "title": "Installation", "content": "If you already have a recent version of `gradio`, then the `gradio_client` is included as a dependency. But note that this documentation reflects the latest version of the `gradio_client`, so upgrade if you're not sure!\n\nThe lightweight `gradio_client` package can be installed from pip (or pip3) and is tested to work with **Python versions 3.10 or higher**:\n\n```bash\n$ pip install --upgrade gradio_client\n```" }, { "id": 465, "parent": 463, "path": "09_gradio-clients-and-lite/01_getting-started-with-the-python-client.md", "level": 2, "title": "Connecting to a Gradio App on Hugging Face Spaces", "content": "Start by connecting instantiating a `Client` object and connecting it to a Gradio app that is running on Hugging Face Spaces.\n\n```python\nfrom gradio_client import Client\n\nclient = Client(\"abidlabs/en2fr\") # a Space that translates from English to French\n```\n\nYou can also connect to private Spaces by passing in your HF token with the `hf_token` parameter. You can get your HF token here: https://huggingface.co/settings/tokens\n\n```python\nfrom gradio_client import Client\n\nclient = Client(\"abidlabs/my-private-space\", hf_token=\"...\")\n```" }, { "id": 466, "parent": 463, "path": "09_gradio-clients-and-lite/01_getting-started-with-the-python-client.md", "level": 2, "title": "Duplicating a Space for private use", "content": "While you can use any public Space as an API, you may get rate limited by Hugging Face if you make too many requests. For unlimited usage of a Space, simply duplicate the Space to create a private Space,\nand then use it to make as many requests as you'd like!\n\nThe `gradio_client` includes a class method: `Client.duplicate()` to make this process simple (you'll need to pass in your [Hugging Face token](https://huggingface.co/settings/tokens) or be logged in using the Hugging Face CLI):\n\n```python\nimport os\nfrom gradio_client import Client, handle_file\n\nHF_TOKEN = os.environ.get(\"HF_TOKEN\")\n\nclient = Client.duplicate(\"abidlabs/whisper\", hf_token=HF_TOKEN)\nclient.predict(handle_file(\"audio_sample.wav\"))\n\n>> \"This is a test of the whisper speech recognition model.\"\n```\n\nIf you have previously duplicated a Space, re-running `duplicate()` will _not_ create a new Space. Instead, the Client will attach to the previously-created Space. So it is safe to re-run the `Client.duplicate()` method multiple times.\n\n**Note:** if the original Space uses GPUs, your private Space will as well, and your Hugging Face account will get billed based on the price of the GPU. To minimize charges, your Space will automatically go to sleep after 1 hour of inactivity. You can also set the hardware using the `hardware` parameter of `duplicate()`." }, { "id": 467, "parent": 463, "path": "09_gradio-clients-and-lite/01_getting-started-with-the-python-client.md", "level": 2, "title": "Connecting a general Gradio app", "content": "If your app is running somewhere else, just provide the full URL instead, including the \"http://\" or \"https://\". Here's an example of making predictions to a Gradio app that is running on a share URL:\n\n```python\nfrom gradio_client import Client\n\nclient = Client(\"https://bec81a83-5b5c-471e.gradio.live\")\n```" }, { "id": 468, "parent": 463, "path": "09_gradio-clients-and-lite/01_getting-started-with-the-python-client.md", "level": 2, "title": "Connecting to a Gradio app with auth", "content": "If the Gradio application you are connecting to [requires a username and password](/guides/sharing-your-app#authentication), then provide them as a tuple to the `auth` argument of the `Client` class:\n\n```python\nfrom gradio_client import Client\n\nClient(\n space_name,\n auth=[username, password]\n)\n```" }, { "id": 469, "parent": 463, "path": "09_gradio-clients-and-lite/01_getting-started-with-the-python-client.md", "level": 2, "title": "Inspecting the API endpoints", "content": "Once you have connected to a Gradio app, you can view the APIs that are available to you by calling the `Client.view_api()` method. For the Whisper Space, we see the following:\n\n```bash\nClient.predict() Usage Info\n---------------------------\nNamed API endpoints: 1\n\n - predict(audio, api_name=\"/predict\") -> output\n Parameters:\n - [Audio] audio: filepath (required) \n Returns:\n - [Textbox] output: str \n```\n\nWe see that we have 1 API endpoint in this space, and shows us how to use the API endpoint to make a prediction: we should call the `.predict()` method (which we will explore below), providing a parameter `input_audio` of type `str`, which is a `filepath or URL`.\n\nWe should also provide the `api_name='/predict'` argument to the `predict()` method. Although this isn't necessary if a Gradio app has only 1 named endpoint, it does allow us to call different endpoints in a single app if they are available." }, { "id": 470, "parent": 463, "path": "09_gradio-clients-and-lite/01_getting-started-with-the-python-client.md", "level": 2, "title": "The \"View API\" Page", "content": "As an alternative to running the `.view_api()` method, you can click on the \"Use via API\" link in the footer of the Gradio app, which shows us the same information, along with example usage. \n\n![](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/gradio-guides/view-api.png)\n\nThe View API page also includes an \"API Recorder\" that lets you interact with the Gradio UI normally and converts your interactions into the corresponding code to run with the Python Client." }, { "id": 471, "parent": 463, "path": "09_gradio-clients-and-lite/01_getting-started-with-the-python-client.md", "level": 2, "title": "Making a prediction", "content": "The simplest way to make a prediction is simply to call the `.predict()` function with the appropriate arguments:\n\n```python\nfrom gradio_client import Client\n\nclient = Client(\"abidlabs/en2fr\", api_name='/predict')\nclient.predict(\"Hello\")\n\n>> Bonjour\n```\n\nIf there are multiple parameters, then you should pass them as separate arguments to `.predict()`, like this:\n\n```python\nfrom gradio_client import Client\n\nclient = Client(\"gradio/calculator\")\nclient.predict(4, \"add\", 5)\n\n>> 9.0\n```\n\nIt is recommended to provide key-word arguments instead of positional arguments:\n\n\n```python\nfrom gradio_client import Client\n\nclient = Client(\"gradio/calculator\")\nclient.predict(num1=4, operation=\"add\", num2=5)\n\n>> 9.0\n```\n\nThis allows you to take advantage of default arguments. For example, this Space includes the default value for the Slider component so you do not need to provide it when accessing it with the client.\n\n```python\nfrom gradio_client import Client\n\nclient = Client(\"abidlabs/image_generator\")\nclient.predict(text=\"an astronaut riding a camel\")\n```\n\nThe default value is the initial value of the corresponding Gradio component. If the component does not have an initial value, but if the corresponding argument in the predict function has a default value of `None`, then that parameter is also optional in the client. Of course, if you'd like to override it, you can include it as well:\n\n```python\nfrom gradio_client import Client\n\nclient = Client(\"abidlabs/image_generator\")\nclient.predict(text=\"an astronaut riding a camel\", steps=25)\n```\n\nFor providing files or URLs as inputs, you should pass in the filepath or URL to the file enclosed within `gradio_client.handle_file()`. This takes care of uploading the file to the Gradio server and ensures that the file is preprocessed correctly:\n\n```python\nfrom gradio_client import Client, handle_file\n\nclient = Client(\"abidlabs/whisper\")\nclient.predict(\n audio=handle_file(\"https://audio-samples.github.io/samples/mp3/blizzard_unconditional/sample-0.mp3\")\n)\n\n>> \"My thought I have nobody by a beauty and will as you poured. Mr. Rochester is serve in that so don't find simpus, and devoted abode, to at might in a r—\"\n```" }, { "id": 472, "parent": 463, "path": "09_gradio-clients-and-lite/01_getting-started-with-the-python-client.md", "level": 2, "title": "Running jobs asynchronously", "content": "Oe should note that `.predict()` is a _blocking_ operation as it waits for the operation to complete before returning the prediction.\n\nIn many cases, you may be better off letting the job run in the background until you need the results of the prediction. You can do this by creating a `Job` instance using the `.submit()` method, and then later calling `.result()` on the job to get the result. For example:\n\n```python\nfrom gradio_client import Client\n\nclient = Client(space=\"abidlabs/en2fr\")\njob = client.submit(\"Hello\", api_name=\"/predict\") # This is not blocking" }, { "id": 473, "parent": null, "path": "09_gradio-clients-and-lite/01_getting-started-with-the-python-client.md", "level": 1, "title": "Do something else", "content": "job.result() # This is blocking\n\n>> Bonjour\n```" }, { "id": 474, "parent": 473, "path": "09_gradio-clients-and-lite/01_getting-started-with-the-python-client.md", "level": 2, "title": "Adding callbacks", "content": "Alternatively, one can add one or more callbacks to perform actions after the job has completed running, like this:\n\n```python\nfrom gradio_client import Client\n\ndef print_result(x):\n print(\"The translated result is: {x}\")\n\nclient = Client(space=\"abidlabs/en2fr\")\n\njob = client.submit(\"Hello\", api_name=\"/predict\", result_callbacks=[print_result])" }, { "id": 475, "parent": null, "path": "09_gradio-clients-and-lite/01_getting-started-with-the-python-client.md", "level": 1, "title": "Do something else", "content": ">> The translated result is: Bonjour\n\n```" }, { "id": 476, "parent": 475, "path": "09_gradio-clients-and-lite/01_getting-started-with-the-python-client.md", "level": 2, "title": "Status", "content": "The `Job` object also allows you to get the status of the running job by calling the `.status()` method. This returns a `StatusUpdate` object with the following attributes: `code` (the status code, one of a set of defined strings representing the status. See the `utils.Status` class), `rank` (the current position of this job in the queue), `queue_size` (the total queue size), `eta` (estimated time this job will complete), `success` (a boolean representing whether the job completed successfully), and `time` (the time that the status was generated).\n\n```py\nfrom gradio_client import Client\n\nclient = Client(src=\"gradio/calculator\")\njob = client.submit(5, \"add\", 4, api_name=\"/predict\")\njob.status()\n\n>> \n```\n\n_Note_: The `Job` class also has a `.done()` instance method which returns a boolean indicating whether the job has completed." }, { "id": 477, "parent": 475, "path": "09_gradio-clients-and-lite/01_getting-started-with-the-python-client.md", "level": 2, "title": "Cancelling Jobs", "content": "The `Job` class also has a `.cancel()` instance method that cancels jobs that have been queued but not started. For example, if you run:\n\n```py\nclient = Client(\"abidlabs/whisper\")\njob1 = client.submit(handle_file(\"audio_sample1.wav\"))\njob2 = client.submit(handle_file(\"audio_sample2.wav\"))\njob1.cancel() # will return False, assuming the job has started\njob2.cancel() # will return True, indicating that the job has been canceled\n```\n\nIf the first job has started processing, then it will not be canceled. If the second job\nhas not yet started, it will be successfully canceled and removed from the queue." }, { "id": 478, "parent": 475, "path": "09_gradio-clients-and-lite/01_getting-started-with-the-python-client.md", "level": 2, "title": "Generator Endpoints", "content": "Some Gradio API endpoints do not return a single value, rather they return a series of values. You can get the series of values that have been returned at any time from such a generator endpoint by running `job.outputs()`:\n\n```py\nfrom gradio_client import Client\n\nclient = Client(src=\"gradio/count_generator\")\njob = client.submit(3, api_name=\"/count\")\nwhile not job.done():\n time.sleep(0.1)\njob.outputs()\n\n>> ['0', '1', '2']\n```\n\nNote that running `job.result()` on a generator endpoint only gives you the _first_ value returned by the endpoint.\n\nThe `Job` object is also iterable, which means you can use it to display the results of a generator function as they are returned from the endpoint. Here's the equivalent example using the `Job` as a generator:\n\n```py\nfrom gradio_client import Client\n\nclient = Client(src=\"gradio/count_generator\")\njob = client.submit(3, api_name=\"/count\")\n\nfor o in job:\n print(o)\n\n>> 0\n>> 1\n>> 2\n```\n\nYou can also cancel jobs that that have iterative outputs, in which case the job will finish as soon as the current iteration finishes running.\n\n```py\nfrom gradio_client import Client\nimport time\n\nclient = Client(\"abidlabs/test-yield\")\njob = client.submit(\"abcdef\")\ntime.sleep(3)\njob.cancel() # job cancels after 2 iterations\n```" }, { "id": 479, "parent": 475, "path": "09_gradio-clients-and-lite/01_getting-started-with-the-python-client.md", "level": 2, "title": "Demos with Session State", "content": "Gradio demos can include [session state](https://www.gradio.app/guides/state-in-blocks), which provides a way for demos to persist information from user interactions within a page session.\n\nFor example, consider the following demo, which maintains a list of words that a user has submitted in a `gr.State` component. When a user submits a new word, it is added to the state, and the number of previous occurrences of that word is displayed:\n\n```python\nimport gradio as gr\n\ndef count(word, list_of_words):\n return list_of_words.count(word), list_of_words + [word]\n\nwith gr.Blocks() as demo:\n words = gr.State([])\n textbox = gr.Textbox()\n number = gr.Number()\n textbox.submit(count, inputs=[textbox, words], outputs=[number, words])\n \ndemo.launch()\n```\n\nIf you were to connect this this Gradio app using the Python Client, you would notice that the API information only shows a single input and output:\n\n```csv\nClient.predict() Usage Info\n---------------------------\nNamed API endpoints: 1\n\n - predict(word, api_name=\"/count\") -> value_31\n Parameters:\n - [Textbox] word: str (required) \n Returns:\n - [Number] value_31: float \n```\n\nThat is because the Python client handles state automatically for you -- as you make a series of requests, the returned state from one request is stored internally and automatically supplied for the subsequent request. If you'd like to reset the state, you can do that by calling `Client.reset_session()`." }, { "id": 480, "parent": null, "path": "04_additional-features/10_resource-cleanup.md", "level": 1, "title": "Resource Cleanup", "content": "Your Gradio application may create resources during its lifetime.\nExamples of resources are `gr.State` variables, any variables you create and explicitly hold in memory, or files you save to disk. \nOver time, these resources can use up all of your server's RAM or disk space and crash your application.\n\nGradio provides some tools for you to clean up the resources created by your app:\n\n1. Automatic deletion of `gr.State` variables.\n2. Automatic cache cleanup with the `delete_cache` parameter.\n2. The `Blocks.unload` event.\n\nLet's take a look at each of them individually." }, { "id": 481, "parent": 480, "path": "04_additional-features/10_resource-cleanup.md", "level": 2, "title": "Automatic deletion of `gr.State`", "content": "When a user closes their browser tab, Gradio will automatically delete any `gr.State` variables associated with that user session after 60 minutes. If the user connects again within those 60 minutes, no state will be deleted.\n\nYou can control the deletion behavior further with the following two parameters of `gr.State`:\n\n1. `delete_callback` - An arbitrary function that will be called when the variable is deleted. This function must take the state value as input. This function is useful for deleting variables from GPU memory.\n2. `time_to_live` - The number of seconds the state should be stored for after it is created or updated. This will delete variables before the session is closed, so it's useful for clearing state for potentially long running sessions." }, { "id": 482, "parent": 480, "path": "04_additional-features/10_resource-cleanup.md", "level": 2, "title": "Automatic cache cleanup via `delete_cache`", "content": "Your Gradio application will save uploaded and generated files to a special directory called the cache directory. Gradio uses a hashing scheme to ensure that duplicate files are not saved to the cache but over time the size of the cache will grow (especially if your app goes viral 😉).\n\nGradio can periodically clean up the cache for you if you specify the `delete_cache` parameter of `gr.Blocks()`, `gr.Interface()`, or `gr.ChatInterface()`. \nThis parameter is a tuple of the form `[frequency, age]` both expressed in number of seconds.\nEvery `frequency` seconds, the temporary files created by this Blocks instance will be deleted if more than `age` seconds have passed since the file was created. \nFor example, setting this to (86400, 86400) will delete temporary files every day if they are older than a day old.\nAdditionally, the cache will be deleted entirely when the server restarts." }, { "id": 483, "parent": 480, "path": "04_additional-features/10_resource-cleanup.md", "level": 2, "title": "The `unload` event", "content": "Additionally, Gradio now includes a `Blocks.unload()` event, allowing you to run arbitrary cleanup functions when users disconnect (this does not have a 60 minute delay).\nUnlike other gradio events, this event does not accept inputs or outptus.\nYou can think of the `unload` event as the opposite of the `load` event." }, { "id": 484, "parent": 480, "path": "04_additional-features/10_resource-cleanup.md", "level": 2, "title": "Putting it all together", "content": "The following demo uses all of these features. When a user visits the page, a special unique directory is created for that user.\nAs the user interacts with the app, images are saved to disk in that special directory.\nWhen the user closes the page, the images created in that session are deleted via the `unload` event.\nThe state and files in the cache are cleaned up automatically as well.\n\n```py\nfrom __future__ import annotations\nimport gradio as gr\nimport numpy as np\nfrom PIL import Image\nfrom pathlib import Path\nimport secrets\nimport shutil\n\ncurrent_dir = Path(__file__).parent\n\ndef generate_random_img(history: list[Image.Image], request: gr.Request):\n \"\"\"Generate a random red, green, blue, orange, yellor or purple image.\"\"\"\n colors = [(255, 0, 0), (0, 255, 0), (0, 0, 255), (255, 165, 0), (255, 255, 0), (128, 0, 128)]\n color = colors[np.random.randint(0, len(colors))]\n img = Image.new('RGB', (100, 100), color)\n\n user_dir: Path = current_dir / str(request.session_hash)\n user_dir.mkdir(exist_ok=True)\n path = user_dir / f\"{secrets.token_urlsafe(8)}.webp\"\n\n img.save(path)\n history.append(img)\n\n return img, history, history\n\ndef delete_directory(req: gr.Request):\n if not req.username:\n return\n user_dir: Path = current_dir / req.username\n shutil.rmtree(str(user_dir))\n\nwith gr.Blocks(delete_cache=(60, 3600)) as demo:\n gr.Markdown(\"\"\"# State Cleanup Demo\n 🖼️ Images are saved in a user-specific directory and deleted when the users closes the page via demo.unload.\n \"\"\")\n with gr.Row():\n with gr.Column(scale=1):\n with gr.Row():\n img = gr.Image(label=\"Generated Image\", height=300, width=300)\n with gr.Row():\n gen = gr.Button(value=\"Generate\")\n with gr.Row():\n history = gr.Gallery(label=\"Previous Generations\", height=500, columns=10)\n state = gr.State(value=[], delete_callback=lambda v: print(\"STATE DELETED\"))\n\n demo.load(generate_random_img, [state], [img, state, history])\n gen.click(generate_random_img, [state], [img, state, history])\n demo.unload(delete_directory)\n\ndemo.launch()\n\n```\n$demo_state_cleanup" }, { "id": 485, "parent": null, "path": "04_additional-features/04_alerts.md", "level": 1, "title": "Alerts", "content": "You may wish to display alerts to the user. To do so, raise a `gr.Error(\"custom message\")` in your function to halt the execution of your function and display an error message to the user.\n\nYou can also issue `gr.Warning(\"custom message\")` or `gr.Info(\"custom message\")` by having them as standalone lines in your function, which will immediately display modals while continuing the execution of your function. The only difference between `gr.Info()` and `gr.Warning()` is the color of the alert. \n\n```python\ndef start_process(name):\n gr.Info(\"Starting process\")\n if name is None:\n gr.Warning(\"Name is empty\")\n ...\n if success == False:\n raise gr.Error(\"Process failed\")\n```\n\nTip: Note that `gr.Error()` is an exception that has to be raised, while `gr.Warning()` and `gr.Info()` are functions that are called directly." }, { "id": 486, "parent": null, "path": "04_additional-features/06_batch-functions.md", "level": 1, "title": "Batch functions", "content": "Gradio supports the ability to pass _batch_ functions. Batch functions are just\nfunctions which take in a list of inputs and return a list of predictions.\n\nFor example, here is a batched function that takes in two lists of inputs (a list of\nwords and a list of ints), and returns a list of trimmed words as output:\n\n```py\nimport time\n\ndef trim_words(words, lens):\n trimmed_words = []\n time.sleep(5)\n for w, l in zip(words, lens):\n trimmed_words.append(w[:int(l)])\n return [trimmed_words]\n```\n\nThe advantage of using batched functions is that if you enable queuing, the Gradio server can automatically _batch_ incoming requests and process them in parallel,\npotentially speeding up your demo. Here's what the Gradio code looks like (notice the `batch=True` and `max_batch_size=16`)\n\nWith the `gr.Interface` class:\n\n```python\ndemo = gr.Interface(\n fn=trim_words, \n inputs=[\"textbox\", \"number\"], \n outputs=[\"output\"],\n batch=True, \n max_batch_size=16\n)\n\ndemo.launch()\n```\n\nWith the `gr.Blocks` class:\n\n```py\nimport gradio as gr\n\nwith gr.Blocks() as demo:\n with gr.Row():\n word = gr.Textbox(label=\"word\")\n leng = gr.Number(label=\"leng\")\n output = gr.Textbox(label=\"Output\")\n with gr.Row():\n run = gr.Button()\n\n event = run.click(trim_words, [word, leng], output, batch=True, max_batch_size=16)\n\ndemo.launch()\n```\n\nIn the example above, 16 requests could be processed in parallel (for a total inference time of 5 seconds), instead of each request being processed separately (for a total\ninference time of 80 seconds). Many Hugging Face `transformers` and `diffusers` models work very naturally with Gradio's batch mode: here's [an example demo using diffusers to\ngenerate images in batches](https://github.com/gradio-app/gradio/blob/main/demo/diffusers_with_batching/run.py)" }, { "id": 487, "parent": null, "path": "04_additional-features/08_file-access.md", "level": 1, "title": "Security and File Access", "content": "Sharing your Gradio app with others (by hosting it on Spaces, on your own server, or through temporary share links) **exposes** certain files on your machine to the internet.\n\nThis guide explains which files are exposed as well as some best practices for making sure the files on your machine are secure." }, { "id": 488, "parent": 487, "path": "04_additional-features/08_file-access.md", "level": 2, "title": "Files Gradio allows users to access ", "content": "- **Static files that you explicitly set via the `gr.set_static_paths` function**. This parameter allows you to pass in a list of directories or filenames that will be considered static. This means that they will not be copied to the cache and will be served directly from your computer. This can help save disk space and reduce the time your app takes to launch but be mindful of possible security implications. (By default, this parameter is an empty list).\n\n\n- **Files in the `allowed_paths` parameter in `launch()`**. This parameter allows you to pass in a list of additional directories or exact filepaths you'd like to allow users to have access to. (By default, this parameter is an empty list).\n\n- **Files in Gradio's cache**. After you launch your Gradio app, Gradio copies certain files into a temporary cache and makes these files accessible to users. Let's unpack this in more detail below." }, { "id": 489, "parent": 487, "path": "04_additional-features/08_file-access.md", "level": 2, "title": "The Gradio cache", "content": "First, it's important to understand why Gradio has a cache at all. Gradio copies files to a cache directory before returning them to the frontend. This prevents files from being overwritten by one user while they are still needed by another user of your application. For example, if your prediction function returns a video file, then Gradio will move that video to the cache after your prediction function runs and returns a URL the frontend can use to show the video. Any file in the cache is available via URL to all users of your running application.\n\nTip: You can customize the location of the cache by setting the `GRADIO_TEMP_DIR` environment variable to an absolute path, such as `/home/usr/scripts/project/temp/`." }, { "id": 490, "parent": 489, "path": "04_additional-features/08_file-access.md", "level": 3, "title": "Files Gradio moves to the cache", "content": "Gradio moves three kinds of files into the cache\n\n1. Files specified by the developer before runtime, e.g. cached examples, default values of components, or files passed into parameters such as the `avatar_images` of `gr.Chatbot`\n2. File paths returned by a prediction function in your Gradio application, if they ALSO meet one of the conditions below:\n\n\n* It is in the `allowed_paths` parameter of the `Blocks.launch` method.\n* It is in the current working directory of the python interpreter.\n* It is in the temp directory obtained by `tempfile.gettempdir()`.\n\n**Note:** files in the current working directory whose name starts with a period (`.`) will not be moved to the cache, even if they are returned from a prediction function, since they often contain sensitive information. \n\nIf none of these criteria are met, the prediction function that is returning that file will raise an exception instead of moving the file to cache. Gradio performs this check so that arbitrary files on your machine cannot be accessed.\n\n3. Files uploaded by a user to your Gradio app (e.g. through the `File` or `Image` input components).\n\n\nTip: If at any time Gradio blocks a file that you would like it to process, add its path to the `allowed_paths` parameter." }, { "id": 491, "parent": 487, "path": "04_additional-features/08_file-access.md", "level": 2, "title": "The files Gradio will not allow others to access", "content": "While running, Gradio apps will NOT ALLOW users to access:\n\n- **Files that you explicitly block via the `blocked_paths` parameter in `launch()`**. You can pass in a list of additional directories or exact filepaths to the `blocked_paths` parameter in `launch()`. This parameter takes precedence over the files that Gradio exposes by default, or by the `allowed_paths` parameter or the `gr.set_static_paths` function.\n\n- **Any other paths on the host machine**. Users should NOT be able to access other arbitrary paths on the host." }, { "id": 492, "parent": 487, "path": "04_additional-features/08_file-access.md", "level": 2, "title": "Uploading Files", "content": "Sharing your Gradio application will also allow users to upload files to your computer or server. You can set a maximum file size for uploads to prevent abuse and to preserve disk space. You can do this with the `max_file_size` parameter of `.launch`. For example, the following two code snippets limit file uploads to 5 megabytes per file.\n\n```python\nimport gradio as gr\n\ndemo = gr.Interface(lambda x: x, \"image\", \"image\")\n\ndemo.launch(max_file_size=\"5mb\")" }, { "id": 493, "parent": null, "path": "04_additional-features/08_file-access.md", "level": 1, "title": "or", "content": "demo.launch(max_file_size=5 * gr.FileSize.MB)\n```" }, { "id": 494, "parent": 493, "path": "04_additional-features/08_file-access.md", "level": 2, "title": "Best Practices", "content": "* Set a `max_file_size` for your application.\n* Do not return arbitrary user input from a function that is connected to a file-based output component (`gr.Image`, `gr.File`, etc.). For example, the following interface would allow anyone to move an arbitrary file in your local directory to the cache: `gr.Interface(lambda s: s, \"text\", \"file\")`. This is because the user input is treated as an arbitrary file path. \n* Make `allowed_paths` as small as possible. If a path in `allowed_paths` is a directory, any file within that directory can be accessed. Make sure the entires of `allowed_paths` only contains files related to your application.\n* Run your gradio application from the same directory the application file is located in. This will narrow the scope of files Gradio will be allowed to move into the cache. For example, prefer `python app.py` to `python Users/sources/project/app.py`." }, { "id": 495, "parent": null, "path": "04_additional-features/09_environment-variables.md", "level": 1, "title": "Environment Variables", "content": "Environment variables in Gradio provide a way to customize your applications and launch settings without changing the codebase. In this guide, we'll explore the key environment variables supported in Gradio and how to set them." }, { "id": 496, "parent": 495, "path": "04_additional-features/09_environment-variables.md", "level": 2, "title": "Key Environment Variables", "content": "" }, { "id": 497, "parent": 496, "path": "04_additional-features/09_environment-variables.md", "level": 3, "title": "1. `GRADIO_SERVER_PORT`", "content": "- **Description**: Specifies the port on which the Gradio app will run.\n- **Default**: `7860`\n- **Example**:\n ```bash\n export GRADIO_SERVER_PORT=8000\n ```" }, { "id": 498, "parent": 496, "path": "04_additional-features/09_environment-variables.md", "level": 3, "title": "2. `GRADIO_SERVER_NAME`", "content": "- **Description**: Defines the host name for the Gradio server. To make Gradio accessible from any IP address, set this to `\"0.0.0.0\"`\n- **Default**: `\"127.0.0.1\"` \n- **Example**:\n ```bash\n export GRADIO_SERVER_NAME=\"0.0.0.0\"\n ```" }, { "id": 499, "parent": 496, "path": "04_additional-features/09_environment-variables.md", "level": 3, "title": "3. `GRADIO_NUM_PORTS`", "content": "- **Description**: Defines the number of ports to try when starting the Gradio server.\n- **Default**: `100`\n- **Example**:\n ```bash\n export GRADIO_NUM_PORTS=200\n ```" }, { "id": 500, "parent": 496, "path": "04_additional-features/09_environment-variables.md", "level": 3, "title": "4. `GRADIO_ANALYTICS_ENABLED`", "content": "- **Description**: Whether Gradio should provide \n- **Default**: `\"True\"`\n- **Options**: `\"True\"`, `\"False\"`\n- **Example**:\n ```sh\n export GRADIO_ANALYTICS_ENABLED=\"True\"\n ```" }, { "id": 501, "parent": 496, "path": "04_additional-features/09_environment-variables.md", "level": 3, "title": "5. `GRADIO_DEBUG`", "content": "- **Description**: Enables or disables debug mode in Gradio. If debug mode is enabled, the main thread does not terminate allowing error messages to be printed in environments such as Google Colab.\n- **Default**: `0`\n- **Example**:\n ```sh\n export GRADIO_DEBUG=1\n ```" }, { "id": 502, "parent": 496, "path": "04_additional-features/09_environment-variables.md", "level": 3, "title": "6. `GRADIO_FLAGGING_MODE`", "content": "- **Description**: Controls whether users can flag inputs/outputs in the Gradio interface. See [the Guide on flagging](/guides/using-flagging) for more details.\n- **Default**: `\"manual\"`\n- **Options**: `\"never\"`, `\"manual\"`, `\"auto\"`\n- **Example**:\n ```sh\n export GRADIO_FLAGGING_MODE=\"never\"\n ```" }, { "id": 503, "parent": 496, "path": "04_additional-features/09_environment-variables.md", "level": 3, "title": "7. `GRADIO_TEMP_DIR`", "content": "- **Description**: Specifies the directory where temporary files created by Gradio are stored.\n- **Default**: System default temporary directory\n- **Example**:\n ```sh\n export GRADIO_TEMP_DIR=\"/path/to/temp\"\n ```" }, { "id": 504, "parent": 496, "path": "04_additional-features/09_environment-variables.md", "level": 3, "title": "8. `GRADIO_ROOT_PATH`", "content": "- **Description**: Sets the root path for the Gradio application. Useful if running Gradio [behind a reverse proxy](/guides/running-gradio-on-your-web-server-with-nginx).\n- **Default**: `\"\"`\n- **Example**:\n ```sh\n export GRADIO_ROOT_PATH=\"/myapp\"\n ```" }, { "id": 505, "parent": 496, "path": "04_additional-features/09_environment-variables.md", "level": 3, "title": "9. `GRADIO_SHARE`", "content": "- **Description**: Enables or disables sharing the Gradio app.\n- **Default**: `\"False\"`\n- **Options**: `\"True\"`, `\"False\"`\n- **Example**:\n ```sh\n export GRADIO_SHARE=\"True\"\n ```" }, { "id": 506, "parent": 496, "path": "04_additional-features/09_environment-variables.md", "level": 3, "title": "10. `GRADIO_ALLOWED_PATHS`", "content": "- **Description**: Sets a list of complete filepaths or parent directories that gradio is allowed to serve. Must be absolute paths. Warning: if you provide directories, any files in these directories or their subdirectories are accessible to all users of your app. Multiple items can be specified by separating items with commas.\n- **Default**: `\"\"`\n- **Example**:\n ```sh\n export GRADIO_ALLOWED_PATHS=\"/mnt/sda1,/mnt/sda2\"\n ```" }, { "id": 507, "parent": 496, "path": "04_additional-features/09_environment-variables.md", "level": 3, "title": "11. `GRADIO_BLOCKED_PATHS`", "content": "- **Description**: Sets a list of complete filepaths or parent directories that gradio is not allowed to serve (i.e. users of your app are not allowed to access). Must be absolute paths. Warning: takes precedence over `allowed_paths` and all other directories exposed by Gradio by default. Multiple items can be specified by separating items with commas.\n- **Default**: `\"\"`\n- **Example**:\n ```sh\n export GRADIO_BLOCKED_PATHS=\"/users/x/gradio_app/admin,/users/x/gradio_app/keys\"\n ```" }, { "id": 508, "parent": 496, "path": "04_additional-features/09_environment-variables.md", "level": 3, "title": "12. `FORWARDED_ALLOW_IPS`", "content": "- **Description**: This is not a Gradio-specific environment variable, but rather one used in server configurations, specifically `uvicorn` which is used by Gradio internally. This environment variable is useful when deploying applications behind a reverse proxy. It defines a list of IP addresses that are trusted to forward traffic to your application. When set, the application will trust the `X-Forwarded-For` header from these IP addresses to determine the original IP address of the user making the request. This means that if you use the `gr.Request` [object's](https://www.gradio.app/docs/gradio/request) `client.host` property, it will correctly get the user's IP address instead of the IP address of the reverse proxy server. Note that only trusted IP addresses (i.e. the IP addresses of your reverse proxy servers) should be added, as any server with these IP addresses can modify the `X-Forwarded-For` header and spoof the client's IP address.\n- **Default**: `\"127.0.0.1\"`\n- **Example**:\n ```sh\n export FORWARDED_ALLOW_IPS=\"127.0.0.1,192.168.1.100\"\n ```" }, { "id": 509, "parent": 496, "path": "04_additional-features/09_environment-variables.md", "level": 3, "title": "13. `GRADIO_CACHE_EXAMPLES`", "content": "- **Description**: Whether or not to cache examples by default in `gr.Interface()`, `gr.ChatInterface()` or in `gr.Examples()` when no explicit argument is passed for the `cache_examples` parameter. You can set this environment variable to either the string \"true\" or \"false\".\n- **Default**: `\"false\"`\n- **Example**:\n ```sh\n export GRADIO_CACHE_EXAMPLES=\"true\"\n ```" }, { "id": 510, "parent": 496, "path": "04_additional-features/09_environment-variables.md", "level": 3, "title": "14. `GRADIO_CACHE_MODE`", "content": "- **Description**: How to cache examples. Only applies if `cache_examples` is set to `True` either via enviornment variable or by an explicit parameter, AND no no explicit argument is passed for the `cache_mode` parameter in `gr.Interface()`, `gr.ChatInterface()` or in `gr.Examples()`. Can be set to either the strings \"lazy\" or \"eager.\" If \"lazy\", examples are cached after their first use for all users of the app. If \"eager\", all examples are cached at app launch.\n\n- **Default**: `\"eager\"`\n- **Example**:\n ```sh\n export GRADIO_CACHE_MODE=\"lazy\"\n ```" }, { "id": 511, "parent": 496, "path": "04_additional-features/09_environment-variables.md", "level": 3, "title": "15. `GRADIO_EXAMPLES_CACHE`", "content": "- **Description**: If you set `cache_examples=True` in `gr.Interface()`, `gr.ChatInterface()` or in `gr.Examples()`, Gradio will run your prediction function and save the results to disk. By default, this is in the `.gradio/cached_examples//` subdirectory within your app's working directory. You can customize the location of cached example files created by Gradio by setting the environment variable `GRADIO_EXAMPLES_CACHE` to an absolute path or a path relative to your working directory.\n- **Default**: `\".gradio/cached_examples/\"`\n- **Example**:\n ```sh\n export GRADIO_EXAMPLES_CACHE=\"custom_cached_examples/\"\n ```" }, { "id": 512, "parent": 496, "path": "04_additional-features/09_environment-variables.md", "level": 3, "title": "16. `GRADIO_NODE_SERVER_NAME`", "content": "- **Description**: Defines the host name for the Gradio node server. (Only applies if `ssr_mode` is set to `True`.)\n- **Default**: `GRADIO_SERVER_NAME` if it is set, otherwise `\"127.0.0.1\"`\n- **Example**:\n ```sh\n export GRADIO_NODE_SERVER_NAME=\"0.0.0.0\"\n ```" }, { "id": 513, "parent": 496, "path": "04_additional-features/09_environment-variables.md", "level": 3, "title": "17. `GRADIO_NODE_NUM_PORTS`", "content": "- **Description**: Defines the number of ports to try when starting the Gradio node server. (Only applies if `ssr_mode` is set to `True`.)\n- **Default**: `100`\n- **Example**:\n ```sh\n export GRADIO_NODE_NUM_PORTS=200\n ```" }, { "id": 514, "parent": 496, "path": "04_additional-features/09_environment-variables.md", "level": 3, "title": "18. `GRADIO_RESET_EXAMPLES_CACHE`", "content": "- **Description**: If set to \"True\", Gradio will delete and recreate the examples cache directory when the app starts instead of reusing the cached example if they already exist. \n- **Default**: `\"False\"`\n- **Options**: `\"True\"`, `\"False\"`\n- **Example**:\n ```sh\n export GRADIO_RESET_EXAMPLES_CACHE=\"True\"\n ```" }, { "id": 515, "parent": 495, "path": "04_additional-features/09_environment-variables.md", "level": 2, "title": "How to Set Environment Variables", "content": "To set environment variables in your terminal, use the `export` command followed by the variable name and its value. For example:\n\n```sh\nexport GRADIO_SERVER_PORT=8000\n```\n\nIf you're using a `.env` file to manage your environment variables, you can add them like this:\n\n```sh\nGRADIO_SERVER_PORT=8000\nGRADIO_SERVER_NAME=\"localhost\"\n```\n\nThen, use a tool like `dotenv` to load these variables when running your application." }, { "id": 516, "parent": null, "path": "04_additional-features/08_styling.md", "level": 1, "title": "Styling", "content": "Gradio themes are the easiest way to customize the look and feel of your app. You can choose from a variety of themes, or create your own. To do so, pass the `theme=` kwarg to the `Interface` constructor. For example:\n\n```python\ndemo = gr.Interface(..., theme=gr.themes.Monochrome())\n```\n\nor\n\n```python\nwith gr.Block(theme=gr.themes.Soft()):\n ...\n```\n\nGradio comes with a set of prebuilt themes which you can load from `gr.themes.*`. You can extend these themes or create your own themes from scratch - see the [theming guide](https://gradio.app/guides/theming-guide) for more details.\n\nFor additional styling ability, you can pass any CSS (as well as custom JavaScript) to your Gradio application. This is discussed in more detail in our [custom JS and CSS guide](/guides/custom-CSS-and-JS)." }, { "id": 517, "parent": null, "path": "04_additional-features/03_streaming-inputs.md", "level": 1, "title": "Streaming inputs", "content": "In the previous guide, we covered how to stream a sequence of outputs from an event handler. Gradio also allows you to stream images from a user's camera or audio chunks from their microphone **into** your event handler. This can be used to create real-time object detection apps or conversational chat applications with Gradio.\n\nCurrently, the `gr.Image` and the `gr.Audio` components support input streaming via the `stream` event.\nLet's create the simplest streaming app possible, which simply returns the webcam stream unmodified.\n\n```py\nimport gradio as gr\n\nwith gr.Blocks() as demo:\n with gr.Row():\n with gr.Column():\n input_img = gr.Image(label=\"Input\", sources=\"webcam\")\n with gr.Column():\n output_img = gr.Image(label=\"Output\")\n input_img.stream(lambda s: s, input_img, output_img, time_limit=15, stream_every=0.1, concurrency_limit=30)\n\nif __name__ == \"__main__\":\n\n demo.launch()\n\n```\n$demo_streaming_simple\n\nTry it out! The streaming event is triggered when the user starts recording. Under the hood, the webcam will take a photo every 0.1 seconds and send it to the server. The server will then return that image.\n\nThere are two unique keyword arguments for the `stream` event:\n\n* `time_limit` - This is the amount of time the gradio server will spend processing the event. Media streams are naturally unbounded so it's important to set a time limit so that one user does not hog the Gradio queue. The time limit only counts the time spent processing the stream, not the time spent waiting in the queue. The orange bar displayed at the bottom of the input image represents the remaining time. When the time limit expires, the user will automatically rejoin the queue.\n\n* `stream_every` - This is the frequency (in seconds) with which the stream will capture input and send it to the server. For demos like image detection or manipulation, setting a smaller value is desired to get a \"real-time\" effect. For demos like speech transcription, a higher value is useful so that the transcription algorithm has more context of what's being said." }, { "id": 518, "parent": 517, "path": "04_additional-features/03_streaming-inputs.md", "level": 2, "title": "A Realistic Image Demo", "content": "Let's create a demo where a user can choose a filter to apply to their webcam stream. Users can choose from an edge-detection filter, a cartoon filter, or simply flipping the stream vertically.\n\n```py\nimport gradio as gr\nimport numpy as np\nimport cv2\n\ndef transform_cv2(frame, transform):\n if transform == \"cartoon\":\n # prepare color\n img_color = cv2.pyrDown(cv2.pyrDown(frame))\n for _ in range(6):\n img_color = cv2.bilateralFilter(img_color, 9, 9, 7)\n img_color = cv2.pyrUp(cv2.pyrUp(img_color))\n\n # prepare edges\n img_edges = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)\n img_edges = cv2.adaptiveThreshold(\n cv2.medianBlur(img_edges, 7),\n 255,\n cv2.ADAPTIVE_THRESH_MEAN_C,\n cv2.THRESH_BINARY,\n 9,\n 2,\n )\n img_edges = cv2.cvtColor(img_edges, cv2.COLOR_GRAY2RGB)\n # combine color and edges\n img = cv2.bitwise_and(img_color, img_edges)\n return img\n elif transform == \"edges\":\n # perform edge detection\n img = cv2.cvtColor(cv2.Canny(frame, 100, 200), cv2.COLOR_GRAY2BGR)\n return img\n else:\n return np.flipud(frame)\n\nwith gr.Blocks() as demo:\n with gr.Row():\n with gr.Column():\n transform = gr.Dropdown(choices=[\"cartoon\", \"edges\", \"flip\"],\n value=\"flip\", label=\"Transformation\")\n input_img = gr.Image(sources=[\"webcam\"], type=\"numpy\")\n with gr.Column():\n output_img = gr.Image(streaming=True)\n dep = input_img.stream(transform_cv2, [input_img, transform], [output_img],\n time_limit=30, stream_every=0.1, concurrency_limit=30)\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n$demo_streaming_filter\n\nYou will notice that if you change the filter value it will immediately take effect in the output stream. That is an important difference of stream events in comparison to other Gradio events. The input values of the stream can be changed while the stream is being processed. \n\nTip: We set the \"streaming\" parameter of the image output component to be \"True\". Doing so lets the server automatically convert our output images into base64 format, a format that is efficient for streaming." }, { "id": 519, "parent": 517, "path": "04_additional-features/03_streaming-inputs.md", "level": 2, "title": "Unified Image Demos", "content": "For some image streaming demos, like the one above, we don't need to display separate input and output components. Our app would look cleaner if we could just display the modified output stream.\n\nWe can do so by just specifying the input image component as the output of the stream event.\n\n```py\nimport gradio as gr\nimport numpy as np\nimport cv2\n\ndef transform_cv2(frame, transform):\n if transform == \"cartoon\":\n # prepare color\n img_color = cv2.pyrDown(cv2.pyrDown(frame))\n for _ in range(6):\n img_color = cv2.bilateralFilter(img_color, 9, 9, 7)\n img_color = cv2.pyrUp(cv2.pyrUp(img_color))\n\n # prepare edges\n img_edges = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)\n img_edges = cv2.adaptiveThreshold(\n cv2.medianBlur(img_edges, 7),\n 255,\n cv2.ADAPTIVE_THRESH_MEAN_C,\n cv2.THRESH_BINARY,\n 9,\n 2,\n )\n img_edges = cv2.cvtColor(img_edges, cv2.COLOR_GRAY2RGB)\n # combine color and edges\n img = cv2.bitwise_and(img_color, img_edges)\n return img\n elif transform == \"edges\":\n # perform edge detection\n img = cv2.cvtColor(cv2.Canny(frame, 100, 200), cv2.COLOR_GRAY2BGR)\n return img\n else:\n return np.flipud(frame)\n\n\ncss=\"\"\".my-group {max-width: 500px !important; max-height: 500px !important;}\n .my-column {display: flex !important; justify-content: center !important; align-items: center !important};\"\"\"\n\nwith gr.Blocks(css=css) as demo:\n with gr.Column(elem_classes=[\"my-column\"]):\n with gr.Group(elem_classes=[\"my-group\"]):\n transform = gr.Dropdown(choices=[\"cartoon\", \"edges\", \"flip\"],\n value=\"flip\", label=\"Transformation\")\n input_img = gr.Image(sources=[\"webcam\"], type=\"numpy\", streaming=True)\n input_img.stream(transform_cv2, [input_img, transform], [input_img], time_limit=30, stream_every=0.1)\n\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n$demo_streaming_filter_unified" }, { "id": 520, "parent": 517, "path": "04_additional-features/03_streaming-inputs.md", "level": 2, "title": "Keeping track of past inputs or outputs", "content": "Your streaming function should be stateless. It should take the current input and return its corresponding output. However, there are cases where you may want to keep track of past inputs or outputs. For example, you may want to keep a buffer of the previous `k` inputs to improve the accuracy of your transcription demo. You can do this with Gradio's `gr.State()` component.\n\nLet's showcase this with a sample demo:\n\n```python\ndef transcribe_handler(current_audio, state, transcript):\n next_text = transcribe(current_audio, history=state)\n state.append(current_audio)\n state = state[-3:]\n return state, transcript + next_text\n\nwith gr.Blocks() as demo:\n with gr.Row():\n with gr.Column():\n mic = gr.Audio(sources=\"microphone\")\n state = gr.State(value=[])\n with gr.Column():\n transcript = gr.Textbox(label=\"Transcript\")\n mic.stream(transcribe_handler, [mic, state, transcript], [state, transcript],\n time_limit=10, stream_every=1)\n\n\ndemo.launch()\n```" }, { "id": 521, "parent": 517, "path": "04_additional-features/03_streaming-inputs.md", "level": 2, "title": "End-to-End Examples", "content": "For an end-to-end example of streaming from the webcam, see the object detection from webcam [guide](/main/guides/object-detection-from-webcam-with-webrtc)." }, { "id": 522, "parent": null, "path": "04_additional-features/02_streaming-outputs.md", "level": 1, "title": "Streaming outputs", "content": "In some cases, you may want to stream a sequence of outputs rather than show a single output at once. For example, you might have an image generation model and you want to show the image that is generated at each step, leading up to the final image. Or you might have a chatbot which streams its response one token at a time instead of returning it all at once.\n\nIn such cases, you can supply a **generator** function into Gradio instead of a regular function. Creating generators in Python is very simple: instead of a single `return` value, a function should `yield` a series of values instead. Usually the `yield` statement is put in some kind of loop. Here's an example of an generator that simply counts up to a given number:\n\n```python\ndef my_generator(x):\n for i in range(x):\n yield i\n```\n\nYou supply a generator into Gradio the same way as you would a regular function. For example, here's a a (fake) image generation model that generates noise for several steps before outputting an image using the `gr.Interface` class:\n\n```py\nimport gradio as gr\nimport numpy as np\nimport time\n\ndef fake_diffusion(steps):\n rng = np.random.default_rng()\n for i in range(steps):\n time.sleep(1)\n image = rng.random(size=(600, 600, 3))\n yield image\n image = np.ones((1000,1000,3), np.uint8)\n image[:] = [255, 124, 0]\n yield image\n\ndemo = gr.Interface(fake_diffusion,\n inputs=gr.Slider(1, 10, 3, step=1),\n outputs=\"image\")\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n$demo_fake_diffusion\n\nNote that we've added a `time.sleep(1)` in the iterator to create an artificial pause between steps so that you are able to observe the steps of the iterator (in a real image generation model, this probably wouldn't be necessary).\n\nSimilarly, Gradio can handle streaming inputs, e.g. an image generation model that reruns every time a user types a letter in a textbox. This is covered in more details in our guide on building [reactive Interfaces](/guides/reactive-interfaces)." }, { "id": 523, "parent": 522, "path": "04_additional-features/02_streaming-outputs.md", "level": 2, "title": "Streaming Media", "content": "Gradio can stream audio and video directly from your generator function.\nThis lets your user hear your audio or see your video nearly as soon as it's `yielded` by your function.\nAll you have to do is \n\n1. Set `streaming=True` in your `gr.Audio` or `gr.Video` output component.\n2. Write a python generator that yields the next \"chunk\" of audio or video.\n3. Set `autoplay=True` so that the media starts playing automatically.\n\nFor audio, the next \"chunk\" can be either an `.mp3` or `.wav` file or a `bytes` sequence of audio.\nFor video, the next \"chunk\" has to be either `.mp4` file or a file with `h.264` codec with a `.ts` extension.\nFor smooth playback, make sure chunks are consistent lengths and larger than 1 second.\n\nWe'll finish with some simple examples illustrating these points." }, { "id": 524, "parent": 523, "path": "04_additional-features/02_streaming-outputs.md", "level": 3, "title": "Streaming Audio", "content": "```python\nimport gradio as gr\nfrom time import sleep\n\ndef keep_repeating(audio_file):\n for _ in range(10):\n sleep(0.5)\n yield audio_file\n\ngr.Interface(keep_repeating,\n gr.Audio(sources=[\"microphone\"], type=\"filepath\"),\n gr.Audio(streaming=True, autoplay=True)\n).launch()\n```" }, { "id": 525, "parent": 523, "path": "04_additional-features/02_streaming-outputs.md", "level": 3, "title": "Streaming Video", "content": "```python\nimport gradio as gr\nfrom time import sleep\n\ndef keep_repeating(video_file):\n for _ in range(10):\n sleep(0.5)\n yield video_file\n\ngr.Interface(keep_repeating,\n gr.Video(sources=[\"webcam\"], format=\"mp4\"),\n gr.Video(streaming=True, autoplay=True)\n).launch()\n```" }, { "id": 526, "parent": 522, "path": "04_additional-features/02_streaming-outputs.md", "level": 2, "title": "End-to-End Examples", "content": "For an end-to-end example of streaming media, see the object detection from video [guide](/main/guides/object-detection-from-video) or the streaming AI-generated audio with [transformers](https://huggingface.co/docs/transformers/index) [guide](/main/guides/streaming-ai-generated-audio)." }, { "id": 527, "parent": null, "path": "04_additional-features/01_queuing.md", "level": 1, "title": "Queuing", "content": "Every Gradio app comes with a built-in queuing system that can scale to thousands of concurrent users. Because many of your event listeners may involve heavy processing, Gradio automatically creates a queue to handle every event listener in the backend. Every event listener in your app automatically has a queue to process incoming events." }, { "id": 528, "parent": 527, "path": "04_additional-features/01_queuing.md", "level": 2, "title": "Configuring the Queue", "content": "By default, each event listener has its own queue, which handles one request at a time. This can be configured via two arguments:\n\n- `concurrency_limit`: This sets the maximum number of concurrent executions for an event listener. By default, the limit is 1 unless configured otherwise in `Blocks.queue()`. You can also set it to `None` for no limit (i.e., an unlimited number of concurrent executions). For example:\n\n```python\nimport gradio as gr\n\nwith gr.Blocks() as demo:\n prompt = gr.Textbox()\n image = gr.Image()\n generate_btn = gr.Button(\"Generate Image\")\n generate_btn.click(image_gen, prompt, image, concurrency_limit=5)\n```\n\nIn the code above, up to 5 requests can be processed simultaneously for this event listener. Additional requests will be queued until a slot becomes available.\n\nIf you want to manage multiple event listeners using a shared queue, you can use the `concurrency_id` argument:\n\n- `concurrency_id`: This allows event listeners to share a queue by assigning them the same ID. For example, if your setup has only 2 GPUs but multiple functions require GPU access, you can create a shared queue for all those functions. Here's how that might look:\n\n```python\nimport gradio as gr\n\nwith gr.Blocks() as demo:\n prompt = gr.Textbox()\n image = gr.Image()\n generate_btn_1 = gr.Button(\"Generate Image via model 1\")\n generate_btn_2 = gr.Button(\"Generate Image via model 2\")\n generate_btn_3 = gr.Button(\"Generate Image via model 3\")\n generate_btn_1.click(image_gen_1, prompt, image, concurrency_limit=2, concurrency_id=\"gpu_queue\")\n generate_btn_2.click(image_gen_2, prompt, image, concurrency_id=\"gpu_queue\")\n generate_btn_3.click(image_gen_3, prompt, image, concurrency_id=\"gpu_queue\")\n```\n\nIn this example, all three event listeners share a queue identified by `\"gpu_queue\"`. The queue can handle up to 2 concurrent requests at a time, as defined by the `concurrency_limit`." }, { "id": 529, "parent": 528, "path": "04_additional-features/01_queuing.md", "level": 3, "title": "Notes", "content": "- To ensure unlimited concurrency for an event listener, set `concurrency_limit=None`. This is useful if your function is calling e.g. an external API which handles the rate limiting of requests itself.\n- The default concurrency limit for all queues can be set globally using the `default_concurrency_limit` parameter in `Blocks.queue()`. \n\nThese configurations make it easy to manage the queuing behavior of your Gradio app." }, { "id": 530, "parent": null, "path": "04_additional-features/07_sharing-your-app.md", "level": 1, "title": "Sharing Your App", "content": "In this Guide, we dive more deeply into the various aspects of sharing a Gradio app with others. We will cover:\n\n1. [Sharing demos with the share parameter](#sharing-demos)\n2. [Hosting on HF Spaces](#hosting-on-hf-spaces)\n3. [Embedding hosted spaces](#embedding-hosted-spaces)\n4. [Using the API page](#api-page)\n5. [Accessing network requests](#accessing-the-network-request-directly)\n6. [Mounting within FastAPI](#mounting-within-another-fast-api-app)\n7. [Authentication](#authentication)\n8. [Analytics](#analytics)" }, { "id": 531, "parent": 530, "path": "04_additional-features/07_sharing-your-app.md", "level": 2, "title": "Sharing Demos", "content": "Gradio demos can be easily shared publicly by setting `share=True` in the `launch()` method. Like this:\n\n```python\nimport gradio as gr\n\ndef greet(name):\n return \"Hello \" + name + \"!\"\n\ndemo = gr.Interface(fn=greet, inputs=\"textbox\", outputs=\"textbox\")\n \ndemo.launch(share=True) # Share your demo with just 1 extra parameter 🚀\n```\n\nThis generates a public, shareable link that you can send to anybody! When you send this link, the user on the other side can try out the model in their browser. Because the processing happens on your device (as long as your device stays on), you don't have to worry about any packaging any dependencies. \n\n![sharing](https://github.com/gradio-app/gradio/blob/main/guides/assets/sharing.svg?raw=true)\n\n\nA share link usually looks something like this: **https://07ff8706ab.gradio.live**. Although the link is served through the Gradio Share Servers, these servers are only a proxy for your local server, and do not store any data sent through your app. Share links expire after 72 hours. (it is [also possible to set up your own Share Server](https://github.com/huggingface/frp/) on your own cloud server to overcome this restriction.)\n\nTip: Keep in mind that share links are publicly accessible, meaning that anyone can use your model for prediction! Therefore, make sure not to expose any sensitive information through the functions you write, or allow any critical changes to occur on your device. Or you can [add authentication to your Gradio app](#authentication) as discussed below.\n\nNote that by default, `share=False`, which means that your server is only running locally. (This is the default, except in Google Colab notebooks, where share links are automatically created). As an alternative to using share links, you can use use [SSH port-forwarding](https://www.ssh.com/ssh/tunneling/example) to share your local server with specific users." }, { "id": 532, "parent": 530, "path": "04_additional-features/07_sharing-your-app.md", "level": 2, "title": "Hosting on HF Spaces", "content": "If you'd like to have a permanent link to your Gradio demo on the internet, use Hugging Face Spaces. [Hugging Face Spaces](http://huggingface.co/spaces/) provides the infrastructure to permanently host your machine learning model for free!\n\nAfter you have [created a free Hugging Face account](https://huggingface.co/join), you have two methods to deploy your Gradio app to Hugging Face Spaces:\n\n1. From terminal: run `gradio deploy` in your app directory. The CLI will gather some basic metadata and then launch your app. To update your space, you can re-run this command or enable the Github Actions option to automatically update the Spaces on `git push`.\n\n2. From your browser: Drag and drop a folder containing your Gradio model and all related files [here](https://huggingface.co/new-space). See [this guide how to host on Hugging Face Spaces](https://huggingface.co/blog/gradio-spaces) for more information, or watch the embedded video:\n\n" }, { "id": 533, "parent": 530, "path": "04_additional-features/07_sharing-your-app.md", "level": 2, "title": "Embedding Hosted Spaces", "content": "Once you have hosted your app on Hugging Face Spaces (or on your own server), you may want to embed the demo on a different website, such as your blog or your portfolio. Embedding an interactive demo allows people to try out the machine learning model that you have built, without needing to download or install anything — right in their browser! The best part is that you can embed interactive demos even in static websites, such as GitHub pages.\n\nThere are two ways to embed your Gradio demos. You can find quick links to both options directly on the Hugging Face Space page, in the \"Embed this Space\" dropdown option:\n\n![Embed this Space dropdown option](https://github.com/gradio-app/gradio/blob/main/guides/assets/embed_this_space.png?raw=true)" }, { "id": 534, "parent": 533, "path": "04_additional-features/07_sharing-your-app.md", "level": 3, "title": "Embedding with Web Components", "content": "Web components typically offer a better experience to users than IFrames. Web components load lazily, meaning that they won't slow down the loading time of your website, and they automatically adjust their height based on the size of the Gradio app.\n\nTo embed with Web Components:\n\n1. Import the gradio JS library into into your site by adding the script below in your site (replace {GRADIO_VERSION} in the URL with the library version of Gradio you are using).\n\n```html\n\n```\n\n2. Add\n\n```html\n\n```\n\nelement where you want to place the app. Set the `src=` attribute to your Space's embed URL, which you can find in the \"Embed this Space\" button. For example:\n\n```html\n
\n```\n\n\n\nYou can see examples of how web components look on the Gradio landing page.\n\nYou can also customize the appearance and behavior of your web component with attributes that you pass into the `` tag:\n\n- `src`: as we've seen, the `src` attributes links to the URL of the hosted Gradio demo that you would like to embed\n- `space`: an optional shorthand if your Gradio demo is hosted on Hugging Face Space. Accepts a `username/space_name` instead of a full URL. Example: `gradio/Echocardiogram-Segmentation`. If this attribute attribute is provided, then `src` does not need to be provided.\n- `control_page_title`: a boolean designating whether the html title of the page should be set to the title of the Gradio app (by default `\"false\"`)\n- `initial_height`: the initial height of the web component while it is loading the Gradio app, (by default `\"300px\"`). Note that the final height is set based on the size of the Gradio app.\n- `container`: whether to show the border frame and information about where the Space is hosted (by default `\"true\"`)\n- `info`: whether to show just the information about where the Space is hosted underneath the embedded app (by default `\"true\"`)\n- `autoscroll`: whether to autoscroll to the output when prediction has finished (by default `\"false\"`)\n- `eager`: whether to load the Gradio app as soon as the page loads (by default `\"false\"`)\n- `theme_mode`: whether to use the `dark`, `light`, or default `system` theme mode (by default `\"system\"`)\n- `render`: an event that is triggered once the embedded space has finished rendering.\n\nHere's an example of how to use these attributes to create a Gradio app that does not lazy load and has an initial height of 0px.\n\n```html\n\n```\n\nHere's another example of how to use the `render` event. An event listener is used to capture the `render` event and will call the `handleLoadComplete()` function once rendering is complete. \n\n```html\n\n```\n\n_Note: While Gradio's CSS will never impact the embedding page, the embedding page can affect the style of the embedded Gradio app. Make sure that any CSS in the parent page isn't so general that it could also apply to the embedded Gradio app and cause the styling to break. Element selectors such as `header { ... }` and `footer { ... }` will be the most likely to cause issues._" }, { "id": 535, "parent": 533, "path": "04_additional-features/07_sharing-your-app.md", "level": 3, "title": "Embedding with IFrames", "content": "To embed with IFrames instead (if you cannot add javascript to your website, for example), add this element:\n\n```html\n\n```\n\nAgain, you can find the `src=` attribute to your Space's embed URL, which you can find in the \"Embed this Space\" button.\n\nNote: if you use IFrames, you'll probably want to add a fixed `height` attribute and set `style=\"border:0;\"` to remove the boreder. In addition, if your app requires permissions such as access to the webcam or the microphone, you'll need to provide that as well using the `allow` attribute." }, { "id": 536, "parent": 530, "path": "04_additional-features/07_sharing-your-app.md", "level": 2, "title": "API Page", "content": "You can use almost any Gradio app as an API! In the footer of a Gradio app [like this one](https://huggingface.co/spaces/gradio/hello_world), you'll see a \"Use via API\" link.\n\n![Use via API](https://github.com/gradio-app/gradio/blob/main/guides/assets/use_via_api.png?raw=true)\n\nThis is a page that lists the endpoints that can be used to query the Gradio app, via our supported clients: either [the Python client](https://gradio.app/guides/getting-started-with-the-python-client/), or [the JavaScript client](https://gradio.app/guides/getting-started-with-the-js-client/). For each endpoint, Gradio automatically generates the parameters and their types, as well as example inputs, like this.\n\n![](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/gradio-guides/view-api.png)\n\nThe endpoints are automatically created when you launch a Gradio `Interface`. If you are using Gradio `Blocks`, you can also set up a Gradio API page, though we recommend that you explicitly name each event listener, such as\n\n```python\nbtn.click(add, [num1, num2], output, api_name=\"addition\")\n```\n\nThis will add and document the endpoint `/api/addition/` to the automatically generated API page. Otherwise, your API endpoints will appear as \"unnamed\" endpoints." }, { "id": 537, "parent": 530, "path": "04_additional-features/07_sharing-your-app.md", "level": 2, "title": "Accessing the Network Request Directly", "content": "When a user makes a prediction to your app, you may need the underlying network request, in order to get the request headers (e.g. for advanced authentication), log the client's IP address, getting the query parameters, or for other reasons. Gradio supports this in a similar manner to FastAPI: simply add a function parameter whose type hint is `gr.Request` and Gradio will pass in the network request as that parameter. Here is an example:\n\n```python\nimport gradio as gr\n\ndef echo(text, request: gr.Request):\n if request:\n print(\"Request headers dictionary:\", request.headers)\n print(\"IP address:\", request.client.host)\n print(\"Query parameters:\", dict(request.query_params))\n return text\n\nio = gr.Interface(echo, \"textbox\", \"textbox\").launch()\n```\n\nNote: if your function is called directly instead of through the UI (this happens, for\nexample, when examples are cached, or when the Gradio app is called via API), then `request` will be `None`. \nYou should handle this case explicitly to ensure that your app does not throw any errors. That is why\nwe have the explicit check `if request`." }, { "id": 538, "parent": 530, "path": "04_additional-features/07_sharing-your-app.md", "level": 2, "title": "Mounting Within Another FastAPI App", "content": "In some cases, you might have an existing FastAPI app, and you'd like to add a path for a Gradio demo.\nYou can easily do this with `gradio.mount_gradio_app()`.\n\nHere's a complete example:\n\n```py\nfrom fastapi import FastAPI\nimport gradio as gr\n\nCUSTOM_PATH = \"/gradio\"\n\napp = FastAPI()\n\n@app.get(\"/\")\ndef read_main():\n return {\"message\": \"This is your main app\"}\n\nio = gr.Interface(lambda x: \"Hello, \" + x + \"!\", \"textbox\", \"textbox\")\napp = gr.mount_gradio_app(app, io, path=CUSTOM_PATH)\n\n# Run this from the terminal as you would normally start a FastAPI app: `uvicorn run:app`\n# and navigate to http://localhost:8000/gradio in your browser.\n\n```\n\nNote that this approach also allows you run your Gradio apps on custom paths (`http://localhost:8000/gradio` in the example above)." }, { "id": 539, "parent": 530, "path": "04_additional-features/07_sharing-your-app.md", "level": 2, "title": "Authentication", "content": "" }, { "id": 540, "parent": 539, "path": "04_additional-features/07_sharing-your-app.md", "level": 3, "title": "Password-protected app", "content": "You may wish to put an authentication page in front of your app to limit who can open your app. With the `auth=` keyword argument in the `launch()` method, you can provide a tuple with a username and password, or a list of acceptable username/password tuples; Here's an example that provides password-based authentication for a single user named \"admin\":\n\n```python\ndemo.launch(auth=(\"admin\", \"pass1234\"))\n```\n\nFor more complex authentication handling, you can even pass a function that takes a username and password as arguments, and returns `True` to allow access, `False` otherwise.\n\nHere's an example of a function that accepts any login where the username and password are the same:\n\n```python\ndef same_auth(username, password):\n return username == password\ndemo.launch(auth=same_auth)\n```\n\nIf you have multiple users, you may wish to customize the content that is shown depending on the user that is logged in. You can retrieve the logged in user by [accessing the network request directly](#accessing-the-network-request-directly) as discussed above, and then reading the `.username` attribute of the request. Here's an example:\n\n\n```python\nimport gradio as gr\n\ndef update_message(request: gr.Request):\n return f\"Welcome, {request.username}\"\n\nwith gr.Blocks() as demo:\n m = gr.Markdown()\n demo.load(update_message, None, m)\n \ndemo.launch(auth=[(\"Abubakar\", \"Abubakar\"), (\"Ali\", \"Ali\")])\n```\n\nNote: For authentication to work properly, third party cookies must be enabled in your browser. This is not the case by default for Safari or for Chrome Incognito Mode. \n\nIf users visit the `/logout` page of your Gradio app, they will automatically be logged out and session cookies deleted. This allows you to add logout functionality to your Gradio app as well. Let's update the previous example to include a log out button:\n\n```python\nimport gradio as gr\n\ndef update_message(request: gr.Request):\n return f\"Welcome, {request.username}\"\n\nwith gr.Blocks() as demo:\n m = gr.Markdown()\n logout_button = gr.Button(\"Logout\", link=\"/logout\")\n demo.load(update_message, None, m)\n \ndemo.launch(auth=[(\"Pete\", \"Pete\"), (\"Dawood\", \"Dawood\")])\n```\n\nNote: Gradio's built-in authentication provides a straightforward and basic layer of access control but does not offer robust security features for applications that require stringent access controls (e.g. multi-factor authentication, rate limiting, or automatic lockout policies)." }, { "id": 541, "parent": 539, "path": "04_additional-features/07_sharing-your-app.md", "level": 3, "title": "OAuth (Login via Hugging Face)", "content": "Gradio natively supports OAuth login via Hugging Face. In other words, you can easily add a _\"Sign in with Hugging Face\"_ button to your demo, which allows you to get a user's HF username as well as other information from their HF profile. Check out [this Space](https://huggingface.co/spaces/Wauplin/gradio-oauth-demo) for a live demo.\n\nTo enable OAuth, you must set `hf_oauth: true` as a Space metadata in your README.md file. This will register your Space\nas an OAuth application on Hugging Face. Next, you can use `gr.LoginButton` to add a login button to\nyour Gradio app. Once a user is logged in with their HF account, you can retrieve their profile by adding a parameter of type\n`gr.OAuthProfile` to any Gradio function. The user profile will be automatically injected as a parameter value. If you want\nto perform actions on behalf of the user (e.g. list user's private repos, create repo, etc.), you can retrieve the user\ntoken by adding a parameter of type `gr.OAuthToken`. You must define which scopes you will use in your Space metadata\n(see [documentation](https://huggingface.co/docs/hub/spaces-oauth#scopes) for more details).\n\nHere is a short example:\n\n```py\nfrom __future__ import annotations\n\nimport gradio as gr\nfrom huggingface_hub import whoami\n\ndef hello(profile: gr.OAuthProfile | None) -> str:\n if profile is None:\n return \"I don't know you.\"\n return f\"Hello {profile.name}\"\n\ndef list_organizations(oauth_token: gr.OAuthToken | None) -> str:\n if oauth_token is None:\n return \"Please deploy this on Spaces and log in to list organizations.\"\n org_names = [org[\"name\"] for org in whoami(oauth_token.token)[\"orgs\"]]\n return f\"You belong to {', '.join(org_names)}.\"\n\nwith gr.Blocks() as demo:\n gr.LoginButton()\n m1 = gr.Markdown()\n m2 = gr.Markdown()\n demo.load(hello, inputs=None, outputs=m1)\n demo.load(list_organizations, inputs=None, outputs=m2)\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n\nWhen the user clicks on the login button, they get redirected in a new page to authorize your Space.\n\n
\n\n
\n\nUsers can revoke access to their profile at any time in their [settings](https://huggingface.co/settings/connected-applications).\n\nAs seen above, OAuth features are available only when your app runs in a Space. However, you often need to test your app\nlocally before deploying it. To test OAuth features locally, your machine must be logged in to Hugging Face. Please run `huggingface-cli login` or set `HF_TOKEN` as environment variable with one of your access token. You can generate a new token in your settings page (https://huggingface.co/settings/tokens). Then, clicking on the `gr.LoginButton` will login your local Hugging Face profile, allowing you to debug your app with your Hugging Face account before deploying it to a Space.\n\n**Security Note**: It is important to note that adding a `gr.LoginButton` does not restrict users from using your app, in the same way that adding [username-password authentication](/guides/sharing-your-app#password-protected-app) does. This means that users of your app who have not logged in with Hugging Face can still access and run events in your Gradio app -- the difference is that the `gr.OAuthProfile` or `gr.OAuthToken` will be `None` in the corresponding functions." }, { "id": 542, "parent": 539, "path": "04_additional-features/07_sharing-your-app.md", "level": 3, "title": "OAuth (with external providers)", "content": "It is also possible to authenticate with external OAuth providers (e.g. Google OAuth) in your Gradio apps. To do this, first mount your Gradio app within a FastAPI app ([as discussed above](#mounting-within-another-fast-api-app)). Then, you must write an *authentication function*, which gets the user's username from the OAuth provider and returns it. This function should be passed to the `auth_dependency` parameter in `gr.mount_gradio_app`. \n\nSimilar to [FastAPI dependency functions](https://fastapi.tiangolo.com/tutorial/dependencies/), the function specified by `auth_dependency` will run before any Gradio-related route in your FastAPI app. The function should accept a single parameter: the FastAPI `Request` and return either a string (representing a user's username) or `None`. If a string is returned, the user will be able to access the Gradio-related routes in your FastAPI app. \n\nFirst, let's show a simplistic example to illustrate the `auth_dependency` parameter:\n\n```python\nfrom fastapi import FastAPI, Request\nimport gradio as gr\n\napp = FastAPI()\n\ndef get_user(request: Request):\n return request.headers.get(\"user\")\n\ndemo = gr.Interface(lambda s: f\"Hello {s}!\", \"textbox\", \"textbox\")\n\napp = gr.mount_gradio_app(app, demo, path=\"/demo\", auth_dependency=get_user)\n\nif __name__ == '__main__':\n uvicorn.run(app)\n```\n\nIn this example, only requests that include a \"user\" header will be allowed to access the Gradio app. Of course, this does not add much security, since any user can add this header in their request.\n\nHere's a more complete example showing how to add Google OAuth to a Gradio app (assuming you've already created OAuth Credentials on the [Google Developer Console](https://console.cloud.google.com/project)):\n\n```python\nimport os\nfrom authlib.integrations.starlette_client import OAuth, OAuthError\nfrom fastapi import FastAPI, Depends, Request\nfrom starlette.config import Config\nfrom starlette.responses import RedirectResponse\nfrom starlette.middleware.sessions import SessionMiddleware\nimport uvicorn\nimport gradio as gr\n\napp = FastAPI()" }, { "id": 543, "parent": null, "path": "04_additional-features/07_sharing-your-app.md", "level": 1, "title": "Replace these with your own OAuth settings", "content": "GOOGLE_CLIENT_ID = \"...\"\nGOOGLE_CLIENT_SECRET = \"...\"\nSECRET_KEY = \"...\"\n\nconfig_data = {'GOOGLE_CLIENT_ID': GOOGLE_CLIENT_ID, 'GOOGLE_CLIENT_SECRET': GOOGLE_CLIENT_SECRET}\nstarlette_config = Config(environ=config_data)\noauth = OAuth(starlette_config)\noauth.register(\n name='google',\n server_metadata_url='https://accounts.google.com/.well-known/openid-configuration',\n client_kwargs={'scope': 'openid email profile'},\n)\n\nSECRET_KEY = os.environ.get('SECRET_KEY') or \"a_very_secret_key\"\napp.add_middleware(SessionMiddleware, secret_key=SECRET_KEY)" }, { "id": 544, "parent": null, "path": "04_additional-features/07_sharing-your-app.md", "level": 1, "title": "Dependency to get the current user", "content": "def get_user(request: Request):\n user = request.session.get('user')\n if user:\n return user['name']\n return None\n\n@app.get('/')\ndef public(user: dict = Depends(get_user)):\n if user:\n return RedirectResponse(url='/gradio')\n else:\n return RedirectResponse(url='/login-demo')\n\n@app.route('/logout')\nasync def logout(request: Request):\n request.session.pop('user', None)\n return RedirectResponse(url='/')\n\n@app.route('/login')\nasync def login(request: Request):\n redirect_uri = request.url_for('auth')\n # If your app is running on https, you should ensure that the\n # `redirect_uri` is https, e.g. uncomment the following lines:\n # \n # from urllib.parse import urlparse, urlunparse\n # redirect_uri = urlunparse(urlparse(str(redirect_uri))._replace(scheme='https'))\n return await oauth.google.authorize_redirect(request, redirect_uri)\n\n@app.route('/auth')\nasync def auth(request: Request):\n try:\n access_token = await oauth.google.authorize_access_token(request)\n except OAuthError:\n return RedirectResponse(url='/')\n request.session['user'] = dict(access_token)[\"userinfo\"]\n return RedirectResponse(url='/')\n\nwith gr.Blocks() as login_demo:\n gr.Button(\"Login\", link=\"/login\")\n\napp = gr.mount_gradio_app(app, login_demo, path=\"/login-demo\")\n\ndef greet(request: gr.Request):\n return f\"Welcome to Gradio, {request.username}\"\n\nwith gr.Blocks() as main_demo:\n m = gr.Markdown(\"Welcome to Gradio!\")\n gr.Button(\"Logout\", link=\"/logout\")\n main_demo.load(greet, None, m)\n\napp = gr.mount_gradio_app(app, main_demo, path=\"/gradio\", auth_dependency=get_user)\n\nif __name__ == '__main__':\n uvicorn.run(app)\n```\n\nThere are actually two separate Gradio apps in this example! One that simply displays a log in button (this demo is accessible to any user), while the other main demo is only accessible to users that are logged in. You can try this example out on [this Space](https://huggingface.co/spaces/gradio/oauth-example)." }, { "id": 545, "parent": 544, "path": "04_additional-features/07_sharing-your-app.md", "level": 2, "title": "Analytics", "content": "By default, Gradio collects certain analytics to help us better understand the usage of the `gradio` library. This includes the following information:\n\n* What environment the Gradio app is running on (e.g. Colab Notebook, Hugging Face Spaces)\n* What input/output components are being used in the Gradio app\n* Whether the Gradio app is utilizing certain advanced features, such as `auth` or `show_error` \n* The IP address which is used solely to measure the number of unique developers using Gradio \n* The version of Gradio that is running \n\nNo information is collected from _users_ of your Gradio app. If you'd like to diable analytics altogether, you can do so by setting the `analytics_enabled` parameter to `False` in `gr.Blocks`, `gr.Interface`, or `gr.ChatInterface`. Or, you can set the GRADIO_ANALYTICS_ENABLED environment variable to `\"False\"` to apply this to all Gradio apps created across your system.\n\n*Note*: this reflects the analytics policy as of `gradio>=4.32.0`." }, { "id": 546, "parent": null, "path": "04_additional-features/05_progress-bars.md", "level": 1, "title": "Progress Bars", "content": "Gradio supports the ability to create custom Progress Bars so that you have customizability and control over the progress update that you show to the user. In order to enable this, simply add an argument to your method that has a default value of a `gr.Progress` instance. Then you can update the progress levels by calling this instance directly with a float between 0 and 1, or using the `tqdm()` method of the `Progress` instance to track progress over an iterable, as shown below.\n\n```py\nimport gradio as gr\nimport time\n\ndef slowly_reverse(word, progress=gr.Progress()):\n progress(0, desc=\"Starting\")\n time.sleep(1)\n progress(0.05)\n new_string = \"\"\n for letter in progress.tqdm(word, desc=\"Reversing\"):\n time.sleep(0.25)\n new_string = letter + new_string # type: ignore\n return new_string\n\ndemo = gr.Interface(slowly_reverse, gr.Text(), gr.Text())\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n$demo_progress_simple\n\nIf you use the `tqdm` library, you can even report progress updates automatically from any `tqdm.tqdm` that already exists within your function by setting the default argument as `gr.Progress(track_tqdm=True)`!" }, { "id": 547, "parent": null, "path": "05_chatbots/05_chatbot-specific-events.md", "level": 1, "title": "Liking, Retrying and Undoing Messages", "content": "Tags: LLM, CHAT\n\nUsers expect modern chatbot UIs to let them easily interact with individual chat messages: for example, users might want to retry message generations, undo messages, or click on a like/dislike button to upvote or downvote a generated message.\n\nThankfully, the Gradio Chatbot exposes three events, `.retry`, `.undo`, and `like`, to let you build this functionality into your application. As an application developer, you can attach functions to any of these event, allowing you to run arbitrary Python functions e.g. when a user interacts with a message.\n\nIn this demo, we'll build a UI that implements these events. You can see our finished demo deployed on Hugging Face spaces here:\n\n$demo_chatbot_retry_undo_like\n\nTip: `gr.ChatInterface` automatically uses the `retry` and `.undo` events so it's best to start there in order get a fully working application quickly." }, { "id": 548, "parent": 547, "path": "05_chatbots/05_chatbot-specific-events.md", "level": 2, "title": "The UI", "content": "First, we'll build the UI without handling these events and build from there. \nWe'll use the Hugging Face InferenceClient in order to get started without setting up\nany API keys.\n\nThis is what the first draft of our application looks like:\n\n```python\nfrom huggingface_hub import InferenceClient\nimport gradio as gr\n\nclient = InferenceClient()\n\ndef respond(\n prompt: str,\n history,\n):\n if not history:\n history = [{\"role\": \"system\", \"content\": \"You are a friendly chatbot\"}]\n history.append({\"role\": \"user\", \"content\": prompt})\n\n yield history\n\n response = {\"role\": \"assistant\", \"content\": \"\"}\n for message in client.chat_completion(\n history,\n temperature=0.95,\n top_p=0.9,\n max_tokens=512,\n stream=True,\n model=\"HuggingFaceH4/zephyr-7b-beta\"\n ):\n response[\"content\"] += message.choices[0].delta.content or \"\"\n\n yield history + [response]\n\n\nwith gr.Blocks() as demo:\n gr.Markdown(\"# Chat with Hugging Face Zephyr 7b 🤗\")\n chatbot = gr.Chatbot(\n label=\"Agent\",\n type=\"messages\",\n avatar_images=(\n None,\n \"https://em-content.zobj.net/source/twitter/376/hugging-face_1f917.png\",\n ),\n )\n prompt = gr.Textbox(max_lines=1, label=\"Chat Message\")\n prompt.submit(respond, [prompt, chatbot], [chatbot])\n prompt.submit(lambda: \"\", None, [prompt])\n\n\nif __name__ == \"__main__\":\n demo.launch()\n```" }, { "id": 549, "parent": 547, "path": "05_chatbots/05_chatbot-specific-events.md", "level": 2, "title": "The Undo Event", "content": "Our undo event will populate the textbox with the previous user message and also remove all subsequent assistant responses.\n\nIn order to know the index of the last user message, we can pass `gr.UndoData` to our event handler function like so:\n\n``python\ndef handle_undo(history, undo_data: gr.UndoData):\n return history[:undo_data.index], history[undo_data.index]['content']\n```\n\nWe then pass this function to the `undo` event!\n\n```python\n chatbot.undo(handle_undo, chatbot, [chatbot, prompt])\n```\n\nYou'll notice that every bot response will now have an \"undo icon\" you can use to undo the response - \n\n![undo_event](https://github.com/user-attachments/assets/180b5302-bc4a-4c3e-903c-f14ec2adcaa6)\n\nTip: You can also access the content of the user message with `undo_data.value`" }, { "id": 550, "parent": 547, "path": "05_chatbots/05_chatbot-specific-events.md", "level": 2, "title": "The Retry Event", "content": "The retry event will work similarly. We'll use `gr.RetryData` to get the index of the previous user message and remove all the subsequent messages from the history. Then we'll use the `respond` function to generate a new response. We could also get the previous prompt via the `value` property of `gr.RetryData`.\n\n```python\ndef handle_retry(history, retry_data: gr.RetryData):\n new_history = history[:retry_data.index]\n previous_prompt = history[retry_data.index]['content']\n yield from respond(previous_prompt, new_history)\n\n...\n\nchatbot.retry(handle_retry, chatbot, [chatbot])\n```\n\nYou'll see that the bot messages have a \"retry\" icon now -\n\n![retry_event](https://github.com/user-attachments/assets/cec386a7-c4cd-4fb3-a2d7-78fd806ceac6)\n\nTip: The Hugging Face inference API caches responses, so in this demo, the retry button will not generate a new response." }, { "id": 551, "parent": 547, "path": "05_chatbots/05_chatbot-specific-events.md", "level": 2, "title": "The Like Event", "content": "By now you should hopefully be seeing the pattern!\nTo let users like a message, we'll add a `.like` event to our chatbot.\nWe'll pass it a function that accepts a `gr.LikeData` object.\nIn this case, we'll just print the message that was either liked or disliked.\n\n```python\ndef handle_like(data: gr.LikeData):\n if data.liked:\n print(\"You upvoted this response: \", data.value)\n else:\n print(\"You downvoted this response: \", data.value)\n\n...\n\nchatbot.like(vote, None, None)\n```" }, { "id": 552, "parent": 547, "path": "05_chatbots/05_chatbot-specific-events.md", "level": 2, "title": "Conclusion", "content": "That's it! You now know how you can implement the retry, undo, and like events for the Chatbot." }, { "id": 553, "parent": null, "path": "05_chatbots/03_agents-and-tool-usage.md", "level": 1, "title": "Building a UI for an LLM Agent", "content": "Tags: LLM, AGENTS, CHAT\nRelated spaces: https://huggingface.co/spaces/gradio/agent_chatbot, https://huggingface.co/spaces/gradio/langchain-agent\n\nThe Gradio Chatbot can natively display intermediate thoughts and tool usage. This makes it perfect for creating UIs for LLM agents. This guide will show you how." }, { "id": 554, "parent": 553, "path": "05_chatbots/03_agents-and-tool-usage.md", "level": 2, "title": "The metadata key", "content": "In addition to the `content` and `role` keys, the messages dictionary accepts a `metadata` key. At present, the `metadata` key accepts a dictionary with a single key called `title`. \nIf you specify a `title` for the message, it will be displayed in a collapsible box.\n\nHere is an example, were we display the agent's thought to use a weather API tool to answer the user query.\n\n```python\nwith gr.Blocks() as demo:\n chatbot = gr.Chatbot(type=\"messages\",\n value=[{\"role\": \"user\", \"content\": \"What is the weather in San Francisco?\"},\n {\"role\": \"assistant\", \"content\": \"I need to use the weather API tool\",\n \"metadata\": {\"title\": \"🧠 Thinking\"}}]\n )\n```\n\n![simple-metadat-chatbot](https://github.com/freddyaboulton/freddyboulton/assets/41651716/3941783f-6835-4e5e-89a6-03f850d9abde)" }, { "id": 555, "parent": 553, "path": "05_chatbots/03_agents-and-tool-usage.md", "level": 2, "title": "A real example using transformers.agents", "content": "We'll create a Gradio application simple agent that has access to a text-to-image tool.\n\nTip: Make sure you read the transformers agent [documentation](https://huggingface.co/docs/transformers/en/agents) first\n\nWe'll start by importing the necessary classes from transformers and gradio. \n\n```python\nimport gradio as gr\nfrom gradio import ChatMessage\nfrom transformers import load_tool, ReactCodeAgent, HfEngine\nfrom utils import stream_from_transformers_agent" }, { "id": 556, "parent": null, "path": "05_chatbots/03_agents-and-tool-usage.md", "level": 1, "title": "Import tool from Hub", "content": "image_generation_tool = load_tool(\"m-ric/text-to-image\")\n\n\nllm_engine = HfEngine(\"meta-llama/Meta-Llama-3-70B-Instruct\")" }, { "id": 557, "parent": null, "path": "05_chatbots/03_agents-and-tool-usage.md", "level": 1, "title": "Initialize the agent with both tools", "content": "agent = ReactCodeAgent(tools=[image_generation_tool], llm_engine=llm_engine)\n```\n\nThen we'll build the UI. The bulk of the logic is handled by `stream_from_transformers_agent`. We won't cover it in this guide because it will soon be merged to transformers but you can see its source code [here](https://huggingface.co/spaces/gradio/agent_chatbot/blob/main/utils.py).\n\n```python\ndef interact_with_agent(prompt, messages):\n messages.append(ChatMessage(role=\"user\", content=prompt))\n yield messages\n for msg in stream_from_transformers_agent(agent, prompt):\n messages.append(msg)\n yield messages\n yield messages\n\n\nwith gr.Blocks() as demo:\n stored_message = gr.State([])\n chatbot = gr.Chatbot(label=\"Agent\",\n type=\"messages\",\n avatar_images=(None, \"https://em-content.zobj.net/source/twitter/53/robot-face_1f916.png\"))\n text_input = gr.Textbox(lines=1, label=\"Chat Message\")\n text_input.submit(lambda s: (s, \"\"), [text_input], [stored_message, text_input]).then(interact_with_agent, [stored_message, chatbot], [chatbot])\n```\n\nYou can see the full demo code [here](https://huggingface.co/spaces/gradio/agent_chatbot/blob/main/app.py).\n\n\n![transformers_agent_code](https://github.com/freddyaboulton/freddyboulton/assets/41651716/c8d21336-e0e6-4878-88ea-e6fcfef3552d)" }, { "id": 558, "parent": 557, "path": "05_chatbots/03_agents-and-tool-usage.md", "level": 2, "title": "A real example using langchain agents", "content": "We'll create a UI for langchain agent that has access to a search engine.\n\nWe'll begin with imports and setting up the langchain agent. Note that you'll need an .env file with\nthe following environment variables set - \n\n```\nSERPAPI_API_KEY=\nHF_TOKEN=\nOPENAI_API_KEY=\n```\n\n```python\nfrom langchain import hub\nfrom langchain.agents import AgentExecutor, create_openai_tools_agent, load_tools\nfrom langchain_openai import ChatOpenAI\nfrom gradio import ChatMessage\nimport gradio as gr\n\nfrom dotenv import load_dotenv\n\nload_dotenv()\n\nmodel = ChatOpenAI(temperature=0, streaming=True)\n\ntools = load_tools([\"serpapi\"])" }, { "id": 559, "parent": null, "path": "05_chatbots/03_agents-and-tool-usage.md", "level": 1, "title": "Get the prompt to use - you can modify this!", "content": "prompt = hub.pull(\"hwchase17/openai-tools-agent\")" }, { "id": 560, "parent": null, "path": "05_chatbots/03_agents-and-tool-usage.md", "level": 1, "title": "print(prompt.messages) -- to see the prompt", "content": "agent = create_openai_tools_agent(\n model.with_config({\"tags\": [\"agent_llm\"]}), tools, prompt\n)\nagent_executor = AgentExecutor(agent=agent, tools=tools).with_config(\n {\"run_name\": \"Agent\"}\n)\n```\n\nThen we'll create the Gradio UI\n\n```python\nasync def interact_with_langchain_agent(prompt, messages):\n messages.append(ChatMessage(role=\"user\", content=prompt))\n yield messages\n async for chunk in agent_executor.astream(\n {\"input\": prompt}\n ):\n if \"steps\" in chunk:\n for step in chunk[\"steps\"]:\n messages.append(ChatMessage(role=\"assistant\", content=step.action.log,\n metadata={\"title\": f\"🛠️ Used tool {step.action.tool}\"}))\n yield messages\n if \"output\" in chunk:\n messages.append(ChatMessage(role=\"assistant\", content=chunk[\"output\"]))\n yield messages\n\n\nwith gr.Blocks() as demo:\n gr.Markdown(\"# Chat with a LangChain Agent 🦜⛓️ and see its thoughts 💭\")\n chatbot = gr.Chatbot(\n type=\"messages\",\n label=\"Agent\",\n avatar_images=(\n None,\n \"https://em-content.zobj.net/source/twitter/141/parrot_1f99c.png\",\n ),\n )\n input = gr.Textbox(lines=1, label=\"Chat Message\")\n input.submit(interact_with_langchain_agent, [input_2, chatbot_2], [chatbot_2])\n\ndemo.launch()\n```\n\n![langchain_agent_code](https://github.com/freddyaboulton/freddyboulton/assets/41651716/762283e5-3937-47e5-89e0-79657279ea67)\n\nThat's it! See our finished langchain demo [here](https://huggingface.co/spaces/gradio/langchain-agent)." }, { "id": 561, "parent": null, "path": "05_chatbots/04_creating-a-custom-chatbot-with-blocks.md", "level": 1, "title": "How to Create a Custom Chatbot with Gradio Blocks", "content": "Tags: NLP, TEXT, CHAT\nRelated spaces: https://huggingface.co/spaces/gradio/chatbot_streaming, https://huggingface.co/spaces/project-baize/Baize-7B," }, { "id": 562, "parent": 561, "path": "05_chatbots/04_creating-a-custom-chatbot-with-blocks.md", "level": 2, "title": "Introduction", "content": "**Important Note**: if you are getting started, we recommend using the `gr.ChatInterface` to create chatbots -- its a high-level abstraction that makes it possible to create beautiful chatbot applications fast, often with a single line of code. [Read more about it here](/guides/creating-a-chatbot-fast).\n\nThis tutorial will show how to make chatbot UIs from scratch with Gradio's low-level Blocks API. This will give you full control over your Chatbot UI. You'll start by first creating a a simple chatbot to display text, a second one to stream text responses, and finally a chatbot that can handle media files as well. The chatbot interface that we create will look something like this:\n\n$demo_chatbot_streaming\n\n**Prerequisite**: We'll be using the `gradio.Blocks` class to build our Chatbot demo.\nYou can [read the Guide to Blocks first](https://gradio.app/blocks-and-event-listeners) if you are not already familiar with it. Also please make sure you are using the **latest version** version of Gradio: `pip install --upgrade gradio`." }, { "id": 563, "parent": 561, "path": "05_chatbots/04_creating-a-custom-chatbot-with-blocks.md", "level": 2, "title": "A Simple Chatbot Demo", "content": "Let's start with recreating the simple demo above. As you may have noticed, our bot simply randomly responds \"How are you?\", \"Today is a great day\", or \"I'm very hungry\" to any input. Here's the code to create this with Gradio:\n\n```py\nimport gradio as gr\nimport random\nimport time\n\nwith gr.Blocks() as demo:\n chatbot = gr.Chatbot(type=\"messages\")\n msg = gr.Textbox()\n clear = gr.ClearButton([msg, chatbot])\n\n def respond(message, chat_history):\n bot_message = random.choice([\"How are you?\", \"Today is a great day\", \"I'm very hungry\"])\n chat_history.append({\"role\": \"user\", \"content\": message})\n chat_history.append({\"role\": \"assistant\", \"content\": bot_message})\n time.sleep(2)\n return \"\", chat_history\n\n msg.submit(respond, [msg, chatbot], [msg, chatbot])\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n\nThere are three Gradio components here:\n\n- A `Chatbot`, whose value stores the entire history of the conversation, as a list of response pairs between the user and bot.\n- A `Textbox` where the user can type their message, and then hit enter/submit to trigger the chatbot response\n- A `ClearButton` button to clear the Textbox and entire Chatbot history\n\nWe have a single function, `respond()`, which takes in the entire history of the chatbot, appends a random message, waits 1 second, and then returns the updated chat history. The `respond()` function also clears the textbox when it returns.\n\nOf course, in practice, you would replace `respond()` with your own more complex function, which might call a pretrained model or an API, to generate a response.\n\n$demo_chatbot_simple\n\nTip: For better type hinting and auto-completion in your IDE, you can use the `gr.ChatMessage` dataclass:\n\n```python\nfrom gradio import ChatMessage\n\ndef chat_function(message, history):\n history.append(ChatMessage(role=\"user\", content=message))\n history.append(ChatMessage(role=\"assistant\", content=\"Hello, how can I help you?\"))\n return history\n```" }, { "id": 564, "parent": 561, "path": "05_chatbots/04_creating-a-custom-chatbot-with-blocks.md", "level": 2, "title": "Add Streaming to your Chatbot", "content": "There are several ways we can improve the user experience of the chatbot above. First, we can stream responses so the user doesn't have to wait as long for a message to be generated. Second, we can have the user message appear immediately in the chat history, while the chatbot's response is being generated. Here's the code to achieve that:\n\n```py\nimport gradio as gr\nimport random\nimport time\n\nwith gr.Blocks() as demo:\n chatbot = gr.Chatbot(type=\"messages\")\n msg = gr.Textbox()\n clear = gr.Button(\"Clear\")\n\n def user(user_message, history: list):\n return \"\", history + [{\"role\": \"user\", \"content\": user_message}]\n\n def bot(history: list):\n bot_message = random.choice([\"How are you?\", \"I love you\", \"I'm very hungry\"])\n history.append({\"role\": \"assistant\", \"content\": \"\"})\n for character in bot_message:\n history[-1]['content'] += character\n time.sleep(0.05)\n yield history\n\n msg.submit(user, [msg, chatbot], [msg, chatbot], queue=False).then(\n bot, chatbot, chatbot\n )\n clear.click(lambda: None, None, chatbot, queue=False)\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n\nYou'll notice that when a user submits their message, we now _chain_ two event events with `.then()`:\n\n1. The first method `user()` updates the chatbot with the user message and clears the input field. Because we want this to happen instantly, we set `queue=False`, which would skip any queue had it been enabled. The chatbot's history is appended with `{\"role\": \"user\", \"content\": user_message}`.\n\n2. The second method, `bot()` updates the chatbot history with the bot's response. Finally, we construct the message character by character and `yield` the intermediate outputs as they are being constructed. Gradio automatically turns any function with the `yield` keyword [into a streaming output interface](/guides/key-features/#iterative-outputs).\n\n\nOf course, in practice, you would replace `bot()` with your own more complex function, which might call a pretrained model or an API, to generate a response." }, { "id": 565, "parent": 561, "path": "05_chatbots/04_creating-a-custom-chatbot-with-blocks.md", "level": 2, "title": "Adding Markdown, Images, Audio, or Videos", "content": "The `gr.Chatbot` component supports a subset of markdown including bold, italics, and code. For example, we could write a function that responds to a user's message, with a bold **That's cool!**, like this:\n\n```py\ndef bot(history):\n response = {\"role\": \"assistant\", \"content\": \"**That's cool!**\"}\n history.append(response)\n return history\n```\n\nIn addition, it can handle media files, such as images, audio, and video. You can use the `MultimodalTextbox` component to easily upload all types of media files to your chatbot. To pass in a media file, we must pass in the file a dictionary with a `path` key pointing to a local file and an `alt_text` key. The `alt_text` is optional, so you can also just pass in a tuple with a single element `{\"path\": \"filepath\"}`, like this:\n\n```python\ndef add_message(history, message):\n for x in message[\"files\"]:\n history.append({\"role\": \"user\", \"content\": {\"path\": x}})\n if message[\"text\"] is not None:\n history.append({\"role\": \"user\", \"content\": message[\"text\"]})\n return history, gr.MultimodalTextbox(value=None, interactive=False, file_types=[\"image\"])\n```\n\nPutting this together, we can create a _multimodal_ chatbot with a multimodal textbox for a user to submit text and media files. The rest of the code looks pretty much the same as before:\n\n```py\nimport gradio as gr\nimport time\n\n# Chatbot demo with multimodal input (text, markdown, LaTeX, code blocks, image, audio, & video). Plus shows support for streaming text.\n\n\ndef print_like_dislike(x: gr.LikeData):\n print(x.index, x.value, x.liked)\n\n\ndef add_message(history, message):\n for x in message[\"files\"]:\n history.append({\"role\": \"user\", \"content\": {\"path\": x}})\n if message[\"text\"] is not None:\n history.append({\"role\": \"user\", \"content\": message[\"text\"]})\n return history, gr.MultimodalTextbox(value=None, interactive=False)\n\n\ndef bot(history: list):\n response = \"**That's cool!**\"\n history.append({\"role\": \"assistant\", \"content\": \"\"})\n for character in response:\n history[-1][\"content\"] += character\n time.sleep(0.05)\n yield history\n\n\nwith gr.Blocks() as demo:\n chatbot = gr.Chatbot(elem_id=\"chatbot\", bubble_full_width=False, type=\"messages\")\n\n chat_input = gr.MultimodalTextbox(\n interactive=True,\n file_count=\"multiple\",\n placeholder=\"Enter message or upload file...\",\n show_label=False,\n )\n\n chat_msg = chat_input.submit(\n add_message, [chatbot, chat_input], [chatbot, chat_input]\n )\n bot_msg = chat_msg.then(bot, chatbot, chatbot, api_name=\"bot_response\")\n bot_msg.then(lambda: gr.MultimodalTextbox(interactive=True), None, [chat_input])\n\n chatbot.like(print_like_dislike, None, None, like_user_message=True)\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n$demo_chatbot_multimodal\n\nAnd you're done! That's all the code you need to build an interface for your chatbot model. Finally, we'll end our Guide with some links to Chatbots that are running on Spaces so that you can get an idea of what else is possible:\n\n- [project-baize/Baize-7B](https://huggingface.co/spaces/project-baize/Baize-7B): A stylized chatbot that allows you to stop generation as well as regenerate responses.\n- [MAGAer13/mPLUG-Owl](https://huggingface.co/spaces/MAGAer13/mPLUG-Owl): A multimodal chatbot that allows you to upvote and downvote responses." }, { "id": 566, "parent": null, "path": "05_chatbots/01_creating-a-chatbot-fast.md", "level": 1, "title": "How to Create a Chatbot with Gradio", "content": "Tags: LLM, CHATBOT, NLP" }, { "id": 567, "parent": 566, "path": "05_chatbots/01_creating-a-chatbot-fast.md", "level": 2, "title": "Introduction", "content": "Chatbots are a popular application of large language models (LLMs). Using Gradio, you can easily build a demo of your LLM and share that with your users, or try it yourself using an intuitive chatbot UI.\n\nThis tutorial uses `gr.ChatInterface()`, which is a high-level abstraction that allows you to create your chatbot UI fast, often with a _single line of Python_. It can be easily adapted to support multimodal chatbots, or chatbots that require further customization.\n\n**Prerequisites**: please make sure you are using the latest version of Gradio:\n\n```bash\n$ pip install --upgrade gradio\n```" }, { "id": 568, "parent": 566, "path": "05_chatbots/01_creating-a-chatbot-fast.md", "level": 2, "title": "Defining a chat function", "content": "When working with `gr.ChatInterface()`, the first thing you should do is define your **chat function**. In the simplest case, your chat function should accept two arguments: `message` and `history` (the arguments can be named anything, but must be in this order).\n\n- `message`: a `str` representing the user's most recent message.\n- `history`: a list of openai-style dictionaries with `role` and `content` keys, representing the previous conversation history. May also include additional keys representing message metadata.\n\nFor example, the `history` could look like this:\n\n```python\n[\n {\"role\": \"user\", \"content\": \"What is the capital of France?\"},\n {\"role\": \"assistant\", \"content\": \"Paris\"}\n]\n```\n\nYour chat function simply needs to return: \n\n* a `str` value, which is the chatbot's response based on the chat `history` and most recent `message`.\n\nLet's take a look at a few example chat functions:\n\n**Example: a chatbot that randomly responds with yes or no**\n\nLet's write a chat function that responds `Yes` or `No` randomly.\n\nHere's our chat function:\n\n```python\nimport random\n\ndef random_response(message, history):\n return random.choice([\"Yes\", \"No\"])\n```\n\nNow, we can plug this into `gr.ChatInterface()` and call the `.launch()` method to create the web interface:\n\n```python\nimport gradio as gr\n\ngr.ChatInterface(\n fn=random_response, \n type=\"messages\"\n).launch()\n```\n\nTip: Always set type=\"messages\" in gr.ChatInterface. The default value (type=\"tuples\") is deprecated and will be removed in a future version of Gradio.\n\nThat's it! Here's our running demo, try it out:\n\n$demo_chatinterface_random_response\n\n**Example: a chatbot that alternates between agreeing and disagreeing**\n\nOf course, the previous example was very simplistic, it didn't take user input or the previous history into account! Here's another simple example showing how to incorporate a user's input as well as the history.\n\n```python\nimport gradio as gr\n\ndef alternatingly_agree(message, history):\n if len([h for h in history if h['role'] == \"assistant\"]) % 2 == 0:\n return f\"Yes, I do think that: {message}\"\n else:\n return \"I don't think so\"\n\ngr.ChatInterface(\n fn=alternatingly_agree, \n type=\"messages\"\n).launch()\n```\n\nWe'll look at more realistic examples of chat functions in our next Guide, which shows [examples of using `gr.ChatInterface` with popular LLMs](../guides/chatinterface-examples)." }, { "id": 569, "parent": 566, "path": "05_chatbots/01_creating-a-chatbot-fast.md", "level": 2, "title": "Streaming chatbots", "content": "In your chat function, you can use `yield` to generate a sequence of partial responses, each replacing the previous ones. This way, you'll end up with a streaming chatbot. It's that simple!\n\n```python\nimport time\nimport gradio as gr\n\ndef slow_echo(message, history):\n for i in range(len(message)):\n time.sleep(0.3)\n yield \"You typed: \" + message[: i+1]\n\ngr.ChatInterface(\n fn=slow_echo, \n type=\"messages\"\n).launch()\n```\n\nWhile the response is streaming, the \"Submit\" button turns into a \"Stop\" button that can be used to stop the generator function.\n\nTip: Even though you are yielding the latest message at each iteration, Gradio only sends the \"diff\" of each message from the server to the frontend, which reduces latency and data consumption over your network." }, { "id": 570, "parent": 566, "path": "05_chatbots/01_creating-a-chatbot-fast.md", "level": 2, "title": "Customizing the Chat UI", "content": "If you're familiar with Gradio's `gr.Interface` class, the `gr.ChatInterface` includes many of the same arguments that you can use to customize the look and feel of your Chatbot. For example, you can:\n\n- add a title and description above your chatbot using `title` and `description` arguments.\n- add a theme or custom css using `theme` and `css` arguments respectively.\n- add `examples` and even enable `cache_examples`, which make your Chatbot easier for users to try it out.\n- customize the chatbot (e.g. to change the height or add a placeholder) or textbox (e.g. to add a max number of characters or add a placeholder).\n\n**Adding examples**\n\nYou can add preset examples to your `gr.ChatInterface` with the `examples` parameter, which takes a list of string examples. Any examples will appear as \"buttons\" within the Chatbot before any messages are sent. If you'd like to include images or other files as part of your examples, you can do so by using this dictionary format for each example instead of a string: `{\"text\": \"What's in this image?\", \"files\": [\"cheetah.jpg\"]}`. Each file will be a separate message that is added to your Chatbot history.\n\nYou can change the displayed text for each example by using the `example_labels` argument. You can add icons to each example as well using the `example_icons` argument. Both of these arguments take a list of strings, which should be the same length as the `examples` list.\n\nIf you'd like to cache the examples so that they are pre-computed and the results appear instantly, set `cache_examples=True`.\n\n**Customizing the chatbot or textbox component**\n\nIf you want to customize the `gr.Chatbot` or `gr.Textbox` that compose the `ChatInterface`, then you can pass in your own chatbot or textbox components. Here's an example of how we to apply the parameters we've discussed in this section:\n\n```python\nimport gradio as gr\n\ndef yes_man(message, history):\n if message.endswith(\"?\"):\n return \"Yes\"\n else:\n return \"Ask me anything!\"\n\ngr.ChatInterface(\n yes_man,\n type=\"messages\",\n chatbot=gr.Chatbot(height=300),\n textbox=gr.Textbox(placeholder=\"Ask me a yes or no question\", container=False, scale=7),\n title=\"Yes Man\",\n description=\"Ask Yes Man any question\",\n theme=\"ocean\",\n examples=[\"Hello\", \"Am I cool?\", \"Are tomatoes vegetables?\"],\n cache_examples=True,\n).launch()\n```\n\nHere's another example that adds a \"placeholder\" for your chat interface, which appears before the user has started chatting. The `placeholder` argument of `gr.Chatbot` accepts Markdown or HTML:\n\n```python\ngr.ChatInterface(\n yes_man,\n type=\"messages\",\n chatbot=gr.Chatbot(placeholder=\"Your Personal Yes-Man
Ask Me Anything\"),\n...\n```\n\nThe placeholder appears vertically and horizontally centered in the chatbot." }, { "id": 571, "parent": 566, "path": "05_chatbots/01_creating-a-chatbot-fast.md", "level": 2, "title": "Multimodal Chat Interface", "content": "You may want to add multimodal capabilities to your chat interface. For example, you may want users to be able to upload images or files to your chatbot and ask questions about them. You can make your chatbot \"multimodal\" by passing in a single parameter (`multimodal=True`) to the `gr.ChatInterface` class.\n\nWhen `multimodal=True`, the signature of your chat function changes slightly: the first parameter of your function (what we referred to as `message` above) should accept a dictionary consisting of the submitted text and uploaded files that looks like this: \n\n```py\n{\n \"text\": \"user input\", \n \"files\": [\n \"updated_file_1_path.ext\",\n \"updated_file_2_path.ext\", \n ...\n ]\n}\n```\n\nThis second parameter of your chat function, `history`, will be in the same openai-style dictionary format as before. However, if the history contains uploaded files, the `content` key for a file will be not a string, but rather a single-element tuple consisting of the filepath. Each file will be a separate message in the history. So after uploading two files and asking a question, your history might look like this:\n\n```python\n[\n {\"role\": \"user\", \"content\": (\"cat1.png\")},\n {\"role\": \"user\", \"content\": (\"cat2.png\")},\n {\"role\": \"user\", \"content\": \"What's the difference between these two images?\"},\n]\n```\n\nThe return type of your chat function does *not change* when setting `multimodal=True` (i.e. in the simplest case, you should still return a string value). We discuss more complex cases, e.g. returning files [below](#returning-complex-responses).\n\nIf you are customizing a multimodal chat interface, you should pass in an instance of `gr.MultimodalTextbox` to the `textbox` parameter. Here's an example that illustrates how to set up and customize and multimodal chat interface:\n \n\n```python\nimport gradio as gr\n\ndef count_images(message, history):\n num_images = len(message[\"files\"])\n total_images = 0\n for message in history:\n if isinstance(message[\"content\"], tuple):\n total_images += 1\n return f\"You just uploaded {num_images} images, total uploaded: {total_images+num_images}\"\n\ndemo = gr.ChatInterface(\n fn=count_images, \n type=\"messages\", \n examples=[\n {\"text\": \"No files\", \"files\": []}\n ], \n multimodal=True,\n textbox=gr.MultimodalTextbox(file_count=\"multiple\", file_types=[\"image\"])\n)\n\ndemo.launch()\n```" }, { "id": 572, "parent": 566, "path": "05_chatbots/01_creating-a-chatbot-fast.md", "level": 2, "title": "Additional Inputs", "content": "You may want to add additional inputs to your chat function and expose them to your users through the chat UI. For example, you could add a textbox for a system prompt, or a slider that sets the number of tokens in the chatbot's response. The `gr.ChatInterface` class supports an `additional_inputs` parameter which can be used to add additional input components.\n\nThe `additional_inputs` parameters accepts a component or a list of components. You can pass the component instances directly, or use their string shortcuts (e.g. `\"textbox\"` instead of `gr.Textbox()`). If you pass in component instances, and they have _not_ already been rendered, then the components will appear underneath the chatbot within a `gr.Accordion()`. \n\nHere's a complete example:\n\n```py\nimport gradio as gr\nimport time\n\ndef echo(message, history, system_prompt, tokens):\n response = f\"System prompt: {system_prompt}\\n Message: {message}.\"\n for i in range(min(len(response), int(tokens))):\n time.sleep(0.05)\n yield response[: i + 1]\n\ndemo = gr.ChatInterface(\n echo,\n type=\"messages\",\n additional_inputs=[\n gr.Textbox(\"You are helpful AI.\", label=\"System Prompt\"),\n gr.Slider(10, 100),\n ],\n)\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n\nIf the components you pass into the `additional_inputs` have already been rendered in a parent `gr.Blocks()`, then they will _not_ be re-rendered in the accordion. This provides flexibility in deciding where to lay out the input components. In the example below, we position the `gr.Textbox()` on top of the Chatbot UI, while keeping the slider underneath.\n\n```python\nimport gradio as gr\nimport time\n\ndef echo(message, history, system_prompt, tokens):\n response = f\"System prompt: {system_prompt}\\n Message: {message}.\"\n for i in range(min(len(response), int(tokens))):\n time.sleep(0.05)\n yield response[: i+1]\n\nwith gr.Blocks() as demo:\n system_prompt = gr.Textbox(\"You are helpful AI.\", label=\"System Prompt\")\n slider = gr.Slider(10, 100, render=False)\n\n gr.ChatInterface(\n echo, additional_inputs=[system_prompt, slider], type=\"messages\"\n )\n\ndemo.launch()\n```\n\n**Examples with additional inputs**\n\nYou can also add example values for your additional inputs. Pass in a list of lists to the `examples` parameter, where each inner list represents one sample, and each inner list should be `1 + len(additional_inputs)` long. The first element in the inner list should be the example value for the chat message, and each subsequent element should be an example value for one of the additional inputs, in order. When additional inputs are provided, examples are rendered in a table underneath the chat interface.\n\nIf you need to create something even more custom, then its best to construct the chatbot UI using the low-level `gr.Blocks()` API. We have [a dedicated guide for that here](/guides/creating-a-custom-chatbot-with-blocks)." }, { "id": 573, "parent": 566, "path": "05_chatbots/01_creating-a-chatbot-fast.md", "level": 2, "title": "Returning Complex Responses", "content": "We mentioned earlier that in the simplest case, your chat function should return a `str` response, which will be rendered as text in the chatbot. However, you can also return more complex responses as we discuss below:\n\n**Returning Gradio components**\n\nCurrently, the following Gradio components can be displayed inside the chat interface:\n* `gr.Image`\n* `gr.Plot`\n* `gr.Audio`\n* `gr.HTML`\n* `gr.Video`\n* `gr.Gallery`\n\nSimply return one of these components from your function to use it with `gr.ChatInterface`. Here's an example:\n\n```py\nimport gradio as gr\n\ndef music(message, history):\n if message.strip():\n return gr.Audio(\"https://github.com/gradio-app/gradio/raw/main/test/test_files/audio_sample.wav\")\n else:\n return \"Please provide the name of an artist\"\n\ngr.ChatInterface(\n fake,\n type=\"messages\",\n textbox=gr.Textbox(placeholder=\"Which artist's music do you want to listen to?\", scale=7),\n).launch()\n```\n\n\n**Returning image, audio, video, or other files**:\n\nSometimes, you don't want to return a complete Gradio component, but rather simply an image/audio/video/other file to be displayed inside the chatbot. You can do this by returning a complete openai-style dictionary from your chat function. The dictionary should consist of the following keys:\n\n* `role`: set to `\"assistant\"`\n* `content`: set to a dictionary with key `path` and value the filepath or URL you'd like to return\n\nHere is an example:\n\n```py\nimport gradio as gr\n\ndef fake(message, history):\n if message.strip():\n return {\n \"role\": \"assistant\", \n \"content\": {\n \"path\": \"https://github.com/gradio-app/gradio/raw/main/test/test_files/audio_sample.wav\"\n }\n }\n else:\n return \"Please provide the name of an artist\"\n\ngr.ChatInterface(\n fake,\n type=\"messages\",\n textbox=gr.Textbox(placeholder=\"Which artist's music do you want to listen to?\", scale=7),\n chatbot=gr.Chatbot(placeholder=\"Play music by any artist!\"),\n).launch()\n```\n\n\n**Providing preset responses**\n\nYou may want to provide preset responses that a user can choose between when conversing with your chatbot. You can add the `options` key to the dictionary returned from your chat function to set these responses. The value corresponding to the `options` key should be a list of dictionaries, each with a `value` (a string that is the value that should be sent to the chat function when this response is clicked) and an optional `label` (if provided, is the text displayed as the preset response instead of the `value`). \n\nThis example illustrates how to use preset responses:\n\n```python\nimport gradio as gr\n\nexample_code = '''\nHere's the code I generated:\n\ndef greet(x):\n return f\"Hello, {x}!\"\n\nIs this correct?\n'''\n\ndef chat(message, history):\n if message == \"Yes, that's correct.\":\n return \"Great!\"\n else:\n return {\n \"role\": \"assistant\",\n \"content\": example_code,\n \"options\": [\n {\"value\": \"Yes, that's correct.\", \"label\": \"Yes\"},\n {\"value\": \"No\"}\n ]\n }\n\ndemo = gr.ChatInterface(\n chat,\n type=\"messages\",\n examples=[\"Write a Python function that takes a string and returns a greeting.\"]\n)\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```" }, { "id": 574, "parent": 566, "path": "05_chatbots/01_creating-a-chatbot-fast.md", "level": 2, "title": "Using Your Chatbot via API", "content": "Once you've built your Gradio chat interface and are hosting it on [Hugging Face Spaces](https://hf.space) or somewhere else, then you can query it with a simple API at the `/chat` endpoint. The endpoint just expects the user's message (and potentially additional inputs if you have set any using the `additional_inputs` parameter), and will return the response, internally keeping track of the messages sent so far.\n\n[](https://github.com/gradio-app/gradio/assets/1778297/7b10d6db-6476-4e2e-bebd-ecda802c3b8f)\n\nTo use the endpoint, you should use either the [Gradio Python Client](/guides/getting-started-with-the-python-client) or the [Gradio JS client](/guides/getting-started-with-the-js-client). Or, you can deploy your Chat Interface to other platforms, such as [Discord](../guides/creating-a-discord-bot-from-a-gradio-app)." }, { "id": 575, "parent": 566, "path": "05_chatbots/01_creating-a-chatbot-fast.md", "level": 2, "title": "What's Next?", "content": "Now that you've learned about the `gr.ChatInterface` class and how it can be used to create chatbot UIs quickly, we recommend reading one of the following:\n\n* [Our next Guide](../guides/chatinterface-examples) shows examples of how to use `gr.ChatInterface` with popular LLM libraries.\n* If you'd like to build very custom chat applications from scratch, you can build them using the low-level Blocks API, as [discussed in this Guide](../guides/creating-a-custom-chatbot-with-blocks).\n* Once you've deployed your Gradio Chat Interface, its easy to use it other applications because of the built-in API. Here's a tutorial on [how to deploy a Gradio chat interface as a Discord bot](../guides/creating-a-discord-bot-from-a-gradio-app)." }, { "id": 576, "parent": null, "path": "05_chatbots/02_chatinterface-examples.md", "level": 1, "title": "Using Popular LLM libraries and APIs", "content": "Tags: LLM, CHATBOT, API\n\nIn this Guide, we go through several examples of how to use `gr.ChatInterface` with popular LLM libraries and API providers.\n\nWe will cover the following libraries and API providers:\n\n* [Llama Index](#llama-index)\n* [LangChain](#lang-chain)\n* [OpenAI](#open-ai)\n* [Hugging Face `transformers`](#hugging-face-transformers)\n* [SambaNova](#samba-nova)\n* [Hyperbolic](#hyperbolic)\n* [Anthropic's Claude](#anthropics-claude)\n\nFor many LLM libraries and providers, there exist community-maintained integration libraries that make it even easier to spin up Gradio apps. We reference these libraries in the appropriate sections below." }, { "id": 577, "parent": 576, "path": "05_chatbots/02_chatinterface-examples.md", "level": 2, "title": "Llama Index", "content": "Let's start by using `llama-index` on top of `openai` to build a RAG chatbot on any text or PDF files that you can demo and share in less than 30 lines of code. You'll need to have an OpenAI key for this example (keep reading for the free, open-source equivalent!)\n\n```py\n# This is a simple RAG chatbot built on top of Llama Index and Gradio. It allows you to upload any text or PDF files and ask questions about them!\n# Before running this, make sure you have exported your OpenAI API key as an environment variable:\n# export OPENAI_API_KEY=\"your-openai-api-key\"\n\nfrom llama_index.core import VectorStoreIndex, SimpleDirectoryReader\nimport gradio as gr\n\ndef answer(message, history):\n files = []\n for msg in history:\n if msg['role'] == \"user\" and isinstance(msg['content'], tuple):\n files.append(msg['content'][0])\n for file in message[\"files\"]:\n files.append(file)\n\n documents = SimpleDirectoryReader(input_files=files).load_data()\n index = VectorStoreIndex.from_documents(documents)\n query_engine = index.as_query_engine()\n return str(query_engine.query(message[\"text\"]))\n\ndemo = gr.ChatInterface(\n answer,\n type=\"messages\",\n title=\"Llama Index RAG Chatbot\",\n description=\"Upload any text or pdf files and ask questions about them!\",\n textbox=gr.MultimodalTextbox(file_types=[\".pdf\", \".txt\"]),\n multimodal=True\n)\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```" }, { "id": 578, "parent": 576, "path": "05_chatbots/02_chatinterface-examples.md", "level": 2, "title": "LangChain", "content": "Here's an example using `langchain` on top of `openai` to build a general-purpose chatbot. As before, you'll need to have an OpenAI key for this example.\n\n```py\n# This is a simple general-purpose chatbot built on top of LangChain and Gradio.\n# Before running this, make sure you have exported your OpenAI API key as an environment variable:\n# export OPENAI_API_KEY=\"your-openai-api-key\"\n\nfrom langchain_openai import ChatOpenAI\nfrom langchain.schema import AIMessage, HumanMessage\nimport gradio as gr\n\nmodel = ChatOpenAI(model=\"gpt-4o-mini\")\n\ndef predict(message, history):\n history_langchain_format = []\n for msg in history:\n if msg['role'] == \"user\":\n history_langchain_format.append(HumanMessage(content=msg['content']))\n elif msg['role'] == \"assistant\":\n history_langchain_format.append(AIMessage(content=msg['content']))\n history_langchain_format.append(HumanMessage(content=message))\n gpt_response = model.invoke(history_langchain_format)\n return gpt_response.content\n\ndemo = gr.ChatInterface(\n predict,\n type=\"messages\"\n)\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n\nTip: For quick prototyping, the community-maintained langchain-gradio repo makes it even easier to build chatbots on top of LangChain." }, { "id": 579, "parent": 576, "path": "05_chatbots/02_chatinterface-examples.md", "level": 2, "title": "OpenAI", "content": "Of course, we could also use the `openai` library directy. Here a similar example to the LangChain , but this time with streaming as well:\n\nTip: For quick prototyping, the openai-gradio library makes it even easier to build chatbots on top of OpenAI models." }, { "id": 580, "parent": 576, "path": "05_chatbots/02_chatinterface-examples.md", "level": 2, "title": "Hugging Face `transformers`", "content": "Of course, in many cases you want to run a chatbot locally. Here's the equivalent example using the SmolLM2-135M-Instruct model using the Hugging Face `transformers` library.\n\n```py\nfrom transformers import AutoModelForCausalLM, AutoTokenizer\nimport gradio as gr\n\ncheckpoint = \"HuggingFaceTB/SmolLM2-135M-Instruct\"\ndevice = \"cpu\" # \"cuda\" or \"cpu\"\ntokenizer = AutoTokenizer.from_pretrained(checkpoint)\nmodel = AutoModelForCausalLM.from_pretrained(checkpoint).to(device)\n\ndef predict(message, history):\n history.append({\"role\": \"user\", \"content\": message})\n input_text = tokenizer.apply_chat_template(history, tokenize=False)\n inputs = tokenizer.encode(input_text, return_tensors=\"pt\").to(device) # type: ignore\n outputs = model.generate(inputs, max_new_tokens=100, temperature=0.2, top_p=0.9, do_sample=True)\n decoded = tokenizer.decode(outputs[0])\n response = decoded.split(\"<|im_start|>assistant\\n\")[-1].split(\"<|im_end|>\")[0]\n return response\n\ndemo = gr.ChatInterface(predict, type=\"messages\")\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```" }, { "id": 581, "parent": 576, "path": "05_chatbots/02_chatinterface-examples.md", "level": 2, "title": "SambaNova", "content": "The SambaNova Cloud API provides access to full-precision open-source models, such as the Llama family. Here's an example of how to build a Gradio app around the SambaNova API\n\n```py\n# This is a simple general-purpose chatbot built on top of SambaNova API. \n# Before running this, make sure you have exported your SambaNova API key as an environment variable:\n# export SAMBANOVA_API_KEY=\"your-sambanova-api-key\"\n\nimport os\nimport gradio as gr\nfrom openai import OpenAI\n\napi_key = os.getenv(\"SAMBANOVA_API_KEY\")\n\nclient = OpenAI(\n base_url=\"https://api.sambanova.ai/v1/\",\n api_key=api_key,\n)\n\ndef predict(message, history):\n history.append({\"role\": \"user\", \"content\": message})\n stream = client.chat.completions.create(messages=history, model=\"Meta-Llama-3.1-70B-Instruct-8k\", stream=True)\n chunks = []\n for chunk in stream:\n chunks.append(chunk.choices[0].delta.content or \"\")\n yield \"\".join(chunks)\n\ndemo = gr.ChatInterface(predict, type=\"messages\")\n\nif __name__ == \"__main__\":\n demo.launch()\n\n\n```\n\nTip: For quick prototyping, the sambanova-gradio library makes it even easier to build chatbots on top of SambaNova models." }, { "id": 582, "parent": 576, "path": "05_chatbots/02_chatinterface-examples.md", "level": 2, "title": "Hyperbolic", "content": "The Hyperbolic AI API provides access to many open-source models, such as the Llama family. Here's an example of how to build a Gradio app around the SambaNova API\n\n```py\n# This is a simple general-purpose chatbot built on top of Hyperbolic API. \n# Before running this, make sure you have exported your Hyperbolic API key as an environment variable:\n# export HYPERBOLIC_API_KEY=\"your-hyperbolic-api-key\"\n\nimport os\nimport gradio as gr\nfrom openai import OpenAI\n\napi_key = os.getenv(\"HYPERBOLIC_API_KEY\")\n\nclient = OpenAI(\n base_url=\"https://api.hyperbolic.xyz/v1/\",\n api_key=api_key,\n)\n\ndef predict(message, history):\n history.append({\"role\": \"user\", \"content\": message})\n stream = client.chat.completions.create(messages=history, model=\"gpt-4o-mini\", stream=True)\n chunks = []\n for chunk in stream:\n chunks.append(chunk.choices[0].delta.content or \"\")\n yield \"\".join(chunks)\n\ndemo = gr.ChatInterface(predict, type=\"messages\")\n\nif __name__ == \"__main__\":\n demo.launch()\n\n\n```\n\nTip: For quick prototyping, the hyperbolic-gradio library makes it even easier to build chatbots on top of Hyperbolic models." }, { "id": 583, "parent": 576, "path": "05_chatbots/02_chatinterface-examples.md", "level": 2, "title": "Anthropic's Claude ", "content": "Anthropic's Claude model can also be used via API. Here's a simple 20 questions-style game built on top of the Anthropic API:\n\n```py\n# This is a simple 20 questions-style game built on top of the Anthropic API.\n# Before running this, make sure you have exported your Anthropic API key as an environment variable:\n# export ANTHROPIC_API_KEY=\"your-anthropic-api-key\"\n\nimport anthropic\nimport gradio as gr\n\nclient = anthropic.Anthropic()\n\ndef predict(message, history):\n keys_to_keep = [\"role\", \"content\"]\n history = [{k: d[k] for k in keys_to_keep if k in d} for d in history]\n history.append({\"role\": \"user\", \"content\": message})\n if len(history) > 20:\n history.append({\"role\": \"user\", \"content\": \"DONE\"})\n output = client.messages.create(\n messages=history, # type: ignore\n model=\"claude-3-5-sonnet-20241022\",\n max_tokens=1000,\n system=\"You are guessing an object that the user is thinking of. You can ask 10 yes/no questions. Keep asking questions until the user says DONE\"\n )\n return {\n \"role\": \"assistant\",\n \"content\": output.content[0].text, # type: ignore\n \"options\": [{\"value\": \"Yes\"}, {\"value\": \"No\"}]\n }\n\nplaceholder = \"\"\"\n

10 Questions


Think of a person, place, or thing. I'll ask you 10 yes/no questions to try and guess it.\n
\n\"\"\"\n\ndemo = gr.ChatInterface(\n predict,\n examples=[\"Start!\"],\n chatbot=gr.Chatbot(placeholder=placeholder),\n type=\"messages\"\n)\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```" }, { "id": 584, "parent": null, "path": "05_chatbots/06_creating-a-discord-bot-from-a-gradio-app.md", "level": 1, "title": "🚀 Creating Discord Bots from Gradio Apps 🚀", "content": "Tags: NLP, TEXT, CHAT\n\nWe're excited to announce that Gradio can now automatically create a discord bot from a deployed app! 🤖\n\nDiscord is a popular communication platform that allows users to chat and interact with each other in real-time. By turning your Gradio app into a Discord bot, you can bring cutting edge AI to your discord server and give your community a whole new way to interact." }, { "id": 585, "parent": 584, "path": "05_chatbots/06_creating-a-discord-bot-from-a-gradio-app.md", "level": 2, "title": "💻 How does it work? 💻", "content": "With `gradio_client` version `0.3.0`, any gradio `ChatInterface` app on the internet can automatically be deployed as a discord bot via the `deploy_discord` method of the `Client` class.\n\nTechnically, any gradio app that exposes an api route that takes in a single string and outputs a single string can be deployed to discord. In this guide, we will focus on `gr.ChatInterface` as those apps naturally lend themselves to discord's chat functionality." }, { "id": 586, "parent": 584, "path": "05_chatbots/06_creating-a-discord-bot-from-a-gradio-app.md", "level": 2, "title": "🛠️ Requirements 🛠️", "content": "Make sure you have the latest `gradio_client` and `gradio` versions installed.\n\n```bash\npip install gradio_client>=0.3.0 gradio>=3.38.0\n```\n\nAlso, make sure you have a [Hugging Face account](https://huggingface.co/) and a [write access token](https://huggingface.co/docs/hub/security-tokens).\n\n⚠️ Tip ⚠️: Make sure you login to the Hugging Face Hub by running `huggingface-cli login`. This will let you skip passing your token in all subsequent commands in this guide." }, { "id": 587, "parent": 584, "path": "05_chatbots/06_creating-a-discord-bot-from-a-gradio-app.md", "level": 2, "title": "🏃‍♀️ Quickstart 🏃‍♀️", "content": "" }, { "id": 588, "parent": 587, "path": "05_chatbots/06_creating-a-discord-bot-from-a-gradio-app.md", "level": 3, "title": "Step 1: Implementing our chatbot", "content": "Let's build a very simple Chatbot using `ChatInterface` that simply repeats the user message. Write the following code into an `app.py`\n\n```python\nimport gradio as gr\n\ndef slow_echo(message, history):\n return message\n\ndemo = gr.ChatInterface(slow_echo).queue().launch()\n```" }, { "id": 589, "parent": 587, "path": "05_chatbots/06_creating-a-discord-bot-from-a-gradio-app.md", "level": 3, "title": "Step 2: Deploying our App", "content": "In order to create a discord bot for our app, it must be accessible over the internet. In this guide, we will use the `gradio deploy` command to deploy our chatbot to Hugging Face spaces from the command line. Run the following command.\n\n```bash\ngradio deploy --title echo-chatbot --app-file app.py\n```\n\nThis command will ask you some questions, e.g. requested hardware, requirements, but the default values will suffice for this guide.\nNote the URL of the space that was created. Mine is https://huggingface.co/spaces/freddyaboulton/echo-chatbot" }, { "id": 590, "parent": 587, "path": "05_chatbots/06_creating-a-discord-bot-from-a-gradio-app.md", "level": 3, "title": "Step 3: Creating a Discord Bot", "content": "Turning our space into a discord bot is also a one-liner thanks to the `gradio deploy-discord`. Run the following command:\n\n```bash\ngradio deploy-discord --src freddyaboulton/echo-chatbot\n```\n\n❗️ Advanced ❗️: If you already have a discord bot token you can pass it to the `deploy-discord` command. Don't worry, if you don't have one yet!\n\n```bash\ngradio deploy-discord --src freddyaboulton/echo-chatbot --discord-bot-token \n```\n\nNote the URL that gets printed out to the console. Mine is https://huggingface.co/spaces/freddyaboulton/echo-chatbot-gradio-discord-bot" }, { "id": 591, "parent": 587, "path": "05_chatbots/06_creating-a-discord-bot-from-a-gradio-app.md", "level": 3, "title": "Step 4: Getting a Discord Bot Token", "content": "If you didn't have a discord bot token for step 3, go to the URL that got printed in the console and follow the instructions there.\nOnce you obtain a token, run the command again but this time pass in the token:\n\n```bash\ngradio deploy-discord --src freddyaboulton/echo-chatbot --discord-bot-token \n```" }, { "id": 592, "parent": 587, "path": "05_chatbots/06_creating-a-discord-bot-from-a-gradio-app.md", "level": 3, "title": "Step 5: Add the bot to your server", "content": "Visit the space of your discord bot. You should see \"Add this bot to your server by clicking this link:\" followed by a URL. Go to that URL and add the bot to your server!" }, { "id": 593, "parent": 587, "path": "05_chatbots/06_creating-a-discord-bot-from-a-gradio-app.md", "level": 3, "title": "Step 6: Use your bot!", "content": "By default the bot can be called by starting a message with `/chat`, e.g. `/chat `.\n\n⚠️ Tip ⚠️: If either of the deployed spaces goes to sleep, the bot will stop working. By default, spaces go to sleep after 48 hours of inactivity. You can upgrade the hardware of your space to prevent it from going to sleep. See this [guide](https://huggingface.co/docs/hub/spaces-gpus#using-gpu-spaces) for more information.\n\n" }, { "id": 594, "parent": 587, "path": "05_chatbots/06_creating-a-discord-bot-from-a-gradio-app.md", "level": 3, "title": "Using the `gradio_client.Client` Class", "content": "You can also create a discord bot from a deployed gradio app with python.\n\n```python\nimport gradio_client as grc\ngrc.Client(\"freddyaboulton/echo-chatbot\").deploy_discord()\n```" }, { "id": 595, "parent": 584, "path": "05_chatbots/06_creating-a-discord-bot-from-a-gradio-app.md", "level": 2, "title": "🦾 Using State of The Art LLMs 🦾", "content": "We have created an organization on Hugging Face called [gradio-discord-bots](https://huggingface.co/gradio-discord-bots) containing several template spaces that explain how to deploy state of the art LLMs powered by gradio as discord bots.\n\nThe easiest way to get started is by deploying Meta's Llama 2 LLM with 70 billion parameter. Simply go to this [space](https://huggingface.co/spaces/gradio-discord-bots/Llama-2-70b-chat-hf) and follow the instructions.\n\nThe deployment can be done in one line! 🤯\n\n```python\nimport gradio_client as grc\ngrc.Client(\"ysharma/Explore_llamav2_with_TGI\").deploy_discord(to_id=\"llama2-70b-discord-bot\")\n```" }, { "id": 596, "parent": 584, "path": "05_chatbots/06_creating-a-discord-bot-from-a-gradio-app.md", "level": 2, "title": "🦜 Additional LLMs 🦜", "content": "In addition to Meta's 70 billion Llama 2 model, we have prepared template spaces for the following LLMs and deployment options:\n\n- [gpt-3.5-turbo](https://huggingface.co/spaces/gradio-discord-bots/gpt-35-turbo), powered by openai. Required OpenAI key.\n- [falcon-7b-instruct](https://huggingface.co/spaces/gradio-discord-bots/falcon-7b-instruct) powered by Hugging Face Inference Endpoints.\n- [Llama-2-13b-chat-hf](https://huggingface.co/spaces/gradio-discord-bots/Llama-2-13b-chat-hf) powered by Hugging Face Inference Endpoints.\n- [Llama-2-13b-chat-hf](https://huggingface.co/spaces/gradio-discord-bots/llama-2-13b-chat-transformers) powered by Hugging Face transformers.\n\nTo deploy any of these models to discord, simply follow the instructions in the linked space for that model." }, { "id": 597, "parent": 584, "path": "05_chatbots/06_creating-a-discord-bot-from-a-gradio-app.md", "level": 2, "title": "Deploying non-chat gradio apps to discord", "content": "As mentioned above, you don't need a `gr.ChatInterface` if you want to deploy your gradio app to discord. All that's needed is an api route that takes in a single string and outputs a single string.\n\nThe following code will deploy a space that translates english to german as a discord bot.\n\n```python\nimport gradio_client as grc\nclient = grc.Client(\"freddyaboulton/english-to-german\")\nclient.deploy_discord(api_names=['german'])\n```" }, { "id": 598, "parent": 584, "path": "05_chatbots/06_creating-a-discord-bot-from-a-gradio-app.md", "level": 2, "title": "Conclusion", "content": "That's it for this guide! We're really excited about this feature. Tag [@Gradio](https://twitter.com/Gradio) on twitter and show us how your discord community interacts with your discord bots." }, { "id": 599, "parent": null, "path": "06_data-science-and-plots/04_connecting-to-a-database.md", "level": 1, "title": "Connecting to a Database", "content": "The data you wish to visualize may be stored in a database. Let's use SQLAlchemy to quickly extract database content into pandas Dataframe format so we can use it in gradio.\n\nFirst install `pip install sqlalchemy` and then let's see some examples." }, { "id": 600, "parent": 599, "path": "06_data-science-and-plots/04_connecting-to-a-database.md", "level": 2, "title": "SQLite", "content": "```python\nfrom sqlalchemy import create_engine\nimport pandas as pd\n\nengine = create_engine('sqlite:///your_database.db')\n\nwith gr.Blocks() as demo:\n gr.LinePlot(pd.read_sql_query(\"SELECT time, price from flight_info;\", engine), x=\"time\", y=\"price\")\n```\n\nLet's see a a more interactive plot involving filters that modify your SQL query:\n\n```python\nfrom sqlalchemy import create_engine\nimport pandas as pd\n\nengine = create_engine('sqlite:///your_database.db')\n\nwith gr.Blocks() as demo:\n origin = gr.Dropdown([\"DFW\", \"DAL\", \"HOU\"], value=\"DFW\", label=\"Origin\")\n\n gr.LinePlot(lambda origin: pd.read_sql_query(f\"SELECT time, price from flight_info WHERE origin = {origin};\", engine), inputs=origin, x=\"time\", y=\"price\")\n```" }, { "id": 601, "parent": 599, "path": "06_data-science-and-plots/04_connecting-to-a-database.md", "level": 2, "title": "Postgres, mySQL, and other databases", "content": "If you're using a different database format, all you have to do is swap out the engine, e.g.\n\n```python\nengine = create_engine('postgresql://username:password@host:port/database_name')\n```\n\n```python\nengine = create_engine('mysql://username:password@host:port/database_name')\n```\n\n```python\nengine = create_engine('oracle://username:password@host:port/database_name')\n```" }, { "id": 602, "parent": null, "path": "06_data-science-and-plots/03_filters-tables-and-stats.md", "level": 1, "title": "Filters, Tables and Stats", "content": "Your dashboard will likely consist of more than just plots. Let's take a look at some of the other common components of a dashboard." }, { "id": 603, "parent": 602, "path": "06_data-science-and-plots/03_filters-tables-and-stats.md", "level": 2, "title": "Filters", "content": "Use any of the standard Gradio form components to filter your data. You can do this via event listeners or function-as-value syntax. Let's look at the event listener approach first:\n\n```py\nimport gradio as gr\nfrom data import df\n\nwith gr.Blocks() as demo:\n with gr.Row():\n origin = gr.Dropdown([\"All\", \"DFW\", \"DAL\", \"HOU\"], value=\"All\", label=\"Origin\")\n destination = gr.Dropdown([\"All\", \"JFK\", \"LGA\", \"EWR\"], value=\"All\", label=\"Destination\")\n max_price = gr.Slider(0, 1000, value=1000, label=\"Max Price\")\n\n plt = gr.ScatterPlot(df, x=\"time\", y=\"price\", inputs=[origin, destination, max_price])\n\n @gr.on(inputs=[origin, destination, max_price], outputs=plt)\n def filtered_data(origin, destination, max_price):\n _df = df[df[\"price\"] <= max_price]\n if origin != \"All\":\n _df = _df[_df[\"origin\"] == origin]\n if destination != \"All\":\n _df = _df[_df[\"destination\"] == destination]\n return _df\n\n \nif __name__ == \"__main__\":\n demo.launch()\n```\n$demo_plot_guide_filters_events\n\nAnd this would be the function-as-value approach for the same demo.\n\n```py\nimport gradio as gr\nfrom data import df\n\nwith gr.Blocks() as demo:\n with gr.Row():\n origin = gr.Dropdown([\"All\", \"DFW\", \"DAL\", \"HOU\"], value=\"All\", label=\"Origin\")\n destination = gr.Dropdown([\"All\", \"JFK\", \"LGA\", \"EWR\"], value=\"All\", label=\"Destination\")\n max_price = gr.Slider(0, 1000, value=1000, label=\"Max Price\")\n\n def filtered_data(origin, destination, max_price):\n _df = df[df[\"price\"] <= max_price]\n if origin != \"All\":\n _df = _df[_df[\"origin\"] == origin]\n if destination != \"All\":\n _df = _df[_df[\"destination\"] == destination]\n return _df\n\n gr.ScatterPlot(filtered_data, x=\"time\", y=\"price\", inputs=[origin, destination, max_price])\n \nif __name__ == \"__main__\":\n demo.launch()\n```" }, { "id": 604, "parent": 602, "path": "06_data-science-and-plots/03_filters-tables-and-stats.md", "level": 2, "title": "Tables and Stats", "content": "Add `gr.DataFrame` and `gr.Label` to your dashboard for some hard numbers.\n\n```py\nimport gradio as gr\nfrom data import df\n\nwith gr.Blocks() as demo:\n with gr.Row():\n gr.Label(len(df), label=\"Flight Count\")\n gr.Label(f\"${df['price'].min()}\", label=\"Cheapest Flight\")\n gr.DataFrame(df)\n\n \nif __name__ == \"__main__\":\n demo.launch()\n```\n$demo_plot_guide_tables_stats" }, { "id": 605, "parent": null, "path": "06_data-science-and-plots/02_time-plots.md", "level": 1, "title": "Time Plots", "content": "Creating visualizations with a time x-axis is a common use case. Let's dive in!" }, { "id": 606, "parent": 605, "path": "06_data-science-and-plots/02_time-plots.md", "level": 2, "title": "Creating a Plot with a pd.Dataframe", "content": "Time plots need a datetime column on the x-axis. Here's a simple example with some flight data:\n\n```py\nimport gradio as gr\nimport pandas as pd\nimport numpy as np\nimport random\n\nfrom datetime import datetime, timedelta\nnow = datetime.now()\n\ndf = pd.DataFrame({\n 'time': [now - timedelta(minutes=5*i) for i in range(25)],\n 'price': np.random.randint(100, 1000, 25),\n 'origin': [random.choice([\"DFW\", \"DAL\", \"HOU\"]) for _ in range(25)],\n 'destination': [random.choice([\"JFK\", \"LGA\", \"EWR\"]) for _ in range(25)],\n})\n\nwith gr.Blocks() as demo:\n gr.LinePlot(df, x=\"time\", y=\"price\")\n gr.ScatterPlot(df, x=\"time\", y=\"price\", color=\"origin\")\n\nif __name__ == \"__main__\":\n demo.launch()\n```\n$demo_plot_guide_temporal" }, { "id": 607, "parent": 605, "path": "06_data-science-and-plots/02_time-plots.md", "level": 2, "title": "Aggregating by Time", "content": "You may wish to bin data by time buckets. Use `x_bin` to do so, using a string suffix with \"s\", \"m\", \"h\" or \"d\", such as \"15m\" or \"1d\".\n\n```py\nimport gradio as gr\nfrom data import df\n\nwith gr.Blocks() as demo:\n plot = gr.BarPlot(df, x=\"time\", y=\"price\", x_bin=\"10m\")\n\n bins = gr.Radio([\"10m\", \"30m\", \"1h\"], label=\"Bin Size\")\n bins.change(lambda bins: gr.BarPlot(x_bin=bins), bins, plot)\n\nif __name__ == \"__main__\":\n demo.launch()\n```\n$demo_plot_guide_aggregate_temporal" }, { "id": 608, "parent": 605, "path": "06_data-science-and-plots/02_time-plots.md", "level": 2, "title": "DateTime Components", "content": "You can use `gr.DateTime` to accept input datetime data. This works well with plots for defining the x-axis range for the data.\n\n```py\nimport gradio as gr\nfrom data import df\n\nwith gr.Blocks() as demo:\n with gr.Row():\n start = gr.DateTime(\"now - 24h\")\n end = gr.DateTime(\"now\")\n apply_btn = gr.Button(\"Apply\")\n plot = gr.LinePlot(df, x=\"time\", y=\"price\")\n\n apply_btn.click(lambda start, end: gr.BarPlot(x_lim=[start, end]), [start, end], plot)\n \nif __name__ == \"__main__\":\n demo.launch()\n```\n$demo_plot_guide_datetime\n\nNote how `gr.DateTime` can accept a full datetime string, or a shorthand using `now - [0-9]+[smhd]` format to refer to a past time.\n\nYou will often have many time plots in which case you'd like to keep the x-axes in sync. The `DateTimeRange` custom component keeps a set of datetime plots in sync, and also uses the `.select` listener of plots to allow you to zoom into plots while keeping plots in sync. \n\nBecause it is a custom component, you first need to `pip install gradio_datetimerange`. Then run the following:\n\n```py\nimport gradio as gr\nfrom gradio_datetimerange import DateTimeRange\nfrom data import df\n\nwith gr.Blocks() as demo:\n daterange = DateTimeRange([\"now - 24h\", \"now\"])\n plot1 = gr.LinePlot(df, x=\"time\", y=\"price\")\n plot2 = gr.LinePlot(df, x=\"time\", y=\"price\", color=\"origin\")\n daterange.bind([plot1, plot2])\n\nif __name__ == \"__main__\":\n demo.launch()\n```\n$demo_plot_guide_datetimerange\n\nTry zooming around in the plots and see how DateTimeRange updates. All the plots updates their `x_lim` in sync. You also have a \"Back\" link in the component to allow you to quickly zoom in and out." }, { "id": 609, "parent": 605, "path": "06_data-science-and-plots/02_time-plots.md", "level": 2, "title": "RealTime Data", "content": "In many cases, you're working with live, realtime date, not a static dataframe. In this case, you'd update the plot regularly with a `gr.Timer()`. Assuming there's a `get_data` method that gets the latest dataframe:\n\n```python\nwith gr.Blocks() as demo:\n timer = gr.Timer(5)\n plot1 = gr.BarPlot(x=\"time\", y=\"price\")\n plot2 = gr.BarPlot(x=\"time\", y=\"price\", color=\"origin\")\n\n timer.tick(lambda: [get_data(), get_data()], outputs=[plot1, plot2])\n```\n\nYou can also use the `every` shorthand to attach a `Timer` to a component that has a function value:\n\n```python\nwith gr.Blocks() as demo:\n timer = gr.Timer(5)\n plot1 = gr.BarPlot(get_data, x=\"time\", y=\"price\", every=timer)\n plot2 = gr.BarPlot(get_data, x=\"time\", y=\"price\", color=\"origin\", every=timer)\n```" }, { "id": 610, "parent": null, "path": "06_data-science-and-plots/01_creating-plots.md", "level": 1, "title": "Creating Plots", "content": "Gradio is a great way to create extremely customizable dashboards. Gradio comes with three native Plot components: `gr.LinePlot`, `gr.ScatterPlot` and `gr.BarPlot`. All these plots have the same API. Let's take a look how to set them up." }, { "id": 611, "parent": 610, "path": "06_data-science-and-plots/01_creating-plots.md", "level": 2, "title": "Creating a Plot with a pd.Dataframe", "content": "Plots accept a pandas Dataframe as their value. The plot also takes `x` and `y` which represent the names of the columns that represent the x and y axes respectively. Here's a simple example:\n\n```py\nimport gradio as gr\nimport pandas as pd\nimport numpy as np\nimport random\n\ndf = pd.DataFrame({\n 'height': np.random.randint(50, 70, 25),\n 'weight': np.random.randint(120, 320, 25),\n 'age': np.random.randint(18, 65, 25),\n 'ethnicity': [random.choice([\"white\", \"black\", \"asian\"]) for _ in range(25)]\n})\n\nwith gr.Blocks() as demo:\n gr.LinePlot(df, x=\"weight\", y=\"height\")\n\nif __name__ == \"__main__\":\n demo.launch()\n```\n$demo_plot_guide_line\n\nAll plots have the same API, so you could swap this out with a `gr.ScatterPlot`:\n\n```py\nimport gradio as gr\nfrom data import df\n\nwith gr.Blocks() as demo:\n gr.ScatterPlot(df, x=\"weight\", y=\"height\")\n\nif __name__ == \"__main__\":\n demo.launch()\n```\n$demo_plot_guide_scatter\n\nThe y axis column in the dataframe should have a numeric type, but the x axis column can be anything from strings, numbers, categories, or datetimes.\n\n```py\nimport gradio as gr\nfrom data import df\n\nwith gr.Blocks() as demo:\n gr.ScatterPlot(df, x=\"ethnicity\", y=\"height\")\n\nif __name__ == \"__main__\":\n demo.launch()\n```\n$demo_plot_guide_scatter_nominal" }, { "id": 612, "parent": 610, "path": "06_data-science-and-plots/01_creating-plots.md", "level": 2, "title": "Breaking out Series by Color", "content": "You can break out your plot into series using the `color` argument.\n\n```py\nimport gradio as gr\nfrom data import df\n\nwith gr.Blocks() as demo:\n gr.ScatterPlot(df, x=\"weight\", y=\"height\", color=\"ethnicity\")\n\nif __name__ == \"__main__\":\n demo.launch()\n```\n$demo_plot_guide_series_nominal\n\nIf you wish to assign series specific colors, use the `color_map` arg, e.g. `gr.ScatterPlot(..., color_map={'white': '#FF9988', 'asian': '#88EEAA', 'black': '#333388'})`\n\nThe color column can be numeric type as well.\n\n```py\nimport gradio as gr\nfrom data import df\n\nwith gr.Blocks() as demo:\n gr.ScatterPlot(df, x=\"weight\", y=\"height\", color=\"age\")\n\nif __name__ == \"__main__\":\n demo.launch()\n```\n$demo_plot_guide_series_quantitative" }, { "id": 613, "parent": 610, "path": "06_data-science-and-plots/01_creating-plots.md", "level": 2, "title": "Aggregating Values", "content": "You can aggregate values into groups using the `x_bin` and `y_aggregate` arguments. If your x-axis is numeric, providing an `x_bin` will create a histogram-style binning:\n\n```py\nimport gradio as gr\nfrom data import df\n\nwith gr.Blocks() as demo:\n gr.BarPlot(df, x=\"weight\", y=\"height\", x_bin=10, y_aggregate=\"sum\")\n\nif __name__ == \"__main__\":\n demo.launch()\n```\n$demo_plot_guide_aggregate_quantitative\n\nIf your x-axis is a string type instead, they will act as the category bins automatically:\n\n```py\nimport gradio as gr\nfrom data import df\n\nwith gr.Blocks() as demo:\n gr.BarPlot(df, x=\"ethnicity\", y=\"height\", y_aggregate=\"mean\")\n\nif __name__ == \"__main__\":\n demo.launch()\n```\n$demo_plot_guide_aggregate_nominal" }, { "id": 614, "parent": 610, "path": "06_data-science-and-plots/01_creating-plots.md", "level": 2, "title": "Selecting Regions", "content": "You can use the `.select` listener to select regions of a plot. Click and drag on the plot below to select part of the plot.\n\n```py\nimport gradio as gr\nfrom data import df\n\nwith gr.Blocks() as demo:\n plt = gr.LinePlot(df, x=\"weight\", y=\"height\")\n selection_total = gr.Number(label=\"Total Weight of Selection\")\n\n def select_region(selection: gr.SelectData):\n min_w, max_w = selection.index\n return df[(df[\"weight\"] >= min_w) & (df[\"weight\"] <= max_w)][\"weight\"].sum()\n\n plt.select(select_region, None, selection_total)\n\nif __name__ == \"__main__\":\n demo.launch()\n```\n$demo_plot_guide_selection\n\nYou can combine this and the `.double_click` listener to create some zoom in/out effects by changing `x_lim` which sets the bounds of the x-axis:\n\n```py\nimport gradio as gr\nfrom data import df\n\nwith gr.Blocks() as demo:\n plt = gr.LinePlot(df, x=\"weight\", y=\"height\")\n\n def select_region(selection: gr.SelectData):\n min_w, max_w = selection.index\n return gr.LinePlot(x_lim=(min_w, max_w)) # type: ignore\n\n plt.select(select_region, None, plt)\n plt.double_click(lambda: gr.LinePlot(x_lim=None), None, plt)\n\nif __name__ == \"__main__\":\n demo.launch()\n```\n$demo_plot_guide_zoom\n\nIf you had multiple plots with the same x column, your event listeners could target the x limits of all other plots so that the x-axes stay in sync.\n\n```py\nimport gradio as gr\nfrom data import df\n\nwith gr.Blocks() as demo:\n plt1 = gr.LinePlot(df, x=\"weight\", y=\"height\")\n plt2 = gr.BarPlot(df, x=\"weight\", y=\"age\", x_bin=10)\n plots = [plt1, plt2]\n\n def select_region(selection: gr.SelectData):\n min_w, max_w = selection.index\n return [gr.LinePlot(x_lim=(min_w, max_w))] * len(plots) # type: ignore\n\n for plt in plots:\n plt.select(select_region, None, plots)\n plt.double_click(lambda: [gr.LinePlot(x_lim=None)] * len(plots), None, plots)\n\nif __name__ == \"__main__\":\n demo.launch()\n```\n$demo_plot_guide_zoom_sync" }, { "id": 615, "parent": 610, "path": "06_data-science-and-plots/01_creating-plots.md", "level": 2, "title": "Making an Interactive Dashboard", "content": "Take a look how you can have an interactive dashboard where the plots are functions of other Components.\n\n```py\nimport gradio as gr\nfrom data import df\n\nwith gr.Blocks() as demo:\n with gr.Row():\n ethnicity = gr.Dropdown([\"all\", \"white\", \"black\", \"asian\"], value=\"all\")\n max_age = gr.Slider(18, 65, value=65)\n\n def filtered_df(ethnic, age):\n _df = df if ethnic == \"all\" else df[df[\"ethnicity\"] == ethnic]\n _df = _df[_df[\"age\"] < age]\n return _df\n\n gr.ScatterPlot(filtered_df, inputs=[ethnicity, max_age], x=\"weight\", y=\"height\", title=\"Weight x Height\")\n gr.LinePlot(filtered_df, inputs=[ethnicity, max_age], x=\"age\", y=\"height\", title=\"Age x Height\")\n\nif __name__ == \"__main__\":\n demo.launch()\n```\n$demo_plot_guide_interactive\n\nIt's that simple to filter and control the data presented in your visualization!" }, { "id": 616, "parent": null, "path": "07_streaming/02_object-detection-from-webcam-with-webrtc.md", "level": 1, "title": "Real Time Object Detection from a Webcam Stream with WebRTC", "content": "Tags: VISION, STREAMING, WEBCAM\n\nIn this guide, we'll use YOLOv10 to perform real-time object detection in Gradio from a user's webcam feed. We'll utilize the latest streaming features introduced in Gradio 5.0. You can see the finished product in action below:\n\n" }, { "id": 617, "parent": 616, "path": "07_streaming/02_object-detection-from-webcam-with-webrtc.md", "level": 2, "title": "Setting up", "content": "Start by installing all the dependencies. Add the following lines to a `requirements.txt` file and run `pip install -r requirements.txt`:\n\n```bash\nopencv-python\ntwilio\ngradio>=5.0\ngradio-webrtc\nonnxruntime-gpu\n```\n\nWe'll use the ONNX runtime to speed up YOLOv10 inference. This guide assumes you have access to a GPU. If you don't, change `onnxruntime-gpu` to `onnxruntime`. Without a GPU, the model will run slower, resulting in a laggy demo.\n\nWe'll use OpenCV for image manipulation and the [Gradio WebRTC](https://github.com/freddyaboulton/gradio-webrtc) custom component to use [WebRTC](https://webrtc.org/) under the hood, achieving near-zero latency.\n\n**Note**: If you want to deploy this app on any cloud provider, you'll need to use the free Twilio API for their [TURN servers](https://www.twilio.com/docs/stun-turn). Create a free account on Twilio. If you're not familiar with TURN servers, consult this [guide](https://www.twilio.com/docs/stun-turn/faq#faq-what-is-nat)." }, { "id": 618, "parent": 616, "path": "07_streaming/02_object-detection-from-webcam-with-webrtc.md", "level": 2, "title": "The Inference Function", "content": "We'll download the YOLOv10 model from the Hugging Face hub and instantiate a custom inference class to use this model. \n\nThe implementation of the inference class isn't covered in this guide, but you can find the source code [here](https://huggingface.co/spaces/freddyaboulton/webrtc-yolov10n/blob/main/inference.py#L9) if you're interested. This implementation borrows heavily from this [github repository](https://github.com/ibaiGorordo/ONNX-YOLOv8-Object-Detection).\n\nWe're using the `yolov10-n` variant because it has the lowest latency. See the [Performance](https://github.com/THU-MIG/yolov10?tab=readme-ov-file#performance) section of the README in the YOLOv10 GitHub repository.\n\n```python\nfrom huggingface_hub import hf_hub_download\nfrom inference import YOLOv10\n\nmodel_file = hf_hub_download(\n repo_id=\"onnx-community/yolov10n\", filename=\"onnx/model.onnx\"\n)\n\nmodel = YOLOv10(model_file)\n\ndef detection(image, conf_threshold=0.3):\n image = cv2.resize(image, (model.input_width, model.input_height))\n new_image = model.detect_objects(image, conf_threshold)\n return new_image\n```\n\nOur inference function, `detection`, accepts a numpy array from the webcam and a desired confidence threshold. Object detection models like YOLO identify many objects and assign a confidence score to each. The lower the confidence, the higher the chance of a false positive. We'll let users adjust the confidence threshold.\n\nThe function returns a numpy array corresponding to the same input image with all detected objects in bounding boxes." }, { "id": 619, "parent": 616, "path": "07_streaming/02_object-detection-from-webcam-with-webrtc.md", "level": 2, "title": "The Gradio Demo", "content": "The Gradio demo is straightforward, but we'll implement a few specific features:\n\n1. Use the `WebRTC` custom component to ensure input and output are sent to/from the server with WebRTC. \n2. The [WebRTC](https://github.com/freddyaboulton/gradio-webrtc) component will serve as both an input and output component.\n3. Utilize the `time_limit` parameter of the `stream` event. This parameter sets a processing time for each user's stream. In a multi-user setting, such as on Spaces, we'll stop processing the current user's stream after this period and move on to the next. \n\nWe'll also apply custom CSS to center the webcam and slider on the page.\n\n```python\nimport gradio as gr\nfrom gradio_webrtc import WebRTC\n\ncss = \"\"\".my-group {max-width: 600px !important; max-height: 600px !important;}\n .my-column {display: flex !important; justify-content: center !important; align-items: center !important;}\"\"\"\n\nwith gr.Blocks(css=css) as demo:\n gr.HTML(\n \"\"\"\n

\n YOLOv10 Webcam Stream (Powered by WebRTC ⚡️)\n

\n \"\"\"\n )\n with gr.Column(elem_classes=[\"my-column\"]):\n with gr.Group(elem_classes=[\"my-group\"]):\n image = WebRTC(label=\"Stream\", rtc_configuration=rtc_configuration)\n conf_threshold = gr.Slider(\n label=\"Confidence Threshold\",\n minimum=0.0,\n maximum=1.0,\n step=0.05,\n value=0.30,\n )\n\n image.stream(\n fn=detection, inputs=[image, conf_threshold], outputs=[image], time_limit=10\n )\n\nif __name__ == \"__main__\":\n demo.launch()\n```" }, { "id": 620, "parent": 616, "path": "07_streaming/02_object-detection-from-webcam-with-webrtc.md", "level": 2, "title": "Conclusion", "content": "Our app is hosted on Hugging Face Spaces [here](https://huggingface.co/spaces/freddyaboulton/webrtc-yolov10n). \n\nYou can use this app as a starting point to build real-time image applications with Gradio. Don't hesitate to open issues in the space or in the [WebRTC component GitHub repo](https://github.com/freddyaboulton/gradio-webrtc) if you have any questions or encounter problems." }, { "id": 621, "parent": null, "path": "07_streaming/03_object-detection-from-video.md", "level": 1, "title": "Streaming Object Detection from Video", "content": "Tags: VISION, STREAMING, VIDEO\n\nIn this guide we'll use the [RT-DETR](https://huggingface.co/docs/transformers/en/model_doc/rt_detr) model to detect objects in a user uploaded video. We'll stream the results from the server using the new video streaming features introduced in Gradio 5.0.\n\n![video_object_detection_stream_latest](https://github.com/user-attachments/assets/4e27ac58-5ded-495d-9e0d-5e87e68b1355)" }, { "id": 622, "parent": 621, "path": "07_streaming/03_object-detection-from-video.md", "level": 2, "title": "Setting up the Model", "content": "First, we'll install the following requirements in our system:\n\n```\nopencv-python\ntorch\ntransformers>=4.43.0\nspaces\n```\n\nThen, we'll download the model from the Hugging Face Hub:\n\n```python\nfrom transformers import RTDetrForObjectDetection, RTDetrImageProcessor\n\nimage_processor = RTDetrImageProcessor.from_pretrained(\"PekingU/rtdetr_r50vd\")\nmodel = RTDetrForObjectDetection.from_pretrained(\"PekingU/rtdetr_r50vd\").to(\"cuda\")\n```\n\nWe're moving the model to the GPU. We'll be deploying our model to Hugging Face Spaces and running the inference in the [free ZeroGPU cluster](https://huggingface.co/zero-gpu-explorers)." }, { "id": 623, "parent": 621, "path": "07_streaming/03_object-detection-from-video.md", "level": 2, "title": "The Inference Function", "content": "Our inference function will accept a video and a desired confidence threshold.\nObject detection models identify many objects and assign a confidence score to each object. The lower the confidence, the higher the chance of a false positive. So we will let our users set the conference threshold.\n\nOur function will iterate over the frames in the video and run the RT-DETR model over each frame.\nWe will then draw the bounding boxes for each detected object in the frame and save the frame to a new output video.\nThe function will yield each output video in chunks of two seconds.\n\nIn order to keep inference times as low as possible on ZeroGPU (there is a time-based quota),\nwe will halve the original frames-per-second in the output video and resize the input frames to be half the original \nsize before running the model.\n\nThe code for the inference function is below - we'll go over it piece by piece.\n\n```python\nimport spaces\nimport cv2\nfrom PIL import Image\nimport torch\nimport time\nimport numpy as np\nimport uuid\n\nfrom draw_boxes import draw_bounding_boxes\n\nSUBSAMPLE = 2\n\n@spaces.GPU\ndef stream_object_detection(video, conf_threshold):\n cap = cv2.VideoCapture(video)\n\n # This means we will output mp4 videos\n video_codec = cv2.VideoWriter_fourcc(*\"mp4v\") # type: ignore\n fps = int(cap.get(cv2.CAP_PROP_FPS))\n\n desired_fps = fps // SUBSAMPLE\n width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) // 2\n height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) // 2\n\n iterating, frame = cap.read()\n\n n_frames = 0\n\n # Use UUID to create a unique video file\n output_video_name = f\"output_{uuid.uuid4()}.mp4\"\n\n # Output Video\n output_video = cv2.VideoWriter(output_video_name, video_codec, desired_fps, (width, height)) # type: ignore\n batch = []\n\n while iterating:\n frame = cv2.resize( frame, (0,0), fx=0.5, fy=0.5)\n frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)\n if n_frames % SUBSAMPLE == 0:\n batch.append(frame)\n if len(batch) == 2 * desired_fps:\n inputs = image_processor(images=batch, return_tensors=\"pt\").to(\"cuda\")\n\n with torch.no_grad():\n outputs = model(**inputs)\n\n boxes = image_processor.post_process_object_detection(\n outputs,\n target_sizes=torch.tensor([(height, width)] * len(batch)),\n threshold=conf_threshold)\n \n for i, (array, box) in enumerate(zip(batch, boxes)):\n pil_image = draw_bounding_boxes(Image.fromarray(array), box, model, conf_threshold)\n frame = np.array(pil_image)\n # Convert RGB to BGR\n frame = frame[:, :, ::-1].copy()\n output_video.write(frame)\n\n batch = []\n output_video.release()\n yield output_video_name\n output_video_name = f\"output_{uuid.uuid4()}.mp4\"\n output_video = cv2.VideoWriter(output_video_name, video_codec, desired_fps, (width, height)) # type: ignore\n\n iterating, frame = cap.read()\n n_frames += 1\n```\n\n1. **Reading from the Video**\n\nOne of the industry standards for creating videos in python is OpenCV so we will use it in this app.\n\nThe `cap` variable is how we will read from the input video. Whenever we call `cap.read()`, we are reading the next frame in the video.\n\nIn order to stream video in Gradio, we need to yield a different video file for each \"chunk\" of the output video.\nWe create the next video file to write to with the `output_video = cv2.VideoWriter(output_video_name, video_codec, desired_fps, (width, height))` line. The `video_codec` is how we specify the type of video file. Only \"mp4\" and \"ts\" files are supported for video sreaming at the moment.\n\n\n2. **The Inference Loop**\n\nFor each frame in the video, we will resize it to be half the size. OpenCV reads files in `BGR` format, so will convert to the expected `RGB` format of transfomers. That's what the first two lines of the while loop are doing. \n\nWe take every other frame and add it to a `batch` list so that the output video is half the original FPS. When the batch covers two seconds of video, we will run the model. The two second threshold was chosen to keep the processing time of each batch small enough so that video is smoothly displayed in the server while not requiring too many separate forward passes. In order for video streaming to work properly in Gradio, the batch size should be at least 1 second. \n\nWe run the forward pass of the model and then use the `post_process_object_detection` method of the model to scale the detected bounding boxes to the size of the input frame.\n\nWe make use of a custom function to draw the bounding boxes (source [here](https://huggingface.co/spaces/gradio/rt-detr-object-detection/blob/main/draw_boxes.py#L14)). We then have to convert from `RGB` to `BGR` before writing back to the output video.\n\nOnce we have finished processing the batch, we create a new output video file for the next batch." }, { "id": 624, "parent": 621, "path": "07_streaming/03_object-detection-from-video.md", "level": 2, "title": "The Gradio Demo", "content": "The UI code is pretty similar to other kinds of Gradio apps. \nWe'll use a standard two-column layout so that users can see the input and output videos side by side.\n\nIn order for streaming to work, we have to set `streaming=True` in the output video. Setting the video\nto autoplay is not necessary but it's a better experience for users.\n\n```python\nimport gradio as gr\n\nwith gr.Blocks() as app:\n gr.HTML(\n \"\"\"\n

\n Video Object Detection with RT-DETR\n

\n \"\"\")\n with gr.Row():\n with gr.Column():\n video = gr.Video(label=\"Video Source\")\n conf_threshold = gr.Slider(\n label=\"Confidence Threshold\",\n minimum=0.0,\n maximum=1.0,\n step=0.05,\n value=0.30,\n )\n with gr.Column():\n output_video = gr.Video(label=\"Processed Video\", streaming=True, autoplay=True)\n\n video.upload(\n fn=stream_object_detection,\n inputs=[video, conf_threshold],\n outputs=[output_video],\n )\n\n\n```" }, { "id": 625, "parent": 621, "path": "07_streaming/03_object-detection-from-video.md", "level": 2, "title": "Conclusion", "content": "You can check out our demo hosted on Hugging Face Spaces [here](https://huggingface.co/spaces/gradio/rt-detr-object-detection). \n\nIt is also embedded on this page below\n\n$demo_rt-detr-object-detection" }, { "id": 626, "parent": null, "path": "07_streaming/04_conversational-chatbot.md", "level": 1, "title": "Building Conversational Chatbots with Gradio", "content": "Tags: AUDIO, STREAMING, CHATBOTS" }, { "id": 627, "parent": 626, "path": "07_streaming/04_conversational-chatbot.md", "level": 2, "title": "Introduction", "content": "The next generation of AI user interfaces is moving towards audio-native experiences. Users will be able to speak to chatbots and receive spoken responses in return. Several models have been built under this paradigm, including GPT-4o and [mini omni](https://github.com/gpt-omni/mini-omni).\n\nIn this guide, we'll walk you through building your own conversational chat application using mini omni as an example. You can see a demo of the finished app below:\n\n" }, { "id": 628, "parent": 626, "path": "07_streaming/04_conversational-chatbot.md", "level": 2, "title": "Application Overview", "content": "Our application will enable the following user experience:\n\n1. Users click a button to start recording their message\n2. The app detects when the user has finished speaking and stops recording\n3. The user's audio is passed to the omni model, which streams back a response\n4. After omni mini finishes speaking, the user's microphone is reactivated\n5. All previous spoken audio, from both the user and omni, is displayed in a chatbot component\n\nLet's dive into the implementation details." }, { "id": 629, "parent": 626, "path": "07_streaming/04_conversational-chatbot.md", "level": 2, "title": "Processing User Audio", "content": "We'll stream the user's audio from their microphone to the server and determine if the user has stopped speaking on each new chunk of audio.\n\nHere's our `process_audio` function:\n\n```python\nimport numpy as np\nfrom utils import determine_pause\n\ndef process_audio(audio: tuple, state: AppState):\n if state.stream is None:\n state.stream = audio[1]\n state.sampling_rate = audio[0]\n else:\n state.stream = np.concatenate((state.stream, audio[1]))\n\n pause_detected = determine_pause(state.stream, state.sampling_rate, state)\n state.pause_detected = pause_detected\n\n if state.pause_detected and state.started_talking:\n return gr.Audio(recording=False), state\n return None, state\n```\n\nThis function takes two inputs:\n1. The current audio chunk (a tuple of `(sampling_rate, numpy array of audio)`)\n2. The current application state\n\nWe'll use the following `AppState` dataclass to manage our application state:\n\n```python\nfrom dataclasses import dataclass\n\n@dataclass\nclass AppState:\n stream: np.ndarray | None = None\n sampling_rate: int = 0\n pause_detected: bool = False\n stopped: bool = False\n conversation: list = []\n```\n\nThe function concatenates new audio chunks to the existing stream and checks if the user has stopped speaking. If a pause is detected, it returns an update to stop recording. Otherwise, it returns `None` to indicate no changes.\n\nThe implementation of the `determine_pause` function is specific to the omni-mini project and can be found [here](https://huggingface.co/spaces/gradio/omni-mini/blob/eb027808c7bfe5179b46d9352e3fa1813a45f7c3/app.py#L98)." }, { "id": 630, "parent": 626, "path": "07_streaming/04_conversational-chatbot.md", "level": 2, "title": "Generating the Response", "content": "After processing the user's audio, we need to generate and stream the chatbot's response. Here's our `response` function:\n\n```python\nimport io\nimport tempfile\nfrom pydub import AudioSegment\n\ndef response(state: AppState):\n if not state.pause_detected and not state.started_talking:\n return None, AppState()\n \n audio_buffer = io.BytesIO()\n\n segment = AudioSegment(\n state.stream.tobytes(),\n frame_rate=state.sampling_rate,\n sample_width=state.stream.dtype.itemsize,\n channels=(1 if len(state.stream.shape) == 1 else state.stream.shape[1]),\n )\n segment.export(audio_buffer, format=\"wav\")\n\n with tempfile.NamedTemporaryFile(suffix=\".wav\", delete=False) as f:\n f.write(audio_buffer.getvalue())\n \n state.conversation.append({\"role\": \"user\",\n \"content\": {\"path\": f.name,\n \"mime_type\": \"audio/wav\"}})\n \n output_buffer = b\"\"\n\n for mp3_bytes in speaking(audio_buffer.getvalue()):\n output_buffer += mp3_bytes\n yield mp3_bytes, state\n\n with tempfile.NamedTemporaryFile(suffix=\".mp3\", delete=False) as f:\n f.write(output_buffer)\n \n state.conversation.append({\"role\": \"assistant\",\n \"content\": {\"path\": f.name,\n \"mime_type\": \"audio/mp3\"}})\n yield None, AppState(conversation=state.conversation)\n```\n\nThis function:\n1. Converts the user's audio to a WAV file\n2. Adds the user's message to the conversation history\n3. Generates and streams the chatbot's response using the `speaking` function\n4. Saves the chatbot's response as an MP3 file\n5. Adds the chatbot's response to the conversation history\n\nNote: The implementation of the `speaking` function is specific to the omni-mini project and can be found [here](https://huggingface.co/spaces/gradio/omni-mini/blob/main/app.py#L116)." }, { "id": 631, "parent": 626, "path": "07_streaming/04_conversational-chatbot.md", "level": 2, "title": "Building the Gradio App", "content": "Now let's put it all together using Gradio's Blocks API:\n\n```python\nimport gradio as gr\n\ndef start_recording_user(state: AppState):\n if not state.stopped:\n return gr.Audio(recording=True)\n\nwith gr.Blocks() as demo:\n with gr.Row():\n with gr.Column():\n input_audio = gr.Audio(\n label=\"Input Audio\", sources=\"microphone\", type=\"numpy\"\n )\n with gr.Column():\n chatbot = gr.Chatbot(label=\"Conversation\", type=\"messages\")\n output_audio = gr.Audio(label=\"Output Audio\", streaming=True, autoplay=True)\n state = gr.State(value=AppState())\n\n stream = input_audio.stream(\n process_audio,\n [input_audio, state],\n [input_audio, state],\n stream_every=0.5,\n time_limit=30,\n )\n respond = input_audio.stop_recording(\n response,\n [state],\n [output_audio, state]\n )\n respond.then(lambda s: s.conversation, [state], [chatbot])\n\n restart = output_audio.stop(\n start_recording_user,\n [state],\n [input_audio]\n )\n cancel = gr.Button(\"Stop Conversation\", variant=\"stop\")\n cancel.click(lambda: (AppState(stopped=True), gr.Audio(recording=False)), None,\n [state, input_audio], cancels=[respond, restart])\n\nif __name__ == \"__main__\":\n demo.launch()\n```\n\nThis setup creates a user interface with:\n- An input audio component for recording user messages\n- A chatbot component to display the conversation history\n- An output audio component for the chatbot's responses\n- A button to stop and reset the conversation\n\nThe app streams user audio in 0.5-second chunks, processes it, generates responses, and updates the conversation history accordingly." }, { "id": 632, "parent": 626, "path": "07_streaming/04_conversational-chatbot.md", "level": 2, "title": "Conclusion", "content": "This guide demonstrates how to build a conversational chatbot application using Gradio and the mini omni model. You can adapt this framework to create various audio-based chatbot demos. To see the full application in action, visit the Hugging Face Spaces demo: https://huggingface.co/spaces/gradio/omni-mini\n\nFeel free to experiment with different models, audio processing techniques, or user interface designs to create your own unique conversational AI experiences!" }, { "id": 633, "parent": null, "path": "07_streaming/05_real-time-speech-recognition.md", "level": 1, "title": "Real Time Speech Recognition", "content": "Tags: ASR, SPEECH, STREAMING" }, { "id": 634, "parent": 633, "path": "07_streaming/05_real-time-speech-recognition.md", "level": 2, "title": "Introduction", "content": "Automatic speech recognition (ASR), the conversion of spoken speech to text, is a very important and thriving area of machine learning. ASR algorithms run on practically every smartphone, and are becoming increasingly embedded in professional workflows, such as digital assistants for nurses and doctors. Because ASR algorithms are designed to be used directly by customers and end users, it is important to validate that they are behaving as expected when confronted with a wide variety of speech patterns (different accents, pitches, and background audio conditions).\n\nUsing `gradio`, you can easily build a demo of your ASR model and share that with a testing team, or test it yourself by speaking through the microphone on your device.\n\nThis tutorial will show how to take a pretrained speech-to-text model and deploy it with a Gradio interface. We will start with a **_full-context_** model, in which the user speaks the entire audio before the prediction runs. Then we will adapt the demo to make it **_streaming_**, meaning that the audio model will convert speech as you speak." }, { "id": 635, "parent": 634, "path": "07_streaming/05_real-time-speech-recognition.md", "level": 3, "title": "Prerequisites", "content": "Make sure you have the `gradio` Python package already [installed](/getting_started). You will also need a pretrained speech recognition model. In this tutorial, we will build demos from 2 ASR libraries:\n\n- Transformers (for this, `pip install torch transformers torchaudio`)\n\nMake sure you have at least one of these installed so that you can follow along the tutorial. You will also need `ffmpeg` [installed on your system](https://www.ffmpeg.org/download.html), if you do not already have it, to process files from the microphone.\n\nHere's how to build a real time speech recognition (ASR) app:\n\n1. [Set up the Transformers ASR Model](#1-set-up-the-transformers-asr-model)\n2. [Create a Full-Context ASR Demo with Transformers](#2-create-a-full-context-asr-demo-with-transformers)\n3. [Create a Streaming ASR Demo with Transformers](#3-create-a-streaming-asr-demo-with-transformers)" }, { "id": 636, "parent": 633, "path": "07_streaming/05_real-time-speech-recognition.md", "level": 2, "title": "1. Set up the Transformers ASR Model", "content": "First, you will need to have an ASR model that you have either trained yourself or you will need to download a pretrained model. In this tutorial, we will start by using a pretrained ASR model from the model, `whisper`.\n\nHere is the code to load `whisper` from Hugging Face `transformers`.\n\n```python\nfrom transformers import pipeline\n\np = pipeline(\"automatic-speech-recognition\", model=\"openai/whisper-base.en\")\n```\n\nThat's it!" }, { "id": 637, "parent": 633, "path": "07_streaming/05_real-time-speech-recognition.md", "level": 2, "title": "2. Create a Full-Context ASR Demo with Transformers", "content": "We will start by creating a _full-context_ ASR demo, in which the user speaks the full audio before using the ASR model to run inference. This is very easy with Gradio -- we simply create a function around the `pipeline` object above.\n\nWe will use `gradio`'s built in `Audio` component, configured to take input from the user's microphone and return a filepath for the recorded audio. The output component will be a plain `Textbox`.\n\n```py\nimport gradio as gr\nfrom transformers import pipeline\nimport numpy as np\n\ntranscriber = pipeline(\"automatic-speech-recognition\", model=\"openai/whisper-base.en\")\n\ndef transcribe(audio):\n sr, y = audio\n \n # Convert to mono if stereo\n if y.ndim > 1:\n y = y.mean(axis=1)\n \n y = y.astype(np.float32)\n y /= np.max(np.abs(y))\n\n return transcriber({\"sampling_rate\": sr, \"raw\": y})[\"text\"] # type: ignore\n\ndemo = gr.Interface(\n transcribe,\n gr.Audio(sources=\"microphone\"),\n \"text\",\n)\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n$demo_asr\n\nThe `transcribe` function takes a single parameter, `audio`, which is a numpy array of the audio the user recorded. The `pipeline` object expects this in float32 format, so we convert it first to float32, and then extract the transcribed text." }, { "id": 638, "parent": 633, "path": "07_streaming/05_real-time-speech-recognition.md", "level": 2, "title": "3. Create a Streaming ASR Demo with Transformers", "content": "To make this a *streaming* demo, we need to make these changes:\n\n1. Set `streaming=True` in the `Audio` component\n2. Set `live=True` in the `Interface`\n3. Add a `state` to the interface to store the recorded audio of a user\n\nTip: You can also set `time_limit` and `stream_every` parameters in the interface. The `time_limit` caps the amount of time each user's stream can take. The default is 30 seconds so users won't be able to stream audio for more than 30 seconds. The `stream_every` parameter controls how frequently data is sent to your function. By default it is 0.5 seconds.\n\nTake a look below.\n\n```py\nimport gradio as gr\nfrom transformers import pipeline\nimport numpy as np\n\ntranscriber = pipeline(\"automatic-speech-recognition\", model=\"openai/whisper-base.en\")\n\ndef transcribe(stream, new_chunk):\n sr, y = new_chunk\n \n # Convert to mono if stereo\n if y.ndim > 1:\n y = y.mean(axis=1)\n \n y = y.astype(np.float32)\n y /= np.max(np.abs(y))\n\n if stream is not None:\n stream = np.concatenate([stream, y])\n else:\n stream = y\n return stream, transcriber({\"sampling_rate\": sr, \"raw\": stream})[\"text\"] # type: ignore\n\ndemo = gr.Interface(\n transcribe,\n [\"state\", gr.Audio(sources=[\"microphone\"], streaming=True)],\n [\"state\", \"text\"],\n live=True,\n)\n\nif __name__ == \"__main__\":\n demo.launch()\n\n```\n\nNotice that we now have a state variable because we need to track all the audio history. `transcribe` gets called whenever there is a new small chunk of audio, but we also need to keep track of all the audio spoken so far in the state. As the interface runs, the `transcribe` function gets called, with a record of all the previously spoken audio in the `stream` and the new chunk of audio as `new_chunk`. We return the new full audio to be stored back in its current state, and we also return the transcription. Here, we naively append the audio together and call the `transcriber` object on the entire audio. You can imagine more efficient ways of handling this, such as re-processing only the last 5 seconds of audio whenever a new chunk of audio is received. \n\n$demo_stream_asr\n\nNow the ASR model will run inference as you speak!" }, { "id": 639, "parent": null, "path": "07_streaming/01_streaming-ai-generated-audio.md", "level": 1, "title": "Streaming AI Generated Audio", "content": "Tags: AUDIO, STREAMING\n\nIn this guide, we'll build a novel AI application to showcase Gradio's audio output streaming. We're going to a build a talking [Magic 8 Ball](https://en.wikipedia.org/wiki/Magic_8_Ball) 🎱\n\nA Magic 8 Ball is a toy that answers any question after you shake it. Our application will do the same but it will also speak its response!\n\nWe won't cover all the implementation details in this blog post but the code is freely available on [Hugging Face Spaces](https://huggingface.co/spaces/gradio/magic-8-ball)." }, { "id": 640, "parent": 639, "path": "07_streaming/01_streaming-ai-generated-audio.md", "level": 2, "title": "The Overview", "content": "Just like the classic Magic 8 Ball, a user should ask it a question orally and then wait for a response. Under the hood, we'll use Whisper to transcribe the audio and then use an LLM to generate a magic-8-ball-style answer. Finally, we'll use Parler TTS to read the response aloud." }, { "id": 641, "parent": 639, "path": "07_streaming/01_streaming-ai-generated-audio.md", "level": 2, "title": "The UI", "content": "First let's define the UI and put placeholders for all the python logic.\n\n```python\nimport gradio as gr\n\nwith gr.Blocks() as block:\n gr.HTML(\n f\"\"\"\n

Magic 8 Ball 🎱

\n

Ask a question and receive wisdom

\n

Powered by Parler-TTS\n \"\"\"\n )\n with gr.Group():\n with gr.Row():\n audio_out = gr.Audio(label=\"Spoken Answer\", streaming=True, autoplay=True)\n answer = gr.Textbox(label=\"Answer\")\n state = gr.State()\n with gr.Row():\n audio_in = gr.Audio(label=\"Speak your question\", sources=\"microphone\", type=\"filepath\")\n\n audio_in.stop_recording(generate_response, audio_in, [state, answer, audio_out])\\\n .then(fn=read_response, inputs=state, outputs=[answer, audio_out])\n\nblock.launch()\n```\n\nWe're placing the output Audio and Textbox components and the input Audio component in separate rows. In order to stream the audio from the server, we'll set `streaming=True` in the output Audio component. We'll also set `autoplay=True` so that the audio plays as soon as it's ready.\nWe'll be using the Audio input component's `stop_recording` event to trigger our application's logic when a user stops recording from their microphone.\n\nWe're separating the logic into two parts. First, `generate_response` will take the recorded audio, transcribe it and generate a response with an LLM. We're going to store the response in a `gr.State` variable that then gets passed to the `read_response` function that generates the audio.\n\nWe're doing this in two parts because only `read_response` will require a GPU. Our app will run on Hugging Faces [ZeroGPU](https://huggingface.co/zero-gpu-explorers) which has time-based quotas. Since generating the response can be done with Hugging Face's Inference API, we shouldn't include that code in our GPU function as it will needlessly use our GPU quota." }, { "id": 642, "parent": 639, "path": "07_streaming/01_streaming-ai-generated-audio.md", "level": 2, "title": "The Logic", "content": "As mentioned above, we'll use [Hugging Face's Inference API](https://huggingface.co/docs/huggingface_hub/guides/inference) to transcribe the audio and generate a response from an LLM. After instantiating the client, I use the `automatic_speech_recognition` method (this automatically uses Whisper running on Hugging Face's Inference Servers) to transcribe the audio. Then I pass the question to an LLM (Mistal-7B-Instruct) to generate a response. We are prompting the LLM to act like a magic 8 ball with the system message.\n\nOur `generate_response` function will also send empty updates to the output textbox and audio components (returning `None`). \nThis is because I want the Gradio progress tracker to be displayed over the components but I don't want to display the answer until the audio is ready.\n\n\n```python\nfrom huggingface_hub import InferenceClient\n\nclient = InferenceClient(token=os.getenv(\"HF_TOKEN\"))\n\ndef generate_response(audio):\n gr.Info(\"Transcribing Audio\", duration=5)\n question = client.automatic_speech_recognition(audio).text\n\n messages = [{\"role\": \"system\", \"content\": (\"You are a magic 8 ball.\"\n \"Someone will present to you a situation or question and your job \"\n \"is to answer with a cryptic adage or proverb such as \"\n \"'curiosity killed the cat' or 'The early bird gets the worm'.\"\n \"Keep your answers short and do not include the phrase 'Magic 8 Ball' in your response. If the question does not make sense or is off-topic, say 'Foolish questions get foolish answers.'\"\n \"For example, 'Magic 8 Ball, should I get a dog?', 'A dog is ready for you but are you ready for the dog?'\")},\n {\"role\": \"user\", \"content\": f\"Magic 8 Ball please answer this question - {question}\"}]\n \n response = client.chat_completion(messages, max_tokens=64, seed=random.randint(1, 5000),\n model=\"mistralai/Mistral-7B-Instruct-v0.3\")\n\n response = response.choices[0].message.content.replace(\"Magic 8 Ball\", \"\").replace(\":\", \"\")\n return response, None, None\n```\n\n\nNow that we have our text response, we'll read it aloud with Parler TTS. The `read_response` function will be a python generator that yields the next chunk of audio as it's ready.\n\n\nWe'll be using the [Mini v0.1](https://huggingface.co/parler-tts/parler_tts_mini_v0.1) for the feature extraction but the [Jenny fine tuned version](https://huggingface.co/parler-tts/parler-tts-mini-jenny-30H) for the voice. This is so that the voice is consistent across generations.\n\n\nStreaming audio with transformers requires a custom Streamer class. You can see the implementation [here](https://huggingface.co/spaces/gradio/magic-8-ball/blob/main/streamer.py). Additionally, we'll convert the output to bytes so that it can be streamed faster from the backend. \n\n\n```python\nfrom streamer import ParlerTTSStreamer\nfrom transformers import AutoTokenizer, AutoFeatureExtractor, set_seed\nimport numpy as np\nimport spaces\nimport torch\nfrom threading import Thread\n\n\ndevice = \"cuda:0\" if torch.cuda.is_available() else \"mps\" if torch.backends.mps.is_available() else \"cpu\"\ntorch_dtype = torch.float16 if device != \"cpu\" else torch.float32\n\nrepo_id = \"parler-tts/parler_tts_mini_v0.1\"\n\njenny_repo_id = \"ylacombe/parler-tts-mini-jenny-30H\"\n\nmodel = ParlerTTSForConditionalGeneration.from_pretrained(\n jenny_repo_id, torch_dtype=torch_dtype, low_cpu_mem_usage=True\n).to(device)\n\ntokenizer = AutoTokenizer.from_pretrained(repo_id)\nfeature_extractor = AutoFeatureExtractor.from_pretrained(repo_id)\n\nsampling_rate = model.audio_encoder.config.sampling_rate\nframe_rate = model.audio_encoder.config.frame_rate\n\n@spaces.GPU\ndef read_response(answer):\n\n play_steps_in_s = 2.0\n play_steps = int(frame_rate * play_steps_in_s)\n\n description = \"Jenny speaks at an average pace with a calm delivery in a very confined sounding environment with clear audio quality.\"\n description_tokens = tokenizer(description, return_tensors=\"pt\").to(device)\n\n streamer = ParlerTTSStreamer(model, device=device, play_steps=play_steps)\n prompt = tokenizer(answer, return_tensors=\"pt\").to(device)\n\n generation_kwargs = dict(\n input_ids=description_tokens.input_ids,\n prompt_input_ids=prompt.input_ids,\n streamer=streamer,\n do_sample=True,\n temperature=1.0,\n min_new_tokens=10,\n )\n\n set_seed(42)\n thread = Thread(target=model.generate, kwargs=generation_kwargs)\n thread.start()\n\n for new_audio in streamer:\n print(f\"Sample of length: {round(new_audio.shape[0] / sampling_rate, 2)} seconds\")\n yield answer, numpy_to_mp3(new_audio, sampling_rate=sampling_rate)\n```" }, { "id": 643, "parent": 639, "path": "07_streaming/01_streaming-ai-generated-audio.md", "level": 2, "title": "Conclusion", "content": "You can see our final application [here](https://huggingface.co/spaces/gradio/magic-8-ball)!" }, { "id": 644, "parent": null, "path": "07_streaming/06_automatic-voice-detection.md", "level": 1, "title": "Multimodal Gradio App Powered by Groq with Automatic Speech Detection", "content": "Tags: AUDIO, STREAMING, CHATBOTS, VOICE" }, { "id": 645, "parent": 644, "path": "07_streaming/06_automatic-voice-detection.md", "level": 2, "title": "Introduction", "content": "Modern voice applications should feel natural and responsive, moving beyond the traditional \"click-to-record\" pattern. By combining Groq's fast inference capabilities with automatic speech detection, we can create a more intuitive interaction model where users can simply start talking whenever they want to engage with the AI.\n\n> Credits: VAD and Gradio code inspired by [WillHeld's Diva-audio-chat](https://huggingface.co/spaces/WillHeld/diva-audio-chat/tree/main).\n\nIn this tutorial, you will learn how to create a multimodal Gradio and Groq app that has automatic speech detection. You can also watch the full video tutorial which includes a demo of the application:\n\n" }, { "id": 646, "parent": 644, "path": "07_streaming/06_automatic-voice-detection.md", "level": 2, "title": "Background", "content": "Many voice apps currently work by the user clicking record, speaking, then stopping the recording. While this can be a powerful demo, the most natural mode of interaction with voice requires the app to dynamically detect when the user is speaking, so they can talk back and forth without having to continually click a record button. \n\nCreating a natural interaction with voice and text requires a dynamic and low-latency response. Thus, we need both automatic voice detection and fast inference. With @ricky0123/vad-web powering speech detection and Groq powering the LLM, both of these requirements are met. Groq provides a lightning fast response, and Gradio allows for easy creation of impressively functional apps.\n\nThis tutorial shows you how to build a calorie tracking app where you speak to an AI that automatically detects when you start and stop your response, and provides its own text response back to guide you with questions that allow it to give a calorie estimate of your last meal." }, { "id": 647, "parent": 644, "path": "07_streaming/06_automatic-voice-detection.md", "level": 2, "title": "Key Components", "content": "- **Gradio**: Provides the web interface and audio handling capabilities\n- **@ricky0123/vad-web**: Handles voice activity detection\n- **Groq**: Powers fast LLM inference for natural conversations\n- **Whisper**: Transcribes speech to text" }, { "id": 648, "parent": 647, "path": "07_streaming/06_automatic-voice-detection.md", "level": 3, "title": "Setting Up the Environment", "content": "First, let’s install and import our essential libraries and set up a client for using the Groq API. Here’s how to do it:\n\n`requirements.txt`\n```\ngradio\ngroq\nnumpy\nsoundfile\nlibrosa\nspaces\nxxhash\ndatasets\n```\n\n`app.py`\n```python\nimport groq\nimport gradio as gr\nimport soundfile as sf\nfrom dataclasses import dataclass, field\nimport os" }, { "id": 649, "parent": null, "path": "07_streaming/06_automatic-voice-detection.md", "level": 1, "title": "Initialize Groq client securely", "content": "api_key = os.environ.get(\"GROQ_API_KEY\")\nif not api_key:\n raise ValueError(\"Please set the GROQ_API_KEY environment variable.\")\nclient = groq.Client(api_key=api_key)\n```\n\nHere, we’re pulling in key libraries to interact with the Groq API, build a sleek UI with Gradio, and handle audio data. We’re accessing the Groq API key securely with a key stored in an environment variable, which is a security best practice for avoiding leaking the API key.\n\n---" }, { "id": 650, "parent": 649, "path": "07_streaming/06_automatic-voice-detection.md", "level": 3, "title": "State Management for Seamless Conversations", "content": "We need a way to keep track of our conversation history, so the chatbot remembers past interactions, and manage other states like whether recording is currently active. To do this, let’s create an `AppState` class:\n\n```python\n@dataclass\nclass AppState:\n conversation: list = field(default_factory=list)\n stopped: bool = False\n model_outs: Any = None\n```\n\nOur `AppState` class is a handy tool for managing conversation history and tracking whether recording is on or off. Each instance will have its own fresh list of conversations, making sure chat history is isolated to each session. \n\n---" }, { "id": 651, "parent": 649, "path": "07_streaming/06_automatic-voice-detection.md", "level": 3, "title": "Transcribing Audio with Whisper on Groq", "content": "Next, we’ll create a function to transcribe the user’s audio input into text using Whisper, a powerful transcription model hosted on Groq. This transcription will also help us determine whether there’s meaningful speech in the input. Here’s how:\n\n```python\ndef transcribe_audio(client, file_name):\n if file_name is None:\n return None\n\n try:\n with open(file_name, \"rb\") as audio_file:\n response = client.audio.transcriptions.with_raw_response.create(\n model=\"whisper-large-v3-turbo\",\n file=(\"audio.wav\", audio_file),\n response_format=\"verbose_json\",\n )\n completion = process_whisper_response(response.parse())\n return completion\n except Exception as e:\n print(f\"Error in transcription: {e}\")\n return f\"Error in transcription: {str(e)}\"\n```\n\nThis function opens the audio file and sends it to Groq’s Whisper model for transcription, requesting detailed JSON output. verbose_json is needed to get information to determine if speech was included in the audio. We also handle any potential errors so our app doesn’t fully crash if there’s an issue with the API request. \n\n```python\ndef process_whisper_response(completion):\n \"\"\"\n Process Whisper transcription response and return text or null based on no_speech_prob\n \n Args:\n completion: Whisper transcription response object\n \n Returns:\n str or None: Transcribed text if no_speech_prob <= 0.7, otherwise None\n \"\"\"\n if completion.segments and len(completion.segments) > 0:\n no_speech_prob = completion.segments[0].get('no_speech_prob', 0)\n print(\"No speech prob:\", no_speech_prob)\n\n if no_speech_prob > 0.7:\n return None\n \n return completion.text.strip()\n \n return None\n```\n\nWe also need to interpret the audio data response. The process_whisper_response function takes the resulting completion from Whisper and checks if the audio was just background noise or had actual speaking that was transcribed. It uses a threshold of 0.7 to interpret the no_speech_prob, and will return None if there was no speech. Otherwise, it will return the text transcript of the conversational response from the human.\n\n\n---" }, { "id": 652, "parent": 649, "path": "07_streaming/06_automatic-voice-detection.md", "level": 3, "title": "Adding Conversational Intelligence with LLM Integration", "content": "Our chatbot needs to provide intelligent, friendly responses that flow naturally. We’ll use a Groq-hosted Llama-3.2 for this:\n\n```python\ndef generate_chat_completion(client, history):\n messages = []\n messages.append(\n {\n \"role\": \"system\",\n \"content\": \"In conversation with the user, ask questions to estimate and provide (1) total calories, (2) protein, carbs, and fat in grams, (3) fiber and sugar content. Only ask *one question at a time*. Be conversational and natural.\",\n }\n )\n\n for message in history:\n messages.append(message)\n\n try:\n completion = client.chat.completions.create(\n model=\"llama-3.2-11b-vision-preview\",\n messages=messages,\n )\n return completion.choices[0].message.content\n except Exception as e:\n return f\"Error in generating chat completion: {str(e)}\"\n```\n\nWe’re defining a system prompt to guide the chatbot’s behavior, ensuring it asks one question at a time and keeps things conversational. This setup also includes error handling to ensure the app gracefully manages any issues.\n\n---" }, { "id": 653, "parent": 649, "path": "07_streaming/06_automatic-voice-detection.md", "level": 3, "title": "Voice Activity Detection for Hands-Free Interaction", "content": "To make our chatbot hands-free, we’ll add Voice Activity Detection (VAD) to automatically detect when someone starts or stops speaking. Here’s how to implement it using ONNX in JavaScript:\n\n```javascript\nasync function main() {\n const script1 = document.createElement(\"script\");\n script1.src = \"https://cdn.jsdelivr.net/npm/onnxruntime-web@1.14.0/dist/ort.js\";\n document.head.appendChild(script1)\n const script2 = document.createElement(\"script\");\n script2.onload = async () => {\n console.log(\"vad loaded\");\n var record = document.querySelector('.record-button');\n record.textContent = \"Just Start Talking!\"\n \n const myvad = await vad.MicVAD.new({\n onSpeechStart: () => {\n var record = document.querySelector('.record-button');\n var player = document.querySelector('#streaming-out')\n if (record != null && (player == null || player.paused)) {\n record.click();\n }\n },\n onSpeechEnd: (audio) => {\n var stop = document.querySelector('.stop-button');\n if (stop != null) {\n stop.click();\n }\n }\n })\n myvad.start()\n }\n script2.src = \"https://cdn.jsdelivr.net/npm/@ricky0123/vad-web@0.0.7/dist/bundle.min.js\";\n}\n```\n\nThis script loads our VAD model and sets up functions to start and stop recording automatically. When the user starts speaking, it triggers the recording, and when they stop, it ends the recording.\n\n---" }, { "id": 654, "parent": 649, "path": "07_streaming/06_automatic-voice-detection.md", "level": 3, "title": "Building a User Interface with Gradio", "content": "Now, let’s create an intuitive and visually appealing user interface with Gradio. This interface will include an audio input for capturing voice, a chat window for displaying responses, and state management to keep things synchronized.\n\n```python\nwith gr.Blocks(theme=theme, js=js) as demo:\n with gr.Row():\n input_audio = gr.Audio(\n label=\"Input Audio\",\n sources=[\"microphone\"],\n type=\"numpy\",\n streaming=False,\n waveform_options=gr.WaveformOptions(waveform_color=\"#B83A4B\"),\n )\n with gr.Row():\n chatbot = gr.Chatbot(label=\"Conversation\", type=\"messages\")\n state = gr.State(value=AppState())\n```\n\nIn this code block, we’re using Gradio’s `Blocks` API to create an interface with an audio input, a chat display, and an application state manager. The color customization for the waveform adds a nice visual touch.\n\n---" }, { "id": 655, "parent": 649, "path": "07_streaming/06_automatic-voice-detection.md", "level": 3, "title": "Handling Recording and Responses", "content": "Finally, let’s link the recording and response components to ensure the app reacts smoothly to user inputs and provides responses in real-time.\n\n```python\n stream = input_audio.start_recording(\n process_audio,\n [input_audio, state],\n [input_audio, state],\n )\n respond = input_audio.stop_recording(\n response, [state, input_audio], [state, chatbot]\n )\n```\n\nThese lines set up event listeners for starting and stopping the recording, processing the audio input, and generating responses. By linking these events, we create a cohesive experience where users can simply talk, and the chatbot handles the rest.\n\n---" }, { "id": 656, "parent": 649, "path": "07_streaming/06_automatic-voice-detection.md", "level": 2, "title": "Summary", "content": "1. When you open the app, the VAD system automatically initializes and starts listening for speech\n2. As soon as you start talking, it triggers the recording automatically\n3. When you stop speaking, the recording ends and:\n - The audio is transcribed using Whisper\n - The transcribed text is sent to the LLM\n - The LLM generates a response about calorie tracking\n - The response is displayed in the chat interface\n4. This creates a natural back-and-forth conversation where you can simply talk about your meals and get instant feedback on nutritional content\n\nThis app demonstrates how to create a natural voice interface that feels responsive and intuitive. By combining Groq's fast inference with automatic speech detection, we've eliminated the need for manual recording controls while maintaining high-quality interactions. The result is a practical calorie tracking assistant that users can simply talk to as naturally as they would to a human nutritionist.\n\nLink to GitHub repository: [Groq Gradio Basics](https://github.com/bklieger-groq/gradio-groq-basics/tree/main/calorie-tracker)" } ]