""" services/content_template.py 内容模板系统 — 管理和应用创作模板 """ import json import os import logging logger = logging.getLogger("autobot") TEMPLATES_FILE = "templates.json" # 内置默认模板 (templates.json 不存在时使用) DEFAULT_TEMPLATES = [ { "name": "好物种草", "description": "适合分享好用的产品和购物推荐", "topic_pattern": "", "style": "好物种草", "prompt_override": "请以真实使用者的口吻分享产品体验,突出个人感受和使用前后对比,避免像广告文案。", "tags_preset": ["好物推荐", "真实测评", "分享好物"], }, { "name": "日常分享", "description": "记录日常生活点滴、感悟和心情", "topic_pattern": "", "style": "日常分享", "prompt_override": "请以轻松随意的语气记录生活日常,像发朋友圈那样自然,多用短句和口语化表达。", "tags_preset": ["日常", "生活记录", "碎碎念"], }, { "name": "攻略教程", "description": "分享经验技巧、教程和攻略指南", "topic_pattern": "", "style": "攻略教程", "prompt_override": "请以过来人的身份分享干货经验,用分步骤的方式让读者易懂,加入踩坑经历增加可信度。", "tags_preset": ["干货分享", "经验", "保姆级教程"], }, ] class ContentTemplate: """ 内容模板管理器 从 xhs_workspace/templates.json 加载模板, 文件不存在时使用内置默认模板。 """ def __init__(self, workspace_dir: str = "xhs_workspace"): self.workspace_dir = workspace_dir self.templates_path = os.path.join(workspace_dir, TEMPLATES_FILE) self._templates: list[dict] = self._load_templates() def _load_templates(self) -> list[dict]: """加载模板列表""" if os.path.exists(self.templates_path): try: with open(self.templates_path, "r", encoding="utf-8") as f: templates = json.load(f) if isinstance(templates, list) and templates: logger.info("已从 %s 加载 %d 个模板", self.templates_path, len(templates)) return templates except (json.JSONDecodeError, IOError) as e: logger.warning("模板文件加载失败,使用默认模板: %s", e) logger.info("使用内置默认模板 (%d 个)", len(DEFAULT_TEMPLATES)) return list(DEFAULT_TEMPLATES) def save_templates(self): """将当前模板保存到文件""" try: os.makedirs(self.workspace_dir, exist_ok=True) with open(self.templates_path, "w", encoding="utf-8") as f: json.dump(self._templates, f, ensure_ascii=False, indent=2) logger.info("模板已保存到 %s", self.templates_path) except IOError as e: logger.error("模板保存失败: %s", e) @property def templates(self) -> list[dict]: """获取所有模板""" return self._templates def get_template_names(self) -> list[str]: """获取模板名称列表""" return [t.get("name", "未命名") for t in self._templates] def get_template(self, name: str) -> dict | None: """按名称获取模板""" for t in self._templates: if t.get("name") == name: return t return None def apply_template(self, template_name: str) -> dict: """ 应用模板,返回用于文案生成的参数覆盖 Returns: dict with keys: - style: str - prompt_override: str (附加到 LLM prompt 的额外指令) - tags_preset: list[str] (标签默认值) """ template = self.get_template(template_name) if not template: logger.warning("模板 '%s' 不存在,返回空覆盖", template_name) return {"style": "", "prompt_override": "", "tags_preset": []} return { "style": template.get("style", ""), "prompt_override": template.get("prompt_override", ""), "tags_preset": template.get("tags_preset", []), } def add_template(self, template: dict): """添加新模板""" required_fields = {"name", "description", "style"} if not required_fields.issubset(template.keys()): raise ValueError(f"模板缺少必要字段: {required_fields - template.keys()}") self._templates.append(template) self.save_templates() def remove_template(self, name: str) -> bool: """删除模板""" before = len(self._templates) self._templates = [t for t in self._templates if t.get("name") != name] if len(self._templates) < before: self.save_templates() return True return False