Servir un modèle ou un outil en API avec FastAPI
Enveloppez un modèle ou une fonction de scoring dans un endpoint FastAPI : une requête et une réponse typées avec Pydantic, une route POST /predict, exécutez-le avec uvicorn et appelez-le — puis voyez pourquoi le schéma OpenAPI généré automatiquement permet à un agent IA de l’appeler comme un outil.
Transformez un modèle entraîné ou une fonction utile en une API HTTP que des applications — et des agents IA — peuvent appeler, avec FastAPI. Enveloppez le modèle, déclarez une requête et une réponse typées avec Pydantic pour que les entrées invalides soient rejetées à votre place, exposez un endpoint POST /predict, exécutez-le en local avec uvicorn, et appelez-le avec du vrai JSON capturé. Voyez ensuite pourquoi le schéma OpenAPI généré automatiquement est exactement ce qui permet à un agent IA de découvrir et d’appeler votre endpoint comme un outil. Copiez le code et exécutez-le en local.
- Servir un modèle, c’est le placer derrière une URL que d’autres programmes peuvent appeler — pas envoyer un fichier pickle par e-mail. FastAPI est le framework Python moderne pour cela : quelques lignes enveloppent votre modèle dans une API (application programming interface — une URL qu’un programme appelle pour obtenir des données ou déclencher une action) que n’importe quelle application, n’importe quel script ou agent IA peut atteindre en HTTP.
- Déclarez une requête et une réponse typées avec Pydantic — le framework valide l’entrée à votre place. Un modèle Pydantic est une classe qui liste les champs attendus et leurs types ; FastAPI la lit, si bien qu’une requête à laquelle il manque un champ, ou qui envoie le mauvais type, est rejetée par une erreur
422claire avant même que votre modèle ne s’exécute. Cette validation, c’est le jugement qu’une réponse d’IA en un seul prompt saute. - Une fonction décorée est un endpoint.
@app.post("/predict")sur une fonction en fait un endpoint POST (une URL sur laquelle l’API répond) ; à l’intérieur, vous exécutez le modèle et retournez un dict, que FastAPI sérialise en JSON. - Exécutez-le en local avec une seule commande :
uvicorn main:app. Uvicorn est le serveur qui exécute votre application ; vous appelez ensuite l’endpoint aveccurlou le module Pythonrequestset récupérez le vrai JSON en retour. - Le schéma OpenAPI généré automatiquement est ce qui fait de votre endpoint un outil. FastAPI publie une documentation interactive sur
/docset une description OpenAPI exploitable par une machine sur/openapi.json— le même contrat typé qui permet à une application ou à un agent IA de découvrir votre endpoint et de l’appeler correctement.
Introduction
Vous avez entraîné un modèle. Il donne de bons scores, il dort dans un notebook, et maintenant un collègue — ou une application web, ou un agent IA — a besoin de l’utiliser. La mauvaise réponse, c’est d’envoyer par e-mail un fichier pickle et un paragraphe d’instructions : chaque appelant a alors besoin de votre Python exact, de vos versions de paquets exactes, et de votre code pour le charger. La bonne réponse, c’est de le servir — placer le modèle derrière une URL pour que tout ce qui sait émettre une requête HTTP puisse envoyer des caractéristiques et récupérer une prédiction, dans n’importe quel langage, sans rien installer.
FastAPI est le framework Python moderne pensé précisément pour cela. Une API (application programming interface) est un ensemble d’URL qu’un programme appelle au lieu qu’un humain clique sur une page ; FastAPI vous permet d’exposer votre modèle sous cette forme en quelques lignes, et — ce qui le distingue d’un framework web brut — il lit les annotations de type Python pour valider chaque requête entrante à votre place. Cette leçon construit tout le parcours sur un exemple petit et reproductible : envelopper un modèle minuscule, déclarer une requête et une réponse typées avec Pydantic, exposer un endpoint POST /predict, l’exécuter avec uvicorn, l’appeler, et lire le schéma généré automatiquement qui permet à un agent IA de l’appeler lui aussi.
Un serveur en cours d’exécution n’est pas quelque chose que le navigateur peut exécuter, donc rien sur cette page ne tourne en direct — copiez le code dans un fichier et exécutez-le en local. Installez les composants une bonne fois dans l’environnement virtuel de votre projet (voir Environnements virtuels et dépendances en Python) :
pip install "fastapi[standard]" scikit-learnLe modèle que nous allons servir
Servir suppose d’avoir quelque chose à servir. Pour garder l’exemple entièrement reproductible, nous entraînons un classifieur minuscule au démarrage — une LogisticRegression sur le jeu de données iris intégré, qui prédit l’espèce d’une fleur à partir de quatre mesures. En situation réelle, vous chargeriez plutôt un modèle entraîné au préalable (model = joblib.load("model.joblib")) ; le code de service autour reste identique dans les deux cas.
from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
X, y = load_iris(return_X_y=True)
model = LogisticRegression(max_iter=1000).fit(X, y)
CLASS_NAMES = ["setosa", "versicolor", "virginica"]model.predict([[5.1, 3.5, 1.4, 0.2]]) retourne désormais un indice de classe (0, 1 ou 2) ; CLASS_NAMES le retraduit en une espèce lisible. La seule règle qui compte pour le service : chargez le modèle une seule fois, au démarrage de l’application — pas à l’intérieur du gestionnaire de requête. Nous reviendrons sur le pourquoi dans Problèmes fréquents.
Une application FastAPI minimale
Tout, dans FastAPI, part d’un unique objet application. Créez-le, puis rattachez une fonction à une URL avec un décorateur d’opération de chemin (path operation decorator) — @app.get("/") signifie « exécute cette fonction sur une requête GET vers / ». Un minuscule endpoint de vérification d’état (health check) est le « hello world » :
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"status": "ok"}La fonction décorée retourne un simple dict Python, et FastAPI le sérialise automatiquement en une réponse JSON — {"status":"ok"}. C’est la forme de tout endpoint : une fonction, décorée avec la méthode HTTP et le chemin sur lequel elle répond, qui retourne des données. Passons maintenant au vrai — mais d’abord, nous indiquons à FastAPI à quoi ressemblent la requête et la réponse. Le tutoriel complet du framework sur ce point est First Steps.
Typer la requête et la réponse avec Pydantic
C’est ici que FastAPI justifie sa place face à un framework web nu. Une requête de prédiction transporte quatre nombres — mais lesquels, dans quel ordre, et que se passe-t-il si un appelant en oublie un ou envoie "tall" à la place d’un nombre ? Vous répondez à cela une fois, de façon déclarative, avec un modèle Pydantic : une classe qui hérite de BaseModel et liste chaque champ avec son type. FastAPI le lit et l’applique à chaque requête.
from pydantic import BaseModel
class IrisFeatures(BaseModel):
sepal_length: float
sepal_width: float
petal_length: float
petal_width: float
class Prediction(BaseModel):
species: str
class_id: int
confidence: floatIrisFeatures est le schéma de requête — la forme du JSON qu’un appelant doit envoyer ; Prediction est le schéma de réponse — la forme que vous promettez de retourner. Un schéma, ici, désigne simplement un contrat typé : des champs nommés avec des types déclarés. Parce que vous les avez déclarés, trois choses se produisent gratuitement : FastAPI parse le JSON entrant en un objet IrisFeatures, le valide (bons champs, bons types), et le documente. Vous n’écrivez aucun test if "sepal_length" not in body — l’annotation de type est la validation. Déclarer un corps de requête de cette manière est expliqué dans le tutoriel FastAPI sur le corps de requête.
L’endpoint /predict
Reliez maintenant le modèle à une URL. @app.post("/predict") crée un endpoint POST (POST est la méthode HTTP pour envoyer des données) ; la fonction prend un argument IrisFeatures, si bien que FastAPI valide le corps de la requête contre ce modèle et vous remet un objet prêt à l’emploi. response_model=Prediction promet la forme de la sortie. Voici l’application complète — enregistrez-la sous main.py :
from fastapi import FastAPI
from pydantic import BaseModel
from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
# Load (here: train) the model ONCE, when the app starts — not per request.
X, y = load_iris(return_X_y=True)
model = LogisticRegression(max_iter=1000).fit(X, y)
CLASS_NAMES = ["setosa", "versicolor", "virginica"]
app = FastAPI()
class IrisFeatures(BaseModel):
sepal_length: float
sepal_width: float
petal_length: float
petal_width: float
class Prediction(BaseModel):
species: str
class_id: int
confidence: float
@app.post("/predict", response_model=Prediction)
def predict(features: IrisFeatures) -> Prediction:
row = [[
features.sepal_length, features.sepal_width,
features.petal_length, features.petal_width,
]]
class_id = int(model.predict(row)[0])
confidence = float(model.predict_proba(row)[0][class_id])
return Prediction(
species=CLASS_NAMES[class_id],
class_id=class_id,
confidence=round(confidence, 4),
)Lisez le gestionnaire de haut en bas : features arrive déjà validé, vous construisez donc la ligne de caractéristiques directement à partir de ses attributs, appelez le modèle exactement comme vous le feriez dans un notebook, et retournez une Prediction. model.predict_proba donne les probabilités de classe, nous retournons donc la probabilité de la classe gagnante en tant que confidence — une petite honnêteté dont l’appelant vous saura gré. Voilà tout le service : une requête validée en entrée, une prédiction typée en sortie.
Exécutez-le en local avec uvicorn
Votre application est un objet Python ; il lui faut un serveur pour recevoir les requêtes HTTP et les lui transmettre. Ce serveur, c’est uvicorn, un serveur ASGI (Asynchronous Server Gateway Interface — la façon standard dont une application web Python et un serveur web dialoguent). Pointez-le sur main:app — l’objet app de main.py :
uvicorn main:app --reloadINFO: Started server process [57778]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
Votre modèle est désormais en ligne sur http://127.0.0.1:8000. --reload redémarre le serveur à chaque fois que vous modifiez le fichier — pratique pendant le développement, à retirer sinon. Cette unique commande est tout ce que cette leçon aborde côté exécution : passer de là à un déploiement public, en production (un gestionnaire de processus, un conteneur, HTTPS), est un sujet à part — le guide de déploiement de FastAPI le couvre quand vous en aurez besoin.
Appelez-le
Le serveur tournant, appelez l’endpoint depuis un second terminal. curl est la vérification la plus rapide — envoyez un corps JSON en POST et lisez la réponse :
curl -X POST http://127.0.0.1:8000/predict \
-H "Content-Type: application/json" \
-d '{"sepal_length": 5.1, "sepal_width": 3.5, "petal_length": 1.4, "petal_width": 0.2}'{"species":"setosa","class_id":0,"confidence":0.9816}
C’est tout l’intérêt réalisé : quatre nombres en entrée, une espèce et une confiance en sortie, en HTTP — pas de Python, pas de pickle, aucun environnement partagé côté appelant. Depuis Python, vous utiliseriez requests (voir Requêtes HTTP et API en Python), en passant le corps à json= et en lisant r.json() en retour :
import requests
r = requests.post(
"http://127.0.0.1:8000/predict",
json={"sepal_length": 6.9, "sepal_width": 3.1, "petal_length": 5.4, "petal_width": 2.1},
timeout=10,
)
print(r.status_code)
print(r.json())200
{'species': 'virginica', 'class_id': 2, 'confidence': 0.9065}
Même endpoint, une autre fleur, un 200 OK et une prédiction virginica. Le service se moque de savoir si l’appelant est curl, un script Python, un front-end JavaScript ou un agent — tous parlent le même HTTP.
La validation que vous avez obtenue gratuitement
Vous vous souvenez du modèle Pydantic ? Voici le retour sur investissement. Envoyez une requête erronée — un champ manquant — et vous n’atteignez jamais le modèle ; FastAPI la rejette par un 422 Unprocessable Entity et un message précis qui nomme le problème :
curl -X POST http://127.0.0.1:8000/predict \
-H "Content-Type: application/json" \
-d '{"sepal_length": 5.1, "sepal_width": 3.5, "petal_length": 1.4}'{"detail":[{"type":"missing","loc":["body","petal_width"],"msg":"Field required","input":{"sepal_length":5.1,"sepal_width":3.5,"petal_length":1.4}}]}
L’erreur pointe droit sur le coupable — loc: ["body", "petal_width"], "Field required". Envoyez les bons champs mais le mauvais type — "tall" là où un nombre est attendu — et la validation l’attrape aussi :
{"detail":[{"type":"float_parsing","loc":["body","sepal_length"],"msg":"Input should be a valid number, unable to parse string as a number","input":"tall"}]}
Vous n’avez écrit aucune de ces vérifications. C’est le jugement qu’une IA en une ligne saute : demandez à un assistant de « servir mon modèle » et vous obtiendrez souvent un gestionnaire qui lit un dict brut et le passe directement à model.predict, si bien qu’une requête malformée devient un 500 déroutant qui plante au fond de scikit-learn, au lieu d’un 422 net qui dit à l’appelant ce qu’il a fait de travers. Le schéma typé transforme le « garbage in » en un rejet précis et auto-documenté, dès la porte.
La documentation interactive — et pourquoi un agent peut appeler votre outil
Démarrez le serveur et ouvrez http://127.0.0.1:8000/docs dans un navigateur : FastAPI a généré une page de documentation complète et interactive — chaque endpoint, les formes exactes de la requête et de la réponse, et un bouton « Try it out » — à partir de vos seules annotations de type. Vous n’avez écrit aucune documentation ; les modèles Pydantic sont la documentation.
Cette page est une vue lisible par un humain de quelque chose de plus important. FastAPI sert aussi une description exploitable par une machine de toute votre API sur http://127.0.0.1:8000/openapi.json, suivant le standard OpenAPI (un format indépendant du langage pour décrire les API HTTP). Voici la partie qui décrit /predict et le schéma de requête :
{
"paths": {
"/predict": {
"post": {
"summary": "Predict",
"operationId": "predict_predict_post",
"requestBody": {
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/IrisFeatures"}
}
},
"required": true
}
}
}
},
"components": {
"schemas": {
"IrisFeatures": {
"type": "object",
"required": ["sepal_length", "sepal_width", "petal_length", "petal_width"],
"properties": {
"sepal_length": {"type": "number", "title": "Sepal Length"},
"sepal_width": {"type": "number", "title": "Sepal Width"},
"petal_length": {"type": "number", "title": "Petal Length"},
"petal_width": {"type": "number", "title": "Petal Width"}
}
}
}
}
}Lisez ce que cela dit : il y a un POST /predict, son corps doit être un objet avec quatre champs number obligatoires, nommés. C’est un contrat précis, exploitable par une machine — et c’est exactement ce dont un agent IA a besoin. Un endpoint qu’un agent peut appeler est un outil, et la description d’un outil, c’est un nom, les arguments qu’il prend, et leurs types. FastAPI a généré cette description à partir des mêmes annotations de type qui pilotent votre validation. Ainsi, les serveurs Model Context Protocol (MCP) et les frameworks de function-calling qui permettent à des agents comme Claude ou ChatGPT d’utiliser des outils externes peuvent consommer votre schéma OpenAPI et savoir comment appeler /predict correctement — les champs obligatoires, leurs types, la forme de la réponse — sans que vous écriviez une spécification d’outil séparée. Le schéma typé que vous avez écrit pour la validation est, tel quel, le contrat d’outil que lit un agent. C’est la raison durable de se tourner vers FastAPI à l’ère agentique : la discipline qui rend votre API sûre pour les applications est la même que celle qui la rend appelable par des agents.
Vous avez un modèle ou une fonction de scoring à exposer ? Décrivez-le à Prova — « enveloppe cette fonction dans un endpoint FastAPI avec une requête et une réponse typées avec Pydantic » — puis exécutez l’application en local et interrogez-la vous-même avec curl. Prova rédige l’endpoint et le schéma ; c’est la vraie réponse 200 de votre serveur en marche qui est la preuve, pas sa parole. Et comme le schéma OpenAPI qu’elle génère est ce que lit un agent, vous pouvez vérifier que le contrat est correct en ouvrant /docs. The runtime is the judge. Demander à Prova →
Problèmes fréquents
Chaque requête reçoit un 422 et n’atteint jamais mon modèle. FastAPI valide le corps contre votre modèle Pydantic et le rejette — le champ detail dit exactement pourquoi. Les causes habituelles : l’appelant a envoyé les mauvais noms de champs (les vôtres sont sepal_length, pas sepalLength), a oublié un champ obligatoire, a envoyé une chaîne là où un nombre est attendu, ou n’a pas défini Content-Type: application/json. Lisez le loc dans l’erreur — ["body", "petal_width"] nomme le champ fautif — et corrigez la requête. Un 422, c’est la validation qui fonctionne, pas un bug.
Le modèle se charge à chaque requête et l’API est lente. Vous avez placé le load_iris(...).fit(...) (ou joblib.load(...)) à l’intérieur de la fonction predict, si bien qu’il se réentraîne / se recharge à chaque appel. Chargez le modèle une seule fois au niveau du module — comme dans le main.py ci-dessus, où le modèle est créé avant app — pour qu’il vive en mémoire pendant toute la durée du processus et que chaque requête n’exécute que model.predict. Charger un vrai modèle à chaque requête peut ajouter des secondes à chaque appel.
ERROR: [Errno 48] Address already in use. Le port 8000 est occupé — généralement un uvicorn précédent que vous n’avez pas arrêté. Soit vous arrêtez l’ancien processus, soit vous lancez sur un autre port : uvicorn main:app --port 8001. Sur le nouveau port, votre endpoint est http://127.0.0.1:8001/predict.
Les requêtes s’accumulent et le serveur devient extrêmement lent sous la charge. La cause habituelle est un gestionnaire async def qui effectue un travail bloquant à l’intérieur — un predict de scikit-learn, une transformation pandas, un appel de bibliothèque synchrone. Un gestionnaire async def s’exécute sur la boucle d’événements, donc un travail bloquant y gèle toutes les autres requêtes jusqu’à ce qu’il se termine. La solution est un gestionnaire def ordinaire : FastAPI exécute les gestionnaires def dans un threadpool, hors de la boucle d’événements, si bien qu’un travail bloquant ne bloque plus le serveur. (La règle conceptuelle indiquant quand utiliser l’un ou l’autre est dans la FAQ ci-dessous ; pour un endpoint qui sert un modèle, def est le bon choix par défaut.)
Questions fréquentes
Les deux permettent de construire une API web en Python, mais FastAPI est bâti autour des annotations de type Python : vous déclarez les formes de la requête et de la réponse avec des modèles Pydantic, et FastAPI valide chaque requête, sérialise la réponse et génère gratuitement une documentation OpenAPI interactive. Flask ne fait rien de tout cela automatiquement — vous validez et documentez à la main ou avec des extensions. FastAPI est aussi natif de l’asynchrone (bâti sur ASGI), donc il gère bien les requêtes concurrentes. Pour servir un modèle ou exposer une API typée aujourd’hui, FastAPI est le choix courant ; Flask reste très bien pour de petites applications simples. Voir la documentation de FastAPI.
Enveloppez le modèle dans un framework web et exposez un endpoint qui l’exécute. Avec FastAPI : chargez le modèle entraîné une seule fois au démarrage de l’application (joblib.load(...) au niveau du module), définissez un modèle Pydantic pour les caractéristiques d’entrée et un pour la prédiction, et écrivez un gestionnaire @app.post("/predict") qui prend le modèle d’entrée, appelle model.predict et retourne le modèle de prédiction. Exécutez-le avec uvicorn main:app, puis n’importe quel client peut envoyer des caractéristiques en POST et récupérer une prédiction en JSON. Passer d’un serveur local à un déploiement public, disponible en permanence (un gestionnaire de processus, un conteneur, HTTPS) est une étape supplémentaire couverte dans la documentation de déploiement de FastAPI.
Pydantic est une bibliothèque de validation de données qui s’appuie sur les annotations de type Python : vous définissez une classe qui hérite de BaseModel avec des champs typés, et Pydantic parse et valide n’importe quelle donnée contre elle, en levant une erreur claire lorsqu’elle ne correspond pas. FastAPI utilise des modèles Pydantic pour décrire les corps de requête et les réponses, si bien que déclarer le modèle revient à déclarer la validation et la documentation. C’est pourquoi un endpoint FastAPI rejette une requête malformée par un 422 précis avant que votre code ne s’exécute — les annotations de type font la vérification.
Oui — c’est un usage naturel. FastAPI génère automatiquement une description OpenAPI de votre API sur /openapi.json : un contrat exploitable par une machine qui liste chaque endpoint, ses champs obligatoires et leurs types. Les agents IA appellent des fonctionnalités externes à travers des outils, et un outil se définit précisément par cela — un nom, ses arguments, et leurs types. Les frameworks de function-calling et les serveurs MCP peuvent consommer votre schéma OpenAPI (ou envelopper vos endpoints) pour qu’un agent sache appeler votre endpoint correctement. Le schéma Pydantic typé que vous avez écrit pour la validation fait aussi office de contrat d’outil que lit l’agent.
async def pour un endpoint FastAPI ?
Non. Utilisez un def ordinaire quand le gestionnaire effectue un travail bloquant comme le predict d’un modèle ou une opération pandas — FastAPI exécute les gestionnaires def dans un threadpool, donc ils ne bloquent pas le serveur. N’utilisez async def que lorsque vous faites await sur des I/O véritablement asynchrones (un pilote de base de données asynchrone, un client HTTP asynchrone). Écrire async def puis y effectuer un travail bloquant est une erreur de performance courante. Pour servir un modèle, def est le bon choix par défaut.
Testez vos connaissances
Le même motif sert n’importe quel appelable, pas seulement un modèle de ML. Supposons que vous ayez une simple fonction de scoring :
def risk_score(age: int, systolic_bp: int) -> float:
return round(0.02 * age + 0.03 * (systolic_bp - 120), 2)Enveloppez-la dans une application FastAPI que n’importe quel appelant — ou agent — peut utiliser.
Tâche 1. Définissez un modèle de requête Pydantic Patient avec deux champs entiers, age et systolic_bp, et un modèle de réponse Score avec un champ flottant, score.
Tâche 2. Écrivez un endpoint POST /score (avec response_model=Score) qui prend un Patient, appelle risk_score et retourne un Score.
Tâche 3. Donnez la commande qui exécute l’application dans main.py, ainsi que la commande curl qui score une personne de 60 ans avec une pression artérielle systolique de 140.
La structure reprend exactement celle de l’application iris : from fastapi import FastAPI, from pydantic import BaseModel, définissez Patient(BaseModel) et Score(BaseModel), puis @app.post("/score", response_model=Score) sur une fonction prenant patient: Patient. Construisez le score avec risk_score(patient.age, patient.systolic_bp). Exécutez avec uvicorn main:app, et envoyez un corps JSON en POST avec curl -X POST ... -d '{"age": 60, "systolic_bp": 140}'.
from fastapi import FastAPI
from pydantic import BaseModel
def risk_score(age: int, systolic_bp: int) -> float:
return round(0.02 * age + 0.03 * (systolic_bp - 120), 2)
app = FastAPI()
class Patient(BaseModel):
age: int
systolic_bp: int
class Score(BaseModel):
score: float
@app.post("/score", response_model=Score)
def score(patient: Patient) -> Score:
value = risk_score(patient.age, patient.systolic_bp)
return Score(score=value)Exécutez-la, puis appelez-la :
uvicorn main:app --reloadcurl -X POST http://127.0.0.1:8000/score \
-H "Content-Type: application/json" \
-d '{"age": 60, "systolic_bp": 140}'La réponse est {"score":1.8} (0.02 * 60 + 0.03 * 20 = 1.2 + 0.6 = 1.8). Notez que age et systolic_bp sont typés int, donc une requête envoyant "sixty" est rejetée par un 422 avant que risk_score ne s’exécute — la même validation gratuite dont le modèle iris a bénéficié.
Vérification rapide. Un appelant envoie en POST {"sepal_length": 5.1, "sepal_width": 3.5, "petal_length": 1.4, "petal_width": 0.2} vers votre endpoint /predict mais reçoit un 422 avec "loc": ["body", "petal_width"] — alors même que petal_width est manifestement présent. Quelle est l’unique chose la plus probablement en cause ?
La requête n’a presque certainement pas été envoyée en JSON — l’appelant a omis -H "Content-Type: application/json" (ou, en Python requests, a utilisé data= au lieu de json=). Sans cet en-tête, FastAPI ne parse pas le corps comme du JSON, il ne voit donc aucun champ valide et signale le premier champ obligatoire comme manquant. Ajoutez le type de contenu JSON (ou utilisez json= dans requests) et le corps se valide. Plus largement, un 422 avec un loc nomme toujours le champ dont FastAPI n’est pas satisfait — lisez-le avant de supposer que ce sont vos données qui sont fausses.
Conclusion
Servir un modèle est un motif simple et reproductible : enveloppez le modèle (chargé une seule fois au démarrage), déclarez une requête et une réponse typées avec Pydantic pour que FastAPI valide chaque appel à votre place, exposez-le comme un endpoint @app.post("/predict"), exécutez-le avec uvicorn main:app, et appelez-le avec curl ou requests. Vous obtenez des erreurs 422 précises sur les entrées invalides, une documentation /docs interactive, et — le gain durable — un schéma OpenAPI généré automatiquement qui est exactement le contrat exploitable par une machine dont une application ou un agent IA a besoin pour appeler votre endpoint comme un outil. Le jugement qu’une réponse en un seul prompt saute, c’est le schéma typé : il transforme un gestionnaire fragile en un service auto-documenté et appelable par un agent. Copiez main.py, exécutez-le en local, et envoyez vos propres caractéristiques en POST — c’est la vraie réponse qui prouve que ça marche.
Leçons connexes
- Poursuivez avec : Requêtes HTTP et API en Python avec requests — le côté client de la même conversation : appelez l’API que vous venez de construire · Environnements virtuels et dépendances en Python — installez FastAPI et scikit-learn dans un environnement isolé et épinglé · Tester du code Python avec pytest — écrivez des tests qui prouvent que votre endpoint retourne ce que vous attendez.
- Allez plus loin : la série Outils et workflow Python · Logging et débogage en Python — instrumentez les requêtes que votre service traite · le pilier Programmation pour l’ensemble des leçons R et Python.
Réutilisation
Citation
@online{2026,
author = {},
title = {Servir un modèle ou un outil en API avec FastAPI},
date = {2026-07-19},
url = {https://www.datanovia.com/learn/programming/python-tools/serve-model-api-fastapi},
langid = {fr}
}