"""LLM 后端抽象接口(可插拔核心)。 新增一个 LLM 后端只需:① 继承 LLMBackend 实现 screen();② 在 graph/llms/__init__.py 的 LLM_BACKENDS 注册表里登记。config 的 ``llm_screen.provider`` 选择用哪个。 """ from abc import ABC, abstractmethod from typing import Any, Dict, List class LLMBackend(ABC): #: 注册名(与 config.llm_screen.provider 对应) name: str = "base" @abstractmethod def screen( self, topics: List[str], country: str, aesthetic_hint: str, system_prompt: str, blacklist: List[str], batch_size: int = 12, ) -> List[Dict[str, Any]]: """对一批话题做合规筛查 + 结构化四要素提取,返回列表。 每条结构(与旧 llm_screen.screen_combined 的 screened 一致): { "topic": <原始话题>, "safe_for_print": bool, "risk_level": "safe" | "review" | "blocked", "risk_reasons": [str], "suitable_for_print": bool, "design_category": "Style"|"Meme"|"Event"|"Niche"|"Pattern"|"Quote"|"Failed", "concept": <中文概念, 1 句>, "motif": <英文主体>, "art_style": <英文风格>, "color_palette": <英文配色>, "composition": <英文构图>, "negative_prompt": <负向>, "confidence": 0-1, } 实现内部必须处理调用失败/超时,失败时抛出异常由节点降级逻辑接管(或直接返回兜底结果)。 """ raise NotImplementedError @abstractmethod def generate_seeds(self, context: Dict[str, Any]) -> Dict[str, Any]: """根据上下文(trending 派生 / 历史热点 / 月份节日)生成 Google Trends 相关查询种子词。 返回 {"style_seeds": [str], "related_seeds": [str]}。 context 字段:country, trending_seeds, history_hotspots, season, month_themes, upcoming_holidays。 实现内部必须处理调用失败/超时,失败时抛异常由 seed_node 降级逻辑接管。 """ raise NotImplementedError