For AI agents: the complete documentation index is available at https://docs.ovhcloud.com/fr/llms.txt, the full documentation bundle is available at https://docs.ovhcloud.com/fr/llms-full.txt, and this page is available as Markdown at https://docs.ovhcloud.com/fr/guides/public-cloud/ai-machine-learning/ai-deploy-densenet-onnx-fastapi.md.

AI Deploy - Tutoriel - Déployer un modèle ONNX avec FastAPI

Voir en Markdown

Découvrez comment déployer le modèle DenseNet au format ONNX pour une inférence optimisée

Objectif

L'objectif de ce tutoriel est de vous montrer comment déployer un modèle ONNX pour une inférence optimisée grâce à AI Deploy.

Pour cela, vous allez utiliser un modèle DenseNet entraîné sur le jeu de données CIFAR-10 pour classifier des images, ainsi que le framework Python FastAPI pour créer l'API. Développer une API vous permettra d'utiliser votre modèle de Machine Learning pour l'inférence. Vous apprendrez également à construire et à utiliser une image Docker personnalisée pour un déploiement FastAPI.

Pour plus d'informations sur la façon d'entraîner DenseNet sur un jeu de données CIFAR-10, reportez-vous à la documentation suivante.

Voici un aperçu de l'API de classification d'images :

APIOverview

Prérequis

  • Un projet AI Deploy créé au sein d'un projet Public Cloud
  • Un utilisateur pour AI Deploy
  • Docker installé sur votre ordinateur local ou une instance Docker Public Cloud déployée
  • Quelques connaissances sur la construction d'images et les Dockerfile
  • Vos poids obtenus après le fine-tuning du modèle DenseNet sur le jeu de données CIFAR-10 (reportez-vous à la partie « Export ONNX model for inference » du notebook sur le fine-tuning de DenseNet)

En pratique

Vous allez suivre différentes étapes pour construire votre app FastAPI.

  • Plus d'informations sur les capacités de FastAPI sont disponibles ici.
  • Un lien direct vers le code complet est disponible ici.
Warning

Avertissement Vous devez avoir préalablement créé un conteneur Object Storage densenet-cifar10-onnx-model lors de l'entraînement de votre modèle via AI Notebooks.

Vérifiez que ce conteneur contient bien vos poids DenseNet au format ONNX. Ils seront nécessaires au déploiement de l'API !

Nous allons ici principalement voir comment écrire le code app.py, le fichier requirements.txt et le Dockerfile.

Créer l'app FastAPI

Créez un fichier Python nommé app.py.

À l'intérieur de ce fichier, importez les modules requis :

import uvicorn
import numpy as np
from fastapi import FastAPI, File, UploadFile, Request
from torchvision import transforms
import onnxruntime
from PIL import Image
from io import BytesIO
import itertools

Initialisez une instance de FastAPI :

app = FastAPI()

Chargez le modèle DenseNet au format ONNX :

session = onnxruntime.InferenceSession("/workspace/models/densenet_onnx_cifar10/1/densenet_onnx_cifar10.onnx", device="cuda")

Créez le dictionnaire avec l'index et le nom des classes :

Trouvez plus d'informations sur ces ID et noms de classes dans le notebook tutoriel.

idx_to_class = {0: 'AIRPLANE', 1: 'AUTOMOBILE', 2: 'BIRD', 3: 'CAT', 4: 'DEER', \
                5: 'DOG', 6: 'FROG', 7: 'HORSE', 8: 'SHIP', 9: 'TRUCK'}

Définissez la fonction Python qui traite les images en entrée :

def process_img(file) -> Image.Image:

    transform = transforms.Compose([
            transforms.Resize(size=224),
            transforms.CenterCrop(size=224),
            transforms.ToTensor(),
            transforms.Normalize([0.485, 0.456, 0.406],
                                 [0.229, 0.224, 0.225])
        ])

    test_image = Image.open(BytesIO(file))
    test_image_tensor = transform(test_image).unsqueeze(0)
    test_image_tensor = test_image_tensor.view(1, 3, 224, 224)

    np_image = test_image_tensor.numpy()

    return np_image.astype(np.float32)

Créez la fonction Python permettant d'obtenir le résultat de la prédiction :

def get_prediction(data):

    input_name = session.get_inputs()[0].name
    output_name = session.get_outputs()[0].name

    result = session.run([output_name], {input_name: data})

    return result

Définissez la méthode GET :

@app.get('/')
def root():
    return {'message': 'Welcome to the Image Classification API'}

Créez la méthode POST :

@app.post("/uploadimage/")
async def create_upload_file(file: bytes = File(...)):

    data = process_img(file)

    result = get_prediction(data)

    predictions_result = {}
    for i in range(10):
        p = np.array(result).squeeze()
        predictions_result[idx_to_class[i]]=p[i]

    top_classes = dict(sorted(predictions_result.items(), key=lambda x:x[1], reverse=True))
    for value in top_classes:
        top_classes[value] = top_classes[value].item()

    return dict(itertools.islice(top_classes.items(), 3))

Écrire le fichier requirements.txt de l'application

Le fichier requirements.txt nous permettra d'indiquer tous les modules nécessaires au fonctionnement de notre application. Ce fichier sera utile lors de l'écriture du Dockerfile.

uvicorn==0.23.2
numpy==1.25.2
fastapi==0.103.1
python-multipart==0.0.6
torch==2.0.1
torchvision==0.15.2
onnx==1.14.1
onnxruntime==1.15.1
pillow==10.0.0

Écrire le Dockerfile de l'application

Votre Dockerfile doit commencer par l'instruction FROM indiquant l'image parente à utiliser. Dans notre cas, nous choisissons de partir d'une image python:3.10 :

FROM python:3.10

Créez le répertoire personnel et ajoutez-y vos fichiers :

WORKDIR /workspace
ADD . /workspace

Installez le fichier requirements.txt qui contient les modules Python nécessaires à l'aide d'une commande pip install ... :

RUN pip install -r requirements.txt

Définissez votre commande de lancement par défaut pour démarrer l'application :

ENTRYPOINT ["uvicorn"]
CMD ["app:app", "--host", "0.0.0.0", "--port", "8080"]

Attribuez les droits d'accès corrects à l'utilisateur OVHcloud (42420:42420) :

RUN chown -R 42420:42420 /workspace
ENV HOME=/workspace

Construire l'image Docker depuis le Dockerfile

Depuis le répertoire contenant votre Dockerfile, exécutez l'une des commandes suivantes pour construire l'image de votre application :

# Build the image using your machine's default architecture
docker build . -t densenet-onnx-fastapi:latest

# Build image targeting the linux/amd64 architecture
docker buildx build --platform linux/amd64 -t densenet-onnx-fastapi:latest .
  • La première commande construit l'image en utilisant l'architecture par défaut de votre système. Cela peut fonctionner si votre machine utilise déjà l'architecture linux/amd64, qui est requise pour exécuter des containers avec nos produits AI. Cependant, sur des systèmes avec une architecture différente (par exemple ARM64 sur Apple Silicon), l'image résultante ne sera pas compatible et ne pourra pas être déployée.

  • La seconde commande cible explicitement l'architecture linux/amd64 afin de garantir la compatibilité avec nos services AI. Elle nécessite buildx, qui n'est pas installé par défaut. Si vous n'avez jamais utilisé buildx auparavant, vous pouvez l'installer en exécutant : docker buildx install

Info

L'argument point . indique que votre contexte de build (emplacement du Dockerfile et des autres fichiers nécessaires) est le répertoire courant.

L'argument -t vous permet de choisir l'identifiant à donner à votre image. Les identifiants d'image sont généralement composés d'un nom et d'un tag de version <name>:<version>. Pour cet exemple, nous avons choisi densenet-onnx-fastapi:latest.

Envoyer l'image vers le registre partagé

Warning

Avertissement Le registre partagé d'AI Deploy ne doit être utilisé qu'à des fins de test. Pensez à rattacher votre propre registre Docker. Plus d'informations à ce sujet sont disponibles ici. Les images envoyées vers ce registre sont réservées aux workloads AI Tools et ne seront pas accessibles pour des usages externes.

Warning

Afin d'exécuter des containers utilisant les produits AI, veuillez vous assurer que l'image Docker que vous allez envoyer respecte l'architecture cible linux/amd64. Vous pouvez, par exemple, construire votre image en utilisant buildx comme suit :

docker buildx build --platform linux/amd64 ...

Trouvez l'adresse de votre registre partagé en lançant cette commande :

ovhai registry list

Connectez-vous au registre partagé avec vos identifiants habituels d'utilisateur AI Platform :

docker login -u `<user>` -p <password> `<shared-registry-address>`

Envoyez l'image compilée vers le registre partagé :

docker tag densenet-onnx-fastapi:latest `<shared-registry-address>`/densenet-onnx-fastapi:latest
docker push `<shared-registry-address>`/densenet-onnx-fastapi:latest

Lancer l'app AI Deploy

La commande suivante démarre une nouvelle app exécutant votre app FastAPI :

ovhai app run `<shared-registry-address>`/densenet-onnx-fastapi:latest \
	   --gpu 1 \
	   --volume densenet-cifar10-onnx-model@GRA/:/workspace/models:RO
Info

Notes

  • --gpu 1 : l'utilisation du modèle nécessite un GPU (device="cuda"). Veuillez choisir au moins 1 GPU.

  • Pensez à ajouter l'attribut --unsecure-http si vous souhaitez que votre application soit accessible sans authentification.

Interagir avec l'API déployée via le dashboard

En cliquant sur le lien de votre app AI Deploy, vous arriverez sur la page suivante.

APIAccess

Comment interagir avec votre API ?

Vous pouvez ajouter /docs à la fin de l'URL de votre app.

Dans notre exemple, l'URL est la suivante : https://1207af6f-1f5f-4c57-9c64-8738b89a16c8.app.gra.ai.cloud.ovh.net/docs

Elle fournit un dashboard complet pour interagir avec l'API !

APIDocs

Pour pouvoir envoyer une image à classifier, sélectionnez /uploadimage/ dans l'encart vert. Cliquez sur Try it out et ajoutez l'image de votre choix dans la zone dédiée.

APIImage

Pour obtenir le résultat de la prédiction, cliquez sur le bouton Execute.

APIPrediction

Félicitations ! Vous avez obtenu les résultats de la prédiction avec les labels et les scores de confiance.

Aller plus loin

Pour une formation ou une assistance technique sur la mise en œuvre de nos solutions, contactez votre commercial ou consultez la page Professional Services pour obtenir un devis et faire analyser votre projet par nos experts.

Cette page vous a-t-elle aidé ?