Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import sqlite3 | |
| import pandas as pd | |
| from huggingface_hub import hf_hub_download | |
| import os | |
| # Download the database from HF dataset | |
| def download_database(): | |
| """Download vla_foundry.db from the HF dataset""" | |
| try: | |
| db_path = hf_hub_download( | |
| repo_id="TRI-ML/vla_foundry_db", | |
| filename="vla_foundry.db", | |
| repo_type="dataset" | |
| ) | |
| return db_path | |
| except Exception as e: | |
| print(f"Error downloading database: {e}") | |
| return None | |
| # Load data from database | |
| def load_database_tables(db_path): | |
| """Load all tables from the database""" | |
| if not db_path or not os.path.exists(db_path): | |
| return {}, [] | |
| conn = sqlite3.connect(db_path) | |
| cursor = conn.cursor() | |
| # Get all table names | |
| cursor.execute("SELECT name FROM sqlite_master WHERE type='table';") | |
| tables = [row[0] for row in cursor.fetchall()] | |
| # Load each table into a DataFrame | |
| table_data = {} | |
| for table in tables: | |
| try: | |
| df = pd.read_sql_query(f"SELECT * FROM {table}", conn) | |
| table_data[table] = df | |
| except Exception as e: | |
| print(f"Error loading table {table}: {e}") | |
| conn.close() | |
| return table_data, tables | |
| # Initialize database | |
| db_path = download_database() | |
| table_data, table_names = load_database_tables(db_path) | |
| # Column width configuration (in pixels) | |
| # Specify widths for specific columns across all tables | |
| # Format: {"column_name": width_in_px} | |
| column_widths = { | |
| "created_by": 150, | |
| "cfg": 500, | |
| "git_commit_hash": 150, | |
| "git_branch": 150, | |
| "git_remote_url": 150, | |
| "git_has_local_changes": 150, | |
| "git_local_chances": 150, | |
| "dataset_source_paths": 500, | |
| "model_checkpoints_path": 500, | |
| "fixed_model_path": 500, | |
| "completed": 150, | |
| } | |
| # Function to get table data with filters | |
| def get_filtered_data(table_name, search_query="", column_filter="All", sort_column="", sort_order="Ascending"): | |
| """Get filtered and sorted data from selected table""" | |
| if table_name not in table_data: | |
| return pd.DataFrame() | |
| df = table_data[table_name].copy() | |
| # Apply search filter | |
| if search_query.strip(): | |
| # Search across all columns | |
| mask = df.astype(str).apply(lambda x: x.str.contains(search_query, case=False, na=False)).any(axis=1) | |
| df = df[mask] | |
| # Apply column-specific filter | |
| if column_filter != "All" and column_filter in df.columns: | |
| # Show only rows where the selected column has non-null values | |
| df = df[df[column_filter].notna()] | |
| # Apply sorting | |
| if sort_column and sort_column in df.columns: | |
| ascending = (sort_order == "Ascending") | |
| df = df.sort_values(by=sort_column, ascending=ascending) | |
| return df | |
| def update_column_choices(table_name): | |
| """Update column choices based on selected table""" | |
| if table_name not in table_data: | |
| return gr.update(choices=["All"]), gr.update(choices=[]) | |
| columns = ["All"] + list(table_data[table_name].columns) | |
| return gr.update(choices=columns, value="All"), gr.update(choices=list(table_data[table_name].columns), value="") | |
| def get_table_info(table_name): | |
| """Get information about the selected table""" | |
| if table_name not in table_data: | |
| return "No table selected" | |
| df = table_data[table_name] | |
| info = f"**Table: {table_name}**\n\n" | |
| info += f"- Total rows: {len(df)}\n" | |
| info += f"- Total columns: {len(df.columns)}\n" | |
| info += f"- Columns: {', '.join(df.columns)}\n" | |
| return info | |
| # Create Gradio interface with CSS | |
| css = """ | |
| /* Default table cell styling */ | |
| table td, | |
| table th { | |
| white-space: nowrap !important; | |
| overflow-x: auto !important; | |
| font-size: 12px !important; | |
| padding: 4px 8px !important; | |
| } | |
| /* Make table container scrollable */ | |
| .table-wrap { | |
| max-height: 600px !important; | |
| overflow-y: auto !important; | |
| overflow-x: visible !important; | |
| } | |
| /* Ensure table uses fixed layout */ | |
| table { | |
| table-layout: fixed !important; | |
| } | |
| /* Prevent editing - make cells read-only but allow selection */ | |
| table input, | |
| table textarea { | |
| background-color: transparent !important; | |
| border: none !important; | |
| cursor: text !important; | |
| user-select: text !important; | |
| } | |
| /* Make cells read-only by preventing editing on focus */ | |
| table input:focus, | |
| table textarea:focus { | |
| outline: none !important; | |
| } | |
| """ | |
| with gr.Blocks(title="VLA Foundry Database Viewer", css=css) as demo: | |
| gr.Markdown("# 🤖 VLA Foundry Database Viewer") | |
| gr.Markdown("Explore the VLA Foundry database with searchable, filterable, and sortable tables.") | |
| if not table_data: | |
| gr.Markdown("⚠️ **Error**: Could not load database. Please check if the database file exists in the dataset.") | |
| else: | |
| # Top section: Table selector and info | |
| with gr.Row(): | |
| with gr.Column(scale=2): | |
| table_selector = gr.Dropdown( | |
| choices=table_names, | |
| label="Select Table", | |
| value=table_names[0] if table_names else None | |
| ) | |
| with gr.Column(scale=3): | |
| table_info = gr.Markdown( | |
| value=get_table_info(table_names[0]) if table_names else "" | |
| ) | |
| # Filters and sorting section | |
| with gr.Row(): | |
| search_box = gr.Textbox( | |
| label="Search (across all columns)", | |
| placeholder="Enter search term...", | |
| value="", | |
| scale=2 | |
| ) | |
| column_filter = gr.Dropdown( | |
| choices=["All"], | |
| label="Filter by Column (show non-null)", | |
| value="All", | |
| scale=1 | |
| ) | |
| sort_column = gr.Dropdown( | |
| choices=[], | |
| label="Sort by Column", | |
| value="", | |
| scale=1 | |
| ) | |
| sort_order = gr.Radio( | |
| choices=["Ascending", "Descending"], | |
| label="Sort Order", | |
| value="Ascending", | |
| scale=1 | |
| ) | |
| clear_btn = gr.Button("Clear Filters", scale=1) | |
| # Data table with custom column widths | |
| initial_df = table_data[table_names[0]] if table_names else pd.DataFrame() | |
| # Build column_widths list based on the column_widths config | |
| col_width_list = [] | |
| if not initial_df.empty: | |
| for col in initial_df.columns: | |
| col_width_list.append(column_widths.get(col, 300)) | |
| data_table = gr.Dataframe( | |
| value=initial_df, | |
| label="Table Data", | |
| interactive=True, | |
| wrap=False, | |
| column_widths=col_width_list if col_width_list else None | |
| ) | |
| # Event handlers | |
| def update_table(table_name, search, col_filter, sort_col, sort_ord): | |
| filtered_df = get_filtered_data(table_name, search, col_filter, sort_col, sort_ord) | |
| info = get_table_info(table_name) | |
| # Build column widths for the current table | |
| col_width_list = [] | |
| if not filtered_df.empty: | |
| for col in filtered_df.columns: | |
| col_width_list.append(column_widths.get(col, 300)) | |
| return gr.update(value=filtered_df, column_widths=col_width_list if col_width_list else None), info | |
| # Update columns when table changes | |
| def on_table_change(table_name): | |
| # Reset filters and update column choices | |
| col_filter_update, sort_col_update = update_column_choices(table_name) | |
| # Get the updated table with reset filters | |
| filtered_df = get_filtered_data(table_name, "", "All", "", "Ascending") | |
| info = get_table_info(table_name) | |
| # Build column widths for the new table | |
| col_width_list = [] | |
| if not filtered_df.empty: | |
| for col in filtered_df.columns: | |
| col_width_list.append(column_widths.get(col, 300)) | |
| table_update = gr.update(value=filtered_df, column_widths=col_width_list if col_width_list else None) | |
| return col_filter_update, sort_col_update, table_update, info, "", "Ascending" | |
| table_selector.change( | |
| fn=on_table_change, | |
| inputs=[table_selector], | |
| outputs=[column_filter, sort_column, data_table, table_info, search_box, sort_order] | |
| ) | |
| # Update table when filters/sorting change | |
| for component in [search_box, column_filter, sort_column, sort_order]: | |
| component.change( | |
| fn=update_table, | |
| inputs=[table_selector, search_box, column_filter, sort_column, sort_order], | |
| outputs=[data_table, table_info] | |
| ) | |
| # Clear filters | |
| def clear_filters(): | |
| return "", "All", "", "Ascending" | |
| clear_btn.click( | |
| fn=clear_filters, | |
| outputs=[search_box, column_filter, sort_column, sort_order] | |
| ).then( | |
| fn=update_table, | |
| inputs=[table_selector, search_box, column_filter, sort_column, sort_order], | |
| outputs=[data_table, table_info] | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch() | |