diff --git a/frontend/llama_stack_ui/distribution/ui/page/distribution/models.py b/frontend/llama_stack_ui/distribution/ui/page/distribution/models.py index 2fbb5df..f4427ee 100644 --- a/frontend/llama_stack_ui/distribution/ui/page/distribution/models.py +++ b/frontend/llama_stack_ui/distribution/ui/page/distribution/models.py @@ -14,13 +14,14 @@ def models(): Inspect available models and display details for a selected one. """ st.header("Models") - # Fetch all models - model_list = llama_stack_api.client.models.list() - if not model_list: - st.info("No models available.") - return - models_info = {m.id: m.to_dict() for m in llama_stack_api.client.models.list()} - - # Let user select and view a model - selected_model = st.selectbox("Select a model", list(models_info.keys())) - st.json(models_info[selected_model], expanded=True) + try: + with st.spinner("Loading models..."): + model_list = llama_stack_api.client.models.list() + if not model_list: + st.info("No models available.") + return + models_info = {m.id: m.to_dict() for m in model_list} + selected_model = st.selectbox("Select a model", list(models_info.keys())) + st.json(models_info[selected_model], expanded=True) + except Exception as e: + st.error(f"Failed to load models: {e}") diff --git a/frontend/llama_stack_ui/distribution/ui/page/distribution/providers.py b/frontend/llama_stack_ui/distribution/ui/page/distribution/providers.py index 749ad81..64f661e 100644 --- a/frontend/llama_stack_ui/distribution/ui/page/distribution/providers.py +++ b/frontend/llama_stack_ui/distribution/ui/page/distribution/providers.py @@ -14,18 +14,19 @@ def providers(): Inspect available API providers by API type and display details. """ st.header("API Providers") - # Retrieve all providers - providers_list = llama_stack_api.client.providers.list() - if not providers_list: - st.info("No API providers registered.") - return + try: + with st.spinner("Loading providers..."): + providers_list = llama_stack_api.client.providers.list() + if not providers_list: + st.info("No API providers registered.") + return - # Group providers by API name - api_to_providers: dict[str, list] = {} - for p in providers_list: - api_to_providers.setdefault(p.api, []).append(p) + api_to_providers: dict[str, list] = {} + for p in providers_list: + api_to_providers.setdefault(p.api, []).append(p) - # Display each group with its providers - for api_name, providers in api_to_providers.items(): - st.markdown(f"###### {api_name}") - st.dataframe([p.to_dict() for p in providers], width=500) + for api_name, api_providers in api_to_providers.items(): + st.markdown(f"###### {api_name}") + st.dataframe([p.to_dict() for p in api_providers], use_container_width=True) + except Exception as e: + st.error(f"Failed to load providers: {e}") diff --git a/frontend/llama_stack_ui/distribution/ui/page/distribution/shields.py b/frontend/llama_stack_ui/distribution/ui/page/distribution/shields.py index 23d4361..0fce86d 100644 --- a/frontend/llama_stack_ui/distribution/ui/page/distribution/shields.py +++ b/frontend/llama_stack_ui/distribution/ui/page/distribution/shields.py @@ -14,13 +14,14 @@ def shields(): Inspect available shields and display details for a selected one. """ st.header("Shields") - # Retrieve all shields - shields_list = llama_stack_api.client.shields.list() - if not shields_list: - st.info("No shields available.") - return - shields_info = {s.identifier: s.to_dict() for s in shields_list} - - # Let user select and view shield details - selected_shield = st.selectbox("Select a shield", list(shields_info.keys())) - st.json(shields_info[selected_shield]) + try: + with st.spinner("Loading shields..."): + shields_list = llama_stack_api.client.shields.list() + if not shields_list: + st.info("No shields available.") + return + shields_info = {s.identifier: s.to_dict() for s in shields_list} + selected_shield = st.selectbox("Select a shield", list(shields_info.keys())) + st.json(shields_info[selected_shield]) + except Exception as e: + st.error(f"Failed to load shields: {e}") diff --git a/frontend/llama_stack_ui/distribution/ui/page/distribution/vector_dbs.py b/frontend/llama_stack_ui/distribution/ui/page/distribution/vector_dbs.py index 0ccb9a9..e2d4d87 100644 --- a/frontend/llama_stack_ui/distribution/ui/page/distribution/vector_dbs.py +++ b/frontend/llama_stack_ui/distribution/ui/page/distribution/vector_dbs.py @@ -15,12 +15,14 @@ def vector_dbs(): Inspect available vector databases and display details for the selected one. """ st.header("Vector Databases") - # Fetch all vector databases - vdb_list = llama_stack_api.client.vector_stores.list() - if not vdb_list: - st.info("No vector databases found.") - return - # Build info dict and allow selection - vdb_info = {get_vector_db_name(v) : v.to_dict() for v in vdb_list} - selected_vector_db = st.selectbox("Select a vector database", list(vdb_info.keys())) - st.json(vdb_info[selected_vector_db], expanded=True) + try: + with st.spinner("Loading vector databases..."): + vdb_list = llama_stack_api.client.vector_stores.list() + if not vdb_list: + st.info("No vector databases found.") + return + vdb_info = {get_vector_db_name(v): v.to_dict() for v in vdb_list} + selected_vector_db = st.selectbox("Select a vector database", list(vdb_info.keys())) + st.json(vdb_info[selected_vector_db], expanded=True) + except Exception as e: + st.error(f"Failed to load vector databases: {e}") diff --git a/frontend/llama_stack_ui/distribution/ui/page/upload/upload.py b/frontend/llama_stack_ui/distribution/ui/page/upload/upload.py index 8553c26..b28b137 100644 --- a/frontend/llama_stack_ui/distribution/ui/page/upload/upload.py +++ b/frontend/llama_stack_ui/distribution/ui/page/upload/upload.py @@ -81,11 +81,11 @@ def _sync_vector_db_selection(dropdown_options, vdb_list): st.session_state["vector_db_selector"] = selected return - # Priority 3: Smart default + # Priority 3: Smart default — pick the first real DB, not "Create New" if vdb_list: - first_db = dropdown_options[0] - st.session_state["selected_vector_db"] = first_db - st.session_state["vector_db_selector"] = first_db + first_real_db = dropdown_options[1] + st.session_state["selected_vector_db"] = first_real_db + st.session_state["vector_db_selector"] = first_real_db else: st.session_state["selected_vector_db"] = dropdown_options[0] st.session_state["vector_db_selector"] = dropdown_options[0] @@ -364,7 +364,7 @@ def _get_documents_from_vector_store(vector_store_id): return list(files_response) if files_response else None except Exception as e: # pylint: disable=broad-exception-caught - print(f"Error listing files from vector store: {e}") + st.warning(f"Could not list files: {e}") return None @@ -416,49 +416,64 @@ def _get_file_sources(files): return source_names -def _render_documents_table(files, source_names): - """Render the documents table with source and document ID columns. +def _render_documents_table(files, source_names, vector_store_id): + """Render the documents table with source, document ID, and delete button. Args: files: List of vector store file objects source_names (dict): Mapping of file_id to source name + vector_store_id (str): The vector store identifier (for delete calls) """ - # Add CSS for bordered table rows st.markdown(""" """, unsafe_allow_html=True) - # Display table header - col1, col2, col3 = st.columns([0.5, 3, 3]) - with col1: - st.markdown("**#**") - with col2: - st.markdown("**Source**") - with col3: - st.markdown("**Document ID**") - - # Display each file in a row - for idx, file_obj in enumerate(files, start=1): - col1, col2, col3 = st.columns([0.5, 3, 3]) - file_id = getattr(file_obj, 'id', 'unknown') - source = source_names.get(file_id) or "unknown" + with st.container(): + st.markdown('
', unsafe_allow_html=True) + col1, col2, col3, col4 = st.columns([0.5, 3, 3, 1]) with col1: - st.write(idx) + st.markdown("**#**") with col2: - st.write(source) + st.markdown("**Source**") with col3: - st.write(file_id) + st.markdown("**Document ID**") + with col4: + st.markdown("**Actions**") + + for idx, file_obj in enumerate(files, start=1): + col1, col2, col3, col4 = st.columns([0.5, 3, 3, 1]) + file_id = getattr(file_obj, 'id', 'unknown') + source = source_names.get(file_id) or "unknown" + + with col1: + st.write(idx) + with col2: + st.write(source) + with col3: + st.write(file_id) + with col4: + if st.button("🗑️", key=f"delete_{file_id}", help=f"Delete {source}"): + success, error_msg = _delete_file_from_vector_store(vector_store_id, file_id) + if success: + st.session_state["delete_status"] = "success" + st.session_state["delete_message"] = f"Deleted '{source}' successfully." + else: + st.session_state["delete_status"] = "error" + st.session_state["delete_message"] = f"Failed to delete '{source}': {error_msg}" + st.rerun() + + st.markdown('
', unsafe_allow_html=True) def _show_existing_documents_table(vector_db_name, vector_db_obj=None): @@ -484,10 +499,12 @@ def _show_existing_documents_table(vector_db_name, vector_db_obj=None): with st.spinner("Checking for documents..."): files = _get_documents_from_vector_store(vector_db_id) + st.subheader(f"📄 Documents in '{vector_db_name}'") if files: - st.subheader(f"📄 Documents in '{vector_db_name}'") source_names = _get_file_sources(files) - _render_documents_table(files, source_names) + _render_documents_table(files, source_names, vector_db_id) + else: + st.info("No documents found in this vector database. Upload some below!") except Exception as e: # pylint: disable=broad-exception-caught st.error(f"Error loading document information: {str(e)}")