修复种草图生成:以三合一主图为参考 img2img 生成,按颜色分配(每色优先、超出随机补足);新增 BR/CA/DE/ES/IT/PL/SA 七国配置与提示词;删除验证用测试脚本
This commit is contained in:
@@ -0,0 +1,294 @@
|
||||
# POD 趋势感知 Agent · 对接文档
|
||||
|
||||
> 面向开发者/维护者的适配与扩展指南。覆盖:项目架构、**如何适配新国家**、核心流程、缓存机制、合规红线、常见问题与打包发布。
|
||||
> 适用版本:dist_v67 / 源码 `pod_trend_agent/`
|
||||
|
||||
---
|
||||
|
||||
## 1. 项目概览
|
||||
|
||||
**目标**:为 POD(Print on Demand)出海业务自动捕捉海外热点 → 生成可打印的 T 恤印花设计 → 三图合成模特图 → 多语言标题 → 导出商品上传模板。
|
||||
|
||||
**技术栈**:Python 3.13 · LangGraph(7 节点流水线)· tkinter 桌面 UI · requests · Pillow · PyInstaller 打包
|
||||
|
||||
**两条运行路径**:
|
||||
|
||||
| 路径 | 触发条件 | 行为 |
|
||||
|---|---|---|
|
||||
| **缓存热点模式**(日常) | `output/<国>/collected_keywords.json` 存在 | 直接用采集缓存分配热点;简报不足时**从采集缓存自动生成简报**(轻量补齐),**绝不触发 Google** |
|
||||
| **完整流水线**(首次) | 完全无缓存 | `seed → fetch → filter → score → screen → prompt_build → compose → product → seed_shot → template_export → oss_upload` |
|
||||
|
||||
---
|
||||
|
||||
## 2. 目录结构
|
||||
|
||||
```
|
||||
pod_trend_agent/
|
||||
├── ui_app.py # 桌面 UI:选品/采集/运行/模板/结果表格
|
||||
├── cli.py # 命令行入口
|
||||
├── config.yaml # 全局配置(countries/sources/llm_screen/prompt_templates/compose/oss/product…)
|
||||
├── configs/countries/<CC>.yaml# ★每国独立配置:种子词/related 种子/采集限额
|
||||
├── prompts/<CC>/ # ★每国提示词:system_prompt.md + aesthetics.yaml
|
||||
├── graph/
|
||||
│ ├── agent.py # LangGraph 流水线编排(START→seed→fetch→…→END)
|
||||
│ ├── nodes/ # 各节点实现(seed/fetch/filter/score/screen/prompt/compose/product/seed_shot/template/oss)
|
||||
│ ├── product_batch.py # 缓存热点批量流程:分配/三级去重/review 兜底/轻量补齐
|
||||
│ ├── backends/ # 图像后端:openai_image_backend / mock_image_backend
|
||||
│ ├── llms/ # LLM 后端:openai_compat_backend(多模态标题)/ mock_backend
|
||||
│ ├── seeds/ # 种子策略:dynamic_strategy(统一池+加权随机)/ static / holidays
|
||||
│ ├── sources/ # 数据源注册表:google_trends(pytrends,429 兜底)/ pinterest
|
||||
│ ├── product.py # 底图/模特查找(IMG_EXTS 全格式)、SKU 逻辑
|
||||
│ ├── style_rules.py # 风格/配色/构图规则 + sanitize_image_prompt + review 魔改引导
|
||||
│ ├── paths.py # config_root / project_root / runtime_root 路径解析
|
||||
│ └── validate.py # 校验 + with_fallback 兜底装饰器
|
||||
├── templates/ # 商品上传模板 + template_router.py(模板读写)
|
||||
├── basemap/<款号>/<颜色>/ # 平铺底图(jpg/png…)
|
||||
├── material_library/<品类>/ # 模特图(webp/jpg/png/avif…)
|
||||
├── db/ # 商品数据库(sqlite)
|
||||
└── dist_vNN/ # PyInstaller 打包产物(含全部数据)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. ★适配新国家(核心章节)
|
||||
|
||||
以新增 **DE(德国)** 为例,完整步骤:
|
||||
|
||||
### 3.1 国家代码入列
|
||||
|
||||
`config.yaml`:
|
||||
```yaml
|
||||
countries:
|
||||
- US
|
||||
- GB
|
||||
- JP
|
||||
- AU
|
||||
- MX
|
||||
- DE # ← 新增
|
||||
```
|
||||
|
||||
### 3.2 每国配置 `configs/countries/DE.yaml`
|
||||
|
||||
```yaml
|
||||
# 德国专属数据源配置
|
||||
trending:
|
||||
enabled: true
|
||||
limit: 40 # Google Trends 抓取上限
|
||||
|
||||
style:
|
||||
enabled: true
|
||||
seeds: # ★印花风格种子词(重点,越多越好,20~30 个)
|
||||
- lederhosen
|
||||
- alpine
|
||||
- berlin street art
|
||||
- bauhaus pattern
|
||||
- autobahn
|
||||
- ...
|
||||
|
||||
related:
|
||||
enabled: true
|
||||
seed_keywords:
|
||||
- ...
|
||||
|
||||
exclude_topics: [] # 黑名单热点(已用过/明确不分配的词,可选)
|
||||
```
|
||||
|
||||
**种子词选词红线**(写配置时注意):
|
||||
- ❌ 会被 `review 兜底 _UNSUITABLE` 剔除的类目:`nails / recipes / lottery / weather / results / prices / jobs / mortgage / election…`(见 `graph/product_batch.py`)
|
||||
- ❌ 品牌/版权/真实人物:`nike / disney / margot robbie / prison break…`
|
||||
- ❌ 图像策略敏感词:`skull / skeleton / blood / gun / demon…`(生成时会被 `sanitize_image_prompt` 替换,主题会变味)
|
||||
- ✅ 用各国**本土流行 + 全球趋势**的印花主题(2026 参考:retro vintage / 极简 typography / 自然户外 / 手绘涂鸦 / Y2K / coquette / western / 幽默 quote / 星座塔罗 / 植物线稿)
|
||||
|
||||
### 3.3 每国提示词 `prompts/DE/`
|
||||
|
||||
- **`system_prompt.md`**:screen 阶段 LLM 的角色/输出规则(风险判定、motif/art_style/color_palette/composition 四要素),**必须包含 "Return JSON…" 字样**(阿里云 MaaS 的 `response_format=json_object` 硬性要求)。
|
||||
- **`aesthetics.yaml`**:
|
||||
```yaml
|
||||
extra_style_rules: [...] # 该国风格倾向(配色/构图/审美)
|
||||
extra_blacklist: [...] # 该国合规红线词(德国:纳粹符号等)
|
||||
```
|
||||
|
||||
### 3.4 节假日 `graph/seeds/holidays.py`
|
||||
|
||||
`_HOLIDAYS_BY_COUNTRY` 增加国家节日(名称/月/日/规则/窗口),节日种子词自动带权重 3.0 进入统一池:
|
||||
```python
|
||||
"DE": [
|
||||
("Oktoberfest", 9, 21, "third_saturday", 30), # 啤酒节(9 月)
|
||||
("Weihnachten", 12, 25, "fixed", 25), # 圣诞节
|
||||
...
|
||||
]
|
||||
```
|
||||
|
||||
### 3.5 国家模板站点校验 `ui_app.py`
|
||||
|
||||
`_check_template_site` 的 `country_sites` 字典加国家→站点关键词:
|
||||
```python
|
||||
country_sites = {
|
||||
...
|
||||
"DE": ("德国站", "德国"),
|
||||
}
|
||||
```
|
||||
(模板「模版」sheet 第 1 行定位「经营站点」列 → 第 2 行站点名 → 与所选国家不匹配则**导入失败**,提示重新导入)
|
||||
|
||||
### 3.6 图像提示词模板 `config.yaml → prompt_templates`
|
||||
|
||||
`image_prompt` / `wearable_prompt` / `composite_prompt` 各加国家版本(`{motif}` 等占位符保持不变),注意:
|
||||
- **提示词中不得出现任何背景描述**("isolated on … background"、"no background scene")——透明背景只由 `background="transparent"` 参数控制(官方要求)
|
||||
- 不含安全规则段("no politics / no religion / no hate / no violence / no sexual"——这些词本身会触发图像 API 内容政策拦截)
|
||||
|
||||
### 3.7 验证清单
|
||||
|
||||
```bash
|
||||
python cli.py -c DE --provider mock # mock 跑通全流程(不花钱)
|
||||
python -c "from graph.seeds.dynamic_strategy import DynamicStrategy; ..." # 验证种子池
|
||||
# UI 打开 → 切 DE → 采集 → 运行
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 核心流程详解
|
||||
|
||||
### 4.1 完整流水线(LangGraph 7 节点)
|
||||
|
||||
```
|
||||
START → seed(种子词) → fetch(采集) → filter(过滤) → score(打分) → screen(风险筛选+简报)
|
||||
→ prompt_build(提示词) → compose(设计稿) → product(合成/标题) → seed_shot(种草图)
|
||||
→ template_export(模板) → oss_upload(压缩上传) → END
|
||||
```
|
||||
每个节点均套 `with_fallback` 兜底(失败不中断整体流程)。
|
||||
|
||||
### 4.2 缓存热点模式(日常入口,`ui_app` / `run_product_batch`)
|
||||
|
||||
```
|
||||
判断:output/<国>/ 有 collected_keywords.json 或 design_briefs.json → 缓存模式
|
||||
→ load 简报(简报不足 → _rebuild_briefs_from_cache 从采集缓存生成,不碰 Google)
|
||||
→ assign_hotspots 分配(三级去重 + review 兜底)
|
||||
→ product 节点批量处理(并发 ≤5,每 SPU 一线程)
|
||||
→ 模板导出
|
||||
```
|
||||
|
||||
### 4.3 热点分配与去重(`assign_hotspots`)
|
||||
|
||||
| 层级 | 逻辑 |
|
||||
|---|---|
|
||||
| ① 热点去重 | 本批优先不同 topic(热点1-风格1、热点2-风格1…) |
|
||||
| ② 风格去重 | 热点用完后自动切:热点1-风格2、热点2-风格2…(同 topic 不同 art_style) |
|
||||
| ③ 兜底 | 剩余未用指纹(低分热点也可);**历史已用 (topic, style) 指纹绝不重复出** |
|
||||
| review 兜底 | `_UNSUITABLE` 正则剔除不适合类目(美甲/食谱/彩票/天气/比分…),日志提示 |
|
||||
|
||||
### 4.4 种子词机制(`dynamic_strategy.py`)
|
||||
|
||||
- **统一池**:静态 style + 静态 related + 月份主题 + 节日 + LLM 动态 → 全部合并去重(跨类型同词权重累加)
|
||||
- **权重**:节日 3.0 > 月份主题 2.0 > 静态/动态 1.0(加权随机抽取)
|
||||
- **每次随机取**(加权不重复);**用完全用**(池 ≤ 需要数时全部使用,不随机限量)
|
||||
- 每国独立配置(`configs/countries/<CC>.yaml`),种子缓存 `.cache/seeds/`(按 国家+provider+日期,防 Google 429)
|
||||
|
||||
---
|
||||
|
||||
## 5. 缓存文件
|
||||
|
||||
| 文件 | 位置 | 作用 |
|
||||
|---|---|---|
|
||||
| `collected_keywords.json` | `output/<国>/` | 采集热点池(关键词列表) |
|
||||
| `design_briefs.json` | `output/<国>/` | 简报池(topic/motif/risk/score/image_prompt…) |
|
||||
| `used_designs.json` | `output/<国>/` | 已用 (topic, art_style) 指纹(成功生成才写入) |
|
||||
| `.cache/seeds/` | 项目根 | 种子词日缓存(防 429 重采集) |
|
||||
| `.cache/llm_screen/` | 项目根 | LLM 筛查缓存 |
|
||||
|
||||
> 注意:**失败产品不写 used_designs**(合成/设计失败的,热点下次仍可用)。
|
||||
> 已用过不要的热点:直接从 `collected_keywords.json` / `design_briefs.json` 物理删除即可(如 8-22 的 18 个 GB 热点处理方式)。
|
||||
|
||||
---
|
||||
|
||||
## 6. 合规红线(最重要)
|
||||
|
||||
1. **review 判定**:screen 阶段 LLM 判定疑似商标/版权/真实人物 → `risk_level=review`;openai 模式下生成设计时**自动注入原创化魔改引导**(`REVIEW_REBRAND_HINT`:只做风格参考、禁止复刻 logo/商标/角色、换名换细节)
|
||||
2. **提示词清洗** `sanitize_image_prompt`(生成设计前必过):
|
||||
- 删除一切背景描述(透明背景由参数控制)
|
||||
- 删除内容策略触发段(`any text must be safe: no politics/religion/hate/violence/sexual…`)
|
||||
- 21+ 个敏感词安全替换(skull→smiley mascot、gun→star…)
|
||||
3. **各国红线**:美国慎政治/宗教;德国慎纳粹符号(`aesthetics.yaml extra_blacklist` 扩展);中东整体保守;真实人物一律不进
|
||||
4. **review 兜底 `_UNSUITABLE`**:不适合类目自动剔除(分配源头拦截)
|
||||
|
||||
---
|
||||
|
||||
## 7. 图像生成与合成
|
||||
|
||||
### 7.1 设计稿生成(`compose` / `product` 的 `generate`)
|
||||
- **透明背景**:`background="transparent"` 参数(compose/product 配置均已设);**提示词不得提背景**
|
||||
- 并发:compose 并发生成(`compose.design_workers` 默认 5);product 阶段每 SPU 一线程,并发上限 5
|
||||
- 底图/模特/设计 >2MB → 自动压缩到 <2MB 再上传网关(`_shrink_blob_to_2mb`)
|
||||
|
||||
### 7.2 三图合成(`product` 的 `print`,mark=1)
|
||||
- 上传顺序:**图1 模特图 → 图2 印花设计稿 → 图3 衣服平铺底图**(与提示词角色一一对应)
|
||||
- 图3 只提取衣服本身底色与面料材质(忽略平铺图背景/桌面/场景)
|
||||
- 合成失败 → 退避重试 3 次(5/20/40s);仍失败 → 跳过该产品(不生成标题、不写模板)
|
||||
- 网关处理约 2-6 分钟属正常(重负载 img2img)
|
||||
|
||||
---
|
||||
|
||||
## 8. 模型与网络配置(`config.yaml`)
|
||||
|
||||
```yaml
|
||||
llm_screen: # LLM(screen/种子/标题共用)
|
||||
model: "qwen3.7-..." # ★标题生成需视觉模型(qwen-vl 系列);纯文本模型会 400
|
||||
base_url: "https://...maas.aliyuncs.com/compatible-mode/v1"
|
||||
api_key: "sk-..." # 或环境变量 LLM_API_KEY
|
||||
|
||||
compose: # 设计稿图像网关
|
||||
backend: "openai"
|
||||
model: "gpt-image-2" # 支持 background=transparent
|
||||
base_url: "https://api.tofastcode.xyz"
|
||||
background: "transparent"
|
||||
|
||||
product:
|
||||
backend: "mock" # openai / mock
|
||||
background: "transparent"
|
||||
concurrency: 5 # 合成并发上限(默认 min(任务数,5))
|
||||
```
|
||||
|
||||
**代理策略**:模型调用(LLM + 图像)一律直连(`NO_PROXY` + 环境变量级 `no_proxy=*`,用户挂 VPN 也不走代理);**Google 采集(pytrends)走系统代理**(需要 VPN)。
|
||||
|
||||
---
|
||||
|
||||
## 9. 打包发布(每版流程)
|
||||
|
||||
```bash
|
||||
# 1. 打包(不跑 self-test:会撞 Google 429,浪费 7-10 分钟)
|
||||
pyinstaller -y PODTrendAgent.spec --distpath dist_vNN --workpath build_cleanNN
|
||||
|
||||
# 2. 补齐 dist 数据(必须,否则 exe 缺资源)
|
||||
cp -r templates db basemap material_library configs prompts .cache dist_vNN/
|
||||
cp config.yaml dist_vNN/
|
||||
|
||||
# 3. 拷贝最近缓存(output/<国>/*.json),避免 exe 首次运行重新采集
|
||||
# 4. 验证:find_first_model_folder 能查到模特(material_library 拷贝不完整是常见坑)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. 常见问题(FAQ)
|
||||
|
||||
| 现象 | 根因 | 解决 |
|
||||
|---|---|---|
|
||||
| 有缓存还去采集(Google 429 刷屏) | UI 判断只看 design_briefs,忽略 collected | v60+ 已修:有 collected 即缓存模式,绝不触发 seed/fetch |
|
||||
| Google 429 / SSL EOF | 限流 | 换 VPN 节点;已采集后运行走缓存不再碰 Google |
|
||||
| 三图合成全部超时 | 并发过高压垮网关 / 底图过大 | 并发上限 5 + 输入图压缩 <2MB + 退避重试 |
|
||||
| 生成设计全是商标侵权 | review 简报未魔改 | v57+ 自动注入 REVIEW_REBRAND_HINT |
|
||||
| 内容政策拦截频繁 | 提示词含敏感词/安全规则段/背景描述 | sanitize_image_prompt 自动清理 |
|
||||
| 设计稿不透明(RGB 白底) | product 后端未配 background | `product.background: transparent` |
|
||||
| 标题 400 | 模型不支持图片输入(非视觉模型) | 换 qwen-vl 系列视觉模型 |
|
||||
| 模特找不到 | material_library 拷贝不全 / avif 不识别 | 全量拷贝;IMG_EXTS 已含 avif/gif/tiff |
|
||||
| 生成的设计 6 个重复 | compose 只生成 safe 简报的设计 | v48+ 为全部简报(含 review)生成设计 |
|
||||
|
||||
---
|
||||
|
||||
## 11. 开发环境
|
||||
|
||||
```bash
|
||||
python -m venv .venv
|
||||
.venv/Scripts/pip install -r requirements.txt # 或 uv sync(uv.lock 已锁定)
|
||||
# 环境变量:LLM_API_KEY / LLM_BASE_URL / OSS_ACCESS_KEY_ID / OSS_ACCESS_KEY_SECRET
|
||||
```
|
||||
|
||||
**对接新国家一句话总结**:`configs/countries/<CC>.yaml`(种子词)+ `prompts/<CC>/`(提示词)+ `holidays.py`(节日)+ `config.yaml countries 列表` + UI 国家下拉 + 模板站点映射 → mock 跑通 → 真 LLM 验证。
|
||||
Reference in New Issue
Block a user