Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow showing progress updates on specific components #3714

Closed
1 task done
indigoviolet opened this issue Mar 30, 2023 · 31 comments · Fixed by #10492
Closed
1 task done

Allow showing progress updates on specific components #3714

indigoviolet opened this issue Mar 30, 2023 · 31 comments · Fixed by #10492
Assignees
Labels
enhancement New feature or request needs designing The proposed feature needs to be discussed and designed before being implemented

Comments

@indigoviolet
Copy link

  • I have searched to see if a similar issue already exists.

Is your feature request related to a problem? Please describe.

I have a slow step triggered by a Button, and I could not get a progress bar to show up for it. I finally got it to work by adding a fake TextBox and setting it as an output, but that neither seems documented nor the best way.

Describe the solution you'd like
The button should show a spinner or progress bar attached to it somehow.

@abidlabs
Copy link
Member

Hi @indigoviolet please share a code example that can allow us to reproduce this issue, thanks.

@abidlabs abidlabs added the needs repro Awaiting full reproduction label Mar 30, 2023
@indigoviolet
Copy link
Author

indigoviolet commented Mar 31, 2023

import time

import gradio as gr
from tqdm import tqdm


def foo(pr=gr.Progress(track_tqdm=True)):
    for i in tqdm(range(10)):
        print(i)
        time.sleep(1)


with gr.Blocks() as demo:
    btn = gr.Button(label="Sleep")
    btn.click(fn=foo)

demo.queue().launch()

@abidlabs
Copy link
Member

Hi @indigoviolet thanks for providing the script. The ProgressBar appears over the output component, and in this case, no output component is provided so no progress bar appears. Can you describe:

  • Your use case a bit more where (presumably) you are running a slow step without any output component?
  • What your expected UI would look like?

@abidlabs abidlabs added pending clarification and removed needs repro Awaiting full reproduction labels Mar 31, 2023
@indigoviolet
Copy link
Author

My actual use case had a gr.Dataset as the output, which doesn't show a progress bar either.

import time

import gradio as gr
from tqdm import tqdm


def foo(pr=gr.Progress(track_tqdm=True)):
    for i in tqdm(range(10)):
        print(i)
        time.sleep(1)
    return [["foo"], ["bar"]]


with gr.Blocks() as demo:
    ds = gr.Dataset(components=["text"], samples=[])

    btn = gr.Button(label="Sleep")
    btn.click(fn=foo, outputs=[ds])

demo.queue().launch()

There are many options for UI, you could have a progress bar within the button itself, or one that runs along the long border, or a spinner. I think the option that makes most sense for gradio is to add a new ProgressBar component, which can be placed anywhere and hooked up as an output in addition to the Dataset above, and it would show the progress.

@abidlabs abidlabs changed the title Progress bar for Button A ProgressBar component that can be placed anywhere in the UI Apr 4, 2023
@abidlabs abidlabs added new component Involves creating a new component and removed pending clarification labels Apr 4, 2023
@abidlabs
Copy link
Member

abidlabs commented Apr 4, 2023

Makes sense, thanks @indigoviolet. I've updated the issue with your suggestion

@edmcman
Copy link

edmcman commented Sep 18, 2023

Another situation where this would be useful is adding a ProgressBar for interpretation

@jcheroske
Copy link

The progress bar has great potential, but as it stands now it is very strange and not super useful. One very common use case is to show a progress bar as a modal on top of the main UI. Another is to display it on top of assorted UI widgets, such as rows and columns. Being able to declare the progress bar during the layout of the UI makes sense. It could be declared as hidden or visible during creation, but would appear once the Progress object is created. Having a ProgressBar and Progress pair of objects that work together would unlock a lot of power.

@jcampbell05
Copy link

This would be a great way to fix #4857

I would love to be able to do this

with gr.ProgressBar():
  # We will render progress bar over all UI components within this block
   image = gr.Image()
  caption = gr.Text()

Right now I can either output a single component or have no progress UI,

@freddyaboulton
Copy link
Collaborator

freddyaboulton commented Nov 3, 2023

Right now I can either output a single component or have no progress UI

Not saying we won't do this but you can put a progress bar over multiple components

import gradio as gr
import time 

def load_set(progress=gr.Progress()):
    imgs = [None] * 24
    for img in progress.tqdm(imgs, desc="Loading..."):
        time.sleep(0.1)
    return ["Loaded"] * 2


with gr.Blocks() as demo:
    load = gr.Button("Load")
    label = gr.Label(label="Loader")
    label1 = gr.Label(label="Loader1")
    load.click(load_set, outputs=[label, label1])

demo.launch()

multiple_events_progress

@jcampbell05
Copy link

So this isn't working for me, here is the code I have:

import logging
import gradio as gr

with gr.Blocks() as demo:

    # Input Section
    #
    images = gr.File( ) 
    ai_version = gr.Dropdown(
        ["1.0", "3.0", "3.1", "4.0"], value="3.0", label="AI VERSION",
    )

    # Action Button
    #
    enhance_btn = gr.Button("Enhance")

    # Output Section
    #
    with gr.Row():
        uploaded = gr.Image(label="Uploaded Image")
        original = gr.Image(label="Original Image")
        enhanced = gr.Image(label="Enhanced Image")

    def enhance(input, progress=gr.Progress()):

        import time

        for img in progress.tqdm(range(100), desc="Loading..."):
            time.sleep(0.1)
      


    enhance_btn.click(fn=enhance, inputs={
        images,
        ai_version
    }, outputs=[uploaded, original, enhanced], api_name="enhance")

demo.load(show_progress=True)

demo.launch(
    server_name="0.0.0.0",
)  

When I click enhance, no progress bars are shown or even any animated spinner.

Screenshot 2023-11-03 at 14 40 08

@jcampbell05
Copy link

Okay so it won't render the progress bar at all for the image component but will for labels

@abidlabs
Copy link
Member

abidlabs commented Nov 7, 2023

Hey! We've now made it possible for Gradio users to create their own custom components -- meaning that you can write some Python and JavaScript (Svelte), and publish it as a Gradio component. You can use it in your own Gradio apps, or share it so that anyone can use it in their Gradio apps. Here are some examples of custom Gradio components:

You can see the source code for those components by clicking the "Files" icon and then clicking "src". The complete source code for the backend and frontend is visible. In particular, its very fast if you want to build off an existing component. We've put together a Guide: https://www.gradio.app/guides/five-minute-guide, and we're happy to help. Hopefully this will help address this issue.

@jcampbell05
Copy link

jcampbell05 commented Nov 7, 2023

@abidlabs Whilst it may in this case, I also think this issue is still valid. Gradio internally has a Progress Bar component but isn't publicly exposed through the API it's only used internally.

So best solution in my eyes would be to expose an API to allow us to use this UI without recreating it using custom components and would allow us to workaround the bugs with progress bar in other built-in components.

@abidlabs
Copy link
Member

abidlabs commented Nov 7, 2023

Fair enough, leaving the issue open so that we can think about it a bit more

@abidlabs abidlabs added enhancement New feature or request needs designing The proposed feature needs to be discussed and designed before being implemented labels Nov 7, 2023
@jcampbell05
Copy link

It appears the bug with progress bar not showing up may have been fixed in 4.5.0, at least for me it's working

@abidlabs abidlabs removed the new component Involves creating a new component label Dec 5, 2023
@dwipper
Copy link

dwipper commented Dec 6, 2023

While a bit askew from the "progress bar" discussion, it would be nice to turn off any progress status (i.e. spinner and seconds) for specific components that really aren't involved in the processing but are being returned from the function. Something like progress='False' .

@abidlabs
Copy link
Member

abidlabs commented Dec 6, 2023

Its possible to do this globally for all outputs (by setting show_progress="hidden" in the event trigger), but not possible for specific outputs. Can you share a code snippet @dwipper and we can think about how to support it or offer a workaround

@dwipper
Copy link

dwipper commented Dec 6, 2023

Here's the code for the examples and resources Datasets shown in the video. Fairly basic, i.e. call a function, and returns a component update. Apparently the spinner and timer run regardless.:

examples_ds.select(set_question, inputs=None,outputs=question_tbox)

resources_ds.select(get_selected,inputs=None,outputs=[nili_response_html, video_response_html,toggle_html_btn,response_label_md,video_description_tbox])

Uploading scy-jurf-tsx (2023-12-05 19 47 GMT-7).mp4…

@dwipper
Copy link

dwipper commented Dec 6, 2023

@abidlabs Thinking this through, would it make sense to turn off the progress globally, and then turn it on for the specific AI calls/component that do take a significant amount to time?

Maybe less params/coding in the end for certain types of apps? Although it's not clear to me if there's actually a way to turn off the progress spinner/time?

I have turned off the progress bar in one of our apps: progress_item(progress=None)

@Kunz-David
Copy link

Hi, is there any news on this? Is there a way to apply the progress to specific components?

@abidlabs
Copy link
Member

Not yet, we are working on other things at the moment, and hard to say right now when we'll be able to get back to this sorry

@Josef-Ouano
Copy link

Hope you can get back to this.
It would be useful for individual output components.

@ROBERT-MCDOWELL
Copy link

Not yet, we are working on other things at the moment, and hard to say right now when we'll be able to get back to this sorry

is there a hack we can temporary use to avoid to have a progress state on all outputs components but only one we can choose?

@abidlabs
Copy link
Member

abidlabs commented Jan 20, 2025

I think this #8016 (comment) is a good proposal, cc @elismasilva

@abidlabs abidlabs self-assigned this Jan 20, 2025
@elismasilva
Copy link

I think this #8016 (comment) is a good proposal, cc @elismasilva

What I wrote there was a simple solution that I thought of at first. But thinking about scenarios where I have many components in the output, it could make reading the code difficult because we could have several combinations of True/False in a list that we would need to compare the position of each component in the output list. I think it would be better if each component implemented by default a boolean property 'show_progress' limited only to allowing or disabling the progress bar in the component. Then in the event, the behavior continues as it is, defining the type of the progress bar but it will only be displayed in the component if the component property is True (which could be the default value). The only disadvantage of this is that it would not be possible to enable/disable it for specific events because the property would affect the component in use in all other events in which it participates in the output list. But compared to what we have today, I would be happy with any alternative that would be faster for you to implement, as long as I can disable the progress bar for specific components in the output list.

@dwipper
Copy link

dwipper commented Jan 20, 2025

My thought would be to keep the current event param show_progress='hidden' to turn on/off any progress display, but add a param to the component definition show_progress=True/False. If the event param isn't 'hidden', then progress would show for any component with show_progress=True. As with other component params, showing progress could be updated by returning a gr.update(show_progress=True) from a function to the event output= component(s).

@elismasilva
Copy link

My thought would be to keep the current event param show_progress='hidden' to turn on/off any progress display, but add a param to the component definition show_progress=True/False. If the event param isn't 'hidden', then progress would show for any component with show_progress=True. As with other component params, showing progress could be updated by returning a gr.update(show_progress=True) from a function to the event output= component(s).

What you propose summarizes well what I said, and returning gr.update(show_progress=True/False) can be a solution for cases where the component may be involved in more than one event that displays the progress bar and you may want to disable/enable progress only for certain events. If the display of progress in the components happens after updating this attribute, then it should work.

@elismasilva
Copy link

But another possible solution could be what @indigoviolet proposed. Having a general progressBar component. Today I already do this in my interface. I avoid showing the progress in the components and leave a Textbox or HTML as a status field that eventually displays the progress. However, if I have an ImageGallery in the return it ends up displaying the progress as well. So maybe we could have something like this in the event:

.event(fn=function, inputs=inputs, outputs=outputs, show_progres="type", progress_out=progress_component)

For those who don't want to have the progress displayed in all components, this would be a good alternative.

@abidlabs
Copy link
Member

abidlabs commented Jan 20, 2025

My thought would be to keep the current event param show_progress='hidden' to turn on/off any progress display, but add a param to the component definition show_progress=True/False. If the event param isn't 'hidden', then progress would show for any component with show_progress=True. As with other component params, showing progress could be updated by returning a gr.update(show_progress=True) from a function to the event output= component(s).

The limitation with this approach is that the component's param would apply to all events associated with that component. You could, as you mention, update the param but you wouldn't be able to do it within the same function that you want that change to apply to (as the gr.update() would happen at the end of the function).

@abidlabs
Copy link
Member

The approach I'm thinking about is adding a parameter show_progress_on to the event listeners, that could take any component defined in your Gradio Blocks, and the progress indicator only appears on that component or components. Feedback welcome!

@elismasilva
Copy link

The approach I'm thinking about is adding a parameter show_progress_on to the event listeners, that could take any component defined in your Gradio Blocks, and the progress indicator only appears on that component or components. Feedback welcome!

This is a good solution too since we don't have to worry about the order of the components in the list, if we accept it like this:
outputs=[component1, component2, component3], show_progess_on=[component2],
then by default it will only display on the specified components.

@abidlabs abidlabs changed the title A ProgressBar component that can be placed anywhere in the UI Allow showing progress updates on specific components Feb 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request needs designing The proposed feature needs to be discussed and designed before being implemented
Projects
None yet
Development

Successfully merging a pull request may close this issue.