Clear Chat Interface

Hi,

I’m currently building a chatbot with Chat Interface and OpenAI. I’ve been trying to write an input() event listener where the chat history gets cleared when I select a new option on a dropdown (basically automating the clear button). I’ve read the code for the clear button on Gradio’s GitHub page, and it seems that all you have to do is set the component you want cleared to [ ] or None.

Unfortunately, when I set the Chat Interface component to [ ] or None, I get the following error:

gradio.exceptions.InvalidBlockError: Output component with id 1 used in input() event not found in this gr.Blocks context. You are allowed to nest gr.Blocks contexts, but there must be a gr.Blocks context that contains all components and events.

I’m really not sure what the issue is, because I only have one Block and every component is inside it.

The closest I’ve gotten it to working is making a Chatbot component before the Chat Interface and setting it to the chatbot parameter in the Chat Interface, then upon the dropdown selection, resetting the messages sent to OpenAI and setting the Chatbot component to [ ]. This will actually clear the chat history. However, as soon as I submit another message in the Chat Interface, the chat history from before the dropdown change mysteriously reappears, as if I had never reset the Chatbot component in the first place? This is super strange to me as my debugging has confirmed that the message history sent to OpenAI has been totally reset to default, so I wonder where the Chat Interface is getting it from. Maybe Chat Interface is storing the chat history somewhere inaccessible to a reset?

This issue isn’t at all present when I just press the clear button of the Chat Interface, so ideally, if there’s any way to just automate a click, that would be amazing. Thanks.

1 Like

Hi @JFalejczyk can you share a code snippet we can use to reproduce?

Hi @abidlabs, thanks so much for getting back to me on this. I can’t share some variables like contentTypes (which is just a dictionary holding info to train the AI into the characters), but they’re not relevant to the code anyway. Below you can find essentially what I’m doing.

# Function that resets AI in event of character switching
def reset(input):

    return []

# Function that powers the chatbot by sending and receiving messages from OpenAI
def converse(input, history, character):

    # Setup default chat sequence in OpenAI's required format
    openAIHistory = [
        {
            "role": "system",
            "content": contentTypes[character]
        }
    ]
    for human, assistant in history:
        openAIHistory.append({"role": "user", "content": human })
        openAIHistory.append({"role": "assistant", "content": assistant})

    if input:

        # Continue chat sequence and append AI's response
        openAIHistory.append({"role": "user", "content": input})
        chat = openai.ChatCompletion.create(model="gpt-3.5-turbo", messages=openAIHistory) # Get response from OpenAI model
        reply = chat.choices[0].message.content
        
        return reply

# Gradio app
bot = gr.Chatbot()
with gr.Blocks() as demo:

    gr.Markdown(f"<h1 style='text-align: center; margin-bottom: 1rem'>{'My Chatbot'}</h1>")
    dropdown = gr.Dropdown(
        ["Character 1", "Character 2", "Character 3", "Character 4", "Character 5", "Character 6", "Character 7", "Character 8", "Character 9", "Character 10", "Character 11", "Character 12", "Character 13"], label="Characters", info="Select the character that you'd like to speak to", value="Character 1"
    )
    chat = gr.ChatInterface(
        fn=converse,
        chatbot=bot,
        additional_inputs=dropdown
    )
    dropdown.input(fn=reset, inputs=dropdown, outputs=bot) # Reset the chatbot to clear history automatically

demo.queue()
demo.launch()

If I move the chatbot component into the main block before the chat interface, that’s where I get the following error:

gradio.exceptions.DuplicateBlockError: A block with id: 1 has already been rendered in the current Blocks.

So I’ve avoided that and kept it outside the main block. Still though, I can select input on the dropdown and it’ll temporarily clear the chat history, but when I send another message, the old history will strangely come back. I’m not quite sure what’s going on, in case it’s obvious to you. Thanks.

I’ll take a look. Some quick notes:

  1. If you’d like to bring gr.Chatbot() into the main Blocks, just set render=False, e.g. gr.Chatbot(render=False)

  2. But in your code example you shouldn’t even need to define a gr.Chatbot since you’re using the default implementation of gr.ChatInterface which creates a gr.Chatbot for you. So you can just skip the chatbot parameter and everything will be the same.

Does that fix anything for you?

1 Like

Oh never mind, I’m sorry you do use the Chatbot as the output, so you should do what I suggested in (1)

Ah okay I know the issue. It’s a subtle problem that we’ll need to fix on our end but for now, you can fix this by manually resetting the chat.chatbot_state. Here’s a complete example:

import gradio as gr

def converse(x, y, z):
    return z

def reset(z):
    return [], []

# Gradio app
with gr.Blocks() as demo:
    gr.Markdown(f"<h1 style='text-align: center; margin-bottom: 1rem'>{'My Chatbot'}</h1>")
    bot = gr.Chatbot(render=False)
    dropdown = gr.Dropdown(
        ["Character 1", "Character 2", "Character 3", "Character 4", "Character 5", "Character 6", "Character 7", "Character 8", "Character 9", "Character 10", "Character 11", "Character 12", "Character 13"], label="Characters", info="Select the character that you'd like to speak to", value="Character 1"
    )
    chat = gr.ChatInterface(
        fn=converse,
        chatbot=bot,
        additional_inputs=dropdown
    )
    dropdown.input(fn=reset, inputs=dropdown, outputs=[bot, chat.chatbot_state])

demo.queue()
demo.launch()
1 Like

That’s perfect, thank you so much for helping, I definitely wouldn’t have figured that out on my own. Really appreciate it.