Files
pod_trend_agent/graph/nodes/oss_upload_node.py
T
3218485270 5ab5cf6586 v110-v112 自定义模式完善 + 模板导出增强 + 多模态兼容优化
- 自定义模式:分析模型输出 delta 唯一改动指令,生图模板 custom_image_prompt.md({delta} 占位符),不再使用负向提示词;generate_design 按 custom_mode 分支,Pinterest 模式保留原创化指令,两模式互不影响
- 多模态分析 response_format 三级回退(json_schema → json_object → none),兼容 DeepSeek
- 模板导出:details 扩展列(细节1/2/3)、target_audience 扩展列(适用人群1)、固定值风格1=休闲/风格2=运动
- 童装特征库更新 + 标题模板外部化 + 图源映射增强
2026-09-03 18:28:39 +08:00

110 lines
5.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""节点 7/7:压缩 + 上传阿里云 OSSoss_upload)。
在 product 之后运行:把 product 生成的成品图(composite / printed / design / basemap
压缩为 3:4 / ≥1340×1785 / <2MB 的 JPEG,上传到 config.oss 图床。
上传 key(图床路径):{国家}/{任务时间戳}/{货号}_{4位随机}.jpg
- 任务时间戳:任务开始记录(YYYYMMDDHHMMSS),state["task_timestamp"],缺失时取当前时间
- 货号:用户自定义前缀(config.product.code_prefix,默认 DG+ 3 位计数(000 起,最多 999)
- 4 位随机:大小写英文 + 数字
压缩/上传均带兜底:单图失败不影响其它;未配置 oss 或 enabled=false 时静默跳过。
"""
import random
import string
import time
from pathlib import Path
from typing import Any, Dict, List
from graph.validate import with_fallback
# design 设计稿是过程稿(不进模板),不压缩不上传;只传最终商品图
KIND_ORDER = ["composite", "printed", "basemap"]
MAX_CODE = 999 # 货号计数上限(000~998 共 999 张)
def _gen_rand4() -> str:
return "".join(random.choices(string.ascii_letters + string.digits, k=4))
@with_fallback("oss_upload")
def oss_upload_node(state: Dict[str, Any]) -> Dict[str, Any]:
products: List[Dict[str, Any]] = state.get("product") or []
config = state["config"] or {}
oss_cfg = config.get("oss") or {}
country = state.get("country", "")
if not (oss_cfg.get("oss_bucket") and oss_cfg.get("oss_key_id")):
print("[oss] 未配置 ossconfig.oss),跳过压缩上传节点。")
return {"oss": [], "stats": state.get("stats") or {}}
if not bool(oss_cfg.get("enabled", True)):
print("[oss] config.oss.enabled=false,跳过上传。")
return {"oss": [], "stats": state.get("stats") or {}}
from graph.oss_upload import build_oss_key, compress_for_oss, upload_to_oss
# 任务时间戳:任务开始记录;缺失则当前时间
ts = str(state.get("task_timestamp") or time.strftime("%Y%m%d%H%M%S"))
# 货号前缀:config.product.code_prefix(默认 DG
prefix = str(((config.get("product") or {}).get("code_prefix")) or "DG").strip()
# 序号从 state 续接(一次任务内跨多次节点调用不重号)
seq = int(state.get("oss_seq") or 0)
uploaded: List[Dict[str, Any]] = []
stats = dict(state.get("stats") or {})
for r in products:
spu = r.get("spu_code", "")
sku = r.get("sku_code", "")
for kind in KIND_ORDER:
src = r.get(f"{kind}_path")
if not src or not Path(src).exists():
continue
if seq >= MAX_CODE:
print(f"[oss] 货号计数已达上限 999,停止上传后续图片({src}")
break
try:
code = str(r.get("img_code") or "") or f"{prefix}{seq:03d}" # 货号:优先用 product 生成的 img_code,缺省自增
compressed = compress_for_oss(src, str(Path(src).with_suffix(".oss.jpg")))
key = build_oss_key(country, ts, code, _gen_rand4(), local=compressed)
url = upload_to_oss(oss_cfg, compressed, key)
if url:
r[f"{kind}_url"] = url
r["oss_code"] = code
uploaded.append({"spu_code": spu, "sku_code": sku, "kind": kind,
"code": code, "url": url})
seq += 1
except Exception as e: # noqa: BLE001
print(f"[oss] 处理失败 {src}: {e}")
# 多色:color_composites 用于模板按颜色路由——首色用主图 url/code,额外色单独上传(独立货号)
color_ups: List[Dict[str, Any]] = []
comps = r.get("color_composites") or []
if comps and r.get("composite_url"):
color_ups.append({**comps[0], "url": r["composite_url"], "code": r.get("oss_code", "")})
for cc in comps[1:]:
src = cc.get("composite_path")
if not src or not Path(src).exists():
continue
if seq >= MAX_CODE:
print("[oss] 货号计数已达上限 999,停止上传颜色图")
break
try:
code = f"{prefix}{seq:03d}"
compressed = compress_for_oss(src, str(Path(src).with_suffix(".oss.jpg")))
key = build_oss_key(country, ts, code, _gen_rand4(), local=compressed)
url = upload_to_oss(oss_cfg, compressed, key)
if url:
cc["url"] = url
cc["code"] = code
color_ups.append(cc)
uploaded.append({"spu_code": spu, "sku_code": cc.get("sku_code"),
"kind": "composite_color", "code": code, "url": url})
seq += 1
except Exception as e: # noqa: BLE001
print(f"[oss] 颜色图上传失败 {src}: {e}")
if color_ups:
r["color_composites"] = color_ups
stats["oss"] = {"uploaded": len(uploaded), "timestamp": ts, "prefix": prefix, "seq": seq}
return {"oss": uploaded, "product": products, "oss_seq": seq, "stats": stats}