Files
pod_trend_agent/README.md
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

411 lines
30 KiB
Markdown
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.
# POD 热点抓取 AgentLangGraph 工程化版)
自动抓取海外各国(US / GB / JP / AU / MX / DE / BR / SA / PL / ES / IT / CA / KR)实时热点 + 风格趋势,
过滤侵权风险,产出可直接用于 AI 生图的印花设计提示词,并完成 **设计稿 → 三合一模特试穿 → OSS 图床 →
种草图 → 商品上传模板** 的完整 POD 生产链路。本版本用 **LangGraph** 重写,强调**工程化、节点兜底、可插拔**。
## 两种运行模式
| 模式 | 入口 | 数据来源 | 适用 |
|---|---|---|---|
| **热点采集模式** | UI「热点采集」 | Google Trendstrending/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 数据填入商品上传模板 | 模板列名模糊匹配,多语言变体兼容 |
### 模式 BPinterest 参考模式
```
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 # 桌面 UITkinter
├── 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 # 构建并编译 StateGraphbuild_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_levelsafe/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`
头,否则指数退避;5xx500/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` | 1024x10241:1 |
| 三合一合成图 | `compose.size` | 1536x20483:4 |
| 种草图 | `seed_shot.size` | 1536x20483: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
# 跑美国 + 真实 LLMprovider 已在 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
```
## 桌面 UITkinter 轻量版)
```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+ 上传阿里云 OSSURL 写回 `*_url` 字段。
9. `seed_shot` 从三合一主图按颜色选取种草图(模特性别分组),上传 OSS,URL 写入模板「详情图文」。
10. `template_export` 把 SPU/SKU 数据填入商品上传模板,输出 `<SKU>_已填写.xlsx`
> 合规红线(最重要):版权/商标/真实人物/敏感内容一律拦截或降级;二创/重绘仍有风险,
> 拿不准进"待复核"。各国侵权盲区不同(如英国 WWE/游戏/乐队、日本动漫 IP),放在
> `prompts/<country>/aesthetics.yaml` 的 `extra_blacklist` 按国家隔离。