Esegui l'inferenza LLM sulle GPU Cloud Run con Gemma 3 e Ollama

Configura gcloud

Per configurare Google Cloud CLI per il tuo servizio Cloud Run:

  1. Imposta il progetto predefinito:

    gcloud config set project PROJECT_ID

    Fai clic sull'icona per sostituire la variabile PROJECT_ID con il nome del progetto che hai creato per questo tutorial. In questo modo, tutti gli annunci in questa pagina che fanno riferimento a PROJECT_ID hanno già il valore corretto compilato.

  2. Configura Google Cloud CLI in modo da utilizzare la regione europe-west1 per i comandi di Cloud Run.

    gcloud config set run/region europe-west1

Utilizza Docker per creare un'immagine container con Ollama e Gemma

  1. Crea una directory per il servizio Ollama e cambia la directory di lavoro con questa nuova directory:

    mkdir ollama-backend
    cd ollama-backend
  2. Crea un file Dockerfile con i seguenti contenuti:

    FROM ollama/ollama:latest
    
    # Listen on all interfaces, port 8080
    ENV OLLAMA_HOST 0.0.0.0:8080
    
    # Store model weight files in /models
    ENV OLLAMA_MODELS /models
    
    # Reduce logging verbosity
    ENV OLLAMA_DEBUG false
    
    # Never unload model weights from the GPU
    ENV OLLAMA_KEEP_ALIVE -1
    
    # Store the model weights in the container image
    ENV MODEL gemma3:4b
    RUN ollama serve & sleep 5 && ollama pull $MODEL
    
    # Start Ollama
    ENTRYPOINT ["ollama", "serve"]
    

Archivia i pesi del modello nell'immagine container per avviare più rapidamente le istanze

Google consiglia di archiviare i pesi del modello per Gemma 3 (4B) e modelli di dimensioni simili direttamente nell'immagine del container.

I pesi del modello sono i parametri numerici che definiscono il comportamento di un LLM. Ollama deve leggere completamente questi file e caricare i pesi nella memoria della GPU (VRAM) durante l'avvio dell'istanza del container, prima di poter iniziare a gestire le richieste di inferenza.

Su Cloud Run, l'avvio rapido di un'istanza container è importante per ridurre al minimo la latenza delle richieste. Se l'istanza del container ha un tempo di avvio lento, il servizio impiega più tempo per scalare da zero a un'istanza e ha bisogno di più tempo per scalare durante un picco di traffico.

Per garantire un avvio rapido, archivia i file del modello nell'immagine container stessa. Questo metodo è più rapido e affidabile rispetto al download dei file da una posizione remota durante l'avvio. Lo spazio di archiviazione interno delle immagini container di Cloud Run è ottimizzato per gestire i picchi di traffico, consentendo di configurare rapidamente il file system del container all'avvio di un'istanza.

Tieni presente che i pesi del modello per Gemma 3 (4B) occupano 8 GB di spazio di archiviazione. I modelli più grandi hanno file di peso del modello più grandi e potrebbe essere poco pratico archiviarli nell'immagine container. Per una panoramica dei compromessi, consulta Best practice: inferenza AI su Cloud Run con GPU.

Crea ed esegui il deployment del servizio Cloud Run

Crea ed esegui il deployment del servizio su Cloud Run:

gcloud run deploy ollama-gemma \
  --source . \
  --concurrency 4 \
  --cpu 8 \
  --set-env-vars OLLAMA_NUM_PARALLEL=4 \
  --gpu 1 \
  --gpu-type nvidia-l4 \
  --max-instances 1 \
  --memory 32Gi \
  --no-allow-unauthenticated \
  --no-cpu-throttling \
  --no-gpu-zonal-redundancy \
  --timeout=600

Tieni presente i seguenti flag importanti in questo comando:

  • --concurrency 4 è impostato in modo che corrisponda al valore della variabile di ambiente OLLAMA_NUM_PARALLEL.
  • --gpu 1 con --gpu-type nvidia-l4 assegna una GPU NVIDIA L4 a ogni istanza Cloud Run nel servizio.
  • --max-instances 1 specifica il numero massimo di istanze a cui scalare. Deve essere uguale o inferiore alla quota di GPU NVIDIA L4 (Total Nvidia L4 GPU allocation, per project per region) del tuo progetto.
  • --no-allow-unauthenticated limita l'accesso non autenticato al servizio. Mantenendo privato il servizio, puoi fare affidamento sull'autenticazione Identity and Access Management (IAM) integrata di Cloud Run per la comunicazione da servizio a servizio. Consulta la sezione Gestione dell'accesso tramite IAM.
  • --no-cpu-throttling è necessario per abilitare la GPU.
  • --no-gpu-zonal-redundancy imposta le opzioni di ridondanza a livello di zona in base ai requisiti di failover a livello di zona e alla quota disponibile. Per maggiori dettagli, consulta Opzioni di ridondanza a livello di zona delle GPU.

Impostare la concorrenza per prestazioni ottimali

Questa sezione fornisce il contesto delle impostazioni di concorrenza consigliate. Per una latenza delle richieste ottimale, assicurati che l'impostazione --concurrency sia uguale alla variabile di ambiente OLLAMA_NUM_PARALLEL di Ollama.

  • OLLAMA_NUM_PARALLEL determina il numero di slot di richiesta disponibili per ogni modello per gestire le richieste di inferenza contemporaneamente.
  • --concurrency determina il numero di richieste che Cloud Run invia a un'istanza Ollama contemporaneamente.

Se --concurrency supera OLLAMA_NUM_PARALLEL, Cloud Run può inviare più richieste a un modello in Ollama rispetto agli slot di richiesta disponibili. Ciò comporta la creazione di code di richieste all'interno di Ollama, aumentando la latenza delle richieste in coda. Inoltre, la scalabilità automatica è meno reattiva, poiché le richieste in coda non attivano Cloud Run per lo scale out e l'avvio di nuove istanze.

Ollama supporta anche la pubblicazione di più modelli da una singola GPU. Per evitare completamente la coda delle richieste nell'istanza Ollama, devi comunque impostare --concurrency in modo che corrisponda a OLLAMA_NUM_PARALLEL.

È importante notare che l'aumento di OLLAMA_NUM_PARALLEL allunga anche i tempi delle richieste parallele.

Ottimizzazione dell'utilizzo

Per un utilizzo della GPU ottimale, aumenta --concurrency, mantenendolo entro il doppio del valore di OLLAMA_NUM_PARALLEL. Sebbene ciò comporti la messa in coda delle richieste in Ollama, può contribuire a migliorare l'utilizzo: le istanze Ollama possono elaborare immediatamente le richieste dalla coda e le code aiutano ad assorbire i picchi di traffico.

Testare il servizio Ollama di cui è stato eseguito il deployment con curl

Ora che hai eseguito il deployment del servizio Ollama, puoi inviargli richieste. Tuttavia, se invii una richiesta direttamente, Cloud Run risponde con HTTP 401 Unauthorized. Questo è intenzionale, perché un'API di inferenza LLM è destinata ad essere chiamata da altri servizi, ad esempio un'applicazione frontend. Per ulteriori informazioni sull'autenticazione da servizio a servizio su Cloud Run, consulta Autenticazione da servizio a servizio.

Per inviare richieste al servizio Ollama, aggiungi un'intestazione con un token OIDC valido alle richieste, ad esempio utilizzando il proxy per sviluppatori di Cloud Run:

  1. Avvia il proxy e, quando ti viene chiesto di installare il componente cloud-run-proxy, scegli Y:

    gcloud run services proxy ollama-gemma --port=9090
  2. Invia una richiesta in una scheda del terminale separata, lasciando in esecuzione il proxy. Tieni presente che il proxy viene eseguito su localhost:9090:

    curl http://localhost:9090/api/generate -d '{
      "model": "gemma3:4b",
      "prompt": "Why is the sky blue?"
    }'

    Questo comando dovrebbe fornire un output di streaming simile a questo:

    {"model":"gemma3:4b","created_at":"2025-03-10T03:02:18.641492408Z","response":"That","done":false}
    {"model":"gemma3:4b","created_at":"2025-03-10T03:02:18.687529153Z","response":"'","done":false}
    {"model":"gemma3:4b","created_at":"2025-03-10T03:02:18.753284927Z","response":"s","done":false}
    {"model":"gemma3:4b","created_at":"2025-03-10T03:02:18.812957381Z","response":" a","done":false}
    {"model":"gemma3:4b","created_at":"2025-03-10T03:02:18.889102649Z","response":" fantastic","done":false}
    {"model":"gemma3:4b","created_at":"2025-03-10T03:02:18.925748116Z","response":",","done":false}
    {"model":"gemma3:4b","created_at":"2025-03-10T03:02:18.958391572Z","response":" decept","done":false}
    {"model":"gemma3:4b","created_at":"2025-03-10T03:02:18.971035028Z","response":"ively","done":false}
    {"model":"gemma3:4b","created_at":"2025-03-10T03:02:18.989678484Z","response":" tricky","done":false}
    {"model":"gemma3:4b","created_at":"2025-03-10T03:02:18.999321940Z","response":" question","done":false}
    ...