Extraire des données structurées d’un texte libre avec un modèle de langage a longtemps reposé sur une méthode fragile : demander dans le prompt de répondre « au format JSON », puis espérer que la réponse soit effectivement un JSON valide, avant de tenter un json_decode() qui échouait une fois sur dix sur des cas limites. Les sorties structurées, apparues plus largement en 2024, changent la donne en contraignant réellement le format de la réponse au niveau de l’API elle-même.
Ce tutoriel ne traite pas le function calling, abordé séparément : il porte sur l’extraction directe de données structurées à partir d’un texte, sans notion d’appel de fonction ni d’exécution d’action.
La différence entre demander du JSON et l’imposer
Demander « réponds en JSON » dans un prompt reste une instruction que le modèle peut mal suivre, en ajoutant du texte explicatif avant ou après l’objet JSON, ou en produisant une syntaxe légèrement invalide. Le mode de sortie structurée fonctionne différemment : il contraint techniquement la génération du modèle, token par token, pour qu’elle respecte un schéma JSON fourni dans la requête, rendant une sortie non conforme au schéma nettement moins probable.
Définir un schéma précis pour l’extraction
Prenons un cas concret : extraire d’un communiqué de presse envoyé par un client les informations structurées nécessaires pour préremplir un formulaire d’article — titre suggéré, date d’événement, ville, et liste de personnes citées.
$schema = array(
'type' => 'object',
'properties' => array(
'titre_suggere' => array( 'type' => 'string' ),
'date_evenement' => array( 'type' => 'string', 'description' => 'Format AAAA-MM-JJ' ),
'ville' => array( 'type' => 'string' ),
'personnes_citees' => array(
'type' => 'array',
'items' => array( 'type' => 'string' ),
),
),
'required' => array( 'titre_suggere', 'date_evenement', 'ville', 'personnes_citees' ),
'additionalProperties' => false,
);

Envoyer le schéma dans la requête à l’API
Le schéma accompagne la requête dans un paramètre dédié au format de sortie, distinct du contenu du message. La structure exacte de ce paramètre varie selon le fournisseur, mais le principe reste le même : le schéma est transmis en même temps que le prompt, pas décrit uniquement en langage naturel dans le texte de l’instruction.
$reponse = wp_remote_post( 'https://api.openai.com/v1/chat/completions', array(
'timeout' => 20,
'headers' => array(
'Authorization' => 'Bearer ' . WPM_LLM_API_KEY,
'Content-Type' => 'application/json',
),
'body' => wp_json_encode( array(
'model' => 'gpt-4o-mini',
'messages' => array(
array( 'role' => 'user', 'content' => $texte_communique ),
),
'response_format' => array(
'type' => 'json_schema',
'json_schema' => array(
'name' => 'extraction_communique',
'schema' => $schema,
'strict' => true,
),
),
) ),
) );
La validation PHP reste obligatoire malgré tout
Le mode structuré garantit que la réponse respecte la forme du schéma : les bons types, les bonnes clés. Il ne garantit en rien que le contenu est correct sur le fond. Une date d’événement peut être structurellement valide, au format attendu, tout en étant erronée parce que le modèle l’a mal extraite du texte source. La validation métier reste donc entièrement à la charge du code PHP.
function wpm_valider_extraction( $donnees ) {
$erreurs = array();
if ( ! empty( $donnees['date_evenement'] )
&& ! preg_match( '/^\d{4}-\d{2}-\d{2}$/', $donnees['date_evenement'] ) ) {
$erreurs[] = 'Format de date invalide.';
}
if ( empty( $donnees['ville'] ) || mb_strlen( $donnees['ville'] ) > 100 ) {
$erreurs[] = 'Ville manquante ou anormalement longue.';
}
return $erreurs;
}
Le champ toujours prérempli, jamais publié directement
Les données extraites servent uniquement à préremplir le formulaire de création d’article dans l’administration, jamais à publier un article automatiquement. Une personne de la rédaction vérifie et corrige chaque champ avant l’enregistrement effectif, ce qui absorbe les erreurs d’extraction qui échapperaient à la validation technique.
Ce que le mode structuré a changé concrètement
Avant l’usage des sorties structurées, environ une extraction sur dix nécessitait un nouvel appel à cause d’un JSON mal formé. Ce taux d’échec technique est tombé à un niveau négligeable avec le schéma imposé, ce qui a permis de retirer entièrement la logique de nouvelle tentative automatique que nous devions maintenir auparavant.
Le format structuré résout un problème de forme. Il ne dispense jamais de vérifier le fond, particulièrement sur des données qui finiront dans un formulaire prérempli.
Notre verdict
Pour toute extraction de données à partir d’un texte libre, les sorties structurées constituent désormais le point de départ par défaut plutôt qu’une instruction textuelle espérant un JSON bien formé. Elles réduisent fortement les erreurs de format, mais n’exemptent jamais de la validation métier appliquée ensuite côté PHP.