HiAPI
Blog

Tutoriel

Comment appeler muse-image-1.0/image-to-image sur l'API HiAPI : curl, Python et un exemple de requête fonctionnel

Oct 31, 2026
奶油色底上的多层薄纸叠层插画,一块陶红色纸层作点缀,构图克制均衡,为教程文章封面图。

Ce qu'une requête image-to-image envoie réellement

Avant d'écrire la première ligne de code, il est utile de bien comprendre ce qu'attend un appel image-to-image. Contrairement à une requête texte-vers-image où le prompt est la seule entrée créative, muse-image-1.0/image-to-image nécessite une image source, accompagnée d'instructions sur la manière de la transformer.

Au minimum, votre charge utile de requête comprend :

  • model : l'identifiant muse-image-1.0/image-to-image.
  • image : l'image source que vous souhaitez modifier. Elle est généralement envoyée sous forme de chaîne encodée en base64 ou d'URL accessible publiquement, selon le format accepté par le point de terminaison. Consultez le schéma d'entrée du modèle pour confirmer le nom exact du champ et son format.
  • prompt : une description textuelle de la modification souhaitée. Soyez précis sur ce qu'il faut changer et ce qu'il faut conserver.
  • Des paramètres optionnels tels que strength ou guidance (si le modèle les expose) vous permettent de contrôler à quel point la sortie s'écarte de l'image source. L'ensemble exact de paramètres varie selon le modèle, alors vérifiez-le dans la référence de l'API plutôt que de le supposer.

Le changement de mentalité essentiel est le suivant : vous ne générez pas à partir de zéro, vous fournissez un point de départ et une direction. Un prompt vague comme "make it better" produira des résultats imprévisibles, car le modèle dispose de trop de liberté. Un prompt comme "replace the sky with a sunset and keep the buildings unchanged" donne au modèle une contrainte claire.

En outre, vérifiez à l'avance les contraintes relatives à l'image — formats pris en charge, dimensions maximales et taille de fichier. Si votre image source est un PNG de 12 Mo, il faudra peut-être d'abord la sous-échantillonner ou la convertir en JPEG pour que la requête soit acceptée. Traiter correctement l'image avant l'envoi vous évite un aller-retour et un message d'erreur déroutant.

Une fois que vous disposez de l'image source et d'un prompt d'édition clair, vous pouvez effectuer votre premier appel.

Envoyer une première requête avec curl

La méthode la plus rapide pour valider une intégration consiste à envoyer la requête directement depuis le terminal. Le chemin exact du point de terminaison et le schéma de la charge utile sont définis dans la référence de l'API du modèle ; l'exemple ci-dessous montre la forme générale afin que vous puissiez l'adapter à la spécification actuelle.

curl -X POST https://api.hiapi.ai/v1/images/edits \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "muse-image-1.0/image-to-image",
    "image": "https://your-bucket.example.com/source.jpg",
    "prompt": "replace the sky with a warm sunset, keep the buildings unchanged",
    "strength": 0.6
  }'

Remplacez $HIAPI_API_KEY par une variable d'environnement plutôt que de coller la clé directement. Si votre outil le permet, exportez la clé dans la session shell afin qu'elle ne reste pas dans l'historique des commandes.

La réponse renvoyée contient un identifiant de tâche. Comme l'édition d'image est gourmande en calcul, l'API ne renvoie généralement pas l'image finale dans la même réponse. Vous recevez à la place un ID de tâche et un statut. Conservez cet ID — vous l'utiliserez à l'étape suivante pour interroger le résultat.

Si l'appel échoue, lisez attentivement le corps de la réponse d'erreur. Un 400 indique généralement une charge utile mal formée ou un format d'image non pris en charge. Un 401 signifie que la clé est absente ou incorrecte. Un 429 indique que vous envoyez des requêtes trop rapidement. Corriger ces problèmes au stade du terminal est bien plus facile que de déboguer dans une application complète.

La même requête en Python

Une fois l'appel curl réussi, convertissez-le en une petite fonction Python. L'utilisation de requests permet de garder l'exemple avec peu de dépendances et facile à porter.

import os
import requests

HIAPI_API_KEY = os.environ["HIAPI_API_KEY"]
BASE_URL = "https://api.hiapi.ai/v1/images/edits"

def submit_edit(image_url: str, prompt: str, strength: float = 0.6) -> str:
    payload = {
        "model": "muse-image-1.0/image-to-image",
        "image": image_url,
        "prompt": prompt,
        "strength": strength,
    }
    headers = {
        "Authorization": f"Bearer {HIAPI_API_KEY}",
        "Content-Type": "application/json",
    }
    response = requests.post(BASE_URL, json=payload, headers=headers, timeout=30)
    response.raise_for_status()
    data = response.json()
    return data["id"]

Quelques remarques sur cette fonction :

  • Le paramètre timeout empêche le script de rester bloqué indéfiniment en cas de stagnation du réseau. Pour un appel de soumission, 30 secondes sont largement suffisantes, mais ajustez selon vos besoins.
  • raise_for_status() convertit les erreurs HTTP en exceptions, ce qui vous permet de les intercepter à un seul endroit.
  • Ne renvoyer que l'ID de tâche permet de garder la fonction ciblée. La logique d'interrogation doit être placée dans une fonction distincte.

Si vous préférez envoyer l'image source sous forme d'octets plutôt que d'URL, lisez le fichier, encodez-le en base64 et placez le résultat dans le champ image. Avant de basculer, vérifiez le format attendu dans la documentation, car ces deux encodages ne sont pas toujours interchangeables.

Cette fonction est volontairement minimale. Dans un service réel, vous ajouteriez des logs, une gestion des tentatives et une validation des types, mais le modèle de requête central est exactement celui que vous voyez ici.

Gérer les tâches asynchrones et interroger les résultats

L'édition d'image prend du temps — généralement de quelques secondes à quelques dizaines de secondes, selon le prompt et la résolution. L'API procède en acceptant votre requête, en renvoyant un ID de tâche et en traitant le travail en arrière-plan. Votre rôle est de vérifier à plusieurs reprises jusqu'à ce que le statut atteigne un état terminal.

L'interrogation peut sembler simple, mais une boucle naïve déclenchée toutes les 100 millisecondes gaspille du quota et peut déclencher des limitations de débit. Utilisez un intervalle raisonnable et une limite de tentatives :

import time
import requests

def poll_job(job_id: str, interval: float = 2.0, max_attempts: int = 30) -> dict:
    url = f"https://api.hiapi.ai/v1/jobs/{job_id}"
    headers = {"Authorization": f"Bearer {os.environ['HIAPI_API_KEY']}"}
    for attempt in range(max_attempts):
        response = requests.get(url, headers=headers, timeout=15)
        response.raise_for_status()
        data = response.json()
        status = data["status"]
        if status == "succeeded":
            return data
        if status == "failed":
            raise RuntimeError(data.get("error", "job failed"))
        time.sleep(interval)
    raise TimeoutError(f"job {job_id} did not finish after {max_attempts} attempts")

Un intervalle de deux secondes est un point de départ raisonnable. Si vos tâches se terminent généralement en cinq secondes, vous pouvez interroger plus fréquemment au début, puis appliquer un backoff progressif. Si elles prennent généralement plus de temps, réduisez la fréquence d'interrogation pour éviter les appels inutiles.

La limite de tentatives est votre filet de sécurité. Sans elle, une tâche bloquée pourrait boucler indéfiniment. Lorsque la limite est atteinte, levez une erreur explicite afin que l'appelant sache que l'opération a expiré, plutôt que de rester silencieusement suspendu.

En production, envisagez de déplacer l'interrogation vers un worker en arrière-plan ou une file d'attente, afin que votre thread de traitement des requêtes ne soit pas bloqué en attente du rendu de l'image.

Télécharger et stocker l'image de sortie

Lorsque la tâche atteint le statut succeeded, la réponse contient une ou plusieurs images de sortie, généralement fournies sous forme d'URL. Votre étape suivante consiste à télécharger l'image et à la stocker de manière persistante.

def download_image(result: dict, dest_path: str) -> None:
    image_url = result["output"][0]["url"]
    response = requests.get(image_url, timeout=30)
    response.raise_for_status()
    with open(dest_path, "wb") as f:
        f.write(response.content)

Quelques considérations pratiques :

  • Les URL de sortie peuvent être temporaires. Traitez-les comme des ressources à durée de vie courte, téléchargez-les rapidement, et ne stockez pas l'URL comme seule référence.
  • Écrivez le fichier en mode binaire. Une réponse d'image n'est pas du texte ; l'ouvrir avec "w" corromprait les données.
  • Vérifiez que le fichier n'est pas vide avant de déclarer le succès. Un téléchargement de zéro octet signifie généralement que l'URL a expiré ou que la requête a été bloquée.

Pour tout scénario au-delà d'un script local, diffusez directement le téléchargement vers votre fournisseur de stockage plutôt que de l'enregistrer d'abord sur disque. La plupart des SDK de stockage objet acceptent des objets de type fichier ou des flux d'octets, vous pouvez donc transmettre response.raw ou response.content à l'appel de téléversement, sans fichier intermédiaire.

Enfin, enregistrez l'ID de tâche avec l'objet stocké. Si la sortie est corrompue plus tard, ou si vous devez reproduire une édition spécifique, l'ID de tâche plus les entrées d'origine vous permettent de retracer ce qui a été envoyé.

Points de défaillance courants et comment les corriger

La plupart des problèmes d'intégration appartiennent à quelques catégories. Voici comment diagnostiquer chacune.

La requête est rejetée avant la création de la tâche

Une erreur 400 lors de la soumission indique généralement une charge utile incorrecte. Vérifiez que model est exactement muse-image-1.0/image-to-image, que image est accessible ou correctement encodée en base64, et que prompt est une chaîne non vide. Si l'image est une URL, confirmez qu'elle est accessible publiquement — un bucket privé ou une URL signée expirée ne passera pas la validation.

La tâche échoue pendant le traitement

Si l'interrogation renvoie un statut failed, lisez le message d'erreur dans le corps de la réponse. Les causes courantes incluent une image trop volumineuse, un prompt enfreignant la politique de contenu, ou des valeurs de paramètres hors des plages autorisées. Réduisez la taille de l'image et simplifiez le prompt pour isoler la cause.

Expiration de l'interrogation

Si vous atteignez la limite de tentatives sans état terminal, la tâche peut réellement nécessiter plus de temps, ou être bloquée. D'abord, augmentez max_attempts et vérifiez dans la référence de l'API le temps de traitement typique. Si la tâche expire continuellement, vérifiez si l'image source n'est pas anormalement volumineuse. Ne supprimez pas simplement la limite de tentatives — des tentatives bornées empêchent les boucles infinies silencieuses.

Limitation de débit

Une réponse 429 signifie que vous envoyez des requêtes trop rapidement. Appliquez un backoff, respectez tout en-tête retry-after, et échelonnez les soumissions concurrentes. Si vous traitez un lot d'images, traitez-les séquentiellement ou utilisez une limite de concurrence plus faible, plutôt que de tout envoyer d'un coup.

Sortie manquante ou tronquée

Si la tâche réussit mais que le fichier téléchargé est vide, l'URL de sortie a peut-être expiré entre l'interrogation et le téléchargement. Téléchargez immédiatement après le succès. Si l'image est corrompue, vérifiez que vous écrivez en mode binaire et qu'aucun encodage texte n'est appliqué au flux.

Le débogage est plus facile lorsque vous enregistrez la charge utile de la requête, l'ID de tâche et les transitions de statut. Avec ces trois informations, presque tout échec peut être retracé jusqu'à sa source.

Avec la forme de la requête, les modèles curl et Python, la logique d'interrogation et l'étape de téléchargement, vous disposez d'un pipeline fonctionnel pour utiliser muse-image-1.0/image-to-image sur l'API HiAPI. Commencez par l'exemple terminal, déplacez-le dans un script, puis ajoutez les tentatives et les logs une fois le chemin nominal stable.

Articles similaires

Voir tous les articles →

Commencez avec des artefacts IA persistants

Obtenez votre clé API et appelez des modèles d'image, de vidéo et d'audio via une API unique basée sur les tasks.

Lire la documentation de l'API