修复种草图生成:以三合一主图为参考 img2img 生成,按颜色分配(每色优先、超出随机补足);新增 BR/CA/DE/ES/IT/PL/SA 七国配置与提示词;删除验证用测试脚本

This commit is contained in:
2026-08-24 14:02:19 +08:00
parent f493bde8a9
commit 3c341d2e78
51 changed files with 2571 additions and 514 deletions
-111
View File
@@ -1,111 +0,0 @@
# -*- coding: utf-8 -*-
"""用墨西哥主题简报装配 MX 提示词产物(Google Trends 429 限流期间离线验证模板效果)。
构造 5 个墨西哥风格 safe 简报 → prompt_node 用 MX 模板装配 image_prompt →
输出 output/MX/pure_print_prompts.{json,md}(结构同 regen 脚本)。
"""
import json
import sys
import datetime
from pathlib import Path
BASE = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(BASE))
import yaml
from graph.nodes.prompt_node import prompt_node
MX_BRIEFS = [
{"topic": "dia de los muertos catrina", "design_category": "Style",
"motif": "elegant catrina sugar skull with marigold flower crown",
"art_style": "vibrant sugar-skull folk art illustration",
"color_palette": "marigold orange, magenta, deep purple, black, gold",
"composition": "centered portrait emblem with floral frame", "risk_level": "safe"},
{"topic": "loteria mexicana cards", "design_category": "Niche",
"motif": "retro loteria card with el corazon symbol",
"art_style": "retro loteria card illustration with bold frame",
"color_palette": "cream, crimson, teal, gold",
"composition": "card-style centered layout with banner", "risk_level": "safe"},
{"topic": "aztec calendar sun", "design_category": "Pattern",
"motif": "aztec sun calendar geometric emblem",
"art_style": "aztec geometric pattern emblem",
"color_palette": "jade green, terracotta, obsidian black, gold",
"composition": "concentric circular sun emblem", "risk_level": "safe"},
{"topic": "taco fiesta food", "design_category": "Niche",
"motif": "happy taco with avocado and chili peppers",
"art_style": "playful colorful mexican food icon illustration",
"color_palette": "cactus green, chili red, corn yellow, avocado green",
"composition": "centered food icon with border", "risk_level": "safe"},
{"topic": "lucha libre luchador mask", "design_category": "Style",
"motif": "luchador wrestler mask with stars",
"art_style": "bold retro lucha libre poster graphic",
"color_palette": "bright red, electric blue, gold, black",
"composition": "centered mask emblem with rays", "risk_level": "safe"},
{"topic": "talavera ceramic tile", "design_category": "Pattern",
"motif": "talavera blue ceramic tile floral motif",
"art_style": "talavera ceramic pattern style",
"color_palette": "cobalt blue, white, yellow, green",
"composition": "repeating tile pattern with central medallion", "risk_level": "safe"},
{"topic": "monarch butterfly migration", "design_category": "Style",
"motif": "monarch butterfly among marigold flowers",
"art_style": "delicate monarch butterfly folk pattern",
"color_palette": "burnt orange, black, white, gold",
"composition": "centered butterfly with floral border", "risk_level": "safe"},
{"topic": "charro horse rider", "design_category": "Style",
"motif": "charro cowboy with sombrero on horseback",
"art_style": "bold charro cowboy folk illustration",
"color_palette": "black, silver, red, gold",
"composition": "centered rider emblem with banner", "risk_level": "safe"},
]
config = yaml.safe_load(open(BASE / "config.yaml", encoding="utf-8"))
mx_cfg = yaml.safe_load(open(BASE / "configs" / "countries" / "MX.yaml", encoding="utf-8"))
state = {
"country": "MX", "config": config, "country_config": mx_cfg,
"screened": MX_BRIEFS, "stats": {},
}
out = prompt_node(state)
briefs = out["briefs"]
out_dir = BASE / "output" / "MX"
out_dir.mkdir(parents=True, exist_ok=True)
result = {
"country": "MX", "country_name": "墨西哥",
"template": "pure_print_15x18cm_to_26x32cm_v3",
"template_source": "config.yaml prompt_templates.countries.MX",
"generated_at": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
"total": len(briefs), "safe": len(briefs), "review": 0,
"note": "离线演示产物(Google Trends 429 限流期间用墨西哥主题简报装配);正式数据需等限流恢复后跑流水线",
"items": [
{"topic": b["topic"], "category": b.get("design_category"), "verdict": "safe",
"motif": b["motif"], "art_style": b["art_style"],
"color_palette": b["color_palette"], "composition": b["composition"],
"pure_print_prompt": b["image_prompt"]}
for b in briefs
],
}
(out_dir / "pure_print_prompts.json").write_text(
json.dumps(result, ensure_ascii=False, indent=2), encoding="utf-8")
lines = [
"# 墨西哥(MX)纯印花设计提示词产物(15×18cm ~ 26×32cm · v3 国家化模板)\n",
f"- 生成时间:{result['generated_at']}",
"- 模板来源:config.yaml → prompt_templates.countries.MX",
f"- 说明:{result['note']}",
"- 规则:尺寸 **约 15×18cm ~ 26×32cm 自由选择**;英文/西语短标语可加可不加;**任何文字严禁政治/宗教/仇恨/暴力/性/品牌/商标/真实人物(含 Frida Kahlo)/毒枭等敏感内容**\n",
]
for i, it in enumerate(result["items"], 1):
lines.append(f"## {i}. {it['topic']} [{it['category']}] ✅ 可直接用\n")
lines.append(f"- **motif**{it['motif']}")
lines.append(f"- **art_style**{it['art_style']}")
lines.append(f"- **color_palette**{it['color_palette']}")
lines.append(f"- **composition**{it['composition']}\n")
lines.append("```text")
lines.append(it["pure_print_prompt"])
lines.append("```\n")
(out_dir / "pure_print_prompts.md").write_text("\n".join(lines), encoding="utf-8")
print(f"[MX] 产物生成完成:{len(briefs)}")
for b in briefs:
print(f" {b['topic']} | MX-market={'MX-market' in b['image_prompt']} | Spanish={'Spanish slogan' in b['image_prompt']}")
-76
View File
@@ -1,76 +0,0 @@
# -*- coding: utf-8 -*-
"""JP 流程测试:JPTM001 黑色 × 2 个产品(缓存热点模式)。
步骤:
1) 用 mock 种子(6 style + 6 related)生成 JP 主题简报(JP-market 模板装配)→ 写入 output/JP/design_briefs.json 作为缓存
2) run_product_batchtasks=[JPTM001-BL01 × 2]count=2 → 2 个产品各绑一个热点
3) 验证:选色/热点分配/used 去重/JP 标题模板路由/模板导出
"""
import json
import sys
import time
from pathlib import Path
BASE = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(BASE))
import yaml
from graph.templates import assemble_prompts
config = yaml.safe_load(open(BASE / "config.yaml", encoding="utf-8"))
# 种子词 6 个
config["seed_provider"] = "mock"
cfg = config.setdefault("seed_provider_cfg", {})
cfg["max_style_seeds"] = 6
cfg["max_related_seeds"] = 6
# 图像后端 mock、不上传图床
config["compose"]["backend"] = "mock"
config["product"]["backend"] = "mock"
config["oss"]["enabled"] = False
config["seed_shot"]["count"] = 1
jp_topics = [
("kawaii cat cafe", "Style", "original kawaii cat with latte art", "kawaii style, soft rounded shapes", "pink, cream, caramel", "centered mascot"),
("tokyo neon night", "Style", "original neon street lamps silhouette", "retro cyberpunk flat vector", "magenta, cyan, black", "symmetrical emblem"),
("shiba inu summer", "Style", "original shiba inu with watermelon slice", "cute japanese mascot illustration", "orange, red, white", "centered"),
("sakura spring", "Style", "original cherry blossom branch with petals", "soft minimal japanese print", "sakura pink, white, mint", "corner flourish"),
("osaka takoyaki food", "Style", "original takoyaki balls with bonito flakes", "playful food illustration", "golden brown, red, green", "centered badge"),
("mt fuji sunrise", "Style", "original mt fuji with rising sun rays", "ukiyo-e inspired flat design", "indigo, red, cream", "symmetrical"),
]
tpls = config.get("prompt_templates") or {}
briefs = []
for topic, cat, motif, style, palette, comp in jp_topics:
prompts = assemble_prompts(motif, style, palette, comp, tpls, "JP")
briefs.append({
"country": "JP", "topic": topic, "design_category": cat, "risk_level": "safe",
"score": 80 - len(briefs) * 3, "motif": motif, "art_style": style,
"color_palette": palette, "composition": comp,
"image_prompt": prompts["image_prompt"],
"composite_prompt": prompts["composite_prompt"],
"composite_negative": prompts["composite_negative"],
})
out_dir = BASE / "output" / "JP"
out_dir.mkdir(parents=True, exist_ok=True)
(out_dir / "design_briefs.json").write_text(
json.dumps({"generated_at": time.strftime("%Y-%m-%dT%H:%M:%S"), "total": len(briefs),
"design_briefs": briefs}, ensure_ascii=False, indent=2), encoding="utf-8")
print(f"[setup] JP 缓存热点已写入: {len(briefs)} 条(mock 种子 6/6")
p0 = briefs[0]["image_prompt"]
print("[setup] 模板校验: JP-market 风格段 =", "JP-market" in p0, "| 尺寸上限 26x32 =", "26x32" in p0)
from graph.product_batch import run_product_batch
tasks = [{"spu": "JPTM001", "skus": "JPTM001-BL01"}, # 黑色
{"spu": "JPTM001", "skus": "JPTM001-BL01"}] # 数量 2:同一款号生成 2 个产品
out = run_product_batch("JP", config, BASE, BASE, tasks, 2, log_q=None)
print("\n=== 测试结果 ===")
prods = out.get("product") or []
print("产品数:", len(prods))
for r in prods:
print(f" {r.get('spu_code')} | {r.get('sku_code')} | 色={r.get('color')} | topic={r.get('topic')} | "
f"template={bool(r.get('template_path'))} | design={bool(r.get('design_path'))}")
print("errors:", [e.get("message", "")[:80] for e in out.get("errors") or []])
used = json.loads((out_dir / "used_designs.json").read_text(encoding="utf-8")).get("used", []) if (out_dir / "used_designs.json").exists() else []
print("used_designs 记录:", len(used), "条 →", [u.get("topic") for u in used])
-32
View File
@@ -1,32 +0,0 @@
# -*- coding: utf-8 -*-
"""真实 API 全链路验证:JP JPTM001 黑色 × 1oss 真上传)。"""
import json
import sys
from pathlib import Path
BASE = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(BASE))
import yaml
from graph.product_batch import run_product_batch
config = yaml.safe_load(open(BASE / "dist_v2" / "config.yaml", encoding="utf-8"))
config["seed_provider"] = "openai"
config["llm_screen"]["provider"] = "openai"
config["compose"]["backend"] = "openai"
config["product"]["backend"] = "openai"
config["oss"]["enabled"] = True
config["seed_shot"]["count"] = 1
print("使用配置: llm_model =", config["llm_screen"].get("model"), "| img_model =", config["compose"].get("model"))
out = run_product_batch("JP", config, BASE, BASE / "dist_v2",
[{"spu": "JPTM001", "skus": "JPTM001-BL01"}], 1, log_q=None)
print("\n=== 结果 ===")
prods = out.get("product") or []
print("产品数:", len(prods))
for r in prods:
print(f" {r.get('spu_code')} | {r.get('sku_code')} | design={bool(r.get('design_path'))} "
f"| composite={bool(r.get('composite_path'))} | en_title={bool(r.get('en_title'))} "
f"| ja_title={bool(r.get('ja_title'))} | oss_code={r.get('oss_code')}")
print(" URLs:", {k: v[:60] for k, v in r.items() if k.endswith("_url")})
print("errors:", [e.get("message", "")[:100] for e in out.get("errors") or []])