Men-deploy TimesFM di GDC Sandbox

Model TimesFM Google Research adalah model dasar untuk perkiraan deret waktu yang telah dilatih pada miliaran titik waktu dari banyak set data dunia nyata, sehingga Anda dapat menerapkannya ke set data perkiraan baru di berbagai domain.

Panduan tutorial ini menunjukkan cara men-deploy TimesFM di Sandbox GDC dan memiliki tujuan berikut.

  • Buat container Docker yang menjalankan TimesFM,
  • Men-deploy container menggunakan GPU yang disediakan oleh SKU yang Dioptimalkan untuk AI GDC Sandbox, dan
  • Panggil fungsi TimesFM menggunakan permintaan http sederhana.

Sebelum memulai

GPU di GDC Sandbox disertakan dalam cluster org-infra.

  • Untuk menjalankan perintah terhadap cluster infrastruktur org, pastikan Anda memiliki kubeconfig cluster org-1-infra, seperti yang dijelaskan dalam Bekerja dengan cluster:

    • Mengonfigurasi dan melakukan autentikasi dengan command line gdcloud, dan
    • buat file kubeconfig untuk cluster infrastruktur org, dan tetapkan jalurnya ke variabel lingkungan KUBECONFIG.
  • Pastikan pengguna memiliki peran sandbox-gpu-admin yang ditetapkan untuk project sandbox-gpu-project. Secara default, peran ditetapkan kepada pengguna platform-admin. Anda dapat menetapkan peran kepada pengguna lain dengan login sebagai platform-admin dan menjalankan perintah berikut:

    kubectl --kubeconfig ${KUBECONFIG} create rolebinding ${NAME} --role=sandbox-gpu-admin \
    --user=${USER} --namespace=sandbox-gpu-project
    
  • Pastikan untuk menyiapkan repositori Artifact Registry seperti yang dijelaskan dalam Menggunakan Artifact Registry dan login agar dapat mengirim dan menarik image ke registry artefak.

Men-deploy model TimesFM

Deployment diatur melalui serangkaian file konfigurasi Kubernetes (manifest YAML), yang masing-masing menentukan komponen atau layanan tertentu.

  1. Buat skrip python berbasis flask app.py dengan fungsi predict untuk melakukan peramalan deret waktu dan timeseries untuk membuat visualisasi berdasarkan data pengujian.

      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. Buat Dockerfile dengan timesfm yang diinstal saat memanggil aplikasi.

     # 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. Bangun image Docker dan upload ke repositori Artifact Registry.

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

    Ganti kode berikut:

    • REGISTRY_REPOSITORY_URL: URL repositori.
  4. Buat secret untuk menyimpan kredensial 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
    

    Ganti kode berikut:

    • DOCKER_REGISTRY_SECRET nama secret.
  5. Buat file timesfm-deployment.yaml untuk men-deploy timesfm.

    Deployment server timesfm meminta satu 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
    

    Ganti kode berikut:

    • REGISTRY_REPOSITORY_URL: URL repositori.
    • DOCKER_REGISTRY_SECRET: nama secret docker.
  6. Buat file timesfm-service.yaml untuk mengekspos server timesfm secara internal.

    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. Terapkan manifes.

    kubectl --kubeconfig ${KUBECONFIG} apply -f timesfm-deployment.yaml
    kubectl --kubeconfig ${KUBECONFIG} apply -f timesfm-service.yaml
    
  8. Pastikan pod TimesFM sedang berjalan.

    kubectl --kubeconfig ${KUBECONFIG} get deployments timesfm-deployment -n sandbox-gpu-project
    kubectl --kubeconfig ${KUBECONFIG} get service timesfm-service -n sandbox-gpu-project
    
  9. Buat Kebijakan Jaringan Project untuk mengizinkan traffic masuk dari alamat IP eksternal.

    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. Identifikasi IP eksternal layanan TimesFM dengan menjalankan perintah berikut. Catat untuk digunakan pada langkah selanjutnya, di mana Anda akan mengganti nilai ini dengan TIMESFM_END_POINT.

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

Uji layanan.

  1. Untuk mendapatkan prediksi, kirim data ke layanan menggunakan perintah curl, dengan mengganti TIMESFM_END_POINT dengan alamat sebenarnya layanan dan nilai input Anda untuk fitur. Tindakan ini memanggil fungsi predict yang ditentukan dalam app.py, yang akan melakukan beberapa manipulasi pada data input Anda dan menampilkannya dalam format json.

    curl -X POST http://TIMESFM_END_POINT/predict -H "Content-Type: application/json" -d '{"features": [1.2, 3.4, 5.6]}'
    
  2. Kirim permintaan curl ke /timeseries untuk melihat contoh visualisasi data menggunakan data yang dibuat secara acak. Tindakan ini memanggil fungsi deret waktu yang ditentukan di app.py, yang menghasilkan deret waktu acak dan melakukan analisis rata-rata bergerak di dalamnya.

    curl http://TIMESFM_END_POINT/timeseries