Spaces:
Running on Zero
Running on Zero
| import gradio as gr | |
| from functools import partial | |
| NUM_LORAS = 5 | |
| LORA_LIST = [ | |
| {"image": "https://picsum.photos/seed/1/400/300", "title": "Cinematic Style"}, | |
| {"image": "https://picsum.photos/seed/2/400/300", "title": "Anime Style"}, | |
| {"image": "https://picsum.photos/seed/3/400/300", "title": "Portrait LoRA"}, | |
| {"image": "https://picsum.photos/seed/4/400/300", "title": "Landscape LoRA"}, | |
| {"image": "https://picsum.photos/seed/5/400/300", "title": "Sci-Fi Style"} | |
| ] | |
| def update_slider_state(val, state, idx): | |
| # state is list of tuples (image_index, scale) | |
| new_state = list(state) | |
| current_image = new_state[idx][0] | |
| new_state[idx] = (current_image, val) | |
| return new_state, f"State Updated: {new_state}" | |
| def remove_lora(state, idx): | |
| new_state = list(state) | |
| new_state[idx] = (None, 1.0) # Reset to default | |
| # Return updates for: global_state, radio, slider, markdown, delete_btn, output_text | |
| return ( | |
| new_state, # selected_loras | |
| gr.update(value=None), # radio | |
| gr.update(visible=False, value=1.0), # slider | |
| gr.update(value=""), # markdown | |
| gr.update(visible=False), # delete_btn | |
| f"State Updated: {new_state}" # output | |
| ) | |
| def get_selection(evt: gr.SelectData, *args): | |
| # args: radios (N) + scales (N) + mds (N) + selected_loras (1) + gallery (1) | |
| num_radios = NUM_LORAS | |
| radio_vals = args[:num_radios] | |
| scale_vals = args[num_radios:num_radios*2] | |
| md_vals = args[num_radios*2:num_radios*3] | |
| current_state = args[-2] | |
| gallery_val = args[-1] | |
| selected_val = next((val for val in radio_vals if val is not None), None) | |
| # Identify index of selected radio | |
| selected_index = -1 | |
| for i, val in enumerate(radio_vals): | |
| if val is not None: | |
| selected_index = i | |
| break | |
| # Prepare outputs: [output_text] + [md_0_update, ...] + [selected_loras_update] + [scale_0_update, ...] + [del_btn_0_update, ...] + [thumb_0_update, ...] | |
| md_updates = [gr.update() for _ in range(num_radios)] | |
| scale_updates = [gr.update() for _ in range(num_radios)] | |
| del_btn_updates = [gr.update() for _ in range(num_radios)] | |
| new_state = current_state | |
| selected_image_info = "" | |
| if selected_index != -1: | |
| # Get LoRA details | |
| lora = LORA_LIST[evt.index] | |
| lora_name = lora["title"] | |
| lora_image = lora["image"] | |
| # Update specific markdown with image and name | |
| selected_image_info = f"Selected LoRA: {lora_name}" | |
| markdown_content = f"<img src='{lora_image}' style='height:100px; display:block; margin-bottom:10px;' />\n\n**{lora_name}**" | |
| md_updates[selected_index] = gr.update(value=markdown_content) | |
| scale_updates[selected_index] = gr.update(visible=True) | |
| del_btn_updates[selected_index] = gr.update(visible=True) | |
| # Update state for this column: (image_index, scale) | |
| new_state = list(current_state) | |
| new_state[selected_index] = (evt.index, scale_vals[selected_index]) | |
| return [f"Selected Radio: {selected_val}. {selected_image_info}. State: {new_state}"] + md_updates + [new_state] + scale_updates + del_btn_updates | |
| def greet(*args): | |
| # args will contain: radio_0_val, radio_1_val, ..., radio_N-1_val, name, intensity | |
| radio_vals = args[:NUM_LORAS] | |
| name = args[-2] | |
| intensity = args[-1] | |
| selected = next((val for val in radio_vals if val is not None), None) | |
| return "Hola, qué tal " + name + "!" * int(intensity) + f". Selected: {selected}" | |
| css = """ | |
| .disabled { | |
| pointer-events: none; | |
| opacity: 0.5; | |
| } | |
| """ | |
| with gr.Blocks(css=css) as demo: | |
| selected_loras = gr.State([(None, 1.0)] * NUM_LORAS) | |
| radios = [] | |
| scales = [] | |
| mds = [] | |
| delete_btns = [] | |
| with gr.Row(): | |
| for i in range(NUM_LORAS): | |
| with gr.Column(): | |
| # Each radio has a single choice which is its column number | |
| r = gr.Radio([str(i + 1)], label=f"Option {i + 1}") | |
| radios.append(r) | |
| md = gr.Markdown("") | |
| mds.append(md) | |
| lora_scale = gr.Slider(label="LoRA Scale", minimum=0, maximum=3, step=0.1, value=1.0, interactive=True, visible=False) | |
| scales.append(lora_scale) | |
| del_btn = gr.Button("🗑️", visible=False) | |
| delete_btns.append(del_btn) | |
| name = gr.Textbox(label="Name") | |
| intensity = gr.Slider(label="Intensity", minimum=1, maximum=10, step=1) | |
| output = gr.Textbox(label="Output") | |
| gallery = gr.Gallery( | |
| label="Generated Images", | |
| value=[(item["image"], item["title"]) for item in LORA_LIST], | |
| columns=5, | |
| height="auto", | |
| interactive=False, | |
| allow_preview=False, | |
| elem_classes=["disabled"], | |
| elem_id="gallery" | |
| ) | |
| btn = gr.Button("Submit") | |
| btn.click(fn=greet, inputs=radios + [name, intensity], outputs=output) | |
| for i, r in enumerate(radios): | |
| others = radios[:i] + radios[i+1:] | |
| # JS: if val is selected (true), return nulls for all others. | |
| # Otherwise return current values (no change). | |
| js_code = f"(val, ...args) => val ? args.map(_ => null) : args" | |
| r.change(fn=None, inputs=[r] + others, outputs=others, js=js_code) | |
| # JS toggle for gallery class | |
| js_gallery_toggle = "(...args) => { const gallery = document.getElementById('gallery'); const anySelected = args.some(v => v !== null && v !== ''); if (gallery) { if (anySelected) gallery.classList.remove('disabled'); else gallery.classList.add('disabled'); } }" | |
| r.change(fn=None, inputs=radios, outputs=None, js=js_gallery_toggle) | |
| # Bind slider changes separately to ensure all inputs/outputs are available | |
| for i, scale in enumerate(scales): | |
| scale.change(fn=partial(update_slider_state, idx=i), inputs=[scale, selected_loras], outputs=[selected_loras, output]) | |
| # Bind delete buttons | |
| for i, del_btn in enumerate(delete_btns): | |
| del_btn.click( | |
| fn=partial(remove_lora, idx=i), | |
| inputs=[selected_loras], | |
| outputs=[selected_loras, radios[i], scales[i], mds[i], del_btn, output] | |
| ) | |
| gallery.select(fn=get_selection, inputs=radios + scales + mds + [selected_loras, gallery], outputs=[output] + mds + [selected_loras] + scales + delete_btns) | |
| demo.launch() |