Files
pod_trend_agent/graph/seeds/dynamic_strategy.py
T
3218485270 f493bde8a9 POD 趋势感知 Agent:缓存热点模式 + 三图合成 + 热点去重/风格去重 + review 兜底
- 缓存热点批量流程(有采集缓存不触发 Google)
- 简报不足直接从采集缓存生成(轻量补齐)
- 三图合成(模特/印花/底图)+ 底图压缩 <2MB
- 热点去重→风格去重自动切换 + 不适合类目 review 兜底
- 透明背景(background=transparent)+ 提示词清洗(敏感词/背景描述)
- 任务前 basemap 校验 + 模板国家校验 + 模特任务级分配
2026-08-22 14:14:01 +08:00

112 lines
4.9 KiB
Python
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.
"""动态策略:以 yaml 静态种子为基础,叠加动态种子(统一池 + 加权随机 + 用完全用)。
种子词机制(v49 起):
1. 全部类型放一起(统一池):静态 style + 静态 related + 月份主题 + 节日 + LLM 动态
——合并去重(跨类型同词只保留一个,权重累加 = 多来源更受重视);
2. 节日种子词提供权重:节日权重 3.0 > 月份主题 2.0 > 静态/动态 1.0,随机抽取时加权;
3. 每次随机取:从池中按权重随机抽取(不重复),limit 内数量;
4. 用完全用:池中种子数 ≤ 需要数时全部使用(不再随机限量/截断);
5. 每个国家独立配置:configs/countries/<country>.yaml 的 style.seeds / related.seed_keywords。
limit 由 seed_node 从 context 注入(max_style_seeds / max_related_seeds0 或缺失=不限)。
LLM 后端生成失败时自动回退到静态+节日主题,保证不中断。
"""
import random
from typing import Any, Dict, List
from .base import SeedStrategy
def _weighted_sample(pool: List[Dict[str, Any]], k: int) -> List[Dict[str, Any]]:
"""按权重随机不重复取 k 个;池数量 ≤ k(或用完)时全部返回(不随机限量)。"""
if k <= 0 or len(pool) <= k:
return list(pool)
out: List[Dict[str, Any]] = []
rest = list(pool)
for _ in range(k):
weights = [max(float(it["weight"]), 0.0) for it in rest]
if sum(weights) <= 0:
out.extend(rest)
break
idx = random.choices(range(len(rest)), weights=weights)[0]
out.append(rest.pop(idx))
return out
class DynamicStrategy(SeedStrategy):
name = "dynamic"
def resolve(
self,
country: str,
cc: Dict[str, Any],
context: Dict[str, Any],
llm_backend: Any = None,
) -> Dict[str, Any]:
base_style = list((cc.get("style", {}) or {}).get("seeds", []) or [])
base_related = list((cc.get("related", {}) or {}).get("seed_keywords", []) or [])
month_style = list(context.get("month_themes", []) or [])
holidays = list(context.get("upcoming_holidays", []) or [])
holiday_style = [f"{h.lower()} aesthetic" for h in holidays]
# 节日主题同时扩充 related 源(提高节日权重 + 增加 related 扩展)
holiday_related = [f"{h.lower()} tee" if not h.lower().endswith("day") else f"{h.lower()} gift"
for h in holidays]
# LLM 动态种子(失败回退,不影响静态/节日)
dyn_style: List[str] = []
dyn_related: List[str] = []
if llm_backend is not None and hasattr(llm_backend, "generate_seeds"):
try:
res = llm_backend.generate_seeds(context) or {}
dyn_style = list(res.get("style_seeds", []) or [])
dyn_related = list(res.get("related_seeds", []) or [])
except Exception as e: # noqa: BLE001
print(f"[seed] LLM 生成种子失败,仅用静态+节日主题: {e}")
# 1) 统一池:全部类型合并,跨类型去重(同词权重累加 = 多来源更受重视)
pool: Dict[str, Dict[str, Any]] = {}
def add(items: List[str], weight: float, src: str) -> None:
for it in items:
it = (it or "").strip()
if not it:
continue
key = it.lower()
if key in pool:
pool[key]["weight"] += weight
pool[key]["sources"].append(src)
else:
pool[key] = {"word": it, "weight": weight, "sources": [src]}
add(base_style, 1.0, "static")
add(base_related, 1.0, "static")
add(month_style, 2.0, "month")
add(holiday_style, 3.0, "holiday")
add(holiday_related, 3.0, "holiday")
add(dyn_style, 1.0, "dynamic")
add(dyn_related, 1.0, "dynamic")
items = list(pool.values())
limit_style = int(context.get("max_style_seeds") or 0)
limit_related = int(context.get("max_related_seeds") or 0)
# 2) 每次随机取(加权,不重复);池不足 → 全部用
style_pick = _weighted_sample(items, limit_style)
style_keys = {id(it) for it in style_pick}
remaining = [it for it in items if id(it) not in style_keys]
related_pick = _weighted_sample(remaining, limit_related)
return {
"style_seeds": [it["word"] for it in style_pick],
"related_seeds": [it["word"] for it in related_pick],
"dynamic": True,
"pool_size": len(items),
"pool": [it["word"] for it in items],
"llm_style_seeds": dyn_style,
"llm_related_seeds": dyn_related,
"holiday_style_seeds": holiday_style,
"holiday_related_seeds": holiday_related,
"static_style_seeds": base_style,
"static_related_seeds": base_related,
}