Container-based functions require building and pushing a Cloud Functions compatible Docker container image to your container registry.
-
Example containers can be found in the examples directory.
-
The repository also contains helper functions that are useful when authoring your container, including:
- Helpers that parse Cloud Functions-specific parameters on invocation
- Helpers that can be used to instrument your container with Cloud Functions compatible logs
-
It's always a best practice to emit logs from your inference container. Cloud Functions supports third-party logging and metrics emission from your container.
Any server can be implemented within the container, as long as it implements the following:
- For HTTP-based functions, a health check endpoint that returns a 200 HTTP Status Code on success.
- For gRPC-based functions, a standard gRPC health check. See these docs for more info also gRPC Health Checking.
- An inference endpoint (this endpoint will be called during function invocation)
These endpoints are expected to be served on the same port, defined as the inferencePort.
Cloud Functions adds NVCF-INVOCATION-REGION to HTTP requests sent to a function container. Its value is the configured region of the invocation service that accepted the request. Client-supplied values are replaced. Cloud Functions does not add this header to client responses.
- Port
8080 - Port
8010
Cloud Functions also expects the following directories in the container to remain read-only for caching purposes:
/config/directory- Nested directories created inside
/config/
It's possible to use any container with Cloud Functions as long as it implements a server with the above endpoints. The below is an example of a FastAPI-based container compatible with Cloud Functions. Clone the FastAPI echo example.
fastapi==0.110.0
uvicorn==0.29.0
import os
import time
import uvicorn
from pydantic import BaseModel
from fastapi import FastAPI, status
from fastapi.responses import StreamingResponse
app = FastAPI()
class HealthCheck(BaseModel):
status: str = "OK"
# Implement the health check endpoint
@app.get("/health", tags=["healthcheck"], summary="Perform a Health Check", response_description="Return HTTP Status Code 200 (OK)", status_code=status.HTTP_200_OK, response_model=HealthCheck)
def get_health() -> HealthCheck:
return HealthCheck(status="OK")
class Echo(BaseModel):
message: str
delay: float = 0.000001
repeats: int = 1
stream: bool = False
# Implement the inference endpoint
@app.post("/echo")
async def echo(echo: Echo):
if echo.stream:
def stream_text():
for _ in range(echo.repeats):
time.sleep(echo.delay)
yield f"data: {echo.message}\n\n"
return StreamingResponse(stream_text(), media_type="text/event-stream")
else:
time.sleep(echo.delay)
return echo.message*echo.repeats
# Serve the endpoints on a port
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000, workers=int(os.getenv('WORKER_COUNT', 500)))Note in the example above, the function's configuration during creation will be:
- Inference Protocol: HTTP
- Inference Endpoint:
/echo - Health Endpoint:
/health - Inference Port (also used for health check):
8000
FROM python:3.10.13-bookworm
ENV WORKER_COUNT=10
WORKDIR /app
COPY requirements.txt ./
RUN python -m pip install --no-cache-dir -U pip && \
python -m pip install --no-cache-dir -r requirements.txt
COPY http_echo_server.py /app/
CMD uvicorn http_echo_server:app --host=0.0.0.0 --workers=$WORKER_COUNTSee the [Create the Function] section below for the remaining steps.
NVIDIA's PyTriton is a Python native solution of Triton inference server. A minimum version of 0.3.0 is required.
- This file should list the Python dependencies required for your model.
- Add nvidia-pytriton to your
requirements.txtfile.
Here is an example of a requirements.txt file:
--extra-index-url https://pypi.ngc.nvidia.com
opencv-python-headless
pycocotools
matplotlib
torch==2.1.0
nvidia-pytriton==0.3.0
numpy
- Your
run.pyfile (or similar Python file) needs to define a PyTriton model. - This involves importing your model dependencies, creating a PyTritonServer class with an
__init__function, an_infer_fnfunction and arunfunction that serves the inference_function, defining the model name, the inputs and the outputs along with optional configuration.
Here is an example of a run.py file:
import numpy as np
from pytriton.model_config import ModelConfig, Tensor
from pytriton.triton import Triton, TritonConfig
import time
....
class PyTritonServer:
"""triton server for timed_sleeper"""
def __init__(self):
# basically need to accept image, mask(PIL Images), prompt, negative_prompt(str), seed(int)
self.model_name = "timed_sleeper"
def _infer_fn(self, requests):
responses = []
for req in requests:
req_data = req.data
sleep_duration = numpy_array_to_variable(req_data.get("sleep_duration"))
# deal with header dict keys being lowerscale
request_parameters_dict = uppercase_keys(req.parameters)
time.sleep(sleep_duration)
responses.append({"sleep_duration": np.array([sleep_duration])})
return responses
def run(self):
"""run triton server"""
with Triton(
config=TritonConfig(
http_header_forward_pattern="NVCF-*", # this is required
http_port=8000,
grpc_port=8001,
metrics_port=8002,
)
) as triton:
triton.bind(
model_name="timed_sleeper",
infer_func=self._infer_fn,
inputs=[
Tensor(name="sleep_duration", dtype=np.uint32, shape=(1,)),
],
outputs=[Tensor(name="sleep_duration", dtype=np.uint32, shape=(1,))],
config=ModelConfig(batching=False),
)
triton.serve()
if __name__ == "__main__":
server = PyTritonServer()
server.run()- Create a file named
Dockerfilein your model directory. - It's strongly recommended to use NVIDIA-optimized containers like CUDA, Pytorch or TensorRT as your base container. They can be downloaded from the NGC Catalog.
- Make sure to install your Python requirements in your
Dockerfile. - Copy in your model source code, and model weights.
Here is an example of a Dockerfile:
FROM nvcr.io/nvidia/cuda:12.1.1-devel-ubuntu22.04
RUN apt-get update && apt-get install -y \
git \
python3 \
python3-pip \
python-is-python3 \
libsm6 \
libxext6 \
libxrender-dev \
curl \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /workspace/
# Install requirements file
COPY requirements.txt requirements.txt
RUN pip install --no-cache-dir --upgrade pip
RUN pip install --no-cache-dir -r requirements.txt
ENV DEBIAN_FRONTEND=noninteractive
# Copy model source code and weights
COPY model_weights /models
COPY model_source .
COPY run.py .
# Set run command to start PyTriton to serve the model
CMD python3 run.py- Open a terminal or command prompt.
- Navigate to the
my_modeldirectory. - Run the following command to build the docker image:
docker build -t my_model_image .Replace my_model_image with the desired name for your docker image.
Tag and push the docker image to your container registry.
docker tag my_model_image:latest ${REGISTRY}/${REPOSITORY}/my_model_image:latest
docker push ${REGISTRY}/${REPOSITORY}/my_model_image:latestCreate the function via the NVCF API. In this example, we defined the inference port as 8000 and are using the default inference and health endpoint paths.
curl -s -X POST "http://${GATEWAY_ADDR}/v2/nvcf/functions" \
-H "Host: api.${GATEWAY_ADDR}" \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $NVCF_TOKEN" \
-d '{
"name": "my-model-function",
"inferenceUrl": "/v2/models/my_model_image/infer",
"inferencePort": 8000,
"containerImage": "'${REGISTRY}'/'${REPOSITORY}'/my_model_image:latest",
"health": {
"protocol": "HTTP",
"uri": "/v2/health/ready",
"port": 8000,
"timeout": "PT10S",
"expectedStatusCode": 200
}
}'See more examples of containers that are Cloud Functions compatible in the function samples directory.
Cloud Functions supports function invocation via gRPC. During function creation, specify that the function is a gRPC function by setting the inferenceUrl field to /grpc.
-
The function container must implement a gRPC port, endpoint and health check. The health check is expected to be served by the gRPC inference port, there is no need to define a separate health endpoint path.
- See gRPC health checking.
- See an example container with a gRPC server that is Cloud Functions compatible.
When creating the gRPC function, set the inferenceUrl field to /grpc:
curl -s -X POST "http://${GATEWAY_ADDR}/v2/nvcf/functions" \
-H "Host: api.${GATEWAY_ADDR}" \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $NVCF_TOKEN" \
-d '{
"name": "my-grpc-function",
"inferenceUrl": "/grpc",
"inferencePort": 8001,
"containerImage": "'${REGISTRY}'/'${REPOSITORY}'/grpc_echo_sample:latest"
}'For gRPC authentication metadata, gateway address configuration, and client examples, see gRPC Function Invocation.