v89-v91 模板增强 + 图源映射 + 多模态提示词可配置化
- 图源映射统一:热点采集与 Pinterest 模式均走 config.product.mark_dirs 配置,按任务序号随机抽模特图/平铺图 - 商品产地固定:统一为「中国大陆」+「产地省份=广东省」(不再读站点/字典映射) - 模板 SKU 字段检测:按建议售价同一套路检测 SKU分类/SKU数量/SKU数量单位,必填时填入单品/1/件 - 多模态分析提示词可配置:prompts/pinterest_analyze_system.md + user.md,支持国家覆盖,不丢文件回退内置 - 自定义图片模式:新增 pinterest_custom_load_node,图片数量硬校验,选品清单 ≤ 有效图片数 - 模板导出优化:写入前按货号末 3 位升序排序,不再产生空白 xlsx - 修复 v90 project review 10 项(503 致命终止、线程安全、原子写入等)
This commit is contained in:
@@ -379,11 +379,15 @@ def run_pipeline(countries, provider, max_seeds, log_q,
|
||||
|
||||
|
||||
def run_pinterest_pipeline(countries, provider, log_q, spu_tasks=None, spu_count=0,
|
||||
oai=None, markup_percent=0.0, code_prefix="DG", template_path=""):
|
||||
oai=None, markup_percent=0.0, code_prefix="DG", template_path="",
|
||||
custom_image_dir=""):
|
||||
"""Pinterest 参考模式后台线程:独立于 Google Trends 采集链路。
|
||||
|
||||
各国独立种子词池 → LLM 搜索词(json_schema + 动态注入防重复)→ 爬图
|
||||
→ LLM 分析图片 → 设计简报 → 产品生成(设计稿/主图/种草图/模板导出)。
|
||||
|
||||
custom_image_dir 非空 → 自定义图片模式:不搜索不采集,把该文件夹有效图片直接送多模态分析,
|
||||
沿用 Pinterest 后续所有步骤;数量硬校验(有效图片数 ≥ 选品清单总数)由 run_pinterest_ref 执行。
|
||||
"""
|
||||
config = load_config()
|
||||
config["seed_provider"] = provider
|
||||
@@ -401,6 +405,9 @@ def run_pinterest_pipeline(countries, provider, log_q, spu_tasks=None, spu_count
|
||||
p["markup_percent"] = markup_percent
|
||||
if code_prefix:
|
||||
p["code_prefix"] = code_prefix
|
||||
# 自定义模式:把上传文件夹写入配置(run_pinterest_ref 据此进入 custom 图并校验)
|
||||
if custom_image_dir:
|
||||
config.setdefault("pinterest", {})["custom_image_dir"] = custom_image_dir
|
||||
# 任务扩展(与 run_pipeline 一致):每个集合按自己数量复制 N 份
|
||||
if spu_tasks:
|
||||
tasks_list = []
|
||||
@@ -425,7 +432,8 @@ def run_pinterest_pipeline(countries, provider, log_q, spu_tasks=None, spu_count
|
||||
from graph.agent import run_pinterest_ref
|
||||
for c in countries:
|
||||
log_q.put(("log", f"\n===== Pinterest 参考模式 {c}(SPU 数量 {spu_count})=====\n"))
|
||||
state = run_pinterest_ref(c, config, config_root(), runtime_root(), task_timestamp=task_ts)
|
||||
state = run_pinterest_ref(c, config, config_root(), runtime_root(),
|
||||
task_timestamp=task_ts, custom_image_dir=custom_image_dir)
|
||||
items = state.get("product") or []
|
||||
errs = state.get("errors") or []
|
||||
log_q.put(("log", f"[{c}] Pinterest 参考完成:{len(items)} 个产品,兜底错误 {len(errs)}\n"))
|
||||
@@ -538,6 +546,13 @@ class App(tk.Tk):
|
||||
variable=self.flow_var).pack(side="left", padx=2)
|
||||
ttk.Radiobutton(top, text="Pinterest 参考", value="pinterest",
|
||||
variable=self.flow_var).pack(side="left", padx=2)
|
||||
ttk.Radiobutton(top, text="自定义图片", value="custom",
|
||||
variable=self.flow_var).pack(side="left", padx=2)
|
||||
ttk.Button(top, text="📁 选图片文件夹…", command=self._choose_custom_dir).pack(side="left", padx=(8, 0))
|
||||
self.custom_dir_var = tk.StringVar(value="")
|
||||
self.custom_dir_name_var = tk.StringVar(value="")
|
||||
ttk.Label(top, textvariable=self.custom_dir_name_var, anchor="w",
|
||||
foreground="#185FA5").pack(side="left", padx=(6, 0))
|
||||
ttk.Label(top, text=" 种子数量:").pack(side="left", padx=(14, 0))
|
||||
self.seed_var = tk.StringVar(value="24")
|
||||
ttk.Entry(top, textvariable=self.seed_var, width=4).pack(side="left")
|
||||
@@ -854,6 +869,24 @@ class App(tk.Tk):
|
||||
).start()
|
||||
|
||||
# ---------- 运行 ----------
|
||||
def _choose_custom_dir(self):
|
||||
"""选择自定义模式图片文件夹,并立即统计有效图片数量(供数量校验提示)。"""
|
||||
path = filedialog.askdirectory(title="选择自定义图片文件夹(直接送多模态分析)")
|
||||
if not path:
|
||||
return
|
||||
try:
|
||||
from graph.pinterest import list_valid_images
|
||||
imgs = list_valid_images(path)
|
||||
n = len(imgs)
|
||||
except Exception: # noqa: BLE001
|
||||
n = 0
|
||||
self.custom_dir_var.set(path)
|
||||
if n == 0:
|
||||
self.custom_dir_name_var.set(f"已选: {Path(path).name}(0 张有效图片!)")
|
||||
else:
|
||||
self.custom_dir_name_var.set(f"已选: {Path(path).name}({n} 张有效图片)")
|
||||
self._log(f"[UI] 自定义图片文件夹已选择: {path}(有效图片 {n} 张,jpg/jpeg/png/webp)\n")
|
||||
|
||||
def _choose_template(self):
|
||||
"""选择自定义商品上传模板(.xlsx),后续 template_export 从该模板解析。
|
||||
导入时校验「经营站点」是否与当前国家一致(如 JP → 日本站),不一致则导入失败。"""
|
||||
@@ -1022,14 +1055,40 @@ class App(tk.Tk):
|
||||
self._busy = True
|
||||
self.run_btn.config(state="disabled", text="运行中…")
|
||||
self.fetch_btn.config(state="disabled")
|
||||
if self.flow_var.get() == "pinterest":
|
||||
# Pinterest 参考模式:独立于 Google Trends 采集链路
|
||||
flow = self.flow_var.get()
|
||||
if flow in ("pinterest", "custom"):
|
||||
# Pinterest 参考 / 自定义图片:独立于 Google Trends 采集链路
|
||||
custom_dir = self.custom_dir_var.get().strip()
|
||||
if flow == "custom":
|
||||
# —— 自定义图片模式硬校验:必须先选文件夹;有效图片数 ≥ 选品清单总数 ——
|
||||
if not custom_dir:
|
||||
self._busy = False
|
||||
self.run_btn.config(state="normal", text="运行")
|
||||
self.fetch_btn.config(state="normal")
|
||||
messagebox.showwarning("自定义图片模式", "请先点击「📁 选图片文件夹…」选择上传的图片文件夹")
|
||||
return
|
||||
try:
|
||||
from graph.pinterest import list_valid_images, validate_custom_images
|
||||
# 选品清单总数 = 每个任务按 count 扩展后的求和(与 run_pinterest_pipeline 一致)
|
||||
expanded = sum(int(t.get("count") or 0) or spu_count or 1 for t in tasks)
|
||||
ok, valid_n, msg = validate_custom_images(custom_dir, expanded)
|
||||
except Exception as e: # noqa: BLE001
|
||||
ok, valid_n, msg = False, 0, f"校验失败: {e}"
|
||||
if not ok:
|
||||
self._busy = False
|
||||
self.run_btn.config(state="normal", text="运行")
|
||||
self.fetch_btn.config(state="normal")
|
||||
messagebox.showerror("自定义图片数量校验未通过", msg)
|
||||
self._log("[UI] 自定义图片数量校验未通过,任务未运行: " + msg + "\n")
|
||||
return
|
||||
self._log(f"[UI] 自定义图片数量校验通过:有效图片 {valid_n} 张 ≥ 选品清单 {expanded}\n")
|
||||
threading.Thread(
|
||||
target=run_pinterest_pipeline,
|
||||
args=(countries, self.provider_var.get(), self._q,
|
||||
tasks, spu_count, self._oai_cfg(), markup,
|
||||
self.code_prefix_var.get().strip() or "DG",
|
||||
self.template_path_var.get().strip()),
|
||||
self.template_path_var.get().strip(),
|
||||
custom_dir if flow == "custom" else ""),
|
||||
daemon=True,
|
||||
).start()
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user