Files
2026-08-20 12:36:00 +08:00

164 lines
7.4 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Google 图像模型(nano-banana / nano-banana-2 / nano-banana-2-lite / nano-banana-pro)提示词。
语义:Gemini 图像编辑 —— 原生主体保持能力强,输入图即"主体 + 底图"
对自然语言指令遵循好。不套用 GPT 的编辑契约(冗长的拒绝条款反而稀释指令),
也不用负面清单(无 negative_prompt 参数)。要点:
- 开头一句话钉死"主体 = 第一张图里的商品,逐像素保持";
- 指令自然语言描述目标画面(场景/排版/文案),不重述商品外观;
- 标题/参数仅作识别背景并声明以图为准。
"""
from __future__ import annotations
from .common import TEXT_RENDER, requirements_block, resolve_style, selling_point_lines
_SUBJECT_LOCK = (
"SUBJECT LOCK (highest priority): the product in the first image is the subject. "
"Keep it exactly as photographed — same shape, proportions, colors, print/pattern, "
"logo, label and every detail — and place that very product into the result. "
"A second image, when present, is another view of the same product for reference only."
)
_QUALITY = (
"OUTPUT: photorealistic commercial e-commerce photography, ultra-detailed, "
"natural light and shadow, professional retouching."
)
_REMINDER = (
"Reminder: keep the product exactly as in the first image; change only its surroundings, "
"composition, lighting and overlay graphics."
)
def _anchor(ctx: dict) -> str:
"""商品文字锚定:仅供识别,明确以图为准(同 gpt 模块,避免文字反噬商品)。"""
line = f"Context (identification only): the product is \"{ctx['title']}\""
if ctx.get("params_line"):
line += f" ({ctx['params_line']})"
return line + ". The image, not this text, defines the product's appearance."
# ── 各图类型指令(自然语言编辑口吻)────────────────────────────────────────
def _task_white_bg(ctx: dict, lang: str) -> str:
return (
"Replace the background of this product photo with seamless pure white (RGB 255,255,255): "
"product centered in front view filling about 85% of the frame, even studio lighting with only "
"a faint natural contact shadow. No props, no added text, no background elements."
)
def _task_key_features(ctx: dict, lang: str) -> str:
sp = selling_point_lines(ctx, lang) or ctx["title"]
return (
"Create a square key-features infographic: the unchanged product on the left two-thirds, "
"a clean right-hand panel with 3 feature callouts using minimal line icons and thin leader "
f"lines pointing at the product. Callout copy: {sp}."
)
def _task_selling_pt(ctx: dict, lang: str) -> str:
sp = selling_point_lines(ctx, lang, 1) or ctx["title"]
return (
"Turn the photo into a single-selling-point poster: hero close-up of the unchanged product at "
f"a dynamic angle, one large bold headline about \"{sp}\", generous negative space, and a small "
"magnified circle zooming into an existing detail of the product."
)
def _task_material(ctx: dict, lang: str) -> str:
return (
"Create an extreme macro close-up of an existing area of the product's surface, showing its "
"true fabric weave / texture / stitching exactly as in the photo; shallow depth of field, "
"raking light, small caption in a corner."
)
def _task_lifestyle(ctx: dict, lang: str) -> str:
return (
"Place the unchanged product into a realistic everyday scene where it would naturally be used: "
"human-scale surroundings, soft daylight, authentic candid mood, the product as the clear visual focus."
)
def _task_multi_scene(ctx: dict, lang: str) -> str:
sp = selling_point_lines(ctx, lang)
task = (
"Build a triptych of three vertical panels separated by thin gutters: each panel shows an "
"identical copy of the product in a different usage scene (home interior / outdoor street / "
"office desk), with consistent color grading across panels."
)
if sp:
task += f" Panel captions: {sp}."
return task
def _task_ecommerce_detail(ctx: dict, lang: str) -> str:
sp = selling_point_lines(ctx, lang) or ctx["title"]
params = ctx["params_line"]
return (
"Compose a square detail-page hero section: top half a hero banner with the unchanged product "
"at a 3/4 angle; bottom half a clean spec card with 3 feature rows and line icons"
+ (f" (specs: {params})" if params else "")
+ f", one highlighted row: {sp}."
)
def _task_size_chart(ctx: dict, lang: str) -> str:
dims = ctx["params_line"]
return (
"Create a size chart: the unchanged product in clean front and side views on a light background, "
"thin measurement annotation lines (arrows) marking length, width and height with values beside "
"each line"
+ (f" (known specs: {dims})" if dims else "")
+ ", small caption row, precise technical-drawing aesthetic."
)
def _task_sku_collection(ctx: dict, lang: str) -> str:
# 不展开"全部配色":会凭空造出新商品;只排列同一件的多个副本
return (
"Arrange several identical copies of the product in a neat equal grid (2-4 per row) with a small "
"label chip below each copy; identical lighting and scale across copies. Every copy shows this "
"exact product — do not invent other colorways or variants."
)
_TASK_BUILDERS = {
"white_bg": (_task_white_bg, False),
"key_features": (_task_key_features, True),
"selling_pt": (_task_selling_pt, True),
"material": (_task_material, True),
"lifestyle": (_task_lifestyle, True),
"multi_scene": (_task_multi_scene, True),
"ecommerce_detail": (_task_ecommerce_detail, True),
"size_chart": (_task_size_chart, True),
"sku_collection": (_task_sku_collection, True),
}
def build_prompt(type_id: str, ctx: dict, style_set: int, lang: str, extra: dict | None = None,
style_prompt: str | None = None, requirements: str | None = None) -> str:
"""构造指定图类型的 prompt:要求块 → 指令 → 主体锁 → 锚定 → 风格 → 文案 → 画质 → 提醒。"""
style = resolve_style(style_set, style_prompt)
extra = extra or {}
hint = (extra.get("prompt_hint") or "").strip()
if type_id == "custom":
purpose = extra.get("title") or ""
detail = extra.get("detail") or ""
task = "Create an e-commerce marketing image featuring the product from the first image"
task += f" — {purpose}" if purpose else ""
task += f": {detail}" if detail else ""
task += "."
wants_text = True
else:
entry = _TASK_BUILDERS.get(type_id)
if entry is None:
raise ValueError(f"未知图类型: {type_id}")
builder, wants_text = entry
task = builder(ctx, lang)
if hint:
task += f" Composition guidance: {hint}."
parts = [p for p in (requirements_block(requirements),) if p]
parts.append(task)
parts.append(_SUBJECT_LOCK)
parts.append(_anchor(ctx))
parts.append(f"Scene style (scene and background only, never the product): {style['tone']}.")
if wants_text:
parts.append(f"Text overlay (a graphic layer, never printed on the product): {TEXT_RENDER[lang]}")
parts.append(_QUALITY)
parts.append(_REMINDER)
return "\n\n".join(parts)