Aufbau einer Bestseller-to-Image Pipeline für E-Commerce mit Nano Banana 2 + Milvus + Qwen 3.5
Wenn Sie KI-Werkzeuge für E-Commerce-Verkäufer entwickeln, haben Sie diese Anfrage wahrscheinlich schon tausendmal gehört: "Ich habe ein neues Produkt. Geben Sie mir ein Werbebild, das aussieht, als gehöre es in eine Bestsellerliste. Kein Fotograf, kein Studio, und es soll billig sein."
Das ist das Problem in einem Satz. Verkäufer haben flache Fotos und einen Katalog von Bestsellern, die bereits konvertieren. Sie wollen beides mit KI verbinden, und zwar schnell und in großem Umfang.
Als Google am 26. Februar 2026 Nano Banana 2 (Gemini 3.1 Flash Image) veröffentlichte, testeten wir es noch am selben Tag und integrierten es in unsere bestehende Milvus-basierte Retrieval-Pipeline. Das Ergebnis: Die Gesamtkosten für die Bilderzeugung sanken auf etwa ein Drittel der früheren Ausgaben, und der Durchsatz verdoppelte sich. Die Preissenkung pro Bild (etwa 50 % billiger als Nano Banana Pro) trägt einen Teil dazu bei, aber die größeren Einsparungen ergeben sich aus der völligen Eliminierung von Nachbearbeitungszyklen.
In diesem Artikel erfahren Sie, was Nano Banana 2 für den E-Commerce leistet, wo es noch Defizite aufweist und wie Sie die vollständige Pipeline in einem praktischen Tutorial erlernen können: Milvus-Hybridsuche, um visuell ähnliche Bestseller zu finden, Qwen 3.5 für die Stilanalyse und Nano Banana 2 für die finale Generierung.
Was ist neu bei Nano Banana 2?
Nano Banana 2 (Gemini 3.1 Flash Image) wurde am 26. Februar 2026 eingeführt. Es bringt die meisten Funktionen von Nano Banana Pro auf die Flash-Architektur, was eine schnellere Generierung zu einem niedrigeren Preis bedeutet. Hier sind die wichtigsten Neuerungen:
- Profi-Qualität in Flash-Geschwindigkeit. Nano Banana 2 bietet erstklassiges Wissen, logisches Denken und visuelle Wiedergabetreue, die bisher nur Pro vorbehalten waren, aber mit der Latenzzeit und dem Durchsatz von Flash.
- 512px bis 4K Ausgabe. Vier Auflösungsebenen (512px, 1K, 2K, 4K) mit nativer Unterstützung. Die 512px-Ebene ist neu und einzigartig für Nano Banana 2.
- 14 Seitenverhältnisse. Fügt 4:1, 1:4, 8:1 und 1:8 zu den bestehenden Verhältnissen hinzu (1:1, 2:3, 3:2, 3:4, 4:3, 4:5, 5:4, 9:16, 16:9, 21:9).
- Bis zu 14 Referenzbilder. Behält die Zeichenähnlichkeit für bis zu 5 Zeichen und die Objekttreue für bis zu 14 Objekte in einem einzigen Arbeitsablauf bei.
- Verbesserte Textwiedergabe. Generiert lesbaren, präzisen Text im Bild in mehreren Sprachen, mit Unterstützung für Übersetzung und Lokalisierung innerhalb einer einzigen Generierung.
- Bildsuche als Grundlage. Greift auf Echtzeit-Webdaten und Bilder aus der Google-Suche zurück, um genauere Darstellungen von realen Themen zu generieren.
- ~50% billiger pro Bild. Bei 1K Auflösung: 0 ,134.
Ein lustiger Anwendungsfall von Nano Banano 2: Erzeugen eines ortsbezogenen Panoramas auf der Grundlage eines einfachen Google Maps-Screenshots
Anhand eines Google Maps-Screenshots und einer Eingabeaufforderung erkennt das Modell den geografischen Kontext und generiert ein Panorama, das die richtigen räumlichen Beziehungen beibehält. Nützlich für die Erstellung von Werbemitteln, die auf eine bestimmte Region zugeschnitten sind (Hintergrund eines Pariser Cafés, ein Straßenbild in Tokio), ohne dass Stockfotografien beschafft werden müssen.
Den vollständigen Funktionsumfang finden Sie in Googles Ankündigungsblog und in der Entwicklerdokumentation.
Was bedeutet dieses Nano Banana-Update für den E-Commerce?
Der elektronische Handel ist eine der bildintensivsten Branchen. Produktlisten, Marktplatz-Anzeigen, Social-Creatives, Bannerkampagnen, lokalisierte Schaufenster: Jeder Kanal erfordert einen konstanten Strom visueller Assets, jeder mit seinen eigenen Spezifikationen.
Die wichtigsten Anforderungen an die KI-Bilderstellung im E-Commerce lauten:
- Niedrige Kosten - die Kosten pro Bild müssen in Kataloggröße funktionieren.
- Anpassung an das Aussehen bewährter Bestseller - neue Bilder sollten dem visuellen Stil von Angeboten entsprechen, die bereits erfolgreich sind.
- Vermeiden Sie Rechtsverletzungen - kopieren Sie keine Motive von Konkurrenten oder verwenden Sie keine geschützten Inhalte wieder.
Darüber hinaus benötigen grenzüberschreitende Verkäufer:
- Unterstützung von Multiplattform-Formaten - unterschiedliche Seitenverhältnisse und Spezifikationen für Marktplätze, Anzeigen und Schaufenster.
- Mehrsprachiges Text-Rendering - sauberer, akkurater In-Image-Text in mehreren Sprachen.
Nano Banana 2 erfüllt nahezu alle Kriterien. In den folgenden Abschnitten wird aufgeschlüsselt, was die einzelnen Verbesserungen in der Praxis bedeuten: wo sie direkt ein Problem des E-Commerce lösen, wo sie nicht ausreichen und wie sich die tatsächlichen Kosten auswirken.
Bis zu 60 % geringere Output-Erzeugungskosten
Bei einer Auflösung von 1K kostet Nano Banana 2 0 ,134, was einer direkten Senkung um 50% entspricht. Aber der Preis pro Bild ist nur die Hälfte der Geschichte. Was früher die Budgets der Nutzer vernichtete, war die Nachbearbeitung. Jeder Marktplatz erzwingt seine eigenen Bildspezifikationen (1:1 für Amazon, 3:4 für Shopify-Storefronts, ultrawide für Bannerwerbung), und die Produktion jeder Variante bedeutete einen separaten Generierungsdurchlauf mit eigenen Fehlermöglichkeiten.
Nano Banana 2 fasst diese zusätzlichen Durchgänge in einem zusammen.
Vier native Auflösungsebenen.
512px ($0.045)
1K ($0.067)
2K ($0.101)
4K ($0.151).
Die 512px Stufe ist neu und einzigartig in Nano Banana 2. Benutzer können jetzt kostengünstige 512px-Entwürfe für die Iteration erstellen und das endgültige Asset in 2K oder 4K ohne einen separaten Upscaling-Schritt ausgeben.
Insgesamtwerden 14 Seitenverhältnisse unterstützt. Hier sind einige Beispiele:
4:1
1:4
8:1
1:8
Diese neuen ultra-breiten und ultra-hohen Verhältnisse ergänzen die bestehenden. Mit einer Generierungssitzung können verschiedene Formate erzeugt werden, wie z. B.: Amazon-Hauptbild (1:1), Schaufensterheld (3:4) und Werbebanner (ultrabreit oder andere Verhältnisse).
Für diese 4 Formate ist kein Zuschneiden, kein Auffüllen und kein erneutes Aufrufen erforderlich. Die übrigen 10 Seitenverhältnisse sind im vollständigen Satz enthalten, was den Prozess auf verschiedenen Plattformen flexibler macht.
Allein die Einsparungen von ca. 50 % pro Bild würden die Rechnung halbieren. Durch die Eliminierung von Nacharbeiten bei verschiedenen Auflösungen und Seitenverhältnissen sind die Gesamtkosten auf etwa ein Drittel der früheren Ausgaben gesunken.
Unterstützung von bis zu 14 Referenzbildern mit Bestseller-Stil
Von allen Aktualisierungen von Nano Banana 2 hat das Multireferenz-Blending die größten Auswirkungen auf unsere Milvus-Pipeline. Nano Banana 2 akzeptiert bis zu 14 Referenzbilder in einer einzigen Anfrage und behält diese bei:
- Zeichenähnlichkeit für bis zu 5 Zeichen
- Objekttreue für bis zu 14 Objekte
In der Praxis haben wir mehrere Bestseller-Bilder von Milvus abgerufen, sie als Referenzen übergeben und das generierte Bild hat deren Szenenkomposition, Beleuchtung, Posing und Requisitenplatzierung übernommen. Es war kein promptes Engineering erforderlich, um diese Muster von Hand zu rekonstruieren.
Frühere Modelle unterstützten nur ein oder zwei Referenzen, so dass die Benutzer gezwungen waren, einen einzigen Bestseller zur Nachahmung auszuwählen. Mit 14 Referenzplätzen konnten wir Merkmale aus mehreren Top-Listen mischen und das Modell einen zusammengesetzten Stil synthetisieren lassen. Dies ist die Fähigkeit, die die Retrieval-basierte Pipeline in der folgenden Anleitung möglich macht.
Produzieren Sie hochwertiges, werbefähiges Bildmaterial ohne herkömmliche Produktionskosten oder Logistik
Um eine konsistente und zuverlässige Bilderzeugung zu gewährleisten, sollten Sie nicht alle Ihre Anforderungen in eine einzige Eingabeaufforderung packen. Ein zuverlässigerer Ansatz besteht darin, schrittweise vorzugehen: Generieren Sie zuerst den Hintergrund, dann das Modell separat und fügen Sie beide schließlich zusammen.
Wir haben die Hintergrundgenerierung für alle drei Nano Banana-Modelle mit derselben Eingabeaufforderung getestet: eine 4:1-Ultrawide-Skyline von Shanghai an einem verregneten Tag, die durch ein Fenster betrachtet wird, wobei der Oriental Pearl Tower sichtbar ist. Mit dieser Aufforderung werden die Komposition, die architektonischen Details und der Fotorealismus in einem einzigen Durchgang getestet.
Original Nano Banana vs. Nano Banana Pro vs. Nano Banana 2
- Original Nano Banana. Natürliche Regentextur mit glaubwürdiger Tröpfchenverteilung, aber zu stark geglättete Gebäudedetails. Der Oriental Pearl Tower war kaum zu erkennen, und die Auflösung entsprach nicht den Produktionsanforderungen.
- Nano Banana Pro. Filmische Atmosphäre: Die warme Innenbeleuchtung spielte überzeugend mit dem kalten Regen. Allerdings wurde der Fensterrahmen komplett weggelassen, was die Tiefenwirkung des Bildes verringerte. Brauchbar als unterstützendes Bild, nicht als Held.
- Nano-Banane 2. Renderte die gesamte Szene. Der Fensterrahmen im Vordergrund erzeugte Tiefe. Der Oriental Pearl Tower war deutlich detailliert. Schiffe erschienen auf dem Huangpu-Fluss. Die schichtweise Beleuchtung unterschied die Wärme des Innenraums von der Bewölkung des Außenbereichs. Regen- und Wasserfleckentexturen wirkten nahezu fotorealistisch, und das 4:1-Ultraweitbildverhältnis sorgte für die richtige Perspektive mit nur geringer Verzerrung am linken Fensterrand.
Für die meisten Aufgaben der Hintergrundgestaltung in der Produktfotografie fanden wir die Ausgabe der Nano Banana 2 ohne Nachbearbeitung brauchbar.
Sauberes Rendern von Text im Bild in verschiedenen Sprachen
Preisschilder, Werbebanner und mehrsprachige Texte sind in E-Commerce-Bildern unvermeidlich und waren in der Vergangenheit ein Knackpunkt für die KI-Generierung. Nano Banana 2 kommt damit wesentlich besser zurecht und unterstützt das Rendering von Text im Bild in mehreren Sprachen mit Übersetzung und Lokalisierung in einer einzigen Generation.
Standard Textwiedergabe. In unseren Tests war die Textausgabe in jedem von uns getesteten E-Commerce-Format fehlerfrei: Preisetiketten, kurze Marketing-Taglines und zweisprachige Produktbeschreibungen.
Handschriftliche Fortführung. Da im E-Commerce häufig handschriftliche Elemente wie Preisschilder und personalisierte Karten erforderlich sind, haben wir getestet, ob die Modelle einen vorhandenen handschriftlichen Stil übernehmen und erweitern können - insbesondere eine handschriftliche Aufgabenliste und das Hinzufügen von 5 neuen Elementen im gleichen Stil. Ergebnisse für drei Modelle:
- Original Nano-Banane. Wiederholte Sequenznummern, missverstandene Struktur.
- Nano Banana Pro. Korrektes Layout, aber schlechte Wiedergabe des Schriftstils.
- Nano Banana 2. Null Fehler. Strichstärke und Schriftart sind so gut angepasst, dass sie von der Vorlage nicht zu unterscheiden sind.
In der Google-Dokumentation wirdjedoch darauf hingewiesen, dass Nano Banana 2 "noch Probleme mit der korrekten Rechtschreibung und feinen Details in Bildern haben kann". Unsere Ergebnisse waren in allen getesteten Formaten einwandfrei, aber jeder Produktionsworkflow sollte vor der Veröffentlichung eine Textüberprüfung beinhalten.
Schritt-für-Schritt-Anleitung: Aufbau einer Pipeline für Bestseller und Bilder mit Milvus, Qwen 3.5 und Nano Banana 2
Bevor wir beginnen: Architektur und Modellaufbau
Um die Zufälligkeit der Single-Prompt-Generierung zu vermeiden, unterteilen wir den Prozess in drei kontrollierbare Stufen: Abrufen, was bereits mit der Milvus-Hybridsuche funktioniert, Analysieren, warum es mit Qwen 3.5 funktioniert, und dann Generieren des endgültigen Bildes mit diesen Einschränkungen, die mit Nano Banana 2 eingebaut werden.
Eine kurze Einführung in jedes Tool, falls Sie noch nicht mit ihnen gearbeitet haben:
- Milvus: die am weitesten verbreitete Open-Source-Vektordatenbank. Speichert Ihren Produktkatalog als Vektoren und führt eine hybride Suche (dichte + spärliche + skalare Filter) durch, um Bilder von Bestsellern zu finden, die einem neuen Produkt am ähnlichsten sind.
- Qwen 3.5: ein beliebter multimodaler LLM. Nimmt die abgerufenen Bilder von Bestsellern und extrahiert die visuellen Muster dahinter (Szenenaufbau, Beleuchtung, Pose, Stimmung) in eine strukturierte Stil-Eingabeaufforderung.
- Nano Banana 2: Bilderzeugungsmodell von Google (Gemini 3.1 Flash Image). Nimmt drei Eingaben entgegen: das neue Produkt-Flat-Lay, eine Bestseller-Referenz und die Stil-Eingabeaufforderung von Qwen 3.5. Gibt das endgültige Werbefoto aus.
Die Logik hinter dieser Architektur beginnt mit einer Beobachtung: Das wertvollste visuelle Gut in jedem E-Commerce-Katalog ist die Bibliothek der Bestseller-Bilder, die bereits konvertiert wurden. Die Posen, Kompositionen und Beleuchtungen auf diesen Fotos wurden durch echte Werbeausgaben verfeinert. Diese Muster direkt abzurufen, ist um Größenordnungen schneller, als sie durch das Schreiben von Eingabeaufforderungen zurückzuentwickeln, und genau dieser Abrufschritt wird von einer Vektordatenbank übernommen.
Hier ist der vollständige Ablauf. Wir rufen jedes Modell über die OpenRouter-API auf, so dass keine lokale GPU erforderlich ist und keine Modellgewichte heruntergeladen werden müssen.
New product flat-lay
│
│── Embed → Llama Nemotron Embed VL 1B v2
│
│── Search → Milvus hybrid search
│ ├── Dense vectors (visual similarity)
│ ├── Sparse vectors (keyword matching)
│ └── Scalar filters (category + sales volume)
│
│── Analyze → Qwen 3.5 extracts style from retrieved bestsellers
│ └── scene, lighting, pose, mood → style prompt
│
└── Generate → Nano Banana 2
├── Inputs: new product + bestseller reference + style prompt
└── Output: promotional photo
Wir stützen uns auf drei Milvus-Fähigkeiten, um die Abrufphase zu ermöglichen:
- Dense + Sparse Hybrid Search. Wir führen Bildeinbettungen und Text-TF-IDF-Vektoren als parallele Abfragen durch und führen dann die beiden Ergebnismengen mit RRF (Reciprocal Rank Fusion) Reranking zusammen.
- Skalare Feldfilterung. Wir filtern vor dem Vektorvergleich nach Metadatenfeldern wie Kategorie und Verkaufszahl, sodass die Ergebnisse nur relevante, leistungsstarke Produkte enthalten.
- Schema mit mehreren Feldern. Wir speichern dichte Vektoren, spärliche Vektoren und skalare Metadaten in einer einzigen Milvus-Sammlung, so dass die gesamte Abfragelogik in einer einzigen Abfrage enthalten ist und nicht über mehrere Systeme verstreut.
Datenaufbereitung
Historischer Produktkatalog
Wir beginnen mit zwei Assets: einem images/-Ordner mit bestehenden Produktfotos und einer products.csv-Datei mit den Metadaten.
images/
├── SKU001.jpg
├── SKU002.jpg
├── ...
└── SKU040.jpg
products.csv fields:
product_id, image_path, category, color, style, season, sales_count, description, price
Neue Produktdaten
Für die Produkte, für die wir Werbebilder erstellen möchten, bereiten wir eine parallele Struktur vor: einen Ordner new_products/ und eine Datei new_products.csv.
new_products/
├── NEW001.jpg # Blue knit cardigan + grey tulle skirt set
├── NEW002.jpg # Light green floral ruffle maxi dress
├── NEW003.jpg # Camel turtleneck knit dress
└── NEW004.jpg # Dark grey ethnic-style cowl neck top dress
new_products.csv fields:
new_id, image_path, category, style, season, prompt_hint
Schritt 1: Abhängigkeiten installieren
!pip install pymilvus openai requests pillow scikit-learn tqdm
Schritt 2: Module und Konfigurationen importieren
import os, io, base64, csv, time
import requests as req
import numpy as np
from PIL import Image
from tqdm.notebook import tqdm
from sklearn.feature_extraction.text import TfidfVectorizer
from IPython.display import display
from openai import OpenAI
from pymilvus import MilvusClient, DataType, AnnSearchRequest, RRFRanker
Konfigurieren Sie alle Modelle und Pfade:
# -- Config --
OPENROUTER_API_KEY = os.environ.get(
"OPENROUTER_API_KEY",
"<YOUR_OPENROUTER_API_KEY>",
)
# Models (all via OpenRouter, no local download needed)
EMBED_MODEL = “nvidia/llama-nemotron-embed-vl-1b-v2” # free, image+text → 2048d
EMBED_DIM = 2048
LLM_MODEL = “qwen/qwen3.5-397b-a17b” # style analysis
IMAGE_GEN_MODEL = “google/gemini-3.1-flash-image-preview” # Nano Banana 2
# Milvus
MILVUS_URI = “./milvus_fashion.db”
COLLECTION = “fashion_products”
TOP_K = 3
# Paths
IMAGE_DIR = “./images”
NEW_PRODUCT_DIR = “./new_products”
PRODUCT_CSV = “./products.csv”
NEW_PRODUCT_CSV = “./new_products.csv”
# OpenRouter client (shared for LLM + image gen)
llm = OpenAI(api_key=OPENROUTER_API_KEY, base_url=“https://openrouter.ai/api/v1”)
print(“Config loaded. All models via OpenRouter API.”)
Hilfsfunktionen
Diese Hilfsfunktionen übernehmen die Bildkodierung, API-Aufrufe und das Parsen von Antworten:
- image_to_uri(): Konvertiert ein PIL-Bild in einen base64-Daten-URI für den API-Transport.
- get_image_embeddings(): Batch-Kodierung von Bildern in 2048-dimensionale Vektoren über die OpenRouter Embedding API.
- get_text_embedding(): Kodiert Text in denselben 2048-dimensionalen Vektorraum.
- sparse_to_dict(): Konvertiert eine Scipy-Sparse-Matrixzeile in das {index: value}-Format, das Milvus für Sparse-Vektoren erwartet.
- extract_images(): Extrahiert generierte Bilder aus der Nano Banana 2 API Antwort.
# -- Utility functions --
def image_to_uri(img, max_size=1024):
“""Convert PIL Image to base64 data URI.""”
img = img.copy()
w, h = img.size
if max(w, h) > max_size:
r = max_size / max(w, h)
img = img.resize((int(w * r), int(h * r)), Image.LANCZOS)
buf = io.BytesIO()
img.save(buf, format=“JPEG”, quality=85)
return f"data:image/jpeg;base64,{base64.b64encode(buf.getvalue()).decode()}"
def get_image_embeddings(images, batch_size=5):
“""Encode images via OpenRouter embedding API.""”
all_embs = []
for i in tqdm(range(0, len(images), batch_size), desc=“Encoding images”):
batch = images[i : i + batch_size]
inputs = [
{“content”: [{“type”: “image_url”, “image_url”: {“url”: image_to_uri(img, max_size=512)}}]}
for img in batch
]
resp = req.post(
“https://openrouter.ai/api/v1/embeddings”,
headers={“Authorization”: f"Bearer {OPENROUTER_API_KEY}"},
json={“model”: EMBED_MODEL, “input”: inputs},
timeout=120,
)
data = resp.json()
if “data” not in data:
print(f"API error: {data}")
continue
for item in sorted(data[“data”], key=lambda x: x[“index”]):
all_embs.append(item[“embedding”])
time.sleep(0.5) # rate limit friendly
return np.array(all_embs, dtype=np.float32)
def get_text_embedding(text):
“""Encode text via OpenRouter embedding API.""”
resp = req.post(
“https://openrouter.ai/api/v1/embeddings”,
headers={“Authorization”: f"Bearer {OPENROUTER_API_KEY}"},
json={“model”: EMBED_MODEL, “input”: text},
timeout=60,
)
return np.array(resp.json()[“data”][0][“embedding”], dtype=np.float32)
def sparse_to_dict(sparse_row):
“""Convert scipy sparse row to Milvus sparse vector format {index: value}.""”
coo = sparse_row.tocoo()
return {int(i): float(v) for i, v in zip(coo.col, coo.data)}
def extract_images(response):
“""Extract generated images from OpenRouter response.""”
images = []
raw = response.model_dump()
msg = raw[“choices”][0][“message”]
# Method 1: images field (OpenRouter extension)
if “images” in msg and msg[“images”]:
for img_data in msg[“images”]:
url = img_data[“image_url”][“url”]
b64 = url.split(“,”, 1)[1]
images.append(Image.open(io.BytesIO(base64.b64decode(b64))))
# Method 2: inline base64 in content parts
if not images and isinstance(msg.get(“content”), list):
for part in msg[“content”]:
if isinstance(part, dict) and part.get(“type”) == “image_url”:
url = part[“image_url”][“url”]
if url.startswith(“data:image”):
b64 = url.split(“,”, 1)[1]
images.append(Image.open(io.BytesIO(base64.b64decode(b64))))
return images
print(“Utility functions ready.”)
Schritt 3: Laden des Produktkatalogs
Lesen Sie products.csv und laden Sie die entsprechenden Produktbilder:
with open(PRODUCT_CSV, newline="", encoding="utf-8") as f:
products = list(csv.DictReader(f))
product_images = []
for p in products:
img = Image.open(os.path.join(IMAGE_DIR, p[“image_path”])).convert(“RGB”)
product_images.append(img)
print(f"Loaded {len(products)} products.")
for i in range(3):
p = products[i]
print(f"{p[‘product_id’]} | {p[‘category’]} | {p[‘color’]} | {p[‘style’]} | sales: {p[‘sales_count’]}")
display(product_images[i].resize((180, int(180 * product_images[i].height / product_images[i].width))))
Beispielhafte Ausgabe:
Schritt 4: Erzeugen von Einbettungen
Die hybride Suche erfordert zwei Arten von Vektoren für jedes Produkt.
4.1 Dichte Vektoren: Bildeinbettungen
Das Modell nvidia/llama-nemotron-embed-vl-1b-v2 kodiert jedes Produktbild in einen 2048-dimensionalen dichten Vektor. Da dieses Modell sowohl Bild- als auch Texteingaben in einem gemeinsamen Vektorraum unterstützt, funktionieren die gleichen Einbettungen für die Bild-zu-Bild- und die Text-zu-Bild-Suche.
# Dense embeddings: image → 2048-dim vector via OpenRouter API
dense_vectors = get_image_embeddings(product_images, batch_size=5)
print(f"Dense vectors: {dense_vectors.shape} (products x {EMBED_DIM}d)")
Ausgabe:
Dense vectors: (40, 2048) (products x 2048d)
4.2 Dünne Vektoren: TF-IDF Texteinbettungen
Produktbeschreibungen werden mit Hilfe des TF-IDF-Vektorisierers von scikit-learn in spärliche Vektoren kodiert. Diese erfassen Übereinstimmungen auf Schlüsselwortebene, die bei dichten Vektoren fehlen können.
# Sparse embeddings: TF-IDF on product descriptions
descriptions = [p["description"] for p in products]
tfidf = TfidfVectorizer(stop_words="english", max_features=500)
tfidf_matrix = tfidf.fit_transform(descriptions)
sparse_vectors = [sparse_to_dict(tfidf_matrix[i]) for i in range(len(products))]
print(f"Sparse vectors: {len(sparse_vectors)} products, vocab size: {len(tfidf.vocabulary_)}")
print(f"Sample sparse vector (SKU001): {len(sparse_vectors[0])} non-zero terms")
Ausgabe:
Sparse vectors: 40 products, vocab size: 179
Sample sparse vector (SKU001): 11 non-zero terms
Warum beide Vektortypen? Dichte und spärliche Vektoren ergänzen sich gegenseitig. Dichte Vektoren erfassen die visuelle Ähnlichkeit: Farbpalette, Kleidungssilhouette, Gesamtstil. Spärliche Vektoren erfassen die Semantik von Schlüsselwörtern: Begriffe wie "floral", "midi" oder "chiffon", die Produkteigenschaften signalisieren. Die Kombination beider Ansätze führt zu einer deutlich besseren Suchqualität als jeder Ansatz für sich.
Schritt 5: Erstellen einer Milvus-Sammlung mit Hybridschema
In diesem Schritt wird eine einzige Milvus-Sammlung erstellt, die dichte Vektoren, spärliche Vektoren und skalare Metadatenfelder gemeinsam speichert. Dieses vereinheitlichte Schema ermöglicht die hybride Suche in einer einzigen Abfrage.
| Feld | Typ | Zweck |
|---|---|---|
| dichter_vektor | FLOAT_VECTOR (2048d) | Bildeinbettung, COSINE-Ähnlichkeit |
| sparse_vector | SPARSE_FLOAT_VECTOR | TF-IDF Sparse-Vektor, inneres Produkt |
| Kategorie | VARCHAR | Kategoriebezeichnung für die Filterung |
| Umsatz_Zahl | INT64 | Historisches Verkaufsvolumen für die Filterung |
| Farbe, Stil, Saison | VARCHAR | Zusätzliche Metadatenbezeichnungen |
| Preis | FLOAT | Preis des Produkts |
milvus_client = MilvusClient(uri=MILVUS_URI)
if milvus_client.has_collection(COLLECTION):
milvus_client.drop_collection(COLLECTION)
schema = milvus_client.create_schema(auto_id=True, enable_dynamic_field=True)
schema.add_field(“id”, DataType.INT64, is_primary=True)
schema.add_field(“product_id”, DataType.VARCHAR, max_length=20)
schema.add_field(“category”, DataType.VARCHAR, max_length=50)
schema.add_field(“color”, DataType.VARCHAR, max_length=50)
schema.add_field(“style”, DataType.VARCHAR, max_length=50)
schema.add_field(“season”, DataType.VARCHAR, max_length=50)
schema.add_field(“sales_count”, DataType.INT64)
schema.add_field(“description”, DataType.VARCHAR, max_length=500)
schema.add_field(“price”, DataType.FLOAT)
schema.add_field(“dense_vector”, DataType.FLOAT_VECTOR, dim=EMBED_DIM)
schema.add_field(“sparse_vector”, DataType.SPARSE_FLOAT_VECTOR)
index_params = milvus_client.prepare_index_params()
index_params.add_index(field_name=“dense_vector”, index_type=“FLAT”, metric_type=“COSINE”)
index_params.add_index(field_name=“sparse_vector”, index_type=“SPARSE_INVERTED_INDEX”, metric_type=“IP”)
milvus_client.create_collection(COLLECTION, schema=schema, index_params=index_params)
print(f"Milvus collection '{COLLECTION}' created with hybrid schema.")
Fügen Sie die Produktdaten ein:
# Insert all products
rows = []
for i, p in enumerate(products):
rows.append({
"product_id": p["product_id"],
"category": p["category"],
"color": p["color"],
"style": p["style"],
"season": p["season"],
"sales_count": int(p["sales_count"]),
"description": p["description"],
"price": float(p["price"]),
"dense_vector": dense_vectors[i].tolist(),
"sparse_vector": sparse_vectors[i],
})
milvus_client.insert(COLLECTION, rows)
stats = milvus_client.get_collection_stats(COLLECTION)
print(f"Inserted {stats[‘row_count’]} products into Milvus.")
Ausgabe:
Inserted 40 products into Milvus.
Schritt 6: Hybride Suche nach ähnlichen Bestsellern
Dies ist der wichtigste Schritt der Suche. Für jedes neue Produkt führt die Pipeline drei Operationen gleichzeitig aus:
- Dichte Suche: findet Produkte mit visuell ähnlichen Bildeinbettungen.
- Sparsame Suche: Findet Produkte mit übereinstimmenden Text-Schlüsselwörtern über TF-IDF.
- Skalare Filterung: schränkt die Ergebnisse auf dieselbe Kategorie und Produkte mit einer Verkaufszahl > 1500 ein.
- RRF-Reranking: führt die dichten und spärlichen Ergebnislisten mittels Reciprocal Rank Fusion zusammen.
Laden Sie das neue Produkt:
# Load new products
with open(NEW_PRODUCT_CSV, newline="", encoding="utf-8") as f:
new_products = list(csv.DictReader(f))
# Pick the first new product for demo
new_prod = new_products[0]
new_img = Image.open(os.path.join(NEW_PRODUCT_DIR, new_prod[“image_path”])).convert(“RGB”)
print(f"New product: {new_prod[‘new_id’]}")
print(f"Category: {new_prod[‘category’]} | Style: {new_prod[‘style’]} | Season: {new_prod[‘season’]}")
print(f"Prompt hint: {new_prod[‘prompt_hint’]}")
display(new_img.resize((300, int(300 * new_img.height / new_img.width))))
Ausgabe:
Codieren Sie das neue Produkt:
# Encode new product
# Dense: image embedding via API
query_dense = get_image_embeddings([new_img], batch_size=1)[0]
# Sparse: TF-IDF from text query
query_text = f"{new_prod[‘category’]} {new_prod[‘style’]} {new_prod[‘season’]} {new_prod[‘prompt_hint’]}"
query_sparse = sparse_to_dict(tfidf.transform([query_text])[0])
# Scalar filter
filter_expr = f’category == "{new_prod[“category”]}" and sales_count > 1500’
print(f"Dense query: {query_dense.shape}")
print(f"Sparse query: {len(query_sparse)} non-zero terms")
print(f"Filter: {filter_expr}")
Ausgabe:
Dense query: (2048,)
Sparse query: 6 non-zero terms
Filter: category == "midi_dress" and sales_count > 1500
Ausführen der hybriden Suche
Die wichtigsten API-Aufrufe hier:
- AnnSearchRequest erstellt separate Suchanfragen für die dichten und spärlichen Vektorfelder.
- expr=filter_expr wendet skalare Filterung innerhalb jeder Suchanfrage an.
- RRFRanker(k=60) fusioniert die beiden gerankten Ergebnislisten unter Verwendung des Reciprocal Rank Fusion-Algorithmus.
- hybrid_search führt beide Anfragen aus und liefert zusammengeführte, neu bewertete Ergebnisse.
# Hybrid search: dense + sparse + scalar filter + RRF reranking
dense_req = AnnSearchRequest(
data=[query_dense.tolist()],
anns_field="dense_vector",
param={"metric_type": "COSINE"},
limit=20,
expr=filter_expr,
)
sparse_req = AnnSearchRequest(
data=[query_sparse],
anns_field="sparse_vector",
param={"metric_type": "IP"},
limit=20,
expr=filter_expr,
)
results = milvus_client.hybrid_search(
collection_name=COLLECTION,
reqs=[dense_req, sparse_req],
ranker=RRFRanker(k=60),
limit=TOP_K,
output_fields=[“product_id”, “category”, “color”, “style”, “season”,
“sales_count”, “description”, “price”],
)
# Display retrieved bestsellers
retrieved_products = []
retrieved_images = []
print(f"Top-{TOP_K} similar bestsellers:\n")
for hit in results[0]:
entity = hit[“entity”]
pid = entity[“product_id”]
img = Image.open(os.path.join(IMAGE_DIR, f"{pid}.jpg")).convert(“RGB”)
retrieved_products.append(entity)
retrieved_images.append(img)
print(f"{pid} | {entity[‘category’]} | {entity[‘color’]} | {entity[‘style’]} "
f"| sales: {entity[‘sales_count’]} | ${entity[‘price’]:.1f} | score: {hit[‘distance’]:.4f}")
print(f" {entity[‘description’]}")
display(img.resize((250, int(250 * img.height / img.width))))
print()
Ausgabe: die Top 3 der ähnlichsten Bestseller, geordnet nach der verschmolzenen Punktzahl.
Schritt 7: Analysieren des Bestseller-Stils mit Qwen 3.5
Wir geben die abgerufenen Bestseller-Bilder in Qwen 3.5 ein und bitten es, ihre gemeinsame visuelle DNA zu extrahieren: Szenenkomposition, Beleuchtungseinstellung, Model-Pose und Gesamtstimmung. Nach dieser Analyse erhalten wir eine Eingabeaufforderung für eine einzige Generation, die wir an Nano Banana 2 weitergeben können.
content = [
{"type": "image_url", "image_url": {"url": image_to_uri(img)}}
for img in retrieved_images
]
content.append({
"type": "text",
"text": (
"These are our top-selling fashion product photos.\n\n"
"Analyze their common visual style in these dimensions:\n"
"1. Scene / background setting\n"
"2. Lighting and color tone\n"
"3. Model pose and framing\n"
"4. Overall mood and aesthetic\n\n"
"Then, based on this analysis, write ONE concise image generation prompt "
"(under 100 words) that captures this style. The prompt should describe "
"a scene for a model wearing a new clothing item. "
"Output ONLY the prompt, nothing else."
),
})
response = llm.chat.completions.create(
model=LLM_MODEL,
messages=[{“role”: “user”, “content”: content}],
max_tokens=512,
temperature=0.7,
)
style_prompt = response.choices[0].message.content.strip()
print(“Style prompt from Qwen3.5:\n”)
print(style_prompt)
Beispielhafte Ausgabe:
Style prompt from Qwen3.5:
Professional full-body fashion photograph of a model wearing a stylish new dress.
Bright, soft high-key lighting that illuminates the subject evenly. Clean,
uncluttered background, either stark white or a softly blurred bright outdoor
setting. The model stands in a relaxed, natural pose to showcase the garment’s
silhouette and drape. Sharp focus, vibrant colors, fresh and elegant commercial aesthetic.
Schritt 8: Erzeugen des Werbebildes mit Nano Banana 2
Wir geben drei Inputs an Nano Banana 2 weiter: das Flat-Lay-Foto des neuen Produkts, das Bild des bestplatzierten Bestsellers und die im vorherigen Schritt extrahierte Style-Anweisung. Das Modell setzt diese zu einem Werbefoto zusammen, das das neue Kleidungsstück mit einem bewährten visuellen Stil verbindet.
gen_prompt = (
f"I have a new clothing product (Image 1: flat-lay photo) and a reference "
f"promotional photo from our bestselling catalog (Image 2).\n\n"
f"Generate a professional e-commerce promotional photograph of a female model "
f"wearing the clothing from Image 1.\n\n"
f"Style guidance: {style_prompt}\n\n"
f"Scene hint: {new_prod['prompt_hint']}\n\n"
f"Requirements:\n"
f"- Full body shot, photorealistic, high quality\n"
f"- The clothing should match Image 1 exactly\n"
f"- The photo style and mood should match Image 2"
)
gen_content = [
{“type”: “image_url”, “image_url”: {“url”: image_to_uri(new_img)}},
{“type”: “image_url”, “image_url”: {“url”: image_to_uri(retrieved_images[0])}},
{“type”: “text”, “text”: gen_prompt},
]
print(“Generating promotional photo with Nano Banana 2…”)
gen_response = llm.chat.completions.create(
model=IMAGE_GEN_MODEL,
messages=[{“role”: “user”, “content”: gen_content}],
extra_body={
“modalities”: [“text”, “image”],
“image_config”: {“aspect_ratio”: “3:4”, “image_size”: “2K”},
},
)
print(“Done!”)
Schlüsselparameter für den Nano Banana 2 API-Aufruf:
- Modalitäten: ["text", "image"]: legt fest, dass die Antwort ein Bild enthalten soll.
- image_config.aspect_ratio: steuert das Seitenverhältnis der Ausgabe (3:4 eignet sich gut für Porträt-/Modeaufnahmen).
- image_config.image_size: legt die Auflösung fest. Nano Banana 2 unterstützt 512px bis 4K.
Extrahieren Sie das erzeugte Bild:
generated_images = extract_images(gen_response)
text_content = gen_response.choices[0].message.content
if text_content:
print(f"Model response: {text_content[:300]}\n")
if generated_images:
for i, img in enumerate(generated_images):
print(f"— Generated promo photo {i+1} —")
display(img)
img.save(f"promo_{new_prod[‘new_id’]}{i+1}.png")
print(f"Saved: promo{new_prod[‘new_id’]}_{i+1}.png")
else:
print(“No image generated. Raw response:”)
print(gen_response.model_dump())
Ausgabe:
Schritt 9: Seite-an-Seite-Vergleich
Die Ausgabe trifft den Nagel auf den Kopf: Die Beleuchtung ist weich und gleichmäßig, die Pose des Models sieht natürlich aus, und die Stimmung entspricht der Bestseller-Referenz.
Die Schwachstelle ist die Überblendung der Kleidungsstücke. Die Strickjacke sieht aus, als wäre sie auf das Modell geklebt und nicht getragen worden, und ein weißes Etikett am Halsausschnitt blutet durch. Die Single-Pass-Generierung hat mit dieser Art von feinkörniger Kleidungs-Körper-Integration zu kämpfen, weshalb wir in der Zusammenfassung auf Umgehungsmöglichkeiten eingehen.
Schritt 10: Stapelgenerierung für alle neuen Produkte
Wir fassen die gesamte Pipeline in einer einzigen Funktion zusammen und führen sie für die übrigen neuen Produkte aus. Der Batch-Code wird hier der Kürze halber weggelassen; wenden Sie sich an uns, wenn Sie die vollständige Implementierung benötigen.
Bei den Batch-Ergebnissen stechen zwei Dinge hervor. Die Style Prompts, die wir von Qwen 3.5 erhalten, passen sich je nach Produkt sinnvoll an: Ein Sommerkleid und ein Winterstrickkleid erhalten wirklich unterschiedliche Szenenbeschreibungen, die auf die Jahreszeit, den Anwendungsfall und die Accessoires zugeschnitten sind. Die Bilder, die wir von Nano Banana 2 erhalten, können sich in Sachen Beleuchtung, Textur und Komposition mit echten Studioaufnahmen messen.
Fazit
In diesem Artikel haben wir uns damit beschäftigt, was Nano Banana 2 für die Bilderzeugung im E-Commerce bringt, haben es mit dem originalen Nano Banana und Pro bei realen Produktionsaufgaben verglichen und sind durchgegangen, wie man mit Milvus, Qwen 3.5 und Nano Banana 2 eine Pipeline von Bestsellern zu Bildern erstellt.
Diese Pipeline hat vier praktische Vorteile:
- Kontrollierte Kosten, vorhersehbare Budgets. Das Einbettungsmodell (Llama Nemotron Embed VL 1B v2) ist auf OpenRouter kostenlos. Nano Banana 2 kostet nur etwa die Hälfte der Pro-Bild-Kosten, und bei der nativen Multiformat-Ausgabe entfallen die Nachbearbeitungszyklen, die früher die effektive Rechnung verdoppelten oder verdreifachten. Für E-Commerce-Teams, die Tausende von Artikeln pro Saison verwalten, bedeutet diese Vorhersehbarkeit, dass die Bildproduktion mit dem Katalog mitwächst, anstatt das Budget zu sprengen.
- Durchgängige Automatisierung, kürzere Zeit bis zur Listung. Der Fluss vom flachen Produktfoto bis zum fertigen Werbebild läuft ohne manuelle Eingriffe ab. Ein neues Produkt kann innerhalb von Minuten statt Tagen vom Lagerfoto zum vermarktungsfähigen Listungsbild übergehen, was vor allem in der Hochsaison wichtig ist, wenn der Katalogumsatz am höchsten ist.
- Keine lokale GPU erforderlich, niedrigere Einstiegshürde. Jedes Modell läuft über die OpenRouter-API. Ein Team ohne ML-Infrastruktur und ohne eigenes technisches Personal kann diese Pipeline von einem Laptop aus betreiben. Es muss nichts bereitgestellt oder gewartet werden, und es gibt keine Vorabinvestitionen in Hardware.
- Höhere Abrufpräzision, stärkere Markenkonsistenz. Milvus kombiniert dichte, spärliche und skalare Filterung in einer einzigen Abfrage und übertrifft damit durchweg Einzelvektoransätze für den Produktabgleich. In der Praxis bedeutet dies, dass die generierten Bilder zuverlässiger die etablierte visuelle Sprache Ihrer Marke übernehmen: die Beleuchtung, die Komposition und das Styling, mit denen Ihre bestehenden Bestseller bereits überzeugen. Das Ergebnis sieht so aus, wie es in Ihren Shop gehört, und nicht wie generische KI-Bilder.
Es gibt auch Einschränkungen, über die man sich im Klaren sein sollte:
- Überblendung von Kleidungsstücken mit dem Körper. Bei der Erstellung in einem Durchgang kann die Kleidung eher zusammengesetzt als getragen aussehen. Feine Details wie kleine Accessoires verschwimmen manchmal. Abhilfe: Generieren Sie in mehreren Schritten (erst Hintergrund, dann Modellpose, dann Composite). Dieser Multi-Pass-Ansatz gibt jedem Schritt einen engeren Rahmen und verbessert die Qualität der Überblendung erheblich.
- Detailtreue in Randbereichen. Accessoires, Muster und textlastige Layouts können an Schärfe verlieren. Abhilfe: Fügen Sie der Generierungsaufforderung explizite Einschränkungen hinzu ("Kleidung passt natürlich auf den Körper, keine freiliegenden Etiketten, keine zusätzlichen Elemente, Produktdetails sind scharf"). Wenn die Qualität bei einem bestimmten Produkt immer noch zu wünschen übrig lässt, wechseln Sie für die endgültige Erstellung zu Nano Banana Pro.
Milvus ist die Open-Source-Vektordatenbank, die den hybriden Suchschritt antreibt. Wenn Sie ein wenig herumstöbern oder versuchen möchten, Ihre eigenen Produktfotos einzutauschen, dauert der Schnellstart etwa zehn Minuten. Wir haben eine ziemlich aktive Community auf Discord und Slack, und wir würden gerne sehen, was die Leute damit bauen. Und wenn Sie Nano Banana 2 gegen ein anderes Produkt oder einen größeren Katalog einsetzen, teilen Sie uns bitte die Ergebnisse mit! Wir würden uns freuen, von ihnen zu hören.
Lesen Sie weiter
- Nano Banana + Milvus: Aus dem Hype wird ein unternehmenstauglicher multimodaler RAG
- Was ist OpenClaw? Vollständiger Leitfaden für den Open-Source-KI-Agenten
- OpenClaw-Tutorial: Verbindung zu Slack für lokalen KI-Assistenten
- Wir haben das Speichersystem von OpenClaw extrahiert und als Open-Source bereitgestellt (memsearch)
- Persistenter Speicher für Claude Code: memsearch ccplugin
Try Managed Milvus for Free
Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.
Get StartedLike the article? Spread the word



