v92-v105 多国适配 + 模板导出增强 + 生图可靠性优化

- 新增韩国(KR)适配:countries/pinterest 种子词、K-pop 提示词、UI 国家列表
- 爬虫跨运行持久化已采集 URL(.collected_urls.json),同关键词重复搜索采新图
- 模板导出增强:SPU 商品属性列名前缀剥离匹配、尺码下拉框 INDIRECT 动态引用、
  SPU 字段映射(袖长/门襟/胸垫等)、季节/印花图案女装映射、建议售价统一必填、
  SKU 分类/数量/单位直接填默认值
- 自定义模式:多模态提示词独立(custom_analyze_*)、生图提示词模板可配置
- Pinterest:空选品守卫、连续空分析保护(max_empty_analyze)、flat_prompt 配置覆盖
- 生图可靠性:开始/完成进度日志、异步任务轮询超时 60s→300s
This commit is contained in:
2026-08-31 18:35:51 +08:00
parent 71a48e4ed5
commit 3dc594cf57
29 changed files with 1369 additions and 321 deletions
+69 -12
View File
@@ -362,12 +362,8 @@ image_prompt = two parts:
NEVER mention shirts, apparel, models, scenes, sizes, backgrounds or
watermarks — placement is handled externally.
negative_prompt: copy of reference artwork, likenesses, characters, logos,
trademarks, watermark, photorealistic shirt/product mockups, busy background;
add garbled-lettering terms only if your design includes text.
OUTPUT — ONLY valid JSON, no fences:
{"designs":[{"suitable_for_print":<bool>,"negative_prompt":"<str>","image_prompt":"<str>"}]}"""
{"designs":[{"suitable_for_print":<bool>,"image_prompt":"<str>"}]}"""
PINTEREST_ANALYZE_SCHEMA = {
"name": "pinterest_design_briefs",
@@ -380,10 +376,9 @@ PINTEREST_ANALYZE_SCHEMA = {
"type": "object",
"properties": {
"suitable_for_print": {"type": "boolean"},
"negative_prompt": {"type": "string"},
"image_prompt": {"type": "string"},
},
"required": ["suitable_for_print", "negative_prompt", "image_prompt"],
"required": ["suitable_for_print", "image_prompt"],
"additionalProperties": False,
},
}
@@ -411,6 +406,61 @@ def _pinterest_analyze_prompt_file(country: str, filename: str) -> str:
return ""
# 自定义模式(pinterest.mode=custom)多模态分析系统提示词内置默认:
# 输入是「现有爆款产品图」(模特实拍/平铺图),定位衣服上的印花并产出同风格、不同执行的非侵权原创设计。
# 该文本为「内置默认」,可被 prompts/custom_analyze_system.md 覆盖(缺失/留空回退这里)。
CUSTOM_ANALYZE_SYSTEM_PROMPT = """You are a POD T-shirt design analyst working in CUSTOM-REFERENCE mode. You are given ONE existing bestseller product photo — an on-model shot or a flat-lay shot of a printed garment. Your job:
1. Locate the printed artwork on the garment and judge whether that PRINT can inspire a new T-shirt design (ignore the shirt itself, the model, the background, watermarks and photo quality — judge only the printed artwork).
2. Write an ORIGINAL design brief that keeps the bestseller's general vibe (theme, style genre, era, mood) but is a clearly different, non-infringing work.
RULES:
0. REFERENCE HANDLING — the attached photo is a product mockup of an existing bestseller, not an artwork file. Use it ONLY to identify the printed artwork and distill its appeal into generic style keywords (retro, y2k, minimal, grunge, boho, kawaii, western, cottagecore, vintage cartoon...). Never reproduce, trace, rearrange, recolor or closely imitate the print, its layout, characters or text.
1. SAME SUBJECT FAMILY, NEW EXECUTION — the new design must belong to the same visual family as the bestseller print so a buyer would instantly see they are "same style, different shirt". LOCK these elements to the bestseller's: (a) general subject category (e.g., human/animal figure silhouette, celestial object, floral, vehicle, typography-led...), (b) art technique (e.g., grunge ink silhouette, clean line art, watercolor, distressed collage...), (c) palette (monochrome / muted / neon...). VARY these: the exact subject, the pose, the composition and layout, and any decorative framing. The result must be clearly original — no traced or rearranged reuse of the reference artwork — while staying recognizably in the same genre.
2. IP SCREENING — if the bestseller print contains brand logos, trademarks, slogans, mascots, copyrighted characters (including stylized or silhouette versions), real people/celebrities, movie/game/anime/band IP, or lyrics, do NOT imitate them; swap in fully generic equivalents (e.g., an unnamed cartoon animal instead of a recognizable mascot). Also avoid politics, religion, violence, sexual content, alcohol, drugs, gambling, flags, death/occult themes.
3. FORM — ONE clear central subject with strong graphic composition; print-ready standalone artwork. ANY colors are fine — rich palettes, gradients and detailed shading are all acceptable. Because the reference is a product photo, explicitly exclude the garment and the photo itself: never describe shirts, models, hangers, scenes or backgrounds. Photographic elements in the print may be re-rendered as detailed full-color illustrations, retro badges or vintage stickers.
4. TEXT — short ORIGINAL English wording (1-6 words) allowed; wrap exact words in double quotes and demand exact spelling; integrate into composition. Never reuse, translate or near-duplicate the bestseller print's wording; no brand/band/movie names or famous slogans. When unsure, omit.
suitable_for_print: judge ONLY the printed artwork extracted from the bestseller photo. DEFAULT TRUE for graphics, illustrations, badges, vector art, typography prints, or prints visible on mockups. FALSE only for: blank garments with no artwork, prints that are indiscernible due to watermark, blur or very low quality, pure subjectless photo scenery, memes/screenshots/collages with no usable motif. Even when FALSE, still fill all fields so downstream never breaks.
image_prompt = two parts:
1) mandatory opener: "First, carefully examine the printed artwork on the garment in the attached photo: zoom in mentally on the print area, identify its subject, technique, palette and layout, and base the new design on THOSE observed traits. Ignore the model, background and photo quality. Then: use the attached bestseller product photo only as loose inspiration for overall mood, theme, era and style genre — do NOT reproduce, trace, rearrange, recolor or closely imitate its printed artwork, characters, layout or text, and do NOT render a shirt, garment, model, hanger, photo scene, product mockup or background of any kind."
2) the new design: [same subject family as observed] + [same technique and palette family] + [changed exact subject, pose, composition and framing] + [mood], plus quoted original text if used. NEVER mention shirts, apparel, models, scenes, sizes, backgrounds or watermarks — placement is handled externally. Before output, verify the new design shares the locked elements (subject category, technique, palette) with the observed print; if not, revise it.
OUTPUT — ONLY valid JSON, no fences:
{"designs":[{"suitable_for_print":<bool>,"image_prompt":"<str>"}]}"""
def _custom_analyze_prompt_file(filename: str) -> str:
"""定位自定义模式多模态分析提示词文件:优先运行根 prompts(exe 旁,可编辑),回退数据根 prompts。
只读全局 prompts/<filename>(自定义模式不按国家区分)。找不到返回空串,由调用方回退内置默认。
"""
for base in (runtime_root(), project_root()):
p = base / "prompts" / filename
if p.exists():
return p.read_text(encoding="utf-8").strip()
return ""
def resolve_custom_analyze_system_prompt() -> str:
"""自定义模式多模态分析系统提示词(可配置):命中 prompts/custom_analyze_system.md
否则回退内置 CUSTOM_ANALYZE_SYSTEM_PROMPT。"""
text = _custom_analyze_prompt_file("custom_analyze_system.md")
return text if text else CUSTOM_ANALYZE_SYSTEM_PROMPT
def build_custom_analyze_user_prompt() -> str:
"""自定义模式多模态分析用户提示词(可配置):命中 prompts/custom_analyze_user.md 否则内置默认。"""
text = _custom_analyze_prompt_file("custom_analyze_user.md")
if text:
return text
return (
"Analyze the attached bestseller product photo, locate its printed artwork, "
"and produce one ORIGINAL T-shirt print design brief that keeps its general vibe "
"without copying its printed artwork."
)
def resolve_pinterest_analyze_system_prompt(country: str = "") -> str:
"""多模态分析系统提示词(可配置):命中 prompts/pinterest_analyze_system.md(国家覆盖优先),
否则回退内置 PINTEREST_ANALYZE_SYSTEM_PROMPT。"""
@@ -628,12 +678,14 @@ class OpenAICompatBackend(LLMBackend):
terms = [f"{t} {suffix}" if suffix not in t.lower() else t for t in terms]
return {"search_terms": terms}
def analyze_pinterest_images(self, image_paths: List[str], term: str, country: str = "",
on_400=None) -> List[Dict[str, Any]]:
def analyze_pinterest_images(self, image_paths: List[str], term: str = "", country: str = "",
on_400=None, custom_mode: bool = False) -> List[Dict[str, Any]]:
"""多模态分析 Pinterest 图片 → 原创设计简报列表。
图片输入失败/无有效图片时直接放弃(返回 [],不降级纯文本),由节点跳过该产品。
on_400: 每次 HTTP 400(且含「内容/图片」)时回调(供调用方累计放弃计数)。
custom_mode: True=自定义模式,用独立的多模态提示词(CUSTOM-REFERENCE 版,
见 prompts/custom_analyze_system.md / custom_analyze_user.md),输入是现有爆款产品图。
"""
cfg = self._cfg
api_key = cfg.get("api_key", "")
@@ -683,14 +735,20 @@ class OpenAICompatBackend(LLMBackend):
pass
def _call() -> str:
if custom_mode:
sys_prompt = resolve_custom_analyze_system_prompt()
user_prompt = build_custom_analyze_user_prompt()
else:
sys_prompt = resolve_pinterest_analyze_system_prompt(country)
user_prompt = build_pinterest_analyze_user_prompt(country)
user_content: List[Any] = [
{"type": "text", "text": build_pinterest_analyze_user_prompt(country)},
{"type": "text", "text": user_prompt},
]
user_content += [{"type": "image_url", "image_url": {"url": u}} for u in data_uris]
payload = {
"model": model,
"messages": [
{"role": "system", "content": resolve_pinterest_analyze_system_prompt(country)},
{"role": "system", "content": sys_prompt},
{"role": "user", "content": user_content},
],
"temperature": 0.5,
@@ -742,7 +800,6 @@ class OpenAICompatBackend(LLMBackend):
designs.append({
"topic": term,
"suitable_for_print": bool(d.get("suitable_for_print", True)),
"negative_prompt": str(d.get("negative_prompt", "")).strip(),
"image_prompt": str(d.get("image_prompt", "")).strip(),
# 生图参考:每条简报对应其来源爬取图(LLM 按图逐张产出简报,顺序一一对应)
"ref_images": [str(image_paths[i])] if i < len(image_paths) else [],