Classification des images avec Cloudflare Worker

Aujourd'hui, nous expérimentons une fonctionnalité d'IA utile qui concerne la classification des images, c'est-à-dire un modèle d'IA créé spécifiquement pour renvoyer une explication écrite d'une image via l'URL image. À quoi peut-il servir? Comme première application, savoir ce qui se trouve à l'intérieur d'une image sans même l'ouvrir ; cela ouvre les portes à une série d'autres applications telles que la reconnaissance de l'abus ou le comportement inapproprié en scannant une liste de transcriptions de texte des images. Il est également utile pour avoir automatiquement une description de l'image et l'enregistrer dans une base de données. De quoi avons-nous besoin ?
1) Un compte dans Flux nuageux (même libre)
2) A travailleur au sein de votre Compte Cloudflare (même libre)
Dans les travailleurs Cloudflare il y a déjà un script préréglé pour générer des transcriptions de texte à partir d'images, mais les scripts préréglés ne sont pas du tout sûrs à utiliser dans un environnement de production; dans ce post, nous verrons comment personnaliser le script pour le rendre plus sûr et l'utiliser dans un environnement PHP.

Que voulons-nous faire ? L'objectif principal est de créer un script qui, à partir d'une URL d'image envoyée avec la méthode POST, retourne la description de l'image à travers le modèle d'intelligence artificielle appelé "Resnet-50". ResNet est un réseau neuronal convolutionnel très profond (CNN), composé de 152 couches, qui, à l'aide d'une technique connue sous le nom de connexion skip, a ouvert la voie à des réseaux résiduels (réseau résiduel).

Que devons-nous générer? Pour la requête à notre travailleur, nous utiliserons un fichier PHP ; tandis que pour le script à insérer dans notre travailleur, nous utiliserons un fichier personnalisable plus sécurisé que celui par défaut.

Scénario de travail

par défaut d'exportation {
async fetch(request, env) {
// Vérifiez si l'en-tête Autorisation contient un jeton valide
const authHeader = request.headers.get("Autorisation");
Const valable Token = "YOUR_AUTHENTICATION_TOKEN";

Si (!authHeader) `Earer ${validToken}`) {
// Si le jeton est manquant ou invalide, retourner une erreur non autorisée 401
retourner une nouvelle réponse(
JSON.stringify({ erreur: "Jeton d'authentification invalide ou manquant." }),
{ statut: 401, en-têtes: { "Type de contenu": "application/json" }
);
}

// Traitement uniquement des demandes POST valides
si (demande. méthode !== "POST") {
// Si la méthode n'est pas POST, retourner une erreur 405 Méthode non autorisée
retourner une nouvelle méthode de requête invalide. Utiliser POST avec les données requises. {
État : 405,
en-têtes: { "Type de contenu": "texte/plain" },
});
}

essayer {
// Valider le type de contenu de la requête
contenu Type = request.headers.get("Content-Type")
si (!contentType.includes("application/json") {
// Si Content-Type n'est pas JSON, retourner une erreur 400 Bad Request
retourner une nouvelle réponse(
JSON.stringify({ erreur : "Type de contenu invalide. }),
{ statut: 400, en-têtes: { "Type de contenu": "application/json" }
);
}

// Analyser le corps de la demande
le corps const = attend la demande.text();
si (!corps) {
// Si le corps de la requête est vide, retourner une erreur 400 Bad Request
retourner une nouvelle réponse(
JSON.stringify({ erreur: "Le corps de la requête est vide." }),
{ statut: 400, en-têtes: { "Type de contenu": "application/json" }
);
}

const { image } = JSON.parse(corps);
si (!imageUrl) {
// Si l'URL de l'image n'est pas fournie dans le corps, retourner une erreur 400 Bad Request
retourner une nouvelle réponse(
JSON.stringify({ erreur: "Aucune URL d'image fournie." }),
{ statut: 400, en-têtes: { "Type de contenu": "application/json" }
);
}

// Saisissez l'image depuis l'URL fournie
const imageResponse = attendre fetch(imageUrl);
const blob = attendre imageResponse.arrayBuffer();

// Préparer les entrées pour le modèle AI
les entrées de const = {
image: [...new Uint8Array(blob)],
};

// Exécutez le modèle AI et obtenez la réponse
réponse de const = attente env.AI.run("@cf/microsoft/resnet-50", entrées);

// Retourner la réponse du modèle AI
retourner une nouvelle réponse(
JSON.stringify({ réponse }),
{ en-têtes: { "Type de contenu": "application/json" }
);
} prise (erreur) {
// Gérer toute erreur inattendue et retourner une erreur de serveur interne 500
retourner une nouvelle réponse(
JSON.stringify({ erreur: error.message }),
{ statut: 500, en-têtes: { "Type de contenu": "application/json" }
);
}
},
};

Que considérer lors de la personnalisation de ce script? La constante valide Jeton doit contenir votre jeton personnalisé pour passer au moment de la requête, insérer un mot de passe et ensuite le rappeler pour l'entrer de nouveau dans le fichier PHP plus bas; si les jetons ne sont pas égaux, le script retournera une erreur 401 et enregistrera d'autres travaux CPU (cette constante peut être modifiée mais doit être la même sur le script PHP) ; en outre, si la requête ne vient pas d'une méthode POST, le script retournera une erreur 405 également utilisée pour enregistrer le travail CPU ; il y a aussi une vérification pour vérifier que la requête reçue est au format JSON, le seul format acceptable ; à ce point, une vérification pour vérifier si l'URL envoyée existe. Si tout est correct, alors nous pouvons passer à l'envoi du fichier image à l'intelligence artificielle, qui retournera sa description au format JSON prêt à être capturé par le script PHP que nous allons construire.

script PHP

Laissez appeler ce script imageai.php et l'enregistrer dans un répertoire protégé

*?php
// URL de votre Worker Cloudflare
$cloudflare Url = "https://yourl.workers.dev/";
$authToken = "YOUR_AUTHENTICATION_TOKEN"; // Jeton d'authentification correspondant au travailleur

si ($_SERVER['REQUEST_METHOD''] === 'POST') {
$imageUrl = $_POST['imageUrl'];

si (vide($imageUrl)) {
// Vérifiez si l'URL de l'image est fournie; sinon, retournez une erreur
echo json_encode(['error' => 'Image URL est manquante.']);
sortie;
}

// Vérifier si l'URL pointe vers une image réelle en cochant son en-tête Content-Type
$headers = get_headers($imageUrl, 1);
if (!isset($headers['Content-Type']))
// Si l'URL ne pointe pas vers une image, retournez une erreur
echo json_encode(['error' => 'L'URL ne contient pas d'image valide.']);
sortie;
}

// Préparer la charge utile JSON pour la demande
$data = json_encode(['imageUrl' => $imageUrl]);

// Définir les options de requête, y compris l'en-tête Autorisation avec le jeton
$options = [
«http» => [
'en-tête' => "Type de contenu: application/json\r\n".
"Autorisation: porteur $authToken\r\n",
// Inclure le jeton dans l'en-tête Autorisation
'méthode' => 'POST',
«contenu» => Données
- Oui.
];

// Envoyer la demande au travailleur et obtenir la réponse
$context = stream_context_create($options);
$response = file_get_contents($cloudflare Url, faux, $context);

si (réponse = FALSE) {
// Si le travailleur est inaccessible, retourner une erreur
echo json_encode(['error' => "Impossible de contacter le travailleur."]);
sortie;
}

// Décoder la réponse JSON du travailleur
$decodedResponse = json_decode($reponse, true);
si (décodedResponse === null) {
// Si la réponse n'est pas valide JSON, retourner une erreur
echo json_encode(['error' => «La réponse n'est pas valide pour JSON.»]);
sortie;
}

// Sortie de la réponse décodée
echo json_encode($decodedResponse);
}
?>

Que considérer lors de la personnalisation de ce script? La variable $authToken contient les jetons d'authentification que nous avons définis dans le script worker (auparavant); la valeur doit être la même dans les deux scripts. La variable $cloudflare Autres contient l'URL entière où le script worker est sauvegardé (précédemment sauvegardé), habituellement il commence par https:// et se termine par workers. Dev mais vous pouvez également associer un sous-domaine personnalisé (à votre préférence). Le script peut être appelé depuis un
dans html et doit passer l'url d'image d'un champ avec id imageUrl, évidemment il peut également être appelé via POST à partir d'un autre script dans javascript (comme vous préférez); le script PHP à ce point vérifie que l'url passé via POST est là et vérifie si c'est réellement une image; une fois que les vérifications ont passé il appelle le script worker, vérifie si le service est disponible et accessible, et retourne la réponse qui doit être au format JSON.

Formulaire HTML

- Oui. DOCTYPE html>




Classification de l'image



Classification de l'image

Entrez l'URL d'une image pour la classer :

Classer l'image

Conclusion

Ce script peut être utilisé via un formulaire HTML (tel que présenté ici) ou même via un script javascript qui s'occupera de l'envoi de la requête POST, mais il peut également être utilisé entièrement via PHP en veillant peut-être à ce que le résultat soit enregistré directement dans une base de données qui sera renvoyée ultérieurement (lorsque demandé). L'application peut avoir des fonctions différentes selon les besoins; rappelez-vous qu'il est toujours préférable de faire moins de demandes compliquées aux travailleurs parce que, bien qu'ils aient des limites élevées même avec un compte libre, ils ont encore des limites. Il est de bonne pratique de sauvegarder les informations reçues dans une base de données, et pour la même url (ou la même image) et de récupérer les informations via la base de données (cachant) pour ne pas bloquer le travailleur avec trop de demandes. Les contrôles mis en œuvre (vérification du jeton et de l'hôte) sont utilisés précisément pour ne pas envoyer trop de demandes qui pourraient atteindre les limites des travailleurs. De plus, dans Cloudflare, vous pouvez également configurer votre pare-feu d'application (WAF) pour vous assurer que les demandes à ce travailleur doivent venir de l'hôte spécifié (de manière à ne pas augmenter le compteur des limites du travailleur). Rappelez-vous que pour une meilleure performance le modèle resnet-50 s'attend à la taille de l'image 224×224 pixels, il est donc conseillé de redimensionner l'image à ces dimensions avant de l'envoyer.