Files
pod_trend_agent/README.md
T
3218485270 2a96ec0870 v88 功能增强:产品落盘持久化 + 生图网关适配 + 模板导出优化
- 产品持久化:每完成一个产品立即追加写入 products_pending.jsonl,崩溃不丢已完成产品,finish 读盘合并后统一写模板
- 503 致命错误提前终止:compose/product/seed_shot 端到端识别,提前终止搜索分析,丢弃未完成简报,保留已完成落盘产品直接合成模板
- 模特分配:material_library 合格模特图按任务序号独立随机,同 SPU 多款不再共用同一模特
- 图像网关适配:execution_mode/background 默认不再传入 yunfei 等标准网关,base_url 需带 /v1;429/5xx/空响应退避重试
- Pinterest 分析:删除 term 注入与纯文本降级,失败直接放弃;图片上传前 PIL 完整性校验;suitable_for_print=False 过滤丢弃
- 模板导出:不再产生空白 xlsx,文件名=模板原文件名_已填写;写入前按货号末 3 位升序排序
- 删除对接文档.md,更新 README,gitignore 排除测试产物
2026-08-28 10:28:35 +08:00

259 lines
17 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)实时热点 + 风格趋势,
过滤侵权风险,产出可直接用于 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 超限放弃当前种子词)。
**每个节点都用 `graph/validate.with_fallback` 包裹**:任何未预料异常都被捕获、记入
`state['errors']`、返回最小更新,整图继续往下走,单点故障不中断流水线。
## 目录结构
```
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.yaml
│ ├── pinterest/ # 各国 Pinterest 种子词池(<CC>.yaml
│ ├── model_features.yaml # 模特特征库(按性别分组 female/male,种草图用)
│ ├── seed_shot_templates.yaml # 种草图提示词模板
│ └── style_features.yaml
├── prompts/<country>/ # ★ 每个国家不同的提示词单独文件夹
│ ├── system_prompt.md # 该国 LLM 系统提示(补充段,叠加到默认规则)
│ └── aesthetics.yaml # 审美 hint + 风格-配色 extra 规则 + 额外黑名单
├── 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 登录态
└── output/<country>/ # ★ 每个国家的产物独立文件夹
├── design_briefs.json/md # 设计简报(含 image_prompt / composite_prompt
├── designs/ # 纯印花设计稿
├── product/ # 三合一合成图 + 已填写商品模板 <SKU>_已填写.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)。
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`(中断/崩溃也不丢已
完成产品),全部完成后统一合并写模板。
## 生成可靠性 / 错误处理
- **致命 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 次,避免空响应/超时风暴触发限流。
- **yunfei / 标准 OpenAI 网关适配**`compose.execution_mode``background` 参数默认不再传入——
yunfei 等网关不认识它们会返回空 body;`base_url` 需带 `/v1` 前缀(如
`https://img.yunfei.best/v1`),否则请求错误路径得到空响应。
- **模特分配**`material_library/<品类>` 内的合格模特图(3:4 比例过滤)按**任务序号**独立随机,
同一 SPU 的多款不再共用同一张模特。每张种草图随机取不同模特特征。
## 模特性别分组
`configs/model_features.yaml` 的模特特征按性别分组(`female` / `male`)。种草图生成时读取商品上传
模板的「类目」表头值:
- 类目含「男」(如 `男士时尚>男装>男装T恤`)→ 固定从 **male** 组随机取模特
- 类目含「女」→ 固定从 **female** 组随机取模特
- 都不含 → 男女混合随机
## 生图尺寸(读 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 行「款式来源」统一填「现货款」;
- **商品产地**:国家简称映射正式名称(如「沙特」→「沙特阿拉伯」,`_COUNTRY_NAME_MAP` 可扩展);
- **详情图文**:由全部主图 + 种草图组成(不再拼接 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` 按国家隔离。