Tutorial
So verwendest du flux-1.1-pro über die HiAPI API: curl, Python und lauffähige Anfragen
Ein praktischer Integrationsleitfaden: Anfragen, die tatsächlich laufen, asynchrone Verarbeitung und Prompt-Rezepte mit echten Ausgaben
Auf dieser Seite
Was flux-1.1-pro bietet, bevor du mit dem Programmieren beginnst
flux-1.1-pro ist ein Text-zu-Bild-Modell, das über HiAPI.ai als gehosteter Endpunkt aufgerufen wird. Du sendest Prompt und Generierungsparameter als JSON und erhältst das generierte Bild zurück. Es ist nichts zu installieren, keine Gewichte selbst zu hosten und keine GPU-Ressourcen zu verwalten. Deine Integrationsfläche ist ein HTTP-Endpunkt plus Anmeldedaten zur Authentifizierung.
Für Entwickler bedeutet das, dass drei Dinge dein Design prägen, bevor du die erste Codezeile schreibst.
Erstens: Die Anfrage ist JSON rein, Bild raus. Dein Prompt, das Seitenverhältnis und einige wenige Steuerparameter liegen im Request-Body. Die Antwort enthält Bilddaten oder einen Verweis darauf, je nachdem, wie die Aufgabe ausgeliefert wird. Behandle den Request-Body als Vertrag und halte ihn an einer Stelle zentral, damit die curl- und die Python-Route nie voneinander abweichen.
Zweitens: Bildgenerierung ist im Vergleich zu einem normalen API-Aufruf eine langsame Operation. Einige Sekunden sind normal; komplexe Prompts in hoher Auflösung können länger dauern. Jeder Aufrufer in der Produktion muss Latenz annehmen und einplanen, statt den Aufruf als Datenbanklesevorgang zu behandeln.
Drittens: Die Ausgabequalität wird hauptsächlich vom Prompt bestimmt, nicht von der Verdrahtung. Die Integration ist der einfache Teil. Die eigentliche Arbeit besteht darin, präzise zu beschreiben, was du willst, und dein Rezept vor dem Go-live an echten Ausgaben zu validieren.
Mit diesen drei Dingen im Kopf ist der Rest dieses Leitfadens mechanisch: Anfrage bauen, bestätigen, dass sie läuft, portieren, dann härten und optimieren. Durchweg läuft alles über die HiAPI API – ein Satz Anmeldedaten, eine Basis-URL, eine JSON-Struktur zu lernen.
Deine erste curl-Anfrage
Beginne mit curl. Es entfernt jede Abstraktionsebene zwischen dir und dem Endpunkt, sodass du bei einem Fehler genau weißt, dass es an deinem Request-Body liegt und nicht an deinem Framework.
Ein minimaler Aufruf besteht aus drei Teilen: dem Endpunkt, dem Authentifizierungsheader und dem JSON-Request-Body.
curl -X POST "https://api.hiapi.ai/v1/images/generations" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "flux-1.1-pro",
"prompt": "a ceramic coffee mug on a weathered wooden table, soft morning window light, shallow depth of field, product photography",
"aspect_ratio": "1:1"
}'
Lies den Request-Body Feld für Feld:
modelgibt das zu verwendende Modell an. Schreibe es explizit, damit zukünftige Standardwertänderungen niemals stillschweigend deine Ausgabe verändern.promptist die natürlichsprachliche Beschreibung. Hier liegt fast dein gesamtes Qualitätsbudget.aspect_ratiosteuert die Bildkomposition. Wähle es bewusst, statt dich auf einen ungeprüften Standardwert zu verlassen.
Lege den Schlüssel in eine Umgebungsvariable (HIAPI_API_KEY), statt ihn direkt in den Befehl zu kleben. Diese Gewohnheit setzt sich direkt in Python und in jeden CI-Schritt fort, den du später hinzufügst.
Bei einem erfolgreichen Aufruf erhältst du eine JSON-Antwort, die das fertige Bild beschreibt. Prüfe sie und lokalisiere den Bildverweis oder die Daten, bevor du das Terminal schließt. Bei einem Fehlschlag erhältst du einen Fehler-Body mit Statuscode und Meldung; lies die Meldung wörtlich, denn falsch formatierte Felder sind die häufigste Ursache für einen ersten Fehlschlag.
Eine Warnung, die eine Stunde spart: Klebe keine mehrzeiligen Prompts mit unescapten Anführungszeichen in die Shell. Verwende für alles, was länger als ein kurzer Satz ist, ein Heredoc oder eine Datei.
curl -X POST "https://api.hiapi.ai/v1/images/generations" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
--data @request.json
Diese request.json ist das Artefakt, das du in die Versionsverwaltung einchecken solltest. Sie ist die einzige Wahrheitsquelle für den Request-Body, und der nächste Abschnitt verwendet sie unverändert weiter.
Denselben Aufruf nach Python portieren
Das Ziel der Portierung ist nicht, neue Logik zu schreiben, sondern exakt denselben JSON-Request-Body zu senden. Lade dieselbe request.json, damit die beiden Routen nicht auseinanderlaufen können.
import json
import os
import requests
API_URL = "https://api.hiapi.ai/v1/images/generations"
with open("request.json") as f:
payload = json.load(f)
response = requests.post(
API_URL,
headers={
"Authorization": f"Bearer {os.environ['HIAPI_API_KEY']}",
"Content-Type": "application/json",
},
json=payload,
timeout=120,
)
if response.status_code != 200:
print(response.status_code)
print(response.text)
response.raise_for_status()
print(response.json())
Drei Details sind hier wichtig.
Der Authentifizierungsheader und der Content-Type-Header sind dieselben Header. Die Verwendung von json=payload lässt requests den Body für dich serialisieren und den Inhaltstyp setzen; den Header explizit zu schreiben ist harmlos und dokumentiert die Absicht.
Setze ein Timeout. Lass eine Generierungsanfrage niemals an einem unbegrenzten Standardwert hängen. Ein großzügiges explizites Timeout ist in Ordnung – entscheidend ist, dass es explizit ist.
Prüfe den Fehler-Body, bevor du eine Exception wirfst. Wenn du zuerst raise_for_status() ausführst, wirft es den Response-Body aus deinem Log. Gib zuerst Statuscode und Text aus und wirf dann. Wenn ein Feld abgelehnt wird, brauchst du diesen Text.
Wenn du einen asynchronen HTTP-Client verwendest, bleibt die Struktur gleich: gleiche URL, gleiche Header, gleicher Body, nur await client.post(...) mit demselben Timeout. Der Body-Vertrag ist die Konstante; der Client ist ein Implementierungsdetail.
Halte den Request-Body außerhalb des Python-Quellcodes. Wenn ein Prompt-Rezept funktioniert, gehört es in eine Datei oder Datenbankzeile, nicht in ein String-Literal, das in einer Funktion vergraben ist, damit du es diffen und erneut ausführen kannst.
Asynchrone Aufgaben bearbeiten, ohne deine Anwendung zu blockieren
Behandle die Generierung als Aufgabe, nicht als Funktionsaufruf. Ob dein Auslieferungspfad synchron aussieht oder eine Aufgabe zurückgibt, die du pollen musst, die praktische Konsequenz ist dieselbe: Deine Anwendung darf niemals unbegrenzt einen Request-Thread belegen, während sie auf ein Bild wartet.
Ein funktionierendes Muster umfasst vier Schritte.
1. Aus einem Worker heraus absenden, nicht aus einer Benutzeranfrage
Nimm die Generierungsaktion des Benutzers in der Web-Schicht entgegen, persistiere einen Aufgaben-Datensatz, stelle ihn in eine Queue und kehre sofort zurück. Ein Hintergrund-Worker führt den eigentlichen API-Aufruf aus. Der Benutzer pollt deinen Endpunkt, nicht das Modell.
2. Setze Grenzen für das Warten
Setze für jeden Versuch ein Timeout, das du bewusst gewählt hast. Wenn die Plattform eine Aufgabe zurückgibt, die du pollen musst, polle in festen Intervallen, mit einer maximalen Anzahl von Versuchen und einer Deadline, die ab dem Startzeitpunkt der Aufgabe (nicht ab der Anzahl der Versuche) berechnet wird. Bevorzuge moderates Backoff statt einer engen Schleife.
3. Wiederhole nur Fehler, die es wert sind
Wiederhole Transportfehler, Timeouts und Serverfehler mit exponentiellem Backoff plus Jitter, begrenzt auf wenige Versuche. Wiederhole nicht Validierungsfehler: Ein abgelehntes Feld oder ein leerer Prompt schlägt jedes Mal auf dieselbe Weise fehl, und ein erneuter Versuch lässt den Benutzer nur länger warten, bevor er die eigentliche Meldung sieht.
4. Mache die Aufgabe auf deiner Seite idempotent
Zeichne den exakten Request-Body und die Aufgaben-ID in der Datenbank auf. Wenn dein Worker nach dem Absenden, aber vor dem Aufzeichnen des Erfolgs abstürzt, kannst du die Aufgabe erneut prüfen, statt blind erneut zu senden. Wenn du erneut senden musst, füge einen kurzen clientseitigen Deduplizierungsschlüssel hinzu, damit ein vorübergehender Fehler nicht dreimal dieselbe Generierung in die Queue stellt.
import time
def poll_until_done(fetch_status, job_id, deadline_seconds=180):
start = time.monotonic()
delay = 2.0
while True:
status = fetch_status(job_id)
if status["state"] in ("succeeded", "failed"):
return status
if time.monotonic() - start > deadline_seconds:
raise TimeoutError(f"generation {job_id} exceeded deadline")
time.sleep(delay)
delay = min(delay * 1.5, 10.0)
Dieser Helfer ist bewusst allgemein gehalten: Er nimmt eine Funktion zum Abrufen des Status entgegen, sodass dieselbe Schleife für jeden aufgabenbasierten Endpunkt funktioniert, den du später integrierst. Die wichtigen Eigenschaften sind Deadline, begrenztes Backoff und Prüfung des Endzustands – nicht der konkrete Transportweg.
Prompts bauen, die zuverlässig rendern
Ein langer Prompt ist kein besserer Prompt. Struktur ist es. Ein wiederholbares Gerüst liefert dir konsistente Ergebnisse und bietet dir eine Stelle, an der du bei Problemen jeweils nur eine Variable änderst.
Verwende vier Slots in dieser Reihenfolge:
- Subjekt – was im Bild ist, konkret. „Eine Keramik-Kaffeetasse“ schlägt „irgendetwas für ein Café“.
- Stil – visueller Ton: Fotografie, Illustration, Aquarell, 3D-Rendering, Produktaufnahme. Benenne das Medium und, wenn hilfreich, das Licht.
- Komposition – Bildausschnitt und Kamera: Seitenverhältnis, Aufnahmeabstand, Winkel, Schärfentiefe, Position des Subjekts im Bild.
- Einschränkungen – was du ausdrücklich willst und nicht willst, kurz gehalten.
[subject] a single ceramic coffee mug, matte glaze, small handle
[style] product photography, soft diffused window light, muted palette
[composition] 1:1, eye-level, subject centered, shallow depth of field, plain background
[constraints] no text, no logos, no hands
Flache es beim Senden zu einem einzigen Prompt ab; die eckigen Klammern sind für dich, nicht für das Modell. Der Wert des Schreibens in Slots liegt darin, dass du weißt, welchen Slot du bearbeiten musst, wenn die Ausgabe nicht stimmt.
Ein paar praktische Regeln:
- Setze das Subjekt an den Anfang. Der erste Teilsatz hat das höchste Gewicht.
- Bevorzuge konkrete Substantive und Adjektive gegenüber abstrakten Stimmungswörtern. „Mattglasur“ verändert Pixel; „hochwertig“ im Grunde nicht.
- Setze Kamerasprache in den Kompositions-Slot, nicht in den Subjekt-Slot. Vermischt erzeugt sie eifrige und widersprüchliche Anweisungen.
- Ändere bei Iterationen jeweils nur einen Slot und bewahre den exakten Prompt-Text auf, der die akzeptierte Ausgabe erzeugt hat.
Das Seitenverhältnis ist eine Kompositionsentscheidung, kein nachträglicher Patch. Wähle es passend dazu, wo das Bild erscheinen wird – quadratisch in einem Grid, höher in einem Hero-Banner – und passe den Rest des Prompts an diesen Rahmen an.
Negativlisten effektiv nutzen
Eine Negativliste sagt dem Modell, was es vermeiden soll. Sie ist ein scharfes Werkzeug mit schmalem nützlichem Bereich: hervorragend, um wiederkehrende Fehler zu unterdrücken, aber schlecht als Müllhalde für alles, was dir an Unvollkommenheiten einfällt.
Negativbegriffe sollten kurz und konkret sein. Fünf bis acht kurze Einträge sind für die meisten Prompts ausreichend. Benenne konkrete Dinge:
no text, no watermark, no logos, no extra fingers, no harsh shadows
Diese Liste funktioniert, weil jeder Eintrag etwas Sichtbares und Prüfbares benennt. Vergleiche das mit vagen Verneinungen wie „not ugly“ oder „bad quality“ – sie tragen fast kein umsetzbares Signal und verwässern die Einträge, die wirklich zählen.
Wo Negativbegriffe wirklich helfen:
- Fehler unterdrücken, die du wiederholt siehst. Wenn Hände oder Text immer wieder auftauchen, ist es der direkteste Fix, sie explizit zu nennen.
- Marken- und Rechtshygiene. Logos und Wasserzeichen ausschließen, bevor das Bild eine benutzernahe Oberfläche erreicht.
- Saubere Hintergründe für Produktaufnahmen oder UI-nahe Bilder erzwingen.
Wo sie gegen dich arbeiten:
- Im Widerspruch zum positiven Prompt. „Keine Schatten“ in der Negativliste gegen „dramatisches Seitenlicht“ im Subjekt ist ein Konflikt, den das Modell unvorhersehbar löst. Repariere den positiven Prompt.
- Dinge verneinen, die ohnehin unwahrscheinlich sind. Eine lange Liste unwahrscheinlicher Fehler erhöht nur das Rauschen und ändert das Rendering nicht.
- Negativbegriffe als Ersatz für ein unklares Subjekt. Wenn das Subjekt unklar ist, rettet keine Negativliste es.
Ein praktisches Detail: Manche Clients akzeptieren Negativbegriffe als separates Feld statt als angehängten Text. Prüfe, welche Variante deine Anfrage unterstützt, und behalte das Feld in deinem gespeicherten Request-Body, damit curl und Python sich exakt gleich verhalten.
Prompt-Rezepte mit echten Ausgaben
Die folgenden Rezepte sind Ausgangspunkte, keine Garantien. Der ehrliche Workflow ist: Führe das Rezept über deine eigene Integration aus, sieh dir die Ausgabe an und passe dann einen Slot an. Jede Ausgabe, die du nicht selbst generiert hast, gilt als ungeprüft.
Rezept 1 – Saubere Produktaufnahme
A single matte-black wireless earbud case on a light concrete surface,
studio product photography, soft key light from the left, 1:1, centered,
shallow depth of field, plain background. No text, no logos, no hands.
Erwartete Merkmale: klares, zentriertes Subjekt, weicher Abfall und ein aufgeräumter Hintergrund. Wenn die Oberfläche zu unruhig wirkt, verschärfe „plain background“ und entferne etwaige Texturwörter. Wenn das Licht zu flach ist, füge ein richtungsweisendes Schlüsselwort hinzu – mehr nicht.
Rezept 2 – Redaktionelles Porträt
Portrait of a person in a wool coat, natural window light, calm expression,
3:4, chest-up framing, subject slightly off-center, muted film palette.
No text, no watermark.
Erwartete Merkmale: weiches gerichtetes Licht, zurückhaltende Farben. Wenn der Ausschnitt weiter als erwartet ist, ziehe „chest-up framing“ nach vorne und entferne konkurrierende Kompositionswörter.
Rezept 3 – Isometrische Illustration
Isometric illustration of a small reading nook: armchair, floor lamp, bookshelf,
flat vector style, limited palette of warm neutrals and one accent color,
1:1, centered composition, clean white background. No text, no gradients.
Erwartete Merkmale: klare Geometrie und flache Füllungen. Wenn die Farbpalette abdrifft, benenne die Akzentfarbe explizit und behalte „clean white background“ als letzten Teilsatz, damit er sich durchsetzt.
Rezept 4 – Hero-Banner
A wide misty mountain ridge at sunrise, layered depth, minimal detail,
16:9, subject occupying the lower third, generous empty sky for overlaid text.
No text, no watermark.
Erwartete Merkmale: ein ruhiges, detailarmes Bild mit nutzbarem Negativraum. Die Formulierung „overlaid text“ reserviert Platz; sie rendert keine Buchstaben, und die Negativliste hält Text aus dem Bild selbst heraus.
Zeichne für jedes Rezept den exakten Request-Body, das Seitenverhältnis und das Datum auf. Wenn du es einen Monat später überprüfst, kannst du den aufgezeichneten Request-Body erneut ausführen und mit der aufgezeichneten Ausgabe vergleichen, statt zu raten, warum sich das Ergebnis geändert hat.
Fehler, Grenzen und was zuerst zu prüfen ist
Wenn eine Generierung fehlschlägt oder die Ausgabe nicht stimmt, gehe diese Checkliste durch, bevor du Code änderst.
Prüfe zuerst den Request-Body
- Ist der Body gültiges JSON? Nachgestellte Kommas oder nicht escapte Anführungszeichen sind die häufigste Ursache für einen ersten Fehlschlag. Validiere deine gespeicherte
request.jsonvor dem Senden. - Sind die Feldnamen exakt richtig? Falsch geschriebene Parameter werden oft abgelehnt oder stillschweigend ignoriert. Vergleiche mit der Request-Struktur in der Dokumentation, nicht mit dem Gedächtnis.
- Ist der Modellname korrekt und vorhanden? Verlasse dich nicht auf Standardwerte.
- Ist der Prompt nicht leer und innerhalb der dokumentierten Länge? Die Plattformdokumentation nennt die Grenzen; lies sie dort, statt eine Zahl anzunehmen.
Prüfe dann Authentifizierung und Transport
- Existiert der API-Schlüssel und ist er aktuell gültig? 401 bedeutet normalerweise, dass der Header fehlt, falsch formatiert ist oder der Schlüssel rotiert wurde.
- Sind Endpunkt-URL und Methode korrekt? Ein POST auf einen GET-Pfad schlägt so fehl, dass es wie ein Schlüsselproblem aussieht.
- Ist dein Timeout zu knapp? Wenn dein Client aufgibt, bevor die Aufgabe abgeschlossen ist, hat das Timeout, das du siehst, nichts mit dem Modell zu tun.
Prüfe dann die Request-Struktur
- Die Statuscode-Klasse sagt dir, wo du suchen musst. 4xx ist fast immer ein Problem deiner Anfrage; 5xx ist normalerweise vorübergehend und einen begrenzten erneuten Versuch wert.
- Lies die Fehlermeldung wörtlich. Gib den Response-Body aus, bevor du eine Exception wirfst. Das in der Meldung genannte Feld ist das Feld, das repariert werden muss.
- Rate-Limit- oder Kontingentantworten bedeuten, langsamer zu werden und mit Backoff erneut zu versuchen, nicht den Prompt umzuschreiben.
Prüfe schließlich den Prompt
Wenn der Aufruf erfolgreich ist, aber das Bild nicht stimmt, befindest du dich im Prompt-Bereich, nicht im Fehlerbereich:
- Fehlt das Subjekt oder ist es zu allgemein? Verschiebe es in den ersten Teilsatz und mache es konkret.
- Stimmt die Komposition nicht? Korrigiere sowohl Seitenverhältnis als auch Ausschnittwörter; gleiche nicht das eine mit dem anderen aus.
- Treten Fehler wiederholt auf? Füge einen kurzen, konkreten Negativbegriff hinzu.
- Gibt es einen Widerspruch? Finde den Negativbegriff, der gegen den positiven Prompt arbeitet, und entferne ihn.
Am wichtigsten ist, eine Gewohnheit beizubehalten: Zeichne für jede Generierung, die dir wichtig ist, den exakten Request-Body, den Antwortstatus und den Verweis auf das generierte Bild auf. Reproduzierbarkeit macht aus Debugging ein Diff statt eines Ratespiels. Baue deine erste Anfrage, bestätige die Ausgabe, schärfe dann den Prompt vor dem Go-live – und bewahre den Request-Body auf, den du beim Go-live verwendet hast, damit die nächste Änderung eine echte Vergleichsbasis hat.
Ähnliche Artikel
Alle Artikel ansehen →-
Tutorial
gemini-omni-1.2-flash in der Praxis: 3 geschäftliche Video-Generierungsszenarien und eine Checkliste für die Umsetzung
Drei Anwendungsszenarien: Textkonzept, Startbild-Dynamisierung und visuelle Steuerung durch Referenzbilder
-
Tutorial
So rufen Sie gpt-image-2.5-sunburst/text-to-image über die HiAPI-API auf: curl und Python
Eine Integrationsübung mit funktionierenden Anfragen, Referenzbildverarbeitung und Wiederholungsmustern
-
Tutorial
So rufst du gpt-5.6-terra@azure über die HiAPI API auf: curl- und Python-Leitfaden
Baue eine funktionierende Anfrage, füge Streaming und Tool-Aufrufe hinzu und behandle Fehler, ohne raten zu müssen