Spaces:
Sleeping
Sleeping
| from __future__ import annotations | |
| from typing import Any | |
| import gradio as gr | |
| from src.ui.callbacks import AppCallbacks, current_categories | |
| from src.ui.constants import ( | |
| ALL_CATEGORIES_LABEL, | |
| APP_NAME, | |
| APP_SUBTITLE, | |
| DEFAULT_MIN_SIMILARITY, | |
| DEFAULT_TOP_K, | |
| EXAMPLE_QUERIES, | |
| IMAGE_QUERY_EMPTY_PREVIEW, | |
| MAX_TOP_K, | |
| NO_FAVORITES_STATUS, | |
| TEXT_QUERY_EMPTY_PREVIEW, | |
| gradio_launch_options, | |
| ) | |
| from src.ui.formatters import initial_overview | |
| def create_demo(callbacks: AppCallbacks) -> tuple[gr.Blocks, dict[str, Any]]: | |
| blocks_kwargs, launch_kwargs = gradio_launch_options() | |
| with gr.Blocks(**blocks_kwargs) as demo: | |
| current_results_state = gr.State([]) | |
| selected_result_state = gr.State(None) | |
| favorites_state = gr.State([]) | |
| query_mode_state = gr.State("text") | |
| with gr.Column(elem_id="app-shell"): | |
| gr.Markdown( | |
| f"# {APP_NAME}\n\n{APP_SUBTITLE}", | |
| elem_id="hero-section", | |
| ) | |
| with gr.Row(elem_id="main-dashboard", equal_height=False): | |
| with gr.Column(scale=1, min_width=300, elem_id="left-sidebar"): | |
| with gr.Column(elem_id="search-card", elem_classes=["search-card"]): | |
| with gr.Tabs(elem_id="query-tabs"): | |
| with gr.Tab("Text Search") as text_tab: | |
| text_query = gr.Textbox( | |
| label="Image Description", | |
| placeholder="For example: red apple, milk bottle, green vegetables", | |
| lines=2, | |
| elem_id="text-query", | |
| ) | |
| gr.Examples( | |
| examples=EXAMPLE_QUERIES, | |
| inputs=text_query, | |
| label="Example Queries", | |
| elem_id="example-chips", | |
| ) | |
| text_preview = gr.Markdown( | |
| TEXT_QUERY_EMPTY_PREVIEW, | |
| elem_id="text-preview", | |
| ) | |
| with gr.Tab("Image Search") as image_tab: | |
| image_query = gr.Image( | |
| label="Upload Query Image", | |
| type="pil", | |
| placeholder="Drag an image here, or click to upload", | |
| sources=["upload", "clipboard"], | |
| height=210, | |
| elem_id="image-query", | |
| ) | |
| image_preview = gr.Markdown( | |
| IMAGE_QUERY_EMPTY_PREVIEW, | |
| elem_id="image-preview", | |
| ) | |
| with gr.Column(elem_id="parameter-card", elem_classes=["parameter-card"]): | |
| gr.Markdown("### Search Parameters", elem_id="parameter-title") | |
| top_k = gr.Slider( | |
| minimum=1, | |
| maximum=MAX_TOP_K, | |
| value=DEFAULT_TOP_K, | |
| step=1, | |
| label="Number of Results", | |
| elem_id="top-k", | |
| ) | |
| category_filter = gr.Dropdown( | |
| choices=current_categories(), | |
| value=ALL_CATEGORIES_LABEL, | |
| label="Category Filter", | |
| allow_custom_value=False, | |
| elem_id="category-filter", | |
| ) | |
| min_similarity = gr.Slider( | |
| minimum=0, | |
| maximum=1, | |
| value=DEFAULT_MIN_SIMILARITY, | |
| step=0.01, | |
| label="Minimum Similarity", | |
| elem_id="min-similarity", | |
| ) | |
| with gr.Row(elem_id="action-row"): | |
| search_button = gr.Button( | |
| "Search", | |
| variant="primary", | |
| elem_id="search-button", | |
| elem_classes=["primary-button"], | |
| ) | |
| clear_button = gr.Button( | |
| "Clear Query", | |
| elem_id="clear-button", | |
| elem_classes=["secondary-button"], | |
| ) | |
| with gr.Column(scale=3, min_width=360, elem_id="right-workspace"): | |
| with gr.Column(elem_id="result-card", elem_classes=["result-card"]): | |
| result_overview = gr.Markdown( | |
| initial_overview(), | |
| elem_id="result-overview", | |
| ) | |
| result_gallery = gr.Gallery( | |
| label="Search Results", | |
| columns=4, | |
| height=390, | |
| object_fit="cover", | |
| show_label=True, | |
| elem_id="result-gallery", | |
| elem_classes=["result-gallery"], | |
| ) | |
| with gr.Column(elem_id="favorite-card", elem_classes=["favorite-card"]): | |
| with gr.Row(elem_id="favorite-header"): | |
| gr.Markdown("### My Favorites", elem_id="favorite-title") | |
| favorite_status = gr.Markdown(NO_FAVORITES_STATUS, elem_id="favorite-status") | |
| with gr.Row(elem_id="favorite-actions"): | |
| add_favorite_button = gr.Button( | |
| "Add to Favorites", | |
| elem_id="add-favorite-button", | |
| elem_classes=["secondary-button"], | |
| ) | |
| export_button = gr.DownloadButton( | |
| label="Export Favorites as ZIP", | |
| value=None, | |
| elem_id="export-button", | |
| elem_classes=["primary-button"], | |
| ) | |
| favorite_gallery = gr.Gallery( | |
| label="My Favorites", | |
| columns=5, | |
| height=180, | |
| object_fit="cover", | |
| show_label=True, | |
| elem_id="favorite-gallery", | |
| elem_classes=["favorite-gallery"], | |
| ) | |
| text_tab.select(callbacks.select_text_mode, outputs=query_mode_state) | |
| image_tab.select(callbacks.select_image_mode, outputs=query_mode_state) | |
| text_query.change(callbacks.preview_text_query, inputs=text_query, outputs=text_preview) | |
| image_query.change(callbacks.preview_image_query, inputs=image_query, outputs=image_preview) | |
| search_button.click( | |
| callbacks.run_search, | |
| inputs=[query_mode_state, text_query, image_query, top_k, category_filter, min_similarity], | |
| outputs=[result_overview, result_gallery, selected_result_state, current_results_state], | |
| ) | |
| clear_button.click( | |
| callbacks.clear_search, | |
| inputs=[top_k, category_filter, min_similarity], | |
| outputs=[ | |
| text_query, | |
| image_query, | |
| text_preview, | |
| image_preview, | |
| result_overview, | |
| result_gallery, | |
| selected_result_state, | |
| current_results_state, | |
| ], | |
| ) | |
| result_gallery.select( | |
| callbacks.select_result_from_gallery, | |
| inputs=current_results_state, | |
| outputs=selected_result_state, | |
| show_progress="hidden", | |
| ) | |
| add_favorite_button.click( | |
| callbacks.add_selected_to_favorites, | |
| inputs=[selected_result_state, current_results_state, favorites_state], | |
| outputs=[favorites_state, favorite_gallery, favorite_status, export_button], | |
| ) | |
| return demo, launch_kwargs | |