Tutorial
KI-Bild-Prompt-Enhancer bauen: LLM-Prompt-Erweiterung für ideogram-v4 und flux-2
Kurze Prompts erzeugen nur generische Bilder. „coffee shop logo“ liefert dem Modell praktisch keine verwertbaren Informationen – keinen zu rendernden Namen, keinen Stil, keine Komposition, keine Farbpalette. Moderne Bild-Pipelines lösen dieses Problem mit Prompt-Erweiterung: Bevor der Prompt an die Bild-API geht, verwandelt ein günstiger LLM-Durchlauf den Fünf-Wort-Prompt in eine reichhaltige, modellgerechte Beschreibung. Einige Plattformen haben Erweiterer inzwischen fest in bestimmte Modelle integriert – was für sich spricht, wie verbreitet dieser Vorverarbeitungsschritt ist.
In diesem Tutorial bauen wir diesen Schritt selbst als kleine Python-Pipeline: Ein LLM reichert den kurzen Prompt des Nutzers an, dann wird das Ergebnis über die einheitliche Task-API von hiapi an ideogram-v4 oder flux-2 geschickt. Die Erweiterungsregeln lassen sich pro Modell steuern – was wichtig ist, denn was einen Ideogram-Prompt glänzen lässt (exakter, in Anführungszeichen gesetzter Text), unterscheidet sich von dem, was einen FLUX.2-Prompt glänzen lässt (Szene, Beleuchtung, Kamera).
Voraussetzungen: ein hiapi-API-Key (erstellen im Konsolen-Dashboard), Python 3.10+ und requests (pip install requests) sowie ein chat-completions-kompatibler LLM-Endpunkt für den Erweiterungsschritt (ein kleines/günstiges Modell genügt – der Erweiterer schreibt pro Aufruf nur etwa 100 Wörter).
Warum Prompts erweitern?
Auf hiapi gibt es zwei Modelle mit eingebautem Erweiterungs-Schalter: qwen-image-2.0 hat prompt_extend, flux-1.1-pro hat prompt_upsampling. Ist der Schalter aktiv, reichert die Plattform den Prompt serverseitig an.
Aber ideogram-v4 und flux-2/text-to-image – die beiden stärksten Modelle in Sachen Typografie bzw. Prompt-Treue – haben keinen eingebauten Erweiterer. Ihr Eingabe-Schema akzeptiert nur einen Prompt-String und Generierungsparameter, sonst nichts. Wer auf diesen Modellen reichhaltigere Prompts will, muss den Erweiterungsschritt selbst mitbringen. Der Vorteil: Dein eigener Erweiterer kennt das Modell, kennt die Marke und lässt sich debuggen. Du siehst genau, welcher String gesendet wurde.
Der Erweiterer: ein System-Prompt pro Modellfamilie
Der ganze Trick ist eine Funktion, die einen String hineinnimmt und einen String ausgibt. Hier der anbieterunabhängige LLM-Aufruf – richte LLM_BASE_URL / LLM_API_KEY / LLM_MODEL auf einen beliebigen chat-completions-kompatiblen Endpunkt, den du bereits betreibst:
import os
import requests
LLM_BASE_URL = os.environ["LLM_BASE_URL"] # e.g. https://your-llm-endpoint/v1
LLM_API_KEY = os.environ["LLM_API_KEY"]
LLM_MODEL = os.environ["LLM_MODEL"]
EXPANDER_PROMPTS = {
# ideogram-v4 is a typography specialist: exact strings to render go in
# double quotes, and layout/style language matters more than camera language.
"ideogram-v4": (
"You expand short image prompts for a typography-focused image model. "
"Rules: keep the user's intent exactly; if the image should contain text, "
"put the exact words in double quotes; describe layout (centered, badge, "
"poster), lettering style, palette, and background; flat/vector terms are "
"good; no camera or lens language; output 60-100 words, one paragraph, "
"no preamble."
),
# flux-2 has strong prompt adherence for scenes: subject, setting, lighting,
# mood, camera. It has no negative prompt, so state what you want, not what
# you don't.
"flux-2/text-to-image": (
"You expand short image prompts for a high-fidelity text-to-image model. "
"Rules: keep the user's intent exactly; add subject detail, setting, "
"lighting, mood, composition and camera hints; state desired qualities "
"positively (the model has no negative prompt); output 80-120 words, one "
"paragraph, no preamble."
),
}
def expand_prompt(short_prompt: str, target_model: str) -> str:
"""LLM pass: short user prompt -> enriched, model-appropriate prompt."""
r = requests.post(
f"{LLM_BASE_URL}/chat/completions",
headers={"Authorization": f"Bearer {LLM_API_KEY}"},
json={
"model": LLM_MODEL,
"messages": [
{"role": "system", "content": EXPANDER_PROMPTS[target_model]},
{"role": "user", "content": short_prompt},
],
"temperature": 0.7,
},
timeout=60,
)
r.raise_for_status()
return r.json()["choices"][0]["message"]["content"].strip()
Da die Pipeline nur str -> str braucht, kannst du sie gegen jeden beliebigen Erweiterer austauschen – ein größeres LLM, ein feinabgestimmtes Modell oder sogar ein deterministisches Template für feste Markenkampagnen.
Vorher und Nachher
Eingabe: coffee shop logo
Nach der Erweiterung für ideogram-v4:
Minimalistisches rundes Abzeichen-Logo für ein Spezialitäten-Café namens „Driftwood Coffee“, der Schriftzug „DRIFTWOOD COFFEE“ läuft in einer klaren serifenlosen Großbuchstaben-Schrift um eine schlichte Strichzeichnung einer Kaffeetasse mit drei Dampflinien. Warmer cremefarbener Hintergrund, dunkles Espressobraun für Schrift und Linien, flacher Vektorstil, hoher Kontrast, zentrierte Komposition, reichlich Freiraum an den Rändern.
Nach der Erweiterung für flux-2:
Gemütliches Spezialitäten-Café-Interieur zur goldenen Stunde, warmes Sonnenlicht fällt durch ein breites Frontfenster auf einen Bartresen aus Walnussholz, ein Barista zieht Latte Art in eine Keramiktasse, hinter ihm Regale voller bernsteinfarbener Glasbehälter und Jutesäcke mit Kaffeebohnen, sanfter Dampf steigt auf, geringe Schärfentiefe, 35-mm-Foto-Look, warme, einladende Farbtöne, scharfer Fokus auf der Tasse.
Dieselbe fünfstellige Absicht, zwei völlig verschiedene – und jeweils perfekt passende – Prompts. Die Ideogram-Version setzt den exakt zu rendernden Text in Anführungszeichen (seine Stärke); die FLUX.2-Version verwendet ihre Worte auf Szene und Licht (seine Stärke).
Die komplette Pipeline: Erweitern, Task erstellen, abfragen, herunterladen
Alle hiapi-Generierungsmodelle werden über einen asynchronen Endpunkt aufgerufen: POST /v1/tasks erstellt einen Task, GET /v1/tasks/<id> fragt ihn ab, fertige Artefakte erscheinen unter data.output[0].url.
import json
import os
import time
import requests
HIAPI_KEY = os.environ["HIAPI_API_KEY"]
TASKS = "https://api.hiapi.ai/v1/tasks"
HEADERS = {"Authorization": f"Bearer {HIAPI_KEY}", "Content-Type": "application/json"}
def create_task(model: str, input_obj: dict) -> str:
r = requests.post(TASKS, headers=HEADERS,
json={"model": model, "input": input_obj}, timeout=60)
data = r.json()
task_id = (data.get("data") or {}).get("taskId")
if not task_id:
raise RuntimeError(f"create task failed: {json.dumps(data)[:300]}")
return task_id
def wait_task(task_id: str, timeout_s: int = 300, poll_s: int = 5) -> dict:
deadline = time.time() + timeout_s
while time.time() < deadline:
r = requests.get(f"{TASKS}/{task_id}",
headers={"Authorization": f"Bearer {HIAPI_KEY}"}, timeout=30)
task = r.json().get("data") or {}
if task.get("status") == "success":
return task
if task.get("status") == "fail":
err = task.get("error") or {}
raise RuntimeError(f"task failed: {err.get('code')} {err.get('message')}")
time.sleep(poll_s)
raise TimeoutError(f"task {task_id} still running after {timeout_s}s")
def generate(short_prompt: str, target_model: str) -> str:
expanded = expand_prompt(short_prompt, target_model)
print(f"expanded prompt -> {expanded}\n")
if target_model == "ideogram-v4":
input_obj = {
"prompt": expanded,
"rendering_speed": "BALANCED", # required: TURBO | BALANCED | QUALITY
"aspect_ratio": "1:1", # 1:1, 16:9, 4:3, 9:16, 3:4
}
else: # flux-2/text-to-image
input_obj = {
"prompt": expanded,
"aspect_ratio": "3:2", # 1:1, 16:9, 3:2, 2:3, 4:5, 5:4, 9:16, 3:4, 4:3, custom
"resolution": "1 MP", # '0.5 MP' | '1 MP' | '2 MP' | '4 MP'
}
task_id = create_task(target_model, input_obj)
task = wait_task(task_id)
url = task["output"][0]["url"]
# Output URLs expire — download immediately, don't hot-link them.
img = requests.get(url, timeout=120).content
fname = f"{target_model.replace('/', '-')}.png"
with open(fname, "wb") as f:
f.write(img)
return fname
if __name__ == "__main__":
print(generate("coffee shop logo", "ideogram-v4"))
print(generate("coffee shop logo", "flux-2/text-to-image"))
So führst du es aus:
export HIAPI_API_KEY="sk-..."
export LLM_BASE_URL="https://your-llm-endpoint/v1"
export LLM_API_KEY="..."
export LLM_MODEL="your-small-model"
python pipeline.py
Achte auf das Eingabe-Schema – jedes Modell ist anders
Die Task-API validiert input strikt pro Modell; unbekannte Felder werden abgelehnt statt ignoriert. Wenn du ideogram-v4 ein Feld schickst, das es nicht kennt:
{
"code": 400,
"error_code": "INVALID_REQUEST",
"message": "invalid input: <root>: additional properties 'size' not allowed"
}
Drei Unterschiede in dieser Pipeline sind erwähnenswert:
rendering_speedist bei ideogram-v4 Pflicht (TURBO/BALANCED/QUALITY– die Stufen sind unterschiedlich bepreist). flux-2 hat dieses Feld nicht.- Die Seitenverhältnis-Menüs unterscheiden sich. ideogram-v4 bietet fünf Presets mit ca. 1 MP (
1:1,16:9,4:3,9:16,3:4); flux-2 bietet ein breiteres Set pluscustommit expliziterwidth/height(256–2048, Vielfache von 16). Wenn deine App Nutzer das Seitenverhältnis wählen lässt, mappe es vor dem Senden modellgerecht. - flux-2 dimensioniert nach Megapixel-Stufen (
resolution:'0.5 MP'bis'4 MP') und hat keinen negativen Prompt – ein weiterer Grund, warum der Erweiterer stets in positiven Formulierungen schreiben sollte.
Härtung für den Produktivbetrieb
Bei hoher Last Callbacks statt Polling bevorzugen. Füge beim Erstellen des Tasks einen callback-Block hinzu, dann POSTet hiapi dich im Endzustand an, statt dass du pollen musst:
payload = {
"model": "flux-2/text-to-image",
"input": input_obj,
"callback": {"url": "https://your-domain.com/hiapi/callback", "when": "final"},
}
Polling ist einfacher und passt zu lokalen Skripten, Cron-Jobs und niedriger Last; Callbacks vermeiden verschwendete Requests bei langen Generierungen und benachrichtigen pro Task genau einmal. Ein gängiges Produktionsmuster ist Callback als Hauptkanal mit langsamem Abgleich-Polling als Backup.
Mache Retries idempotent. Sende beim Erstellen des Tasks einen Idempotency-Key-Header (max. 255 Byte, 24 Stunden aufbewahrt). Ein Retry mit demselben Key liefert die ursprüngliche taskId zurück (Antwort-Header Idempotent-Replay: true), statt einen doppelten Task zu erstellen – und zu berechnen. Wird derselbe Key mit einem anderen Request-Body wiederverwendet, kommt 422 IDEMPOTENCY_KEY_MISMATCH; tritt ein Retry in ein Race mit dem laufenden Original, kommt 409 mit Retry-After. Leite den Key aus deiner eigenen Task-ID ab:
headers = {**HEADERS, "Idempotency-Key": f"expand-pipeline-{job_id}"}
Behandle Authentifizierungsfehler explizit. Ungültige oder unzureichend berechtigte Keys scheitern mit HTTP 401 und "code": "permission_denied" im Fehler-Body – fange das getrennt von Generierungsfehlern ab, denn Retries helfen hier nicht:
if r.status_code == 401:
raise SystemExit("hiapi key invalid or lacks access to this model")
Persistiere Ausgaben sofort. Task-Ausgabe-URLs haben eine begrenzte Gültigkeit. Lade die Bytes herunter und speichere sie selbst, sobald der Task erfolgreich ist.
Halte den Erweiterer an der Leine. Begrenze die Erweiterung auf etwa 120 Wörter, setze temperature auf ≤ 0.8 und logge den kurzen Prompt und den erweiterten Prompt zusammen mit der taskId. Wenn ein Ergebnis falsch aussieht, ist die erste Frage immer „Was hat das Modell tatsächlich erhalten?“ – mit deinem eigenen Erweiterer kannst du sie beantworten.
Achte auf Kostenstapelung. Jetzt zahlst du pro Bild für zwei Aufrufe: eine kleine LLM-Completion (meist vernachlässigbar) plus die Bildgenerierung – ideogram-v4 rechnet pro Bild nach rendering_speed-Stufe ab, flux-2 pro Bild nach Auflösungsstufe. Die aktuellen Preise für beide findest du auf der Preisseite.
Wie es weitergeht
- Modelldetails und Parameter: die Modellseiten ideogram-v4 und flux-2
- Wo die Plattform bereits einen eingebauten Erweiterer hat, kannst du den DIY-Erweiterer überspringen: qwen-image-2.0 (
prompt_extend) und flux-1.1-pro (prompt_upsampling) - Task-API-Referenz und weitere Integrationsanleitungen: Dokumentation
- Preise pro Bild über Modelle hinweg vergleichen: Preise
Häufig gestellte Fragen
Kann ich denselben erweiterten Prompt an beide Modelle schicken? Ja, aber auf Kosten der Qualität. Ideogram bevorzugt wörtlichen Text in Anführungszeichen und Layout-Sprache; FLUX.2 bevorzugt Szene, Beleuchtung und Kameradetails. Ein Erweiterer-System-Prompt pro Modellfamilie kostet nur ein paar Zeilen Code und zahlt sich bei jeder Generierung aus.
Gibt es ein hiapi-Modell, das die Prompts für mich erweitert?
Ja – qwen-image-2.0 akzeptiert prompt_extend, flux-1.1-pro akzeptiert prompt_upsampling. Für ideogram-v4 und flux-2/text-to-image gibt es keinen eingebauten Erweiterer, und genau dafür ist dieses Tutorial gedacht.
Wie lang sollte ein erweiterter Prompt sein? Für diese Pipeline sind 60–120 Wörter der Sweet Spot. Darüber hinaus verdünnt sich das Signal, und manche kostengünstigen Modelle schneiden lange Prompts hart ab (z. B. flux-schnell bei etwa 256 Token). Dichte schlägt Länge: Jede neu hinzugefügte Wendung sollte das Bild einschränken.
Unterstützt flux-2 negative Prompts? Nein. Formuliere, was du willst, nicht was du nicht willst – und schreibe diese Regel in den System-Prompt des Erweiterers, damit er niemals Formulierungen wie „no text, no watermark“ ausgibt, die das Modell als Inhalt liest.
Was, wenn das LLM die Absicht des Nutzers verändert? Binde es im System-Prompt („keep the user's intent exactly“), halte die Temperature moderat und logge Vorher-Nachher. Bei risikoreichen Abläufen zeigst du dem Nutzer den erweiterten Prompt vor der Generierung oder bietest einen Schalter „meinen Prompt unverändert verwenden“ an, um den Erweiterer zu umgehen.
Warum scheitert meine Anfrage mit 400, bevor überhaupt eine Generierung stattfindet?
Schema-Validierung. Jedes Modell validiert input strikt – ein fehlendes Pflichtfeld (etwa rendering_speed bei ideogram-v4) oder ein unbekanntes Feld scheitert schnell mit error_code: "INVALID_REQUEST" und einer Meldung, die das beanstandete Feld nennt. Diese Fehler sind kostenlos; korrigiere das Feld und reiche erneut ein.
Ähnliche Artikel
Alle Artikel ansehen →-
Tutorial
So rufen Sie hailuo-2.3-fast/image-to-video über die HiAPI API auf: curl und Python in der Praxis
Die erste lauffähige Anfrage für die schnelle, kostengünstige Bild-zu-Video-Stufe – von der Modell-ID bis zum heruntergeladenen MP4
-
Tutorial
So rufen Sie hailuo-2.3/text-to-video über die HiAPI API auf: curl, Python und lauffähige Anfragebeispiele
-
Tutorial
Kandinsky 6.0 Pro Text-zu-Video auf HiAPI: curl- und Python-Tutorial
Eine anfrageorientierte praktische Demonstration: Aufbau des Aufrufs vom Prompt zum Videoclip, Absenden der Anfrage, Abfragen des Fertigstellungsstatus und Herunterladen des Ergebnisses