Udostępnij przez


Identyfikowanie i usuwanie pustych punktów końcowych wyszukiwania wektorów

Na tej stronie opisano sposób identyfikowania i usuwania pustych punktów końcowych wyszukiwania wektorów. Ponieważ punkty końcowe wyszukiwania wektorów są zasobami specyficznymi dla obszaru roboczego, należy powtórzyć ten proces osobno dla każdego obszaru roboczego.

Requirements

  • Zestaw SDK usługi Databricks dla języka Python (databricks-sdk).
  • Zestaw SDK języka Python wyszukiwania wektorowego usługi Databricks (databricks-vectorsearch).
  • Skonfigurowane uwierzytelnianie (OAuth, PAT lub profile konfiguracji).
  • CAN_MANAGE uprawnienie do punktów końcowych wyszukiwania wektorowego w docelowych obszarach roboczych.

Aby zainstalować wymagane zestawy SDK w notesie usługi Databricks lub lokalnym środowisku języka Python:

# In a Databricks notebook
%pip install databricks-sdk databricks-vectorsearch

# In local Python environment
# pip install databricks-sdk databricks-vectorsearch

Identyfikowanie pustych punktów końcowych

W interfejsie użytkownika usługi Databricks punkty końcowe wyszukiwania wektorów są wyświetlane na karcie Wyszukiwanie wektorowe na ekranie Obliczenia . Przełącz pole wyboru Puste punkty końcowe , aby wyświetlić punkty końcowe, które nie mają skojarzonych z nimi indeksów. Puste punkty końcowe są również oznaczone ikoną trójkąta ostrzegawczego, jak pokazano poniżej.

Ekran obliczeniowy przedstawiający punkt końcowy wyszukiwania wektorów bez indeksów.

Authentication

W tej sekcji opisano opcje uwierzytelniania.

Opcja 1. Uruchamianie wewnątrz notesu usługi Databricks

Po uruchomieniu kodu w notesie obszaru roboczego usługi Databricks uwierzytelnianie jest automatyczne:

from databricks.vector_search.client import VectorSearchClient

# Credentials are picked up automatically from notebook context
client = VectorSearchClient()

Opcja 2. Osobisty token dostępu (PAT)

W przypadku środowisk zewnętrznych podaj jawne poświadczenia:

from databricks.vector_search.client import VectorSearchClient

client = VectorSearchClient(
    workspace_url="https://<your-instance>.cloud.databricks.com",
    personal_access_token="dapiXXXXXXXXXXXXXXXXXXXXXXXX"
)

.databrickscfg Utwórz plik w katalogu głównym i dołącz profil dla każdego obszaru roboczego:

[DEFAULT]
host = https://workspace1.cloud.databricks.com
token = dapiXXXXXXXXXXXXXXXXXXXXXXXX

[PRODUCTION]
host = https://workspace2.cloud.databricks.com
token = dapiYYYYYYYYYYYYYYYYYYYYYYYY

[DEVELOPMENT]
host = https://workspace3.cloud.databricks.com
token = dapiZZZZZZZZZZZZZZZZZZZZZZZZ

Jeśli nie chcesz używać profilów konfiguracji, możesz określić poświadczenia bezpośrednio:

# Define workspaces with explicit credentials
workspace_configs = [
    {
        'workspace_url': 'https://workspace1.cloud.databricks.com',
        'token': 'dapiXXXXXXXXXXXXXXXXXXXXXXXX'
    },
    {
        'workspace_url': 'https://workspace2.cloud.databricks.com',
        'token': 'dapiYYYYYYYYYYYYYYYYYYYYYYYY'
    }
]

# Run cleanup, set `dry_run=False` to perform actual deletion
results = cleanup_multiple_workspaces(workspace_configs, dry_run=True)

Usuwanie punktów końcowych w jednym obszarze roboczym

Punkty końcowe wyszukiwania wektorowego są specyficzne dla obszaru roboczego. Oto podstawowy skrypt służący do znajdowania i usuwania pustych punktów końcowych w jednym obszarze roboczym. Aby wyczyścić puste punkty końcowe w wielu obszarach roboczych, zobacz Usuwanie punktów końcowych w wielu obszarach roboczych.

Ważne

Usunięcie punktu końcowego jest nieodwracalne. Użyj opcji dry_run=True , aby wyświetlić listę punktów końcowych, które zostaną usunięte. Po potwierdzeniu, że lista jest poprawna, uruchom skrypt za pomocą polecenia dry_run=False.

from databricks.vector_search.client import VectorSearchClient

def cleanup_empty_endpoints(client, dry_run=True):
    """
    Find and delete empty Vector Search endpoints.

    Args:
        client: VectorSearchClient instance
        dry_run: If True, only print what would be deleted without actually deleting

    Returns:
        List of deleted endpoint names
    """
    deleted_endpoints = []

    # List all Vector Search endpoints
    endpoints = client.list_endpoints()

    for endpoint in endpoints["endpoints"]:
        # List indexes in this endpoint
        indexes = list(client.list_indexes(name=endpoint["name"])['vector_indexes'])

        if len(indexes) == 0:
            if dry_run:
                print(f"[DRY RUN] Would delete empty endpoint: '{endpoint["name"]}'")
            else:
                print(f"Deleting empty endpoint: '{endpoint["name"]}'")
                try:
                    client.delete_endpoint(endpoint["name"])
                    deleted_endpoints.append(endpoint["name"])
                    print(f"✓ Successfully deleted: {endpoint["name"]}")
                except Exception as e:
                    print(f"✗ Failed to delete {endpoint["name"]}: {str(e)}")
        else:
            print(f"Endpoint '{endpoint["name"]}' has {len(indexes)} indexes - keeping")

    return deleted_endpoints

# Example usage
client = VectorSearchClient()  # Uses default authentication
# Set `dry_run=False` when you are ready to delete endpoints
deleted = cleanup_empty_endpoints(client, dry_run=True)
print(f"\nTotal endpoints deleted: {len(deleted)}")

Usuwanie punktów końcowych w wielu obszarach roboczych

Aby wyczyścić puste punkty końcowe w wielu obszarach roboczych, wykonaj iterację za pośrednictwem profilów konfiguracji:

Ważne

  • Usunięcie punktu końcowego jest nieodwracalne. Użyj opcji dry_run=True , aby wyświetlić listę punktów końcowych, które zostaną usunięte. Po potwierdzeniu, że lista jest poprawna, uruchom skrypt za pomocą polecenia dry_run=False.

  • Podczas przetwarzania wielu obszarów roboczych należy pamiętać o limitach szybkości interfejsu API. W razie potrzeby dodaj opóźnienia:

    import time
    
    for config in workspace_configs:
        # Set `dry_run=False` to perform actual deletion
        result = cleanup_workspace(**config, dry_run=True)
        time.sleep(2)  # Add delay between workspaces
    
from databricks.sdk import WorkspaceClient
from databricks.vector_search.client import VectorSearchClient
import logging

# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

def cleanup_workspace(profile_name=None, workspace_url=None, token=None, dry_run=True):
    """
    Clean up empty endpoints in a specific workspace.

    Args:
        profile_name: Name of configuration profile to use
        workspace_url: Direct workspace URL (if not using profile)
        token: PAT token (if not using profile)
        dry_run: If True, only show what would be deleted

    Returns:
        Dict with cleanup results
    """
    try:
        # Initialize client based on authentication method
        if profile_name:
            # Use Databricks SDK to get credentials from profile
            w = WorkspaceClient(profile=profile_name)
            workspace_url = w.config.host
            client = VectorSearchClient(
                workspace_url=workspace_url,
                personal_access_token=w.config.token
            )
            logger.info(f"Connected to workspace using profile '{profile_name}': {workspace_url}")
        elif workspace_url and token:
            client = VectorSearchClient(
                workspace_url=workspace_url,
                personal_access_token=token
            )
            logger.info(f"Connected to workspace: {workspace_url}")
        else:
            # Use default authentication (notebook context)
            client = VectorSearchClient()
            logger.info("Connected using default authentication")

        # Perform cleanup
        deleted = cleanup_empty_endpoints(client, dry_run=dry_run)

        return {
            'workspace': workspace_url or 'default',
            'success': True,
            'deleted_count': len(deleted),
            'deleted_endpoints': deleted
        }

    except Exception as e:
        logger.error(f"Failed to process workspace: {str(e)}")
        return {
            'workspace': workspace_url or profile_name or 'default',
            'success': False,
            'error': str(e)
        }

def cleanup_multiple_workspaces(workspace_configs, dry_run=True):
    """
    Clean up empty endpoints across multiple workspaces.

    Args:
        workspace_configs: List of workspace configurations
        dry_run: If True, only show what would be deleted

    Returns:
        Summary of cleanup results
    """
    results = []

    for config in workspace_configs:
        logger.info(f"\n{'='*60}")
        result = cleanup_workspace(**config, dry_run=dry_run)
        results.append(result)
        logger.info(f"{'='*60}\n")

    # Print summary
    total_deleted = sum(r['deleted_count'] for r in results if r['success'])
    successful = sum(1 for r in results if r['success'])
    failed = sum(1 for r in results if not r['success'])

    logger.info("\n" + "="*60)
    logger.info("CLEANUP SUMMARY")
    logger.info("="*60)
    logger.info(f"Workspaces processed: {len(results)}")
    logger.info(f"Successful: {successful}")
    logger.info(f"Failed: {failed}")
    logger.info(f"Total endpoints deleted: {total_deleted}")

    if failed > 0:
        logger.warning("\nFailed workspaces:")
        for r in results:
            if not r['success']:
                logger.warning(f"  - {r['workspace']}: {r['error']}")

    return results

# Example: Clean up using configuration profiles
workspace_configs = [
    {'profile_name': 'DEFAULT'},
    {'profile_name': 'PRODUCTION'},
    {'profile_name': 'DEVELOPMENT'}
]

# Set `dry_run=False` to do actual deletion.
results = cleanup_multiple_workspaces(workspace_configs, dry_run=True)

Filtrowanie niestandardowe

Możesz dodać logikę niestandardową, aby wykluczyć niektóre punkty końcowe z usunięcia, jak pokazano poniżej:

def should_delete_endpoint(endpoint, indexes):
    """
    Custom logic to determine if an endpoint should be deleted.

    Args:
        endpoint: Endpoint object
        indexes: List of indexes in the endpoint

    Returns:
        Boolean indicating if endpoint should be deleted
    """
    # Don't delete if it has indexes
    if len(indexes) > 0:
        return False

    # Don't delete endpoints with specific naming patterns
    protected_patterns = ['prod-', 'critical-', 'do-not-delete']
    for pattern in protected_patterns:
        if pattern in endpoint.name.lower():
            logger.warning(f"Skipping protected endpoint: {endpoint.name}")
            return False

    # Add more custom logic as needed
    return True

Eksportowanie wyników

Aby zapisać wyniki oczyszczania w pliku na potrzeby inspekcji:

import json
from datetime import datetime

def export_results(results, filename=None):
    """Export cleanup results to JSON file."""
    if not filename:
        timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
        filename = f'vector_search_cleanup_{timestamp}.json'

    with open(filename, 'w') as f:
        json.dump({
            'timestamp': datetime.now().isoformat(),
            'results': results
        }, f, indent=2)

    logger.info(f"Results exported to: {filename}")

Rozwiązywanie problemów

Problemy z uwierzytelnianiem

  • Sprawdź, czy tokeny pat są prawidłowe i nie wygasły.
  • Upewnij się, że profile konfiguracji są poprawnie sformatowane.
  • Sprawdź, czy tokeny mają niezbędne uprawnienia.

Błędy uprawnień

Sprawdź, czy użytkownik lub jednostka usługi ma CAN_MANAGE uprawnienia do punktów końcowych wyszukiwania wektorów.

Problemy z siecią

W przypadku środowisk z wymaganiami dotyczącymi serwera proxy należy odpowiednio skonfigurować zestaw SDK:

import os
os.environ['HTTPS_PROXY'] = 'http://your-proxy:po

Dalsze kroki

  • Zaplanuj okresowe uruchamianie tego skryptu przy użyciu zadań lakeflow.
  • Integracja z potokiem infrastruktury jako kodu.
  • Dodaj powiadomienia e-mail lub Slack w celu oczyszczenia podsumowań.
  • Tworzenie pulpitu nawigacyjnego w celu śledzenia użycia punktów końcowych w obszarach roboczych.