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
31.8k stars 2.37k forks source link

Gradio 4.17.0 vs 4.16.0- Accordion closes when clicking on a slider #7366

Closed skye0402 closed 6 months ago

skye0402 commented 6 months ago

Describe the bug

It's a clear delta bug between 4.17.0 vs 4.16.0: If you have e.g. a slider with a change event (that is needed!) registered inside an accordion element (nested), then the accordion will close after click. The event of the slider is triggered but it's unacceptable to re-open the accordion every time from a user experience point of view.

Have you searched existing issues? 🔎

Reproduction

import gradio as gr
from gradio import Blocks

TEST_MODELS = [
  {
        "model": "gpt-4-32k", 
        "name": "Azure OpenAI GPT-4 32k", 
        "desc": "GPT-4 is a large multimodal model (accepting text or image inputs and outputting text) that can solve difficult problems with greater accuracy than any of our previous models, thanks to its broader general knowledge and advanced reasoning capabilities.", 
        "platform": "SAP Generative AI Hub",
        "maxToken": 16000,
        "hasImage": False,
        "restricted": False,
        "active": True
    }
]

block_css = """
gradio-app > .gradio-container {
    max-width: 100% !important;

}
.contain { display: flex !important; flex-direction: column !important; }
#chat_window { height: 82vh !important; }
#column_left { height: 88vh !important; }
#sql_col_left1 { height: 82vh !important;}
#arch_gallery { height: 82vh !important;}

#buttons button {
    min-width: min(120px,100%);
}
footer {
    display:none !important
}
"""

def update_pref(user: dict, field: str, value:any)->None:   
    pass

def slider_temp_change(state: dict, model_temperature: float):
    """ Register model temperature changes in preference """
    update_pref(user=state["jwt"], field="model_temperature", value=model_temperature)

# SQL Playground functions ---------------------

def sql_tab_selected(state: dict):
    """ Handles the click on the SQL Generation tab """
    return [
        gr.Accordion(visible=False),
        gr.Accordion(visible=False),
    ]

# User tab functions ----------------------------------------

def user_tab_selected(state: dict):
    """ Set user list dataframe """
    login_data = []
    return [
        login_data,
        gr.Accordion(visible=False),
        gr.Accordion(visible=False)
    ]

# General AI Playground functions ---------------------------

def genai_tab_selected(state: dict):
    """ Handles the click on the Generative AI Playground """
    return [
        gr.Accordion(visible=True),
        gr.Accordion(visible=True),
    ]

def set_user_data(state: dict):
    """ Sets the tabs visibility """
    state["jwt"] = "Test"
    return [
        gr.Tab(visible=True),
        gr.Tab(visible=True),
    ]

def build_chat_view(models: dict, sys_roles: dict)->Blocks:
    """ Build the view with Gradio blocks """
    with gr.Blocks(
            title="Architecture & Platform Advisory - Generative AI Chat", 
            theme=gr.themes.Soft(),
            css=block_css
        ) as chat_view:
        state = gr.State({})
        with gr.Row(elem_id="overall_row") as main_screen:
            with gr.Column(scale=10, elem_id="column_left"):
                with gr.Tab(label="Generative AI", elem_id="genai_tab", visible=False) as genai_tab:
                    chatbot = gr.Chatbot(
                        label="AI Chat",
                        elem_id="chat_window",
                        bubble_full_width=False,
                        show_copy_button=True,
                        show_share_button=True,
                        avatar_images=(None, "./img/saplogo.png")
                    )
                    msg_box = gr.Textbox(
                        elem_id="msg_box",
                        show_label=False,
                        max_lines=5,
                        placeholder="Enter text and press ENTER",
                        container=False
                    )
                    msg_box.autofocus = True
                with gr.Tab(label="Architecture", elem_id="arch_info_tab", visible=True) as arch_info_tab:
                    arch_gallery = gr.Gallery(
                        value=["img/cover_slide.png","img/slide1.png"],
                        label="SAP Reference Architectures",
                        elem_id="arch_gallery",
                        preview=True,
                        interactive=False
                    )
                with gr.Tab(label="SQL Generation", elem_id="sql_gen_tab", visible=True) as sql_gen_tab:
                    with gr.Row(elem_id="sql_row1") as sql_row1:
                        with gr.Column(scale=10, elem_id="sql_col_left1") as sql_col_left1:
                            gr.Markdown("### AI Generated SQL Query")
                            sql_query_tb = gr.Markdown(
                                elem_id="sql_query_tb",
                                label="AI Generated SQL Query",
                                visible=False,
                                show_label=True
                            )
                        with gr.Column(scale=3, elem_id="sql_col_right1") as sql_col_right1:
                            sql_result_tb = gr.Textbox(
                                elem_id="sql_result_tb",
                                label="AI generated response",
                                placeholder="No generation requested.",
                                container=True,
                                visible=False
                            )
                            request_tb = gr.Textbox(
                                elem_id="request_tb",
                                label="Your request",
                                placeholder="No generation requested.",
                                container=True,
                                visible=False
                            )
                    with gr.Row(elem_id="sql_row2") as sql_row2:
                        sql_result_df = gr.Dataframe(
                            elem_id="sql_result_df",
                            label="SQL Retrieval Result",
                            headers=["Username", "Full name", "Email"],
                            datatype=["str", "str", "str"],
                            col_count=(3, "fixed"),
                            visible=False
                        )
                        sql_input_tb = gr.Textbox(
                            elem_id="sql_input_tb",
                            show_label=False,
                            placeholder="Enter query and press ENTER",
                            container=False
                        )
                with gr.Tab(label="User Info", elem_id="user_info_tab", visible=False) as user_info_tab:
                    login_count_df = gr.Dataframe(
                        headers=["Username", "Full name", "Email", "Login Count"],
                        datatype=["str", "str", "str", "number"],
                        row_count=20,
                        col_count=(4, "fixed"),
                    )    
            with gr.Column(scale=3, elem_id="column_right") as column_right:
                with gr.Group(elem_id="model_group") as model_group:
                    model_names = [item["name"] for item in models]
                    state.value["models"] = models
                    model_selector = gr.Dropdown(
                        choices=model_names, 
                        container=True,
                        label="🗨️ Language Model",
                        show_label=True,
                        interactive=True,
                        value=model_names[0] if len(model_names) > 0 else ""
                    )
                    model_info_box = gr.Textbox(value=models[0]["desc"], lines=3, label=f"🆗 {models[0]['platform']}", interactive=False, elem_id="model_info")
                    imagebox = gr.Image(type="filepath", elem_id="image_box", visible=False)
                    def model_change(model_name, state):
                        """ Toggle image upload visibility """
                        is_visible = False
                        result = next((item for item in models if item["name"] == model_name), None)
                        if result["model"] in ["llava","bakllava"]:
                            is_visible = True
                        try:
                            state["model"] = None
                        except Exception as e:
                            pass # No action needed
                        gr.Info("Switching and loading model - first AI response will have a delay.")
                        usage_hint = ""
                        if result['platform'] in ["SAP Generative AI Hub", "Ollama on SAP AI Core"]:
                            usage_hint = "int"
                            usage_icon = "🆗"
                        elif result['platform'] in ["SAP BTP Proxy"]:
                            usage_hint = "pub"
                            usage_icon = "⛔"
                        else:
                            usage_hint = "int"
                            usage_icon = "⛔"
                        logo_update = "## Hello 2"
                        return gr.update(visible = is_visible), gr.update(maximum=result["maxToken"], value=int(result["maxToken"]*0.6)), gr.update(value=result["desc"], label=f"{usage_icon} {result['platform']}"), gr.update(autofocus=True), gr.update(value = logo_update), state
                with gr.Accordion("🔍 Document Talk (RAG)", open=False, elem_id="rag_accordion") as rag_accordion:
                    uplbtn_file = gr.UploadButton(label="Upload",  file_types=[".docx", ".pptx", ".pdf", ".txt"], file_count="multiple", elem_id="rag_btn_upload")
                    file_output = gr.File(elem_id="rag_file_view")
                    cbox_use_document = gr.Checkbox(label="Use document", visible=False, value=False, elem_id="cb_rag_active")
                    btn_remove = gr.Button(value="Remove", visible=False, elem_id="rag_btn_remove")
                    with gr.Accordion("🎚️ Embedding Options", open=False, elem_id="embedding_options") as embedding_accordion:
                        sldr_chunk_size = gr.Slider(minimum=100, maximum=1000, value=1000, step=100, label="Chunk Size")
                        sldr_chunk_overlap = gr.Slider(minimum=0, maximum=500, value=100, step=100, label="Overlap")
                        cbox_use_ocr = gr.Checkbox(label="⚠️ Use Image OCR", visible=True, value=False, elem_id="cb_image_ocr")
                        sldr_k_top = gr.Slider(minimum=1, maximum=20, value=8, step=1, label="k-top from Vector Store")
                with gr.Accordion("🎚️ Model parameters", open=False, elem_id="parameter_accordion") as parameter_accordion:
                    system_role = gr.Dropdown(           
                        allow_custom_value=True,             
                        choices=sys_roles,
                        container=False,
                        label="Select or enter a system role",
                        interactive=True,
                        value=sys_roles[0] if len(sys_roles) > 0 else "",
                    )
                    image_process_mode = gr.Radio(
                        ["Crop", "Resize", "Pad", "Default"],
                        value="Resize",
                        label="Preprocess for non-square image", visible=True)
                    temp_slider = gr.Slider(minimum=0.0, maximum=1.0, value=0.1, step=0.1, interactive=True, label="Temperature",)
                    top_p = gr.Slider(minimum=0.0, maximum=1.0, value=0.7, step=0.1, interactive=True, label="Top P",)
                    max_output_tokens = gr.Slider(minimum=0, maximum=models[0]["maxToken"], value=int(models[0]["maxToken"]*0.6), step=64, interactive=True, label="Max output tokens",)
                clear = gr.Button(value="Clear history")
                logo_box = gr.Markdown(value="### Hello",elem_id="logo_box")
        # Event handling playground tab
        genai_tab.select(
            genai_tab_selected,
            inputs=[state],
            outputs=[rag_accordion, parameter_accordion]
        )
        # Event handling SQL tab
        sql_gen_tab.select(
            sql_tab_selected,
            inputs=[state],
            outputs=[rag_accordion, parameter_accordion]
        )
        # Event handling user tab
        user_info_tab.select(
            user_tab_selected,
            inputs=[state],
            outputs=[login_count_df, rag_accordion, parameter_accordion]
        )        

        # Slider change
        temp_slider.change(slider_temp_change, [state, temp_slider])

        # Event handling: Loading page
        chat_view.load(set_user_data, [state], [genai_tab, user_info_tab])
    return chat_view

def main()->None:

    chat_view = build_chat_view(models=TEST_MODELS, sys_roles=["123","123","125"])
    # chat_view.queue()
    chat_view.launch(
        debug=True,
        show_api=False,
    )

if __name__ == "__main__":
    main()

Screenshot

No response

Logs

No error in browser or on CLI raised with debug logging.

System Info

Gradio Environment Information:
------------------------------
Operating System: Linux
gradio version: 4.17.0
gradio_client version: 0.9.0

------------------------------------------------
gradio dependencies in your environment:

aiofiles: 23.2.1
altair: 5.2.0
fastapi: 0.105.0
ffmpy: 0.3.1
gradio-client==0.9.0 is not installed.
httpx: 0.26.0
huggingface-hub: 0.19.4
importlib-resources: 6.1.1
jinja2: 3.1.2
markupsafe: 2.1.3
matplotlib: 3.8.2
numpy: 1.26.2
orjson: 3.9.10
packaging: 23.2
pandas: 2.1.1
pillow: 10.0.1
pydantic: 2.5.3
pydub: 0.25.1
python-multipart: 0.0.6
pyyaml: 6.0.1
ruff: 0.1.14
semantic-version: 2.10.0
tomlkit==0.12.0 is not installed.
typer: 0.9.0
typing-extensions: 4.9.0
uvicorn: 0.25.0
authlib; extra == 'oauth' is not installed.
itsdangerous; extra == 'oauth' is not installed.

gradio_client dependencies in your environment:

fsspec: 2023.10.0
httpx: 0.26.0
huggingface-hub: 0.19.4
packaging: 23.2
typing-extensions: 4.9.0
websockets: 11.0.3

Severity

I can work around it

JackismyShephard commented 5 months ago

I still have this problem in gradio version 4.24.0. The bug seems to have been reintroduced in gradio version 4.22.0