Tutoriel
Comment appeler recraft-v4-styles-pro/text-to-image sur l'API hiapi : curl et Python
Ce que fait cet endpoint et quand l'utiliser
recraft-v4-styles-pro/text-to-image convertit une invite textuelle en image, avec une particularité notable : la prise en compte du style. Vous pouvez orienter le langage visuel du résultat via des références de style, plutôt que de vous fier uniquement à la formulation de l'invite. C'est un choix judicieux lorsque la sortie doit conserver une cohérence de sensation sur un grand nombre de générations, et non seulement être belle sur une ou deux.
Les développeurs l'utilisent souvent dans les scénarios suivants :
- Supports de cohérence de marque — visuels principaux, cartes sociales et variantes publicitaires, qui doivent tous s'inscrire dans le même système visuel.
- Maquettes produit et marketing — ajuster les invites de façon répétée, fixer le style et produire une série de variantes conformes à la marque.
- Étapes de pipeline — la génération est une phase d'une automatisation plus large, où un autre service consomme les images enregistrées.
Une caractéristique détermine la façon d'écrire chacun des exemples de code ci-dessous : la génération d'images est asynchrone. La requête soumet une tâche et renvoie immédiatement ; l'image n'apparaît que plus tard. Vous devez écrire une étape de soumission et une étape d'interrogation, et les traiter comme deux préoccupations distinctes.
Préparer les identifiants hiapi et la base de la requête
Tous les appels passent par l'interface d'endpoint unifiée de hiapi, il faut donc préparer trois choses avant la première requête :
- Une clé API, issue de votre compte hiapi. Traitez-la comme tout autre secret : chargez-la depuis une variable d'environnement, ne la codez jamais en dur dans un script que vous pourriez partager.
- L'identifiant du modèle, qui doit correspondre exactement à celui publié :
recraft-v4-styles-pro/text-to-image. - Un outil prenant en charge HTTP —
curlpour l'exploration, et une bibliothèque HTTP pour tout scénario persistant.
export HIAPI_API_KEY="your-key-here"
Des conventions à intégrer tôt :
- Utilisez
Content-Type: application/jsonlors de l'envoi d'un corps JSON. - Authentifiez-vous avec un en-tête bearer token.
- Placez l'id du modèle, l'invite et les références de style comme champs distincts dans la charge utile, plutôt que de tout entasser dans une seule chaîne — l'étape d'interrogation et les journaux n'en seront que plus lisibles.
Pour les noms exacts des en-têtes, l'URL de base et les définitions de champs actuelles, consultez la documentation de référence de l'API hiapi pour ce modèle ; considérez ce tutoriel comme la forme de l'appel, et la documentation de référence comme la source d'autorité pour les noms.
Une requête curl fonctionnelle
Voici l'appel de soumission. Comprenez-le en trois couches : transport, authentification et corps de requête.
curl -sS -X POST "$HIAPI_BASE_URL/generate" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "recraft-v4-styles-pro/text-to-image",
"prompt": "photo produit minimaliste d'une tasse en céramique sur une surface en lin, lumière du jour douce",
"style_references": []
}'
Explication ligne par ligne :
-X POST— soumet une tâche, ne récupère pas.Authorization: Bearer ...— le jeton provient de la variable d'environnement, cette commande peut donc être collée sans risque dans un terminal et partagée sans risque une fois la variable retirée.-d '{...}'— le corps JSON.modelest l'identifiant exact.promptest le texte libre décrivant la scène.style_referencesest le point d'ancrage du contrôle de style, abordé plus loin.-sS— barre de progression silencieuse, mais les erreurs restent affichées, les appels en échec sont donc visibles.
Une réponse réussie est une confirmation, pas une image : vous recevez l'identifiant de la tâche et son statut. Notez cet identifiant — c'est le seul handle nécessaire pour l'interrogation. Si vous explorez de manière interactive, passez la réponse dans un formateur JSON pour faire ressortir l'id de tâche et le statut.
Transmettre les références de style avec l'invite
Le modèle mental est simple : l'invite dit quoi, les références de style disent à quoi cela doit ressembler. Gardez-les séparées dans la charge utile, et vous préservez la flexibilité — vous pouvez relancer la même invite sur plusieurs jeux de styles pour comparer les résultats.
{
"model": "recraft-v4-styles-pro/text-to-image",
"prompt": "tasse en céramique sur une surface en lin, lumière du jour douce",
"style_references": [
"https://your-bucket.example.com/styles/mug-ref-01.jpg",
"https://your-bucket.example.com/styles/mug-ref-02.jpg"
]
}
Conseils pratiques :
- Commencez sans référence. Lancez d'abord l'invite nue. Ajoutez ensuite une référence et observez la différence, puis deux. Ne changer qu'un seul élément à la fois apporte bien plus d'informations qu'essayer tout un jeu de styles dès la première tentative.
- Gardez les références accessibles. Hébergez-les là où le service peut les récupérer de manière fiable — un bucket public ou une URL signée avec une durée de validité confortable — et non un lien qui expire après quelques minutes.
- Gardez un ensemble cohérent. Des références cohérentes entre elles (éclairage, palette et textures similaires) produisent souvent des résultats plus stables qu'un assortiment hétérogène, qui oblige le modèle à réconcilier des contradictions.
- Versionnez les références. Stockez-les sous des clés stables. Si les sorties posent problème le mois prochain, vous devrez savoir exactement quels fichiers de référence ont été utilisés.
Consultez la documentation de référence hiapi de ce modèle pour confirmer si les références de style sont transmises sous forme d'URL, de ressources téléversées ou de préréglages nommés, et quelles limites s'appliquent à leur nombre et à leur format.
Le même appel en Python
L'appel curl se transpose directement. Enfermé dans de petites fonctions, il est réutilisable comme étape de pipeline.
import os
import requests
HIAPI_BASE_URL = os.environ["HIAPI_BASE_URL"]
HIAPI_API_KEY = os.environ["HIAPI_API_KEY"]
def submit_generation(prompt: str, style_references: list[str] | None = None) -> str:
"""Soumet une tâche text-to-image et renvoie l'id de la tâche."""
payload = {
"model": "recraft-v4-styles-pro/text-to-image",
"prompt": prompt,
"style_references": style_references or [],
}
response = requests.post(
f"{HIAPI_BASE_URL}/generate",
headers={
"Authorization": f"Bearer {HIAPI_API_KEY}",
"Content-Type": "application/json",
},
json=payload,
timeout=30,
)
response.raise_for_status()
data = response.json()
return data["job_id"]
Notes de conception :
- Définissez toujours un timeout. Une soumission bloquée indéfiniment bloque votre worker aussi efficacement qu'un crash.
raise_for_status()convertit une réponse non 2xx en exception capturable et journalisable, au lieu de poursuivre silencieusement avec un corps de réponse mal formé.- Ne renvoyez que l'id. L'id de tâche est le contrat entre la soumission et l'interrogation. En gardant le reste de la réponse hors du code appelant, la section suivante sera plus simple à écrire.
Confirmez le nom réel du champ de réponse dans la documentation de référence hiapi et ajustez data["job_id"] en conséquence — le nommage des champs est l'endroit le plus susceptible de différer des exemples de cet article.
Interroger l'état d'achèvement de la tâche
La génération prend du temps. Interrogez à intervalle fixe, arrêtez-vous à l'état terminal et abandonnez au bout d'un moment.
import time
def wait_for_job(job_id: str, timeout: float = 300, interval: float = 3) -> dict:
deadline = time.monotonic() + timeout
while time.monotonic() < deadline:
response = requests.get(
f"{HIAPI_BASE_URL}/jobs/{job_id}",
headers={"Authorization": f"Bearer {HIAPI_API_KEY}"},
timeout=30,
)
response.raise_for_status()
job = response.json()
status = job["status"]
if status == "succeeded":
return job
if status == "failed":
raise RuntimeError(f"Job {job_id} failed: {job.get('error')}")
time.sleep(interval)
raise TimeoutError(f"Job {job_id} did not finish within {timeout}s")
Les points moins évidents :
- Trois résultats, pas deux. En attente, succès, échec. Traitez tout statut non reconnu comme en attente et journalisez une ligne, ainsi un statut nouvellement ajouté ne fera pas planter votre worker.
- Une seule échéance pour toute l'attente. Une échéance basée sur
time.monotonic()est insensible aux ajustements d'horloge, contrairement à l'arithmétique sur l'heure murale. - Ne requêtez pas trop souvent. Pour la génération d'images, quelques secondes entre chaque vérification suffisent. Si vous devez interroger plus vite, appliquez un backoff entre les tentatives plutôt que de raccourcir l'intervalle.
- Imposez un timeout. Une tâche qui ne se termine jamais doit se manifester comme une erreur déclenchant une alerte, et non comme une boucle qui tourne jusqu'à ce que le conteneur soit tué.
Si vous exécutez beaucoup de tâches, soumettez-les par lots et interrogez-les en concurrence — avec une boucle d'événements ou un pool de threads et des intervalles décalés — plutôt que de lancer un interrogateur par tâche dans une boucle serrée.
Télécharger et enregistrer la sortie
Une tâche terminée vous donne une référence d'image, généralement une URL. Téléchargez-la rapidement, car ces liens peuvent avoir une durée de validité limitée.
def save_image(job: dict, path: str) -> None:
url = job["output"]["image_url"]
for attempt in range(3):
try:
with requests.get(url, stream=True, timeout=60) as r:
r.raise_for_status()
with open(path, "wb") as f:
for chunk in r.iter_content(chunk_size=8192):
f.write(chunk)
return
except requests.RequestException:
if attempt == 2:
raise
time.sleep(2 ** attempt)
Pratiques à adopter en production :
- Téléchargement en flux. Les images générées ne sont pas petites ; les charger entièrement en mémoire sans raison est un gaspillage.
- Écrivez dans un chemin temporaire, puis renommez. Un crash en cours d'écriture ne doit pas laisser un fichier tronqué là où le pipeline attend une image valide.
- Réessayez le téléchargement, pas la génération. Réessayer une récupération instable depuis un bucket coûte peu ; gaspiller une génération, non. Limitez le nombre de tentatives et utilisez un backoff exponentiel.
- Persistez l'id de tâche avec le fichier. Quand quelqu'un demande d'où vient une image, la réponse devrait tenir en une requête, pas en une fouille des journaux.
Pour le stockage objet, remplacez open() par le téléversement en flux de votre SDK et conservez la même enveloppe de nouvelle tentative.
Erreurs, nouvelles tentatives et contrôle de cohérence des coûts
Les modes de défaillance que vous rencontrerez en premier, et la façon de traiter chacun :
- 401 / erreur d'authentification — clé manquante, mal orthographiée ou non exportée dans le shell qui exécute le script. Vérifiez l'environnement avant de toucher à la charge utile.
- Erreur de validation 4xx — souvent un id de modèle mal orthographié, un
promptmanquant ou une référence de style mal formée. Journalisez le corps de réponse mot pour mot ; les messages de validation sont le chemin de correction le plus rapide ici. - 429 / limite de débit — utilisez un backoff avec jitter, plutôt qu'une nouvelle tentative immédiate. Une file d'attente devant la fonction de soumission vaut mieux qu'une tempête de nouvelles tentatives.
- Timeout de tâche — l'échéance d'interrogation s'est déclenchée. Décidez délibérément de resoumettre ou non ; resoumettre aveuglément double la dépense sans améliorer le taux de réussite.
- Erreurs réseau transitoires — réessayez la soumission et le téléchargement avec un backoff exponentiel plafonné. Réessayez librement un téléchargement en échec ; prudemment une génération.
La discipline de coût, d'un point de vue pratique :
- La facturation suit le travail réellement exécuté par le modèle, donc les tâches en échec et les lots abandonnés sont des coûts cachés. Journalisez chaque soumission avec le hash de son invite et l'id de tâche, pour pouvoir comptabiliser l'usage plus tard.
- Itérez avec les invites les moins coûteuses possible. Ajustez la formulation et les références de style sur des exécutions courtes et à petite échelle, avant de lancer de grands lots.
- Dédupliquez. Si la même invite et le même jeu de styles sont demandés deux fois, servez le résultat de la première fois depuis votre propre cache.
- Ajoutez une limite de concurrence stricte dans le worker. Il est plus facile de relever une limite que d'expliquer une facture imprévue.
En traitant la soumission, l'interrogation et l'enregistrement comme trois fonctions distinctes et testables, cet endpoint s'intègre proprement dans n'importe quel pipeline. Pour les noms de champs exacts, les statuts et la tarification actuelle, consultez la page du modèle recraft-v4-styles-pro/text-to-image sur hiapi avant l'intégration.
Articles similaires
Voir tous les articles →-
Tutoriel
Comment appeler hailuo-2.3-fast/image-to-video via l'API HiAPI : curl et Python en pratique
La première requête exploitable du palier image-vers-vidéo rapide et économique — de l'ID du modèle au téléchargement du MP4
-
Tutoriel
Comment appeler hailuo-2.3/text-to-video via l'API HiAPI : curl, Python et exemples de requêtes exécutables
-
Tutoriel
Utiliser Kandinsky 6.0 Pro texte-vers-vidéo sur HiAPI : tutoriel curl et Python
Démonstration pratique axée sur la requête : construire l'appel du prompt au clip vidéo, soumettre la requête, interroger l'état d'achèvement et télécharger le résultat