Implementa TimesFM en la zona de pruebas de GDC

El modelo TimesFM de Google Research es un modelo fundamental para la previsión de series temporales que se entrenó previamente con miles de millones de puntos temporales de muchos conjuntos de datos del mundo real, por lo que puedes aplicarlo a nuevos conjuntos de datos de previsión en muchos dominios.

En esta guía del instructivo, se muestra cómo implementar TimesFM en el entorno de pruebas de GDC y se incluyen los siguientes objetivos.

  • Crea un contenedor de Docker que ejecute TimesFM.
  • Implementa el contenedor con las GPUs que proporciona el SKU optimizado para IA de GDC Sandbox.
  • Invoca funciones de TimesFM con solicitudes HTTP simples.

Antes de comenzar

Las GPUs en GDC Sandbox se incluyen en el clúster org-infra.

  • Para ejecutar comandos en el clúster de infraestructura de la organización, asegúrate de tener el kubeconfig del clúster org-1-infra, como se describe en Trabaja con clústeres:

    • Configura y autentica la línea de comandos de gdcloud.
    • Genera el archivo kubeconfig para el clúster de infraestructura de la organización y asigna su ruta de acceso a la variable de entorno KUBECONFIG.
  • Asegúrate de que el usuario tenga el rol sandbox-gpu-admin asignado para el proyecto sandbox-gpu-project. De forma predeterminada, el rol se asigna al usuario platform-admin. Puedes asignar el rol a otros usuarios accediendo como platform-admin y ejecutando el siguiente comando:

    kubectl --kubeconfig ${KUBECONFIG} create rolebinding ${NAME} --role=sandbox-gpu-admin \
    --user=${USER} --namespace=sandbox-gpu-project
    
  • Asegúrate de configurar el repositorio de Artifact Registry como se describe en Uso de Artifact Registry y accede para poder enviar y extraer imágenes del registro de artefactos.

Implementa el modelo de TimesFM

La implementación se coordina a través de un conjunto de archivos de configuración de Kubernetes (manifiestos YAML), cada uno de los cuales define un componente o servicio específico.

  1. Crea una secuencia de comandos de Python basada en Flask app.py con funciones predict para realizar previsiones de series temporales y timeseries para generar una visualización basada en los datos de prueba.

      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 instalado que invoque la 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. Compila la imagen de Docker y súbela al repositorio de Artifact Registry.

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

    Reemplaza lo siguiente:

    • REGISTRY_REPOSITORY_URL: Es la URL del repositorio.
  4. Crea un secreto para guardar las credenciales de 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
    

    Reemplaza lo siguiente:

    • Nombre del Secret DOCKER_REGISTRY_SECRET.
  5. Crea un archivo timesfm-deployment.yaml para implementar timesfm.

    La implementación del servidor timesfm solicita 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
    

    Reemplaza lo siguiente:

    • REGISTRY_REPOSITORY_URL: Es la URL del repositorio.
    • DOCKER_REGISTRY_SECRET: Es el nombre del secreto de Docker.
  6. Crea un archivo timesfm-service.yaml para exponer el servidor timesfm de forma interna.

    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. Aplica los manifiestos.

    kubectl --kubeconfig ${KUBECONFIG} apply -f timesfm-deployment.yaml
    kubectl --kubeconfig ${KUBECONFIG} apply -f timesfm-service.yaml
    
  8. Asegúrate de que los pods TimesFM se estén ejecutando.

    kubectl --kubeconfig ${KUBECONFIG} get deployments timesfm-deployment -n sandbox-gpu-project
    kubectl --kubeconfig ${KUBECONFIG} get service timesfm-service -n sandbox-gpu-project
    
  9. Crea una política de red del proyecto para permitir el tráfico entrante desde direcciones IP externas.

    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. Ejecuta el siguiente comando para identificar la IP externa del servicio TimesFM. Toma nota de él para usarlo en pasos posteriores, en los que sustituirás este valor por TIMESFM_END_POINT.

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

Probar el servicio

  1. Para obtener una predicción, envía datos al servicio con un comando curl y reemplaza TIMESFM_END_POINT por la dirección real del servicio y los valores de entrada de las funciones. Esto invoca la función predict definida en app.py, que realizará algunas manipulaciones en tus datos de entrada y los devolverá en formato JSON.

    curl -X POST http://TIMESFM_END_POINT/predict -H "Content-Type: application/json" -d '{"features": [1.2, 3.4, 5.6]}'
    
  2. Envía una solicitud de curl a /timeseries para ver un ejemplo de visualización de datos con datos generados de forma aleatoria. Esto invoca la función de series temporales definida en app.py, que genera una serie temporal aleatoria y realiza un análisis de promedio móvil en ella.

    curl http://TIMESFM_END_POINT/timeseries