Esegui il deployment di TimesFM nella sandbox GDC

Il modello TimesFM di Google Research è un modello di base per la previsione delle serie temporali preaddestrato su miliardi di punti temporali di molti set di dati del mondo reale, quindi puoi applicarlo a nuovi set di dati di previsione in molti domini.

Questa guida tutorial mostra come eseguire il deployment di TimesFM in GDC Sandbox e ha i seguenti obiettivi.

  • Crea un container Docker che esegue TimesFM,
  • Esegui il deployment del container utilizzando le GPU fornite dallo SKU ottimizzato per l'AI di GDC Sandbox e
  • Richiama le funzioni TimesFM utilizzando semplici richieste HTTP.

Prima di iniziare

Le GPU in GDC Sandbox sono incluse nel cluster org-infra.

  • Per eseguire comandi sul cluster di infrastruttura dell'organizzazione, assicurati di disporre del kubeconfig del cluster org-1-infra, come descritto in Utilizzare i cluster:

    • Configura ed esegui l'autenticazione con la riga di comando gdcloud e
    • genera il file kubeconfig per il cluster di infrastruttura dell'organizzazione e assegna il relativo percorso alla variabile di ambiente KUBECONFIG.
  • Assicurati che all'utente sia assegnato il ruolo sandbox-gpu-admin per il progetto sandbox-gpu-project. Per impostazione predefinita, il ruolo viene assegnato all'utente platform-admin. Puoi assegnare il ruolo ad altri utenti accedendo come platform-admin ed eseguendo questo comando:

    kubectl --kubeconfig ${KUBECONFIG} create rolebinding ${NAME} --role=sandbox-gpu-admin \
    --user=${USER} --namespace=sandbox-gpu-project
    
  • Assicurati di configurare il repository Artifact Registry come descritto nella sezione Utilizzo di Artifact Registry e accedi per poter eseguire il push e il pull delle immagini nel registro degli artefatti.

Esegui il deployment del modello TimesFM

Il deployment viene orchestrato tramite un insieme di file di configurazione Kubernetes (manifest YAML), ognuno dei quali definisce un componente o un servizio specifico.

  1. Crea uno script Python basato su Flask app.py con funzioni predict per eseguire la previsione delle serie temporali e timeseries per generare una visualizzazione basata sui dati di test.

      from flask import Flask, jsonify, request
      import numpy as np
      import pandas as pd
      from sklearn.preprocessing import StandardScaler
    
      # Initialize Flask application
      app = Flask(__name__)
    
      # Sample route to display a welcome message
      @app.route('/')
      def home():
          return "Welcome to TimesFM! Use the API to interact with the app."
    
      # Example route for predictions (TimesFM might do time-series forecasting or music recommendations)
      @app.route('/predict', methods=['POST'])
      def predict():
          data = request.get_json()
    
          # Ensure the data is in the right format
          if 'features' not in data:
              return jsonify({'error': 'No features provided'}), 400
    
          # For this example, assume 'features' is a list of numbers that need to be scaled
          features = data['features']
          features = np.array(features).reshape(1, -1)
    
          # Dummy model: Apply standard scaling (you would use an actual model here)
          scaler = StandardScaler()
          scaled_features = scaler.fit_transform(features)
    
          # You would normally load your model here (e.g., using pickle or joblib)
          # For simplicity, let's just return the scaled features as a placeholder for prediction
          result = scaled_features.tolist()
    
          return jsonify({'scaled_features': result})
    
      # Example of a route for data visualization or analysis
      @app.route('/timeseries', methods=['GET'])
      def timeseries_analysis():
          # Generate a dummy time series data (replace with actual data)
          time_series_data = pd.Series(np.random.randn(100), name="Random Data")
    
          # Example analysis: compute simple moving average
          moving_avg = time_series_data.rolling(window=10).mean()
    
          return jsonify({
              'time_series': time_series_data.tolist(),
              'moving_average': moving_avg.tolist()
          })
    
      # Run the app
      if __name__ == '__main__':
          app.run(debug=True, host='0.0.0.0', port=5000)
    
  2. Crea un Dockerfile con timesfm installato richiamando l'app.

     # Use a base image with Python installed
     FROM python:3.11-slim
     # Set the working directory inside the container
     WORKDIR /app
     # Copy the requirements.txt (if any) and install dependencies
     COPY requirements.txt .
     RUN pip install --no-cache-dir numpy pandas timesfm huggingface_hub jax pytest flask scikit-learn
    
     # Copy the rest of the code into the container
     COPY . .
    
     # Expose the necessary port (default 5000 or whatever your app uses)
     EXPOSE 5000
    
     # Define the entrypoint for the container
     CMD ["python", "app.py"] # Replace with the correct entry script for TimesFM
    
  3. Crea l'immagine Docker e caricala nel repository Artifact Registry.

    docker build -t timesfm .
    docker tag timesfm "REGISTRY_REPOSITORY_URL"/timesfm:latest
    docker push "REGISTRY_REPOSITORY_URL"/timesfm:latest
    

    Sostituisci quanto segue:

    • REGISTRY_REPOSITORY_URL: l'URL del repository.
  4. Crea un secret per salvare le credenziali Docker.

    
    export SECRET="DOCKER_REGISTRY_SECRET"
    export DOCKER_TEST_CONFIG=~/.docker/config.json 
    kubectl --kubeconfig ${KUBECONFIG} create secret docker-registry ${SECRET} --from-file=.dockerconfigjson=${DOCKER_TEST_CONFIG} -n sandbox-gpu-project
    

    Sostituisci quanto segue:

    • DOCKER_REGISTRY_SECRET nome del secret.
  5. Crea un file timesfm-deployment.yaml per il deployment di timesfm.

    Il deployment del server timesfm richiede una GPU.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: timesfm-deployment
      namespace: sandbox-gpu-project
      labels:
        app: timesfm
    spec:
      replicas: 1 # You can scale up depending on your needs
      selector:
        matchLabels:
          app: timesfm
      template:
        metadata:
          labels:
            app: timesfm
        spec:
          containers:
          - name: timesfm
            image: REGISTRY_REPOSITORY_URL/timesfm:latest
            ports:
            - containerPort: 5000
            resources:
              requests:
                nvidia.com/gpu-pod-NVIDIA_H100_80GB_HBM3: 1  # Request 1 GPU
              limits:
                nvidia.com/gpu-pod-NVIDIA_H100_80GB_HBM3: 1  # Limit to 1 GPU
            env:
            - name: ENV
              value: "production"
          imagePullSecrets:
          - name: docker-registry-secret
    

    Sostituisci quanto segue:

    • REGISTRY_REPOSITORY_URL: l'URL del repository.
    • DOCKER_REGISTRY_SECRET: il nome del secret Docker.
  6. Crea un file timesfm-service.yaml per esporre internamente il server timesfm.

    apiVersion: v1
    kind: Service
    metadata:
      name: timesfm-service
    spec:
      selector:
        app: timesfm
      ports:
        - protocol: TCP
          port: 80 # External port exposed
          targetPort: 5000 # Internal container port for Flask
      type: LoadBalancer # Use NodePort for internal access
    
  7. Applica i manifest.

    kubectl --kubeconfig ${KUBECONFIG} apply -f timesfm-deployment.yaml
    kubectl --kubeconfig ${KUBECONFIG} apply -f timesfm-service.yaml
    
  8. Assicurati che i pod TimesFM siano in esecuzione.

    kubectl --kubeconfig ${KUBECONFIG} get deployments timesfm-deployment -n sandbox-gpu-project
    kubectl --kubeconfig ${KUBECONFIG} get service timesfm-service -n sandbox-gpu-project
    
  9. Crea un criterio di rete del progetto per consentire il traffico in entrata da indirizzi IP esterni.

    kubectl --kubeconfig ${KUBECONFIG} apply -f - <<EOF
    apiVersion: networking.global.gdc.goog/v1
    kind: ProjectNetworkPolicy
    metadata:
      namespace: sandbox-gpu-project
      name: allow-inbound-traffic-from-external
    spec:
      policyType: Ingress
      subject:
        subjectType: UserWorkload
      ingress:
      - from:
        - ipBlock:
            cidr: 0.0.0.0/0
    EOF
    
  10. Identifica l'IP esterno del servizio TimesFM eseguendo questo comando. Prendi nota di questo valore per utilizzarlo nei passaggi successivi, in cui lo sostituirai a TIMESFM_END_POINT.

      kubectl --kubeconfig ${KUBECONFIG} get service timesfm-service \
            -n sandbox-gpu-project -o jsonpath='{.status.loadBalancer.ingress[*].ip}'
    

Testa il servizio.

  1. Per ottenere una previsione, invia i dati al servizio utilizzando un comando curl, sostituendo TIMESFM_END_POINT con l'indirizzo effettivo del servizio e i valori di input per le funzionalità. Viene richiamata la funzione predict definita in app.py, che eseguirà alcune manipolazioni sui dati di input e li restituirà in formato JSON.

    curl -X POST http://TIMESFM_END_POINT/predict -H "Content-Type: application/json" -d '{"features": [1.2, 3.4, 5.6]}'
    
  2. Invia una richiesta curl a /timeseries per visualizzare un esempio di visualizzazione dei dati utilizzando dati generati in modo casuale. Viene richiamata la funzione di serie temporale definita in app.py, che genera una serie temporale casuale ed esegue un'analisi della media mobile.

    curl http://TIMESFM_END_POINT/timeseries