- 自定义模式:分析模型输出 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=运动
- 童装特征库更新 + 标题模板外部化 + 图源映射增强
411 lines
30 KiB
Markdown
411 lines
30 KiB
Markdown
# POD 热点抓取 Agent(LangGraph 工程化版)
|
||
|
||
自动抓取海外各国(US / GB / JP / AU / MX / DE / BR / SA / PL / ES / IT / CA / KR)实时热点 + 风格趋势,
|
||
过滤侵权风险,产出可直接用于 AI 生图的印花设计提示词,并完成 **设计稿 → 三合一模特试穿 → OSS 图床 →
|
||
种草图 → 商品上传模板** 的完整 POD 生产链路。本版本用 **LangGraph** 重写,强调**工程化、节点兜底、可插拔**。
|
||
|
||
## 两种运行模式
|
||
|
||
| 模式 | 入口 | 数据来源 | 适用 |
|
||
|---|---|---|---|
|
||
| **热点采集模式** | UI「热点采集」 | Google Trends(trending/style/related) | 抓国家实时热点词,LLM 筛出可印花设计 |
|
||
| **Pinterest 参考模式** | UI「Pinterest 参考模式」 | Pinterest 爬图 + LLM 多模态分析 | 从真实图片提炼原创印花设计,侵权风险更低 |
|
||
|
||
## 架构:LangGraph 状态图
|
||
|
||
### 模式 A:热点采集模式
|
||
|
||
```
|
||
START → seed → fetch → filter → score → screen → prompt_build → compose → product
|
||
→ oss_upload → seed_shot → template_export → END
|
||
```
|
||
|
||
| 节点 | 职责 | 可插拔点 / 兜底 |
|
||
|---|---|---|
|
||
| `seed` | 动态生成种子词(trending 派生 + 历史热点 + 月份/节日 → LLM) | 策略可插拔(`graph/seeds/`);LLM 失败回退静态种子 |
|
||
| `fetch` | 抓取热点(Google Trends 多数据源汇总) | 数据源可插拔(`graph/sources/`);单源失败不影响其它源 |
|
||
| `filter` | 黑名单 + 真实人物 + 设计相关性三级过滤 | 各级独立 try,单级失败不影响其它级 |
|
||
| `score` | 归一化 + 跨源融合 + 综合分 | 纯逻辑,空数据返回空 |
|
||
| `screen` | LLM 合规筛查 + 结构化四要素 | LLM 后端可插拔(`graph/llms/`);调用失败降级 Mock |
|
||
| `prompt_build` | 用固定模板装配 image/wearable/composite 提示词 | 四要素缺失时动态推导兜底 |
|
||
| `compose` | 生成纯印花设计稿(白底,可直接打印) | 图像后端可插拔(`graph/backends/`);无底图只导出 |
|
||
| `product` | SPU/颜色选品 → 底图 → 三图合成(图1模特+图2设计稿+图3底图) | 缺底图/模特图自动跳过 |
|
||
| `oss_upload` | 压缩(3:4 / ≥1340×1785 / <2MB)+ 上传阿里云 OSS | 可关闭(`oss.enabled=false`) |
|
||
| `seed_shot` | 从三合一主图按颜色选取种草图 + 上传 | 按 `seed_shot.count` 随机选取 |
|
||
| `template_export` | 把 SPU/SKU 数据填入商品上传模板 | 模板列名模糊匹配,多语言变体兼容 |
|
||
|
||
### 模式 B:Pinterest 参考模式
|
||
|
||
```
|
||
START → pinterest_init → pinterest_search → pinterest_scrape → pinterest_analyze
|
||
→ [pinterest_route 循环:简报不足 → 回 pinterest_search]
|
||
→ pinterest_finalize(排空简报池,后台并发生成 设计→三合一→OSS→种草图)
|
||
→ template_export → END
|
||
```
|
||
|
||
| 节点 | 职责 |
|
||
|---|---|
|
||
| `pinterest_init` | 创建简报池 + 并发生成流水线(`graph/pinterest_pipeline.py`) |
|
||
| `pinterest_search` | 按需生成搜索词(direct=种子词直接拼「 t-shirt design」;llm=LLM 按需生成,json_schema+防重复) |
|
||
| `pinterest_scrape` | 用 Playwright 爬取 Pinterest 图片(共享 Chrome 登录态,并发=1) |
|
||
| `pinterest_analyze` | 从图池取图 → 多并发 LLM 多模态分析 → 原创设计简报(侵权检测 + 原创化引导) |
|
||
| `pinterest_route` | 简报不足 → 图池有未消费图 → 继续分析;图池不足 → 新一轮搜索;轮次耗尽 → 结束 |
|
||
| `pinterest_finalize` | 排空简报池,后台线程池并发生成(设计→三合一→OSS→种草图),合并产品 |
|
||
|
||
**图池机制**:爬取的图片注册到 `image_pool.json`(路径+md5+搜索词);分析过的图片 md5 一律拉黑
|
||
(`used_images.json`,合适/不合适都拉黑);图池有未消费图片 → 直接分析(不搜索);不足 → 新一轮搜索。
|
||
每个简报带 `image_index`/`source_md5` 全局 id 校验,保证简报、设计稿、三合一套图对应同一张图。
|
||
分析前对图片做文件完整性校验(`PIL.verify()` 过滤损坏/截断图),避免把坏 base64 发给多模态网关
|
||
导致 400 拒收;分析失败(无有效图片/网关 400)时直接放弃该产品、跳过后续流程(**不做**纯文本降级、
|
||
**不做** mock 兜底),由路由自动取新图继续。
|
||
|
||
**并发控制**(`config.yaml` 的 `pinterest:`):`analyze_concurrency`(分析线程数)、`analyze_batch`
|
||
(每轮取图数,0=自动补齐让 pipeline 队列满并发)、`max_designs`(每搜索词简报上限)、
|
||
`scrape_concurrency`(爬图并发,必须=1)、`err400_limit`(400 超限放弃当前种子词)、
|
||
`max_empty_analyze`(连续空分析轮次上限,0=自动)。
|
||
|
||
**每个节点都用 `graph/validate.with_fallback` 包裹**:任何未预料异常都被捕获、记入
|
||
`state['errors']`、返回最小更新,整图继续往下走,单点故障不中断流水线。致命图像服务错误(503 /
|
||
"No available compatible accounts")除外——`with_fallback` 不再静默吞掉,会同步标记流水线终止,
|
||
让路由短路到 `pinterest_finalize → template_export` 提前收尾合成模板。
|
||
|
||
### 模式 B-2:自定义图片模式(Custom)
|
||
|
||
无需采集/搜索图片,把用户本地图片文件夹里的**有效图片**直接送进多模态分析,沿用 Pinterest
|
||
后续所有步骤(分析 → 设计稿 → 三合一 → OSS → 种草图 → 模板导出)。
|
||
|
||
```
|
||
START → pinterest_init → pinterest_custom_load → pinterest_analyze
|
||
→ [pinterest_custom_route 循环:图池有未消费图 → 继续分析;图池空/简报达标 → 结束]
|
||
→ pinterest_finalize → template_export → END
|
||
```
|
||
|
||
| 节点 | 职责 |
|
||
|---|---|
|
||
| `pinterest_custom_load` | 读取 `pinterest.custom_image_dir` 文件夹 → 统计有效图片 → **数量硬校验** → 每次重建图池 + 清空已消费拉黑 |
|
||
|
||
**启用方式**(两种任选):
|
||
- 配置 `config.yaml` 的 `pinterest.mode: "custom"` 并填 `pinterest.custom_image_dir: "<文件夹路径>"`;
|
||
- 或直接在 UI 选择「**自定义图片**」流程 →「📁 选图片文件夹…」选择文件夹后运行(自动写入配置)。
|
||
|
||
**数量硬校验(必过)**:
|
||
- 必须先选定上传的文件夹(UI 未选会弹窗报错,任务不启动);
|
||
- 文件夹内所有有效图片(`jpg/jpeg/png/webp`,递归)数量必须 `> 0`;
|
||
- **选品清单总数(`product.spu_tasks` 展开后)不得大于有效图片数**。不满足则在
|
||
UI 弹窗 / `run_pinterest_ref` 提前抛错 / `custom_load` 节点记录错误,三重拦截,任务不进入分析。
|
||
|
||
**行为差异**:自定义模式每次运行把图池重建为该文件夹的图片集(唯一图源)并清空已消费 md5 拉黑,
|
||
保证用户每次重新上传/选择的所有有效图片都会被重新多模态分析;分析批上限按「选品清单总数」截断,
|
||
避免对多余图片浪费配额。`pinterest_custom_route` 只在 wait / analyze / done 间流转,从不 search。
|
||
|
||
**自定义模式提示词独立(与 Pinterest 模式完全隔离,互不影响)**:
|
||
- **多模态分析提示词**:`prompts/custom_analyze_system.md` / `prompts/custom_analyze_user.md`
|
||
(与 Pinterest 模式的 `pinterest_analyze_*` 完全独立)——分析模型只输出**唯一改动指令**
|
||
`{"delta": "<一句话>"}`(同主题换姿态 / 换主体 / 换文字 / 改构图,优先保最小改动,绝不复制原图);
|
||
- **生图提示词模板**:`prompts/custom_image_prompt.md`(优先,可编辑)→
|
||
`config.custom.prompt_pieces.image_prompt_template` → 代码内置默认。模板含 `{delta}` 占位符,
|
||
运行时用分析产出的 delta 替换——以参考图印花为基底,只应用 delta 这一处改动,其余
|
||
(布局 / 元素位置 / 配色 / 阴影 / 纹理 / 线条 / 文字排版)保持不变;
|
||
- **不再使用负向提示词**:约束已全部内置进生图模板,`composite_negative` 置空;
|
||
- **模式隔离**:`generate_design` 按 `custom_mode` 分支——Pinterest 模式保留「原创化指令」
|
||
(防止复制原图),自定义模式不追加(模板已内置防复制约束),两个模式的生图行为互不影响。
|
||
|
||
## 目录结构
|
||
|
||
```
|
||
pod_trend_agent/
|
||
├── cli.py # 命令行入口
|
||
├── ui_app.py # 桌面 UI(Tkinter)
|
||
├── config.yaml # 全局配置(数据源、权重、黑名单、LLM、模板、compose/product/oss/seed_shot)
|
||
├── configs/
|
||
│ ├── countries/ # 各国 Google Trends 种子词(US|GB|JP|AU|MX|DE|BR|SA|PL|ES|IT|CA|KR.yaml)
|
||
│ ├── pinterest/ # 各国 Pinterest 种子词池(<CC>.yaml)
|
||
│ ├── model_features.yaml # 模特特征库(按性别分组 female/male,种草图用)
|
||
│ ├── kids_features.yaml # ★ 童装特征库(男童/女童:模特、场景、服装风格,种草图用)
|
||
│ ├── seed_shot_templates.yaml # 种草图提示词模板
|
||
│ └── style_features.yaml
|
||
├── prompts/<country>/ # ★ 每个国家不同的提示词单独文件夹
|
||
│ ├── system_prompt.md # 该国 LLM 系统提示(补充段,叠加到默认规则)
|
||
│ └── aesthetics.yaml # 审美 hint + 风格-配色 extra 规则 + 额外黑名单
|
||
├── prompts/pinterest_analyze_system.md # 多模态分析系统提示词(Pinterest/自定义模式),可配置
|
||
├── prompts/pinterest_analyze_user.md # 多模态分析用户提示词,可配置
|
||
├── prompts/custom_analyze_system.md # 自定义模式多模态分析系统提示词(独立于 Pinterest)
|
||
├── prompts/custom_analyze_user.md # 自定义模式多模态分析用户提示词(独立于 Pinterest)
|
||
├── prompts/custom_image_prompt.md # ★ 自定义模式生图提示词模板({delta} 占位符,可编辑)
|
||
├── prompts/title_prompt_1.md # ★ 标题生成提示词(英语市场 US/GB/AU/MX)
|
||
├── prompts/title_prompt_2.md # ★ 标题生成提示词(日本市场 JP)
|
||
├── prompts/title_prompt_3.md # ★ 标题生成提示词(西班牙市场 ES)
|
||
├── graph/
|
||
│ ├── state.py # AgentState(共享状态)
|
||
│ ├── validate.py # with_fallback 兜底 + 数据校验
|
||
│ ├── loader.py # 配置/提示词加载与合并
|
||
│ ├── scoring.py # 归一化/融合/过滤(纯逻辑)
|
||
│ ├── style_rules.py # 动态风格/配色推导
|
||
│ ├── templates.py # 固定提示词模板(按国家区分,文字敏感规则)
|
||
│ ├── classify.py # 热点分类
|
||
│ ├── pinterest.py # Pinterest 图池/黑名单/压缩/MD5 去重
|
||
│ ├── pinterest_pipeline.py # 简报池 + 并发生成流水线(Pinterest 模式核心)
|
||
│ ├── product.py / product_batch.py # 三合一合成 / 批量
|
||
│ ├── seed_shot.py # 种草图选取 + 模特特征(性别分组)
|
||
│ ├── template_export.py # 商品上传模板导出(列名模糊匹配)
|
||
│ ├── oss_upload.py # 图片压缩 + 阿里云 OSS 上传
|
||
│ ├── sources/ # 数据源可插拔(google_trends + 注册表)
|
||
│ ├── llms/ # LLM 后端可插拔(mock / openai_compat + 注册表)
|
||
│ ├── backends/ # 图像后端可插拔(openai / mock)
|
||
│ ├── seeds/ # 种子词策略可插拔(static / dynamic + holidays)
|
||
│ ├── nodes/ # 流水线节点(seed/fetch/.../pinterest_*/product/oss/seed_shot/template_export)
|
||
│ └── agent.py # 构建并编译 StateGraph(build_graph / build_pinterest_graph)
|
||
├── templates/
|
||
│ └── template_router.py # 商品上传模板路由(列名定位、数据写入)
|
||
├── scripts/
|
||
│ └── package.py # 一键打包脚本(PyInstaller → dist_vXX)
|
||
├── basemap/ # 平铺衣服底图(<款号>/<SKU.code>/)
|
||
├── material_library/ # 模特图(<品类>/)
|
||
├── db/spu_sku.db # SPU/SKU 数据库
|
||
├── pinterest_scraper/ # Playwright 爬虫 + Chrome 登录态(含跨运行持久化 .collected_urls.json)
|
||
└── output/<country>/ # ★ 每个国家的产物独立文件夹
|
||
├── design_briefs.json/md # 设计简报(含 image_prompt / composite_prompt)
|
||
├── designs/ # 纯印花设计稿
|
||
├── product/ # 三合一合成图 + 已填写商品模板 <SKU>_已填写.xlsx
|
||
├── Preview/ # ★ 成功导入模板产品的 _composite.oss.jpg 压缩图 + result.xlsx(货号|中文标题|英文标题)
|
||
└── report.md # 各阶段统计 + 兜底错误记录
|
||
```
|
||
|
||
## Pinterest 参考模式详解
|
||
|
||
1. **种子词池**:`configs/pinterest/<CC>.yaml` 存各国风格化种子词(含节日词),偏向印花设计。
|
||
2. **按需搜索**:每次只生成 1 个搜索词(`search_terms_per_run=1`),自动追加「 t-shirt design」后缀
|
||
(保证爬到的图是真实印花艺术,而非生活方式/风景图);爬取成功才标记已用,失败不拉黑。
|
||
3. **爬图**:Playwright 打开 Pinterest 搜索页截图采集(共享 `.chrome_session` 登录态,并发强制=1)。
|
||
每个关键词维护**跨运行持久化已采集 URL 集合**(`save_dir/.collected_urls.json`):滚动采集时跳过
|
||
历史 URL 旧图(不计入 count),继续下拉直至凑满新图或滚动到底(连续 10 轮无新图停止)——同一关键词
|
||
重复搜索也能采到新图,而非永远返回顶部旧图。
|
||
4. **图池 + MD5 去重**:图片注册 `image_pool.json`;分析过的 md5 一律拉黑(`used_images.json`);
|
||
设计稿生成后全局 MD5 去重(`.cache/global_design_md5.json`),跨国家生效。
|
||
5. **多模态分析**:大图先压缩(max 1024px / 1.5MB)再送 LLM,产出原创设计简报(motif/风格/配色/构图 +
|
||
risk_level:safe/review/blocked)。blocked 拦截、review 加原创化魔改引导、safe 直接生成。
|
||
每张图由多模态模型判定 `suitable_for_print`(是否适合做印花),False 的简报在节点层被过滤丢弃,
|
||
且该图 md5 立即拉黑,不进入生成流程。
|
||
6. **并发生成**:简报推入 `PinterestPipeline`,后台线程池(`product.concurrency`,默认 5)逐条
|
||
生成 设计稿 → 三合一 → OSS 上传 → 种草图,边分析边生成,不等全部分析完。
|
||
每完成一个产品立即追加落盘到 `output/<country>/<ts>/products_pending.jsonl`(中断/崩溃也不丢已
|
||
完成产品),全部完成后统一合并写模板。
|
||
7. **空选品守卫**:任务清单(`self._tasks`)为空时直接弹窗拦截并提示「请先添加选品(款号 → 颜色 →
|
||
+添加选品)」;`run_pinterest_pipeline` 也有空选品守卫,即使绕过 UI 直接调用也会拒绝启动。
|
||
8. **连续空分析保护**:图片分析连续多轮无新增简报(分析失败 / 图片均不适合印花)时,达到
|
||
`pinterest.max_empty_analyze` 上限(0=自动:目标 SPU 数+2,至少 3)即终止分析直接收尾,
|
||
避免「逐一取下一张参考图」式无限空转。
|
||
|
||
## 多模态分析提示词(可配置)
|
||
|
||
Pinterest 参考模式与自定义图片模式的多模态分析提示词已**外部化为配置**,无需改代码即可调优:
|
||
|
||
- `prompts/pinterest_analyze_system.md`——多模态分析**系统提示词**(POD T 恤设计分析师角色 +
|
||
禁止抄袭/违禁项/输出 JSON 结构等规则);
|
||
- `prompts/pinterest_analyze_user.md`——**用户提示词**("Analyze the attached image and produce
|
||
one ORIGINAL T-shirt print design brief...")。
|
||
|
||
**加载优先级**(`graph/llms/openai_compat_backend.py`):
|
||
1. `prompts/<国家>/pinterest_analyze_*.md`(国家专属覆盖);
|
||
2. `prompts/pinterest_analyze_*.md`(全局配置,先查运行根 exe 旁再查内置);
|
||
3. 内置默认常量(兜底,向前兼容)。
|
||
|
||
直接编辑这两份文件即可自定义分析与生图引导规则;`pinterest_analyze_system.md` 里可调整
|
||
`image_prompt` 二段式结构 / `suitable_for_print` 判定标准等约束(多模态分析不再产出
|
||
`negative_prompt`,生图负向约束由固定 `print_suffix` 承担)。
|
||
|
||
**多模态分析 response_format 三级回退**(`openai_compat_backend.analyze_pinterest_images`):
|
||
1. `json_schema`(OpenAI 原生 strict 输出)→ 2. `json_object`(部分兼容厂商支持,但要求提示词含
|
||
"json",自动追加 "Return your answer as a JSON object.",兼容 DeepSeek)→ 3. 无 `response_format`
|
||
(依赖 `_extract_json` 兜底解析)。DeepSeek 等厂商直接 json_schema 会 400
|
||
"This response_format type is unavailable now",三级回退保证分析不中断。
|
||
|
||
## 标题生成提示词(可配置)
|
||
|
||
标题生成提示词已**外部化为独立文件**,无需改代码即可调优:
|
||
|
||
- `prompts/title_prompt_1.md`——英语市场(US/GB/AU/MX),输出 `en_title` + `cn_title`;
|
||
- `prompts/title_prompt_2.md`——日本市场(JP),输出 `en_title` + `cn_title` + `ja_title`;
|
||
- `prompts/title_prompt_3.md`——西班牙市场(ES),输出 `es_title` + `cn_title`。
|
||
|
||
**路由表**在 `config.yaml` 的 `title_templates.route`(国家 → 模板编号),新增国家/改路由只需编辑
|
||
config.yaml。模板内 `{year}`/`{month}`/`{season}` 占位符运行时自动替换为当前时间;md/yaml 缺失时
|
||
回退代码内置默认模板,标题生成不中断。
|
||
|
||
## 生成可靠性 / 错误处理
|
||
|
||
- **致命 503(图像服务不可用,如 "No available compatible accounts")**:端到端识别
|
||
(设计稿 compose → 三合一 product → 种草图 seed_shot),置位终止标志后**提前终止任务**——
|
||
停止继续搜索/分析,`abort_unfinished` 丢弃未完成简报,**已完成落盘的产品保留**,直接合成模板导出。
|
||
- **图像 API 重试退避**(`graph/backends/openai_image_backend.py`):429 尊重网关 `Retry-After`
|
||
头,否则指数退避;5xx(500/502/503/504 超时)与网关空响应(JSON 解析失败)均退避 3/6/9s 重试、
|
||
最多 3 次,避免空响应/超时风暴触发限流。
|
||
- **生图进度日志**:每次生图调用提交前打印 `[img] 开始图生图/文生图(模型,尺寸,参考图 N 张)→ 文件名`,
|
||
保存后打印 `[img] 已生成(耗时 Xs)`——同步成功不再静默,UI 日志区能实时看到生图进度,避免"看起来卡死"。
|
||
- **异步任务轮询超时**:`_wait_task` 轮询超时 60s → 300s(与提交请求 timeout 一致)。网关异步任务实际
|
||
需 30s~6 分钟(设计稿/三图合成),60s 轮询超时会把仍在处理中的任务误判为失败而重复提交,白白消耗配额和时间。
|
||
- **yunfei / 标准 OpenAI 网关适配**:`compose.execution_mode` 与 `background` 参数默认不再传入——
|
||
yunfei 等网关不认识它们会返回空 body;`base_url` 需带 `/v1` 前缀(如
|
||
`https://img.yunfei.best/v1`),否则请求错误路径得到空响应。
|
||
- **图源映射(可配置)**:`config.product.mark_dirs` 定义 SPU.mark → `material_library` 下的
|
||
`model_dir`(模特图)/ `flat_dir`(平铺图)两个图源文件夹及对应合成提示词。热点采集与 Pinterest
|
||
两种模式统一走该映射:在「有图的文件夹」间按**任务序号**独立随机抽图,抽到模特图用模特三图提示词
|
||
(图1模特+图2印花+图3底图),抽到平铺图用平铺三图提示词(图1平铺实拍+图2印花+图3底图)。
|
||
同一 SPU 的多款不再共用同一张图;某类目录无图则只用另一类。每张种草图随机取不同模特特征。
|
||
**合成提示词可配置覆盖**:`mark_dirs` 下配置 `flat_prompt` / `model_prompt` 时优先生效
|
||
(`product_node._active_prompt`),留空才回退内置 `FLAT_LAY_PROMPT` / `MODEL_WEAR_PROMPT`。
|
||
|
||
## 模特性别分组
|
||
|
||
`configs/model_features.yaml` 的模特特征按性别分组(`female` / `male`)。种草图生成时读取商品上传
|
||
模板的「类目」表头值:
|
||
- 类目含「男童」→ 固定从 **boy_kids** 组随机取模特(童装)
|
||
- 类目含「女童」→ 固定从 **girl_kids** 组随机取模特(童装)
|
||
- 类目含「男」(如 `男士时尚>男装>男装T恤`)→ 固定从 **male** 组随机取模特
|
||
- 类目含「女」→ 固定从 **female** 组随机取模特
|
||
- 都不含 → 男女混合随机
|
||
|
||
**判定顺序**:先判「男童/女童」再判「男/女」(因为"男童"也含"男"、"女童"也含"女")。
|
||
|
||
## 童装场景图生成(男童 / 女童)
|
||
|
||
检测到模板类目为男童/女童时,种草图**不再套用** `seed_shot_templates.yaml`,而是直接使用
|
||
`configs/kids_features.yaml` 里配置的**完整场景提示词**(同一商品全套图固定同一组 模特+场景+服装风格):
|
||
|
||
- `model_features.boy_kids` / `model_features.girl_kids`——童装模特特征
|
||
- `scene_features.boy_kids` / `scene_features.girl_kids`——童装场景完整提示词(支持
|
||
`[商品名称]`/`[材质]`/`[模特特征]`/`[服装风格]` 占位符)
|
||
- `style_features.boy_kids` / `style_features.girl_kids`——童装服装风格
|
||
|
||
**种草图重试**:`config.yaml` 的 `seed_shot.retries`(默认 3)——生成失败(如图像 API 安全策略拦截)
|
||
时自动换一组 场景/模特/风格 重试,全部失败则返回空、不中断流水线;成人模式失败时换模板/特征重试。
|
||
|
||
## 生图尺寸(读 config,不硬编码)
|
||
|
||
| 图片类型 | 配置项 | 默认 |
|
||
|---|---|---|
|
||
| 纯印花设计稿 | `compose.design_size` | 1024x1024(1:1) |
|
||
| 三合一合成图 | `compose.size` | 1536x2048(3:4) |
|
||
| 种草图 | `seed_shot.size` | 1536x2048(3:4) |
|
||
|
||
## 商品上传模板导出
|
||
|
||
生成产品图后,从 db 读该 SPU/SKU 信息(材质/成分/图案/领型/面料/克重/印花类型/尺码表/边长/包装重量…),
|
||
经 `templates/template_router.py` 的路由函数填入商品上传模板,输出 `{模板原文件名}_已填写.xlsx` 到
|
||
`output/<国家>/product/`。模板已自包含在项目 `templates/`(`config.product.template_path`,可改为自由上传)。
|
||
|
||
- 数据从模板第 6 行(数据区空行)开始填,SPU 与各尺码 SKU 紧邻;
|
||
- **写入前按货号最后 3 位升序排序**:`template_export` 在批量填模板前取货号(`img_code`,前端
|
||
`code_prefix` 前缀命名的货号)末 3 位数字从小到大排序再顺序插入,保证 SPU/SKU 块按货号有序,
|
||
不受后台并发生成顺序影响;
|
||
- **不再产生空白 xlsx**:修复了旧版本探测模板可写性时误建空文件的 bug,product 目录只保留填好
|
||
的有效文件,文件名 = 模板原文件名 + `_已填写`(非固定「商品上传」);
|
||
- **列名模糊匹配**:模板列名按名称匹配(非固定行列),支持中/英/日变体;
|
||
- **胸围识别**:识别「基码表-胸围(cm)」「胸围全围(cm)」等含「胸围」的列,全部填 `sku.bust` 值;
|
||
- **申报价格**:模糊匹配所有含「申报价格」的列,统一按加价后价格填写(`price × (1+markup_percent%)`);
|
||
- **款式来源**:SPU 行「款式来源」统一填「现货款」;
|
||
- **商品产地**:所有国家统一填「中国大陆」;新增「产地省份」精确匹配列,统一填「广东省」(不再读站点/做字典映射);
|
||
- **SKU 分类 / SKU 数量 / SKU 数量单位**:模板检测到这些列即统一填固定值(不再检测「非必填」备注):
|
||
`SKU分类=单品`、`SKU数量=1`、`SKU数量单位=件`;
|
||
- **建议售价 / 建议售价单位**:模板存在对应列且 `suggested_price_ratio > 0` 时统一必填——
|
||
建议售价 = 申报价格 ×(1+比例%),单位统一填 `CNY`(不再检测模板备注);
|
||
- **SPU 商品属性列名兼容**:`resolve_col` 支持「SPU商品属性-袖型」前缀剥离匹配——列名带前缀的模板
|
||
(如沙特女装模板)精确匹配,列名不带前缀的模板(如黑白CasualNest Shop)自动剥离前缀后匹配;
|
||
- **尺码下拉框动态引用**:`_read_size_options` 识别 `INDIRECT(...)` 动态引用公式,能解析则按下拉选项
|
||
过滤 SKU 行(尺码不在下拉内跳过),无法解析(空单元格/跨表)时返回 None 不启用过滤,避免误杀全部 SKU 行;
|
||
- **SPU 商品属性字段映射**:`placket_type→门襟类型`、`sleeve_type→袖型`、`sleeve_length_type→袖长`、
|
||
`breast_pad→胸垫`、`layout→版型`、`silhouette→廓形`、`length_type→长度`、`belt→腰带`、
|
||
`occasion→场合`、`scene→场景`、`hemline_shape→下摆形状`,各字段独立不覆盖;
|
||
- **details 扩展列**:精确匹配「细节1 / 细节2 / 细节3」列(`_find_details_headers`),匹配到即全部填
|
||
`spu.details` 值(同一详情写多个扩展列);
|
||
- **target_audience 扩展列**:精确匹配「适用人群1」列(`_find_target_audience_headers`),匹配到即填
|
||
`target_audience` 映射后的值(童装按性别映射,见下);
|
||
- **固定值风格列**:匹配到「风格1」列统一填「休闲」、匹配到「风格2」列统一填「运动」;
|
||
- **季节映射(女装)**:`spu.season` 的「四季」→「ALL/全球/所有」(`config.yaml` 的 `season_map.female` 可配置);
|
||
- **印花图案映射(女装)**:`spu.pattern` 为「印花」时 →「卡通」(`pattern_map` 可配置);
|
||
- **适用人群映射(童装)**:`spu.target_audience` 按童装性别映射(`target_audience_map.kids` 可配置),
|
||
如女童模板「男童」→「女童」、男童模板「女童」→「男童」;
|
||
- **童装字段映射**:检测到男童/女童模板时,`spu.kids_type` →「SPU商品属性-类型」、`spu.kids_age` →「适用年龄段」;
|
||
**kids_type 值映射**:`kids_type_map.girl_kids`(可配置)仅女童模板生效,如「上衣」→「针织上衣」,男童保留原值;
|
||
- **SKU 尺码升序排序**:写入模板前按 `sku.size` 从小到大排序(`_size_rank` 支持数字码/字母码/童装年龄码
|
||
6Y/10Y/1-2Y/均码等),保证每个 SPU 块内尺码有序,不受 db 存储顺序影响;
|
||
- **多站点模板匹配**:模板「经营站点」表头下可配置多个站点(逐行读取),当前国家命中其中任意一个即视为
|
||
匹配,不再只认第一个站点;
|
||
- **Preview 文件夹**:模板导出成功后生成 `output/<国家>/<ts>/Preview/`——复制成功导入模板产品的
|
||
`_composite.oss.jpg` 压缩图 + 生成 `result.xlsx`(货号 | 中文标题 | 英文标题),仅含成功产品;
|
||
- **详情图文**:由全部主图 + 种草图组成(不再拼接 img_url_2);
|
||
- 规格类型2 = `{size}*{color}`;币种=CNY;发货仓1~N 取模板顶头按「、」分隔,库存均 200;
|
||
- 模板文件被占用(打开中)时自动换名 `<SKU>_已填写_N.xlsx`,不中断导出;
|
||
- **多颜色 + 模式**:`sku_code` 支持逗号分隔多颜色;`spu_per_color`(true=每颜色一个 SPU 块 /
|
||
false=单 SPU 挂多颜色变体);CLI 用 `--single-spu` 切单 SPU 模式,UI 用「颜色多选 + 模板模式」。
|
||
|
||
## 用法
|
||
|
||
```bash
|
||
# 跑全部国家(热点采集模式,默认 US GB JP AU)
|
||
python cli.py
|
||
|
||
# 只跑英国,Mock 兜底 LLM
|
||
python cli.py -c GB --provider mock
|
||
|
||
# 跑美国 + 真实 LLM(provider 已在 config.llm_screen 配好时可不传)
|
||
python cli.py -c US
|
||
|
||
# 提供平铺衣服底图,把设计印上去(需 config.compose.backend + api_key)
|
||
python cli.py -c US --base path/to/flatlay.png
|
||
|
||
# 查看 db 可选款号 / 某款颜色
|
||
python cli.py --list-spus
|
||
python cli.py --list-colors DG004
|
||
|
||
# 指定款号+颜色跑流水线(product.backend=mock 占位 / openai 真生图需 compose.api_key)
|
||
python cli.py -c GB --spu DG004 --sku DG004-BL01
|
||
```
|
||
|
||
## 桌面 UI(Tkinter 轻量版)
|
||
|
||
```bash
|
||
# 开发模式直接跑
|
||
python ui_app.py
|
||
|
||
# 无 GUI 自检(验证环境/核心链路,结果写入运行根 self_test_result.txt)
|
||
python ui_app.py --self-test
|
||
```
|
||
|
||
UI 功能:国家多选、**流程选择(热点采集 / Pinterest 参考模式 / 自定义图片模式)**、LLM 后端选择、种子上限、
|
||
**SPU/颜色选品**、运行(后台线程 + 实时日志)、结果表格(双击看完整提示词)、打开产物目录。
|
||
|
||
## 打包
|
||
|
||
```bash
|
||
# 一键打包(自动取下一个版本号)
|
||
python scripts/package.py
|
||
|
||
# 指定版本号
|
||
python scripts/package.py 84
|
||
```
|
||
|
||
产物:`dist_vXX/PODTrendAgent.exe`。打包流程:PyInstaller 构建(不跑自检)→ 同步数据目录
|
||
(config.yaml / configs / prompts / templates / basemap / material_library / db / output / logs)→
|
||
复制当前 Chrome 登录态到 exe 同目录(`pinterest_scraper/.chrome_session`)→ 同步上一个版本的 `.cache`。
|
||
exe 运行时优先读 exe 旁这份配置(改了就生效),exe 内置的作为兜底默认。
|
||
|
||
## 数据流要点
|
||
|
||
0. `seed`(动态种子词):收集 trending 派生(去噪 + 人名 + 风险护栏过滤)、上轮 safe 历史热点、
|
||
当前月份/临近节日,由 LLM 后端(mock 规则 / 真 LLM)生成动态种子词,与 yaml 静态种子合并注入抓取配置。
|
||
1. `fetch` 抓 `gt_trending`(国家 RSS 实时榜)+ `gt_style`/`gt_related`(风格/行业种子关联词)。
|
||
2. `filter` 三级过滤:合规黑名单(全局 + 各国 `extra_blacklist`)→ 真实人物 → 泛新闻/科技/赛事词。
|
||
3. `score` 按 (source,kind) 分组 min-max 归一化、跨源融合加权重。
|
||
4. `screen` LLM 合规筛查,产出 risk_level / 四要素;`keep_review=false` 时丢弃待复核。
|
||
5. `prompt_build` 用四要素 + 固定模板装配 image/wearable/composite 提示词(结构一致、可复用 img2img)。
|
||
6. `compose` 生成纯印花设计稿(白底,可直接打印),product 取第一张作为图2 复用。
|
||
7. `product` SPU/颜色选品 → basemap 底图 → 三图合成(图1模特 + 图2设计稿 + 图3底图)→ 模板。
|
||
8. `oss_upload` 压缩(3:4 / ≥1340×1785 / <2MB)+ 上传阿里云 OSS,URL 写回 `*_url` 字段。
|
||
9. `seed_shot` 从三合一主图按颜色选取种草图(模特性别分组),上传 OSS,URL 写入模板「详情图文」。
|
||
10. `template_export` 把 SPU/SKU 数据填入商品上传模板,输出 `<SKU>_已填写.xlsx`。
|
||
|
||
> 合规红线(最重要):版权/商标/真实人物/敏感内容一律拦截或降级;二创/重绘仍有风险,
|
||
> 拿不准进"待复核"。各国侵权盲区不同(如英国 WWE/游戏/乐队、日本动漫 IP),放在
|
||
> `prompts/<country>/aesthetics.yaml` 的 `extra_blacklist` 按国家隔离。
|