"""固定提示词模板(规则写死,保证每条一致)+ 装配函数。 所有最终提示词都由四要素(motif / art_style / color_palette / composition) 用下面的模板确定性拼出,LLM 不再自由发挥,因此结构永远一致、可复用于 img2img。 v3:模板按国家区分(COUNTRY_TEMPLATES),每国有自己的设计风格引导段; 顶层 DEFAULT_TEMPLATES 作为兜底。文字规则统一:英文可加可不加、适配印花即可, 任何文字严禁政治/宗教/仇恨/暴力/性/品牌/商标/真实人物等敏感内容。 """ from typing import Any, Dict, Optional # —— 通用固定段(所有国家共用,保证结构一致)—— # 尺寸规则:最小约 15×18cm ~ 最大 26×32cm 之间自由选择(防模型默认出满幅大图) SIZE_RULE = ( "size: choose freely between a MINIMUM print area of about 15x18 cm " "and a MAXIMUM of 26x32 cm, any size in this range fits, " "pick the one that best suits the design, keep proportions, " "scale naturally to the content, do NOT stretch, " "do NOT fill the entire canvas, do NOT force full-bleed, " "leave balanced margins around the artwork" ) # 排除段:无衣服/模特/场景/水印 NEG_FIXED = ( "no garment, no shirt, no model, no mannequin, no background scene, no watermark" ) # 文字规则(v3):可加可不加、适配印花即可;任何文字严禁敏感内容 # 注意:正向提示词不写敏感词(no politics/no hate/no violence/no sexual…会被图像审核误判), # 负向约束统一由 negative_prompt 承担 TEXT_RULE = ( "text: optional - add short original English words or a small slogan ONLY if they fit " "the print, or keep it text-free; any text must be safe, short and original; " "no brand names, no logos, no trademarked phrases, no real people names" ) # —— 国家风格引导段(每国不同:US 大胆高对比 / GB 英式自嘲与复古 / JP 卡哇伊极简 / AU 海滨户外)—— COUNTRY_STYLE_HINT: Dict[str, str] = { "US": "US-market aesthetic: bold confident statement graphic, high contrast, " "clean modern vector, sporty or humorous mood", "GB": "UK-market aesthetic: witty understated British charm, heritage-inspired motifs, " "retro sportswear or punk-zine mood", "JP": "JP-market aesthetic: kawaii cute or clean minimal, soft pastel-friendly, " "polished neat lines, small cute mascot mood", "AU": "AU-market aesthetic: laid-back coastal and outdoor vibe, nature-inspired, " "bright fresh energy", "MX": "MX-market aesthetic: vibrant mexican folk art, sugar skull / loteria / aztec motifs, " "fiesta colors, festive cultural pride mood", } def _image_prompt_for(country: str) -> str: hint = COUNTRY_STYLE_HINT.get(country, COUNTRY_STYLE_HINT["US"]) return ( "{motif}, {art_style}, {color_palette}, {composition}, " "standalone pure print design, print-ready artwork, " "isolated on pure white background, flat vector-like graphic, " "crisp clean edges, high resolution, ultra sharp, high contrast, " f"{hint}, {SIZE_RULE}, " f"{NEG_FIXED}, {TEXT_RULE}" ) # 顶层默认(兜底:国家未配置时使用,内容等同 US 风格基线) DEFAULT_TEMPLATES: Dict[str, str] = { "image_prompt": _image_prompt_for("US"), # 预览图:直接印在平铺白T上(无真人),用于快速看效果 "wearable_prompt": ( "{motif}, {art_style}, {color_palette}, {composition}, " "printed centered on the chest of a flat-lay plain white t-shirt, " "print sized freely between about 15x18 cm and a max of 26x32 cm, " "scaled naturally to the artwork, not stretched, not full-bleed, " "studio lighting, e-commerce product photo, no human model" ), # 复合提示词(三图模特合成):图1=模特 / 图2=纯印花设计稿 / 图3=平铺底图 → 模特穿着成品 "composite_prompt": ( "【图片角色,按提交顺序】图1=模特实拍图(基底);图2=纯印花设计稿;" "图3=平铺衣服底图(颜色/面料来源)。\n" "TASK: 把图2的印花设计印到图3底色的衣服上,并让图1的模特穿上" "“图3底色+图2印花”的衣服。\n" "RULES:\n" "1.底色锁定:从图3提取衣服底色与面料,最终合成中必须100%保持不变,严禁偏色。\n" "2.印花提取:从图2精准提取纯印花图案(线条/色号/比例),叠加到图3底色上形成合成面料。\n" "3.主体遮罩:识别图1模特服装穿着区域(忽略皮肤/头发/背景/配饰)," "用合成面料完整覆盖,清除原衣服颜色与图案。\n" "4.精准贴合:合成面料严格跟随图1衣服立体结构,褶皱/扭转处印花相应变形," "杜绝“贴纸感”与“平面涂色感”。\n" "5.光影融合:按图1环境光方向调整亮度/对比度,印花受光影响产生明暗变化但色号不偏移。\n" "6.纯净输出:仅输出一张最终合成图;图1背景/人物/构图/光影100%不变," "仅替换衣服印花与底色。\n" "DESIGN CONTENT: {motif}, {art_style}, {color_palette}, {composition}." ), # 复合负向(印图专用) "composite_negative": ( "garment changed, wrong color, distorted print, blurry, low-res, " "human model, body, extra objects, watermark, glow, 3d render, " "text unless part of design" ), } # —— 按国家覆盖:目前仅 image_prompt 有国家差异化;wearable/composite 共用顶层默认 —— COUNTRY_TEMPLATES: Dict[str, Dict[str, str]] = { cc: {"image_prompt": _image_prompt_for(cc)} for cc in COUNTRY_STYLE_HINT } def resolve_templates(tpls: Optional[Dict[str, Any]], country: Optional[str] = None) -> Dict[str, str]: """解析最终模板:DEFAULT_TEMPLATES 兜底 → config 顶层覆盖 → config countries. 覆盖。 config 结构示例: prompt_templates: image_prompt: "..." # 顶层默认 countries: GB: image_prompt: "..." # 国家专属 """ t = dict(DEFAULT_TEMPLATES) if tpls: t.update({k: v for k, v in tpls.items() if k in DEFAULT_TEMPLATES}) countries = tpls.get("countries") or {} if country and isinstance(countries, dict): cc_tpls = countries.get(country) or {} if isinstance(cc_tpls, dict): t.update({k: v for k, v in cc_tpls.items() if k in DEFAULT_TEMPLATES}) elif country and country in COUNTRY_TEMPLATES: t.update(COUNTRY_TEMPLATES[country]) return t def assemble_prompts( motif: str, art_style: str, palette: str, composition: str, tpls: Optional[Dict[str, Any]] = None, country: Optional[str] = None, ) -> Dict[str, str]: """用固定模板确定性装配三种提示词。tpls 可来自 config 覆盖(按国家优先)。""" t = resolve_templates(tpls, country) out = {} for key in ("image_prompt", "wearable_prompt", "composite_prompt"): out[key] = t[key].format( motif=motif, art_style=art_style, color_palette=palette, composition=composition ) out["composite_negative"] = t["composite_negative"] return out