14 KiB
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:
countries:
- US
- GB
- JP
- AU
- MX
- DE # ← 新增
3.2 每国配置 configs/countries/DE.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:extra_style_rules: [...] # 该国风格倾向(配色/构图/审美) extra_blacklist: [...] # 该国合规红线词(德国:纳粹符号等)
3.4 节假日 graph/seeds/holidays.py
_HOLIDAYS_BY_COUNTRY 增加国家节日(名称/月/日/规则/窗口),节日种子词自动带权重 3.0 进入统一池:
"DE": [
("Oktoberfest", 9, 21, "third_saturday", 30), # 啤酒节(9 月)
("Weihnachten", 12, 25, "fixed", 25), # 圣诞节
...
]
3.5 国家模板站点校验 ui_app.py
_check_template_site 的 country_sites 字典加国家→站点关键词:
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 验证清单
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. 合规红线(最重要)
- review 判定:screen 阶段 LLM 判定疑似商标/版权/真实人物 →
risk_level=review;openai 模式下生成设计时自动注入原创化魔改引导(REVIEW_REBRAND_HINT:只做风格参考、禁止复刻 logo/商标/角色、换名换细节) - 提示词清洗
sanitize_image_prompt(生成设计前必过):- 删除一切背景描述(透明背景由参数控制)
- 删除内容策略触发段(
any text must be safe: no politics/religion/hate/violence/sexual…) - 21+ 个敏感词安全替换(skull→smiley mascot、gun→star…)
- 各国红线:美国慎政治/宗教;德国慎纳粹符号(
aesthetics.yaml extra_blacklist扩展);中东整体保守;真实人物一律不进 - 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)
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. 打包发布(每版流程)
# 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. 开发环境
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 验证。