164 lines
7.4 KiB
Python
164 lines
7.4 KiB
Python
"""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)
|