Offene Modelle mit einem benutzerdefinierten vLLM-Container bereitstellen

Die verschiedenen Optionen zur Modellbereitstellung der Gemini Enterprise Agent Platform sind für viele Anwendungsfälle ausreichend. Es kann jedoch sein, dass Sie eigene Container-Images verwenden müssen, um Modelle auf der Gemini Enterprise Agent Platform bereitzustellen. In diesem Dokument wird beschrieben, wie Sie ein benutzerdefiniertes vLLM-Container-Image verwenden, um Modelle auf der Gemini Enterprise Agent Platform auf CPUs, GPUs oder TPUs bereitzustellen. Weitere Informationen zu den von vLLM unterstützten Modellen finden Sie in der vLLM-Dokumentation.

Der vLLM API-Server implementiert das OpenAI API-Protokoll, unterstützt jedoch nicht die Anfrage- und Antwortanforderungen der Gemini Enterprise Agent Platform. Daher müssen Sie eine Rohinferenzanfrage der Gemini Enterprise Agent Platform verwenden, um Inferenzen von Modellen abzurufen, die auf der Gemini Enterprise Agent Platform mit einem Vorhersage-Endpunkt bereitgestellt wurden. Weitere Informationen zur Methode für Rohvorhersagen im Gemini Enterprise Agent Platform Python SDK finden Sie in der Dokumentation zum Python SDK.

Sie können Modelle sowohl von Hugging Face als auch aus Cloud Storage beziehen. Dieser Ansatz bietet Flexibilität, sodass Sie den Community-gesteuerten Modell-Hub (Hugging Face) und die optimierten Datenübertragungs- und Sicherheitsfunktionen von Cloud Storage für die interne Modellverwaltung oder feinabgestimmte Versionen nutzen können.

vLLM lädt die Modelle von Hugging Face herunter, wenn ein Hugging Face-Zugriffstoken angegeben wird. Andernfalls geht vLLM davon aus, dass das Modell auf dem lokalen Laufwerk verfügbar ist. Mit dem benutzerdefinierten Container-Image kann die Gemini Enterprise Agent Platform das Modell zusätzlich zu Hugging Face ausCloud de Confiance by S3NS herunterladen.

Hinweis

  1. Aktivieren Sie in Ihrem Cloud de Confiance by S3NS -Projekt die Gemini Enterprise Agent Platform API und die Artifact Registry API.

    gcloud services enable aiplatform.googleapis.com \
        artifactregistry.googleapis.com
    
  2. Konfigurieren Sie die Google Cloud CLI mit Ihrer Projekt-ID und initialisieren Sie das Vertex AI SDK.

    PROJECT_ID = "PROJECT_ID"
    LOCATION = "LOCATION"
    import vertexai
    vertexai.init(project=PROJECT_ID, location=LOCATION)
    
    gcloud config set project {PROJECT_ID}
    
  3. ein Docker-Repository in Artifact Registry erstellen

    gcloud artifacts repositories create DOCKER_REPOSITORY \
        --repository-format=docker \
        --location=LOCATION \
        --description="Agent Platform Docker repository"
    
  4. Optional: Wenn Sie Modelle von Hugging Face herunterladen, rufen Sie ein Hugging Face-Token ab.

    1. Erstellen Sie ein Hugging Face-Konto, falls Sie noch keines haben.
    2. Für Modelle mit eingeschränktem Zugriff wie Llama 3.2 müssen Sie den Zugriff auf Hugging Face anfordern und erhalten, bevor Sie fortfahren können.
    3. Zugriffstoken generieren: Rufen Sie Mein Profil > Einstellungen > Zugriffstokens auf.
    4. Wählen Sie Neues Token aus.
    5. Geben Sie einen Namen und eine Rolle mit mindestens Leseberechtigung an.
    6. Wählen Sie Token generieren aus.
    7. Speichern Sie dieses Token für die Bereitstellungsschritte.

Container-Build-Dateien vorbereiten

Mit dem folgenden Dockerfile wird das benutzerdefinierte vLLM-Container-Image für GPUs, TPUs und CPUs erstellt. Dieser benutzerdefinierte Container lädt Modelle von Hugging Face oder Cloud Storage herunter.

ARG BASE_IMAGE
FROM ${BASE_IMAGE}

ENV DEBIAN_FRONTEND=noninteractive
# Install gcloud SDK
RUN apt-get update && \
    apt-get install -y apt-utils git apt-transport-https gnupg ca-certificates curl \
    && echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" | tee -a /etc/apt/sources.list.d/google-cloud-sdk.list \
    && curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | gpg --dearmor -o /usr/share/keyrings/cloud.google.gpg \
    && apt-get update -y && apt-get install google-cloud-cli -y \
    && rm -rf /var/lib/apt/lists/*

WORKDIR /workspace/vllm

# Copy entrypoint.sh to the container
COPY ./entrypoint.sh /workspace/vllm/vertexai/entrypoint.sh
RUN chmod +x /workspace/vllm/vertexai/entrypoint.sh

ENTRYPOINT ["/workspace/vllm/vertexai/entrypoint.sh"]

Erstellen Sie das benutzerdefinierte Container-Image mit Cloud Build. In der folgenden cloudbuild.yaml-Konfigurationsdatei wird gezeigt, wie Sie das Image für mehrere Plattformen mit demselben Dockerfile erstellen.

steps:
-   name: 'gcr.io/cloud-builders/docker'
  automapSubstitutions: true
  script: |
      #!/usr/bin/env bash
      set -euo pipefail
      device_type_param=${_DEVICE_TYPE}
      device_type=${device_type_param,,}
      base_image=${_BASE_IMAGE}
      image_name="vllm-${_DEVICE_TYPE}"
      if [[ $device_type == "cpu" ]]; then
        echo "Quietly building open source vLLM CPU container image"
        git clone https://github.com/vllm-project/vllm.git
        cd vllm && DOCKER_BUILDKIT=1 docker build -t $base_image -f docker/Dockerfile.cpu . -q
        cd ..
      fi
      echo "Quietly building container image for: $device_type"
      docker build -t $LOCATION-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/$image_name --build-arg BASE_IMAGE=$base_image . -q
      docker push $LOCATION-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/$image_name
substitutions:
    _DEVICE_TYPE: gpu
    _BASE_IMAGE: vllm/vllm-openai
    _REPOSITORY: my-docker-repo

Die Dateien sind im GitHub-Repository googlecloudplatform/vertex-ai-samples verfügbar. Klonen Sie das Repository, um sie zu verwenden:

git clone https://github.com/GoogleCloudPlatform/vertex-ai-samples.git

Container-Image erstellen und per Push übertragen

Erstellen Sie das benutzerdefinierte Container-Image mit Cloud Build, indem Sie die Datei cloudbuild.yaml einreichen. Verwenden Sie Substitutionen, um den Zielgerätetyp (GPU, TPU oder CPU) und das entsprechende Basis-Image anzugeben.

GPU

DEVICE_TYPE="gpu"
BASE_IMAGE="vllm/vllm-openai"
cd vertex-ai-samples/notebooks/official/prediction/vertexai_serving_vllm/cloud-build && \
gcloud builds submit \
    --config=cloudbuild.yaml \
    --region=LOCATION \
    --timeout="2h" \
    --machine-type=e2-highcpu-32 \
    --substitutions=_REPOSITORY=DOCKER_REPOSITORY,_DEVICE_TYPE=$DEVICE_TYPE,_BASE_IMAGE=$BASE_IMAGE

TPU

DEVICE_TYPE="tpu"
BASE_IMAGE="vllm/vllm-tpu:nightly"
cd vertex-ai-samples/notebooks/official/prediction/vertexai_serving_vllm/cloud-build && \
gcloud builds submit \
    --config=cloudbuild.yaml \
    --region=LOCATION \
    --timeout="2h" \
    --machine-type=e2-highcpu-32 \
    --substitutions=_REPOSITORY=DOCKER_REPOSITORY,_DEVICE_TYPE=$DEVICE_TYPE,_BASE_IMAGE=$BASE_IMAGE

CPU

DEVICE_TYPE="cpu"
BASE_IMAGE="vllm-cpu-base"
cd vertex-ai-samples/notebooks/official/prediction/vertexai_serving_vllm/cloud-build && \
gcloud builds submit \
    --config=cloudbuild.yaml \
    --region=LOCATION \
    --timeout="2h" \
    --machine-type=e2-highcpu-32 \
    --substitutions=_REPOSITORY=DOCKER_REPOSITORY,_DEVICE_TYPE=$DEVICE_TYPE,_BASE_IMAGE=$BASE_IMAGE

Konfigurieren Sie nach Abschluss des Builds Docker für die Authentifizierung bei Artifact Registry:

gcloud auth configure-docker LOCATION-docker.pkg.dev --quiet

Modell in Model Registry hochladen und bereitstellen

Führen Sie die folgenden Schritte aus, um Ihr Modell in die Model Registry hochzuladen, einen Endpunkt zu erstellen und das Modell bereitzustellen. In diesem Beispiel wird Llama 3.2 3B verwendet, Sie können es aber für andere Modelle anpassen.

  1. Modell- und Bereitstellungsvariablen definieren. Legen Sie die Variable DOCKER_URI auf das Image fest, das Sie im vorherigen Schritt erstellt haben (z. B. für GPU):

    DOCKER_URI = f"LOCATION-docker.pkg.dev/PROJECT_ID/DOCKER_REPOSITORY/vllm-gpu"
    

    Definieren Sie Variablen für das Hugging Face-Token und die Modellattribute. Beispiel für die GPU-Bereitstellung:

    hf_token = "your-hugging-face-auth-token"
    model_name = "gpu-llama3_2_3B-serve-vllm"
    model_id = "meta-llama/Llama-3.2-3B"
    machine_type = "g2-standard-8"
    accelerator_type = "NVIDIA_L4"
    accelerator_count = 1
    
  2. Modell in Model Registry hochladen Die Funktion upload_model variiert je nach Gerätetyp leicht, da unterschiedliche vLLM-Argumente und Umgebungsvariablen verwendet werden.

    from google.cloud import aiplatform
    
    def upload_model_gpu(model_name, model_id, hf_token, accelerator_count, docker_uri):
        vllm_args = [
            "python3", "-m", "vllm.entrypoints.openai.api_server",
            "--host=0.0.0.0", "--port=8080", f"--model={model_id}",
            "--max-model-len=2048", "--gpu-memory-utilization=0.9",
            "--enable-prefix-caching", f"--tensor-parallel-size={accelerator_count}",
        ]
        env_vars = {
            "HF_TOKEN": hf_token,
            "LD_LIBRARY_PATH": "$LD_LIBRARY_PATH:/usr/local/nvidia/lib64",
        }
        model = aiplatform.Model.upload(
            display_name=model_name,
            serving_container_image_uri=docker_uri,
            serving_container_args=vllm_args,
            serving_container_ports=[8080],
            serving_container_predict_route="/v1/completions",
            serving_container_health_route="/health",
            serving_container_environment_variables=env_vars,
            serving_container_shared_memory_size_mb=(16 * 1024),  # 16 GB
            serving_container_deployment_timeout=1800,
        )
        return model
    
    def upload_model_tpu(model_name, model_id, hf_token, tpu_count, docker_uri):
        vllm_args = [
            "python3", "-m", "vllm.entrypoints.openai.api_server",
            "--host=0.0.0.0", "--port=8080", f"--model={model_id}",
            "--max-model-len=2048", "--enable-prefix-caching",
            f"--tensor-parallel-size={tpu_count}",
        ]
        env_vars = {"HF_TOKEN": hf_token}
        model = aiplatform.Model.upload(
            display_name=model_name,
            serving_container_image_uri=docker_uri,
            serving_container_args=vllm_args,
            serving_container_ports=[8080],
            serving_container_predict_route="/v1/completions",
            serving_container_health_route="/health",
            serving_container_environment_variables=env_vars,
            serving_container_shared_memory_size_mb=(16 * 1024),  # 16 GB
            serving_container_deployment_timeout=1800,
        )
        return model
    
    def upload_model_cpu(model_name, model_id, hf_token, docker_uri):
        vllm_args = [
            "python3", "-m", "vllm.entrypoints.openai.api_server",
            "--host=0.0.0.0", "--port=8080", f"--model={model_id}",
            "--max-model-len=2048",
        ]
        env_vars = {"HF_TOKEN": hf_token}
        model = aiplatform.Model.upload(
            display_name=model_name,
            serving_container_image_uri=docker_uri,
            serving_container_args=vllm_args,
            serving_container_ports=[8080],
            serving_container_predict_route="/v1/completions",
            serving_container_health_route="/health",
            serving_container_environment_variables=env_vars,
            serving_container_shared_memory_size_mb=(16 * 1024),  # 16 GB
            serving_container_deployment_timeout=1800,
        )
        return model
    
    # Example for GPU:
    vertexai_model = upload_model_gpu(model_name, model_id, hf_token, accelerator_count, DOCKER_URI)
    
  3. Erstellen Sie einen Endpunkt.

    endpoint = aiplatform.Endpoint.create(display_name=f"model_name-endpoint")
    
  4. Modell auf Endpunkt bereitstellen Die Modellbereitstellung kann 20 bis 30 Minuten dauern.

    # Example for GPU:
    vertexai_model.deploy(
        endpoint=endpoint,
        deployed_model_display_name=model_name,
        machine_type=machine_type,
        accelerator_type=accelerator_type,
        accelerator_count=accelerator_count,
        traffic_percentage=100,
        deploy_request_timeout=1800,
        min_replica_count=1,
        max_replica_count=4,
        autoscaling_target_accelerator_duty_cycle=60,
    )
    

    Lassen Sie für TPUs die Parameter accelerator_type und accelerator_count weg und verwenden Sie autoscaling_target_request_count_per_minute=60. Lassen Sie für CPUs die Parameter accelerator_type und accelerator_count weg und verwenden Sie autoscaling_target_cpu_utilization=60.

Modelle aus Cloud Storage laden

Der benutzerdefinierte Container lädt das Modell von einem Cloud Storage-Speicherort herunter, anstatt es von Hugging Face herunterzuladen. Wenn Sie Cloud Storage verwenden:

  • Legen Sie den Parameter model_id in der Funktion upload_model auf einen Cloud Storage-URI fest, z. B. gs://<var>my-bucket</var>/<var>my-models</var>/<var>llama_3_2_3B</var>.
  • Lassen Sie die Variable HF_TOKEN aus env_vars weg, wenn Sie upload_model aufrufen.
  • Wenn Sie model.deploy aufrufen, geben Sie ein service_account an, das Leseberechtigungen für den Cloud Storage-Bucket hat.

IAM-Dienstkonto für den Zugriff auf Cloud Storage erstellen

Wenn sich Ihr Modell in Cloud Storage befindet, erstellen Sie ein Dienstkonto, mit dem Vertex Prediction-Endpunkte auf die Modellartefakte zugreifen können.

SERVICE_ACCOUNT_NAME = "vertexai-endpoint-sa"
SERVICE_ACCOUNT_EMAIL = f"SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com"
gcloud iam service-accounts create SERVICE_ACCOUNT_NAME \
    --display-name="Agent Platform Endpoint Service Account"

# Grant storage read permission
gcloud projects add-iam-policy-binding PROJECT_ID \
    --member="serviceAccount:SERVICE_ACCOUNT_EMAIL" \
    --role="roles/storage.objectViewer"

Übergeben Sie bei der Bereitstellung die E-Mail-Adresse des Dienstkontos an die Methode deploy: service_account=<var>SERVICE_ACCOUNT_EMAIL</var>.

Vorhersagen über Endpunkt abrufen

Nachdem Sie das Modell erfolgreich auf dem Endpunkt bereitgestellt haben, prüfen Sie die Modellantwort mit raw_predict.

import json

PROMPT = "Distance of moon from earth is "
request_body = json.dumps(
    {
        "prompt": PROMPT,
        "temperature": 0.0,
    },
)

raw_response = endpoint.raw_predict(
    body=request_body, headers={"Content-Type": "application/json"}
)
assert raw_response.status_code == 200
result = json.loads(raw_response.text)

for choice in result["choices"]:
    print(choice)

Beispielausgabe:

{
  "index": 0,
  "text": "384,400 km. The moon is 1/4 of the earth's",
  "logprobs": null,
  "finish_reason": "length",
  "stop_reason": null,
  "prompt_logprobs": null
}

Nächste Schritte