Déployer TimesFM sur GDC Sandbox

Le modèle TimesFM de Google Research est un modèle de fondation pour la prévision de séries temporelles. Il a été pré-entraîné sur des milliards de points temporels provenant de nombreux ensembles de données réels. Vous pouvez donc l'appliquer à de nouveaux ensembles de données de prévision dans de nombreux domaines.

Ce tutoriel explique comment déployer TimesFM sur la sandbox GDC et présente les objectifs suivants.

  • Créer un conteneur Docker qui exécute TimesFM
  • Déployez le conteneur à l'aide des GPU fournis par le SKU optimisé pour l'IA de GDC Sandbox.
  • Appelez les fonctions TimesFM à l'aide de requêtes HTTP simples.

Avant de commencer

Les GPU de GDC Sandbox sont inclus dans le cluster org-infra.

  • Pour exécuter des commandes sur le cluster d'infrastructure de l'organisation, assurez-vous de disposer du fichier kubeconfig du cluster org-1-infra, comme décrit dans Utiliser des clusters :

    • Configurez et authentifiez-vous avec la ligne de commande gdcloud.
    • générez le fichier kubeconfig pour le cluster d'infrastructure de l'organisation et attribuez son chemin d'accès à la variable d'environnement KUBECONFIG.
  • Assurez-vous que le rôle sandbox-gpu-admin est attribué à l'utilisateur pour le projet sandbox-gpu-project. Par défaut, le rôle est attribué à l'utilisateur platform-admin. Vous pouvez attribuer le rôle à d'autres utilisateurs en vous connectant en tant que platform-admin et en exécutant la commande suivante :

    kubectl --kubeconfig ${KUBECONFIG} create rolebinding ${NAME} --role=sandbox-gpu-admin \
    --user=${USER} --namespace=sandbox-gpu-project
    
  • Assurez-vous de configurer le dépôt Artifact Registry comme décrit dans Utiliser Artifact Registry et connectez-vous pour pouvoir transférer des images vers le registre d'artefacts et en extraire.

Déployer le modèle TimesFM

Le déploiement est orchestré à l'aide d'un ensemble de fichiers de configuration Kubernetes (manifestes YAML), chacun définissant un composant ou un service spécifique.

  1. Créez un script Python app.py basé sur Flask avec les fonctions predict pour effectuer des prévisions de séries temporelles et timeseries pour générer une visualisation basée sur les données de 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. Créez un fichier Dockerfile avec timesfm installé pour appeler l'application.

     # 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. Créez l'image Docker et importez-la dans le dépôt Artifact Registry.

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

    Remplacez les éléments suivants :

    • REGISTRY_REPOSITORY_URL : URL du dépôt.
  4. Créez un secret pour enregistrer les identifiants 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
    

    Remplacez les éléments suivants :

    • DOCKER_REGISTRY_SECRET : nom du secret.
  5. Créez un fichier timesfm-deployment.yaml pour déployer timesfm.

    Le déploiement du serveur timesfm nécessite un 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
    

    Remplacez les éléments suivants :

    • REGISTRY_REPOSITORY_URL : URL du dépôt.
    • DOCKER_REGISTRY_SECRET : nom du secret Docker.
  6. Créez un fichier timesfm-service.yaml pour exposer le serveur timesfm en interne.

    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. Appliquez les fichiers manifestes.

    kubectl --kubeconfig ${KUBECONFIG} apply -f timesfm-deployment.yaml
    kubectl --kubeconfig ${KUBECONFIG} apply -f timesfm-service.yaml
    
  8. Assurez-vous que les pods TimesFM sont en cours d'exécution.

    kubectl --kubeconfig ${KUBECONFIG} get deployments timesfm-deployment -n sandbox-gpu-project
    kubectl --kubeconfig ${KUBECONFIG} get service timesfm-service -n sandbox-gpu-project
    
  9. Créez une règle de réseau de projet pour autoriser le trafic entrant provenant d'adresses IP externes.

    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. Identifiez l'adresse IP externe du service TimesFM en exécutant la commande suivante. Notez-le pour l'utiliser dans les étapes suivantes, où vous remplacerez TIMESFM_END_POINT par cette valeur.

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

Tester le service

  1. Pour obtenir une prédiction, envoyez des données au service à l'aide d'une commande curl, en remplaçant TIMESFM_END_POINT par l'adresse réelle du service et vos valeurs d'entrée pour les caractéristiques. Cela appelle la fonction predict définie dans app.py, qui effectue une manipulation sur vos données d'entrée et les renvoie au format JSON.

    curl -X POST http://TIMESFM_END_POINT/predict -H "Content-Type: application/json" -d '{"features": [1.2, 3.4, 5.6]}'
    
  2. Envoyez une requête curl à /timeseries pour voir un exemple de visualisation de données à l'aide de données générées de manière aléatoire. Cela appelle la fonction de série temporelle définie dans app.py, qui génère une série temporelle aléatoire et effectue une analyse de la moyenne mobile.

    curl http://TIMESFM_END_POINT/timeseries