gradio-app / gradio

Build and share delightful machine learning apps, all in Python. 🌟 Star to support our work!
http://www.gradio.app
Apache License 2.0
34.31k stars 2.61k forks source link

Chatbot component does not show status tracker #3914

Closed freddyaboulton closed 1 year ago

freddyaboulton commented 1 year ago

Describe the bug

When running a chatbot demo, I noticed that the chatbot component does not display the queue status or progress information for a pending event.

Is there an existing issue for this?

Reproduction

Add a long sleep to the chatbot_multimodal demo

import gradio as gr
import time

def add_text(history, text):
    history = history + [(text, None)]
    return history, ""

def add_file(history, file):
    history = history + [((file.name,), None)]
    return history

def bot(history):
    time.sleep(10)
    response = "**That's cool!**"
    history[-1][1] = response
    return history

with gr.Blocks() as demo:
    chatbot = gr.Chatbot([], elem_id="chatbot").style(height=750)

    with gr.Row():
        with gr.Column(scale=0.85):
            txt = gr.Textbox(
                show_label=False,
                placeholder="Enter text and press enter, or upload an image",
            ).style(container=False)
        with gr.Column(scale=0.15, min_width=0):
            btn = gr.UploadButton("📁", file_types=["image", "video", "audio"])

    txt.submit(add_text, [chatbot, txt], [chatbot, txt]).then(
        bot, chatbot, chatbot
    )
    btn.upload(add_file, [chatbot, btn], [chatbot]).then(
        bot, chatbot, chatbot
    )

if __name__ == "__main__":
    demo.launch()

Then launch with queueing with SYSTEM=spaces python demo/chatbot_multimodal/run.py

Open up two tabs and send a message at around the same time.

The textbox component shows the queue information:

Screen Shot 2023-04-19 at 3 07 07 PM

But the chatbot does not:

image

This is a problem because if the event handler did not return the textbox, the queue information would not be displayed to the user at all!

Screenshot

No response

Logs

-

System Info

3.27.0

Severity

serious, but I can work around it

aliabid94 commented 1 year ago

We need to come up with a design of a subtler statustracker that doesn't cover up the component, other components would also benefit from being able to optionally have a subtler statustracker instead. For chatbot this could appear in the loading dots. For other components (and maybe chatbot as well), we could have this information tucked in a corner in "subtle status tracker" mode, like a component Label.

freddyaboulton commented 1 year ago

Since chatbot has no status tracker, the error modal will not be displayed if chatbot is the only output component of an event. I think this issue should fix that as well for the chatbot case but #3347 would also be a general fix.

pseudotensor commented 1 year ago

@freddyaboulton What's the work-around?

freddyaboulton commented 1 year ago

Hi @pseudotensor !

The workaround I mentioned is to additionally update a component that properly displays the status tracker. In this case, it's the textbox where users type the message.

In my example above, add_text resets the textbox to be an empty string

def add_text(history, text):
    history = history + [(text, None)]
    return history, ""

And the submit event on the textbox lists itself as output

    txt.submit(add_text, [chatbot, txt], [chatbot, txt]).then(
        bot, chatbot, chatbot
    )

So then the textbox will display the status:

image

pseudotensor commented 1 year ago

Hmm. I tried this, and while it seems to work, it fails more generally.

Try 3+ tabs and puts a message into them at same time. The others will show the correct queue position at first (e.g. 1/4, 2/4, 3/4, 4/4).

However, once the 2nd page gets going, the 3+ tabs suddenly just show the 3 dots again. And so the other 2 pages not yet really going still show the 3 dots instead of queue.

Same thing happens with your code snippet, locally with queue enabled:

import gradio as gr
import time

def add_text(history, text):
    history = history + [(text, None)]
    return history, ""

def add_file(history, file):
    history = history + [((file.name,), None)]
    return history

def bot(history):
    time.sleep(10)
    response = "**That's cool!**"
    history[-1][1] = response
    return history

with gr.Blocks() as demo:
    chatbot = gr.Chatbot([], elem_id="chatbot").style(height=750)

    with gr.Row():
        with gr.Column(scale=0.85):
            txt = gr.Textbox(
                show_label=False,
                placeholder="Enter text and press enter, or upload an image",
            ).style(container=False)
        with gr.Column(scale=0.15, min_width=0):
            btn = gr.UploadButton("📁", file_types=["image", "video", "audio"])

    txt.submit(add_text, [chatbot, txt], [chatbot, txt]).then(
        bot, chatbot, chatbot
    )
    btn.upload(add_file, [chatbot, btn], [chatbot]).then(
        bot, chatbot, chatbot
    )

if __name__ == "__main__":
    demo.queue()
    demo.launch()

~However, I don't really get why it's doing that. concurrency_count=1 by default, and it should queue behind the submit across all user tabs. I don't see how the other tabs slip through without getting queued. Maybe gradio bug?~

If I add prints, I clearly see add_text called "by" the other tabs all together, no queuing occurs. Then bot is queued sequentially.

Ah, of course. The add_text's are queued up first, before the bots. So the queue looks like:

add1 bot1 add2 add3 add4 ... because none of the adds got to bot, but the first got to bot quickly since I cannot click on all tabs simultaneously to within microsecond accuracy. And what I did is normal expected behavior.

Then when bot1 done, then suddenly add2, add3, add4 all get done together. Then bot2, bot3, bot4 get queued, and back to same problem.

One way to fix is if there was choice to only queue something after prior call was successful. While there is a success (instead of then), unfortunately it still puts things in queue regardless of success status.

i.e. instead of just "trigger_after" need a "queue_after", which IMO should have been what was done for .success. I don't see why one would even queue something until status of success is seen.

abidlabs commented 1 year ago

Given all the Chatbot demos, I feel like this is important enough we should add to 3.x milestone. The demos are basically unusable without an ETA / queue rank

pseudotensor commented 1 year ago

@abidlabs any status on this one?

For me, this issue is probably even more important than https://github.com/gradio-app/gradio/issues/4245 -- even though 4245 is pretty bad.