{ "file_path": "travel-algorithms/travel_algorithms/poster_generation/text_generator.py", "file_size": 15888, "line_count": 529, "functions": [ { "name": "__init__", "line_start": 25, "line_end": 49, "args": [ { "name": "self" }, { "name": "config", "type_hint": "AlgorithmConfig" }, { "name": "ai_service", "type_hint": "AIService" }, { "name": "prompt_manager", "type_hint": "PromptManager" }, { "name": "json_processor", "type_hint": "JSONProcessor" } ], "return_type": null, "docstring": "初始化文本生成器\n\nArgs:\n config: 算法配置\n ai_service: AI服务\n prompt_manager: 提示词管理器\n json_processor: JSON处理器", "is_async": false, "decorators": [], "code": " def __init__(\n self, \n config: AlgorithmConfig, \n ai_service: AIService,\n prompt_manager: PromptManager,\n json_processor: JSONProcessor\n ):\n \"\"\"\n 初始化文本生成器\n\n Args:\n config: 算法配置\n ai_service: AI服务\n prompt_manager: 提示词管理器\n json_processor: JSON处理器\n \"\"\"\n self.config = config\n self.ai_service = ai_service\n self.prompt_manager = prompt_manager\n self.json_processor = json_processor\n \n # 获取任务特定的模型配置\n self.task_model_config = config.ai_model.get_task_config(\"poster_generation\")\n \n logger.info(\"海报文本生成器初始化完成\")", "code_hash": "15b338066890e13ec89a2fd8eda25792" }, { "name": "_get_poster_system_prompt", "line_start": 158, "line_end": 177, "args": [ { "name": "self" } ], "return_type": "str", "docstring": "获取海报生成的系统提示词", "is_async": false, "decorators": [], "code": " def _get_poster_system_prompt(self) -> str:\n \"\"\"获取海报生成的系统提示词\"\"\"\n try:\n # 尝试从文件加载\n return self.prompt_manager.get_prompt(\"poster_generation\", \"system\")\n except:\n # 使用默认提示词\n return \"\"\"你是一个专业的海报文案创作者,专门为旅游、美食、生活方式等主题创作吸引人的海报文案。\n\n你的任务是根据给定的主题信息,创作适合海报展示的文案内容,包括:\n1. 吸引人的标题(简洁有力,15字以内)\n2. 核心内容描述(生动形象,突出亮点)\n3. 相关标签(3-5个关键词)\n4. 行动召唤语句(激发用户行动)\n\n要求:\n- 文案要有感染力和画面感\n- 适合目标受众的语言风格\n- 突出主题的独特价值\n- 符合海报的视觉传达需求\"\"\"", "code_hash": "020636f01d802e8b218c8759f9900dcb" }, { "name": "_get_vibrant_system_prompt", "line_start": 179, "line_end": 208, "args": [ { "name": "self" } ], "return_type": "str", "docstring": "获取Vibrant模板专用的系统提示词", "is_async": false, "decorators": [], "code": " def _get_vibrant_system_prompt(self) -> str:\n \"\"\"获取Vibrant模板专用的系统提示词\"\"\"\n return \"\"\"你是一名专业的海报设计师,专门设计宣传海报。你现在要根据用户提供的信息,生成适合Vibrant模板的海报内容。\n\n## Vibrant模板特点:\n- 单图背景,毛玻璃渐变效果\n- 两栏布局(左栏内容,右栏价格)\n- 适合展示套餐内容和价格信息\n\n## 你需要生成的数据结构包含以下字段:\n\n**必填字段:**\n1. `title`: 主标题(8-12字符,体现产品特色)\n2. `slogan`: 副标题/宣传语(10-20字符,吸引人的描述)\n3. `price`: 价格数字(纯数字,不含符号),如果材料中没有价格,则用\"欢迎咨询\"替代\n4. `ticket_type`: 票种类型(如\"成人票\"、\"套餐票\"、\"夜场票\"等)\n5. `content_button`: 内容按钮文字(通常为\"套餐内容\"、\"包含项目\"等)\n6. `content_items`: 套餐内容列表(3-5个项目,每项5-15字符,不要只包含项目名称,要做合适的美化,可以适当省略)\n\n**可选字段:**\n7. `remarks`: 备注信息(1-3条,每条10-20字符)\n8. `tag`: 标签(1条, 如\"#限时优惠\"等)\n9. `pagination`: 分页信息(如\"1/3\",可为空)\n\n## 内容创作要求:\n1. 套餐内容要具体实用:明确说明包含的服务、时间、数量\n2. 价格要有吸引力:突出性价比和优惠信息\n\n## 输出格式:\n请严格按照JSON格式输出,不要有任何额外内容。\"\"\"", "code_hash": "381b1b84d0827b5b7971483267f67d6a" }, { "name": "_build_user_prompt", "line_start": 210, "line_end": 249, "args": [ { "name": "self" }, { "name": "topic_info", "type_hint": "str" }, { "name": "style", "type_hint": "str" }, { "name": "target_audience", "type_hint": "str" }, { "name": "poster_type", "type_hint": "str" } ], "return_type": "str", "docstring": "构建用户提示词", "is_async": false, "decorators": [], "code": " def _build_user_prompt(\n self,\n topic_info: str,\n style: str,\n target_audience: str,\n poster_type: str,\n **kwargs\n ) -> str:\n \"\"\"构建用户提示词\"\"\"\n \n user_prompt_template = \"\"\"请为以下主题创作海报文案:\n\n### 主题信息\n{topic_info}\n\n### 创作要求\n- 文案风格:{style}\n- 目标受众:{target_audience}\n- 海报类型:{poster_type}\n\n### 额外要求\n{additional_requirements}\n\n请按照以下JSON格式输出:\n{\n \"title\": \"海报标题(15字以内)\",\n \"content\": \"主要内容描述\",\n \"tags\": [\"标签1\", \"标签2\", \"标签3\"],\n \"call_to_action\": \"行动召唤语句\"\n}\"\"\"\n\n additional_requirements = self._format_additional_requirements(kwargs)\n \n return user_prompt_template.format(\n topic_info=topic_info,\n style=style,\n target_audience=target_audience,\n poster_type=poster_type,\n additional_requirements=additional_requirements\n )", "code_hash": "84412467535b14d3540aec6efdb7b7db" }, { "name": "_build_vibrant_user_prompt", "line_start": 251, "line_end": 264, "args": [ { "name": "self" }, { "name": "scenic_info", "type_hint": "str" }, { "name": "product_info", "type_hint": "str" }, { "name": "tweet_info", "type_hint": "str" } ], "return_type": "str", "docstring": "构建Vibrant模板专用的用户提示词", "is_async": false, "decorators": [], "code": " def _build_vibrant_user_prompt(self, scenic_info: str, product_info: str, tweet_info: str) -> str:\n \"\"\"构建Vibrant模板专用的用户提示词\"\"\"\n return f\"\"\"请根据以下信息,生成适合在旅游海报上展示的文案:\n\n## 景区信息\n{scenic_info}\n\n## 产品信息\n{product_info}\n\n## 推文信息\n{tweet_info if tweet_info else \"无\"}\n\n请提取关键信息并整合成一个JSON对象,包含title、slogan、price、ticket_type、content_items、remarks和tag字段。\"\"\"", "code_hash": "3d5c1619b583f73645577dc7e23ea4c7" }, { "name": "_format_additional_requirements", "line_start": 266, "line_end": 286, "args": [ { "name": "self" }, { "name": "kwargs", "type_hint": "Dict[str, Any]" } ], "return_type": "str", "docstring": "格式化额外要求", "is_async": false, "decorators": [], "code": " def _format_additional_requirements(self, kwargs: Dict[str, Any]) -> str:\n \"\"\"格式化额外要求\"\"\"\n requirements = []\n \n if kwargs.get(\"color_theme\"):\n requirements.append(f\"- 配色主题:{kwargs['color_theme']}\")\n \n if kwargs.get(\"mood\"):\n requirements.append(f\"- 情感氛围:{kwargs['mood']}\")\n \n if kwargs.get(\"key_points\"):\n key_points = kwargs['key_points']\n if isinstance(key_points, list):\n requirements.append(f\"- 重点突出:{', '.join(key_points)}\")\n else:\n requirements.append(f\"- 重点突出:{key_points}\")\n \n if kwargs.get(\"length_preference\"):\n requirements.append(f\"- 文案长度:{kwargs['length_preference']}\")\n\n return \"\\n\".join(requirements) if requirements else \"无特殊要求\"", "code_hash": "b0a04b1118b2f21e03b4951e75cc6318" }, { "name": "_parse_poster_content", "line_start": 288, "line_end": 306, "args": [ { "name": "self" }, { "name": "raw_content", "type_hint": "str" } ], "return_type": "Dict[str, Any]", "docstring": "解析海报内容生成结果", "is_async": false, "decorators": [], "code": " def _parse_poster_content(self, raw_content: str) -> Dict[str, Any]:\n \"\"\"解析海报内容生成结果\"\"\"\n try:\n # 使用JSON处理器解析\n parsed_data = self.json_processor.parse_llm_output(\n raw_output=raw_content,\n expected_fields=[\"title\", \"content\", \"tags\", \"call_to_action\"],\n required_fields=[\"title\", \"content\"]\n )\n \n if isinstance(parsed_data, dict):\n return parsed_data\n else:\n logger.warning(\"解析结果不是字典格式,使用回退方案\")\n return self._extract_content_from_text(raw_content)\n \n except Exception as e:\n logger.warning(f\"JSON解析失败,使用文本提取: {e}\")\n return self._extract_content_from_text(raw_content)", "code_hash": "efaaad594972eb16fe02238f789cbed1" }, { "name": "_parse_vibrant_content", "line_start": 308, "line_end": 329, "args": [ { "name": "self" }, { "name": "raw_content", "type_hint": "str" } ], "return_type": "Dict[str, Any]", "docstring": "解析Vibrant模板专用内容", "is_async": false, "decorators": [], "code": " def _parse_vibrant_content(self, raw_content: str) -> Dict[str, Any]:\n \"\"\"解析Vibrant模板专用内容\"\"\"\n try:\n # 使用JSON处理器解析,指定Vibrant的字段\n expected_fields = [\"title\", \"slogan\", \"price\", \"ticket_type\", \"content_button\", \"content_items\"]\n required_fields = [\"title\", \"slogan\", \"price\", \"ticket_type\", \"content_items\"]\n \n parsed_data = self.json_processor.parse_llm_output(\n raw_output=raw_content,\n expected_fields=expected_fields + [\"remarks\", \"tag\", \"pagination\"],\n required_fields=required_fields\n )\n \n if isinstance(parsed_data, dict):\n return self._normalize_vibrant_content(parsed_data)\n else:\n logger.warning(\"解析结果不是字典格式,使用回退方案\")\n return self._create_fallback_vibrant_content()\n \n except Exception as e:\n logger.warning(f\"Vibrant内容解析失败,使用回退方案: {e}\")\n return self._create_fallback_vibrant_content()", "code_hash": "babcecb24f8b0ec4280825b32ca658c0" }, { "name": "_normalize_vibrant_content", "line_start": 331, "line_end": 360, "args": [ { "name": "self" }, { "name": "parsed_data", "type_hint": "Dict[str, Any]" } ], "return_type": "Dict[str, Any]", "docstring": "标准化Vibrant内容格式", "is_async": false, "decorators": [], "code": " def _normalize_vibrant_content(self, parsed_data: Dict[str, Any]) -> Dict[str, Any]:\n \"\"\"标准化Vibrant内容格式\"\"\"\n normalized = {\n # 必填字段\n \"title\": parsed_data.get(\"title\", \"精彩旅程\"),\n \"slogan\": parsed_data.get(\"slogan\", \"发现世界的美好\"),\n \"price\": str(parsed_data.get(\"price\", \"欢迎咨询\")),\n \"ticket_type\": parsed_data.get(\"ticket_type\", \"门票\"),\n \"content_button\": parsed_data.get(\"content_button\", \"套餐内容\"),\n \"content_items\": parsed_data.get(\"content_items\", [\"精彩体验项目\"]),\n \n # 可选字段\n \"remarks\": parsed_data.get(\"remarks\", []),\n \"tag\": parsed_data.get(\"tag\", \"\"),\n \"pagination\": parsed_data.get(\"pagination\", \"\")\n }\n \n # 确保content_items是列表\n if isinstance(normalized[\"content_items\"], str):\n normalized[\"content_items\"] = [normalized[\"content_items\"]]\n \n # 确保remarks是列表\n if isinstance(normalized[\"remarks\"], str):\n normalized[\"remarks\"] = [normalized[\"remarks\"]]\n \n # 限制列表长度\n normalized[\"content_items\"] = normalized[\"content_items\"][:5]\n normalized[\"remarks\"] = normalized[\"remarks\"][:3]\n \n return normalized", "code_hash": "d1d0680c8f3c18adea98d7865c839020" }, { "name": "_create_fallback_vibrant_content", "line_start": 362, "line_end": 378, "args": [ { "name": "self" } ], "return_type": "Dict[str, Any]", "docstring": "创建Vibrant模板的回退内容", "is_async": false, "decorators": [], "code": " def _create_fallback_vibrant_content(self) -> Dict[str, Any]:\n \"\"\"创建Vibrant模板的回退内容\"\"\"\n return {\n \"title\": \"精彩旅程体验\",\n \"slogan\": \"探索世界的无限可能\",\n \"price\": \"欢迎咨询\",\n \"ticket_type\": \"体验票\",\n \"content_button\": \"套餐内容\",\n \"content_items\": [\n \"专业导游服务\",\n \"精美旅游纪念品\",\n \"全程保险保障\"\n ],\n \"remarks\": [\"请提前预约\", \"节假日价格另议\"],\n \"tag\": \"#精彩体验\",\n \"pagination\": \"\"\n }", "code_hash": "8f8b25a2a9eb148e87d59918adb56a03" }, { "name": "_extract_content_from_text", "line_start": 380, "line_end": 413, "args": [ { "name": "self" }, { "name": "text", "type_hint": "str" } ], "return_type": "Dict[str, Any]", "docstring": "从文本中提取海报内容(回退方案)", "is_async": false, "decorators": [], "code": " def _extract_content_from_text(self, text: str) -> Dict[str, Any]:\n \"\"\"从文本中提取海报内容(回退方案)\"\"\"\n lines = text.strip().split('\\n')\n \n # 简单的文本解析逻辑\n title = \"\"\n content = \"\"\n tags = []\n call_to_action = \"\"\n \n for line in lines:\n line = line.strip()\n if not line:\n continue\n \n if len(line) <= 20 and not title:\n # 可能是标题\n title = line\n elif '#' in line:\n # 可能是标签\n tags = [tag.strip() for tag in line.replace('#', '').split() if tag.strip()]\n elif not content and len(line) > 10:\n # 可能是主要内容\n content = line\n elif len(line) <= 15 and ('!' in line or '!' in line):\n # 可能是行动召唤\n call_to_action = line\n\n return {\n \"title\": title or \"精彩旅程\",\n \"content\": content or text[:100],\n \"tags\": tags or [\"旅行\", \"探索\"],\n \"call_to_action\": call_to_action or \"立即体验!\"\n }", "code_hash": "763a2eec02d8d8e087f30dec4b6dac89" }, { "name": "_validate_and_enhance_content", "line_start": 415, "line_end": 445, "args": [ { "name": "self" }, { "name": "content", "type_hint": "Dict[str, Any]" }, { "name": "topic_info", "type_hint": "str" } ], "return_type": "Dict[str, Any]", "docstring": "验证和增强海报内容", "is_async": false, "decorators": [], "code": " def _validate_and_enhance_content(\n self, \n content: Dict[str, Any], \n topic_info: str\n ) -> Dict[str, Any]:\n \"\"\"验证和增强海报内容\"\"\"\n \n # 确保所有必需字段存在\n validated_content = {\n \"title\": content.get(\"title\", \"精彩旅程\")[:15], # 限制标题长度\n \"content\": content.get(\"content\", topic_info),\n \"tags\": content.get(\"tags\", [\"旅行\"]),\n \"call_to_action\": content.get(\"call_to_action\", \"立即体验!\")\n }\n \n # 确保标签是列表格式\n if isinstance(validated_content[\"tags\"], str):\n validated_content[\"tags\"] = [tag.strip() for tag in validated_content[\"tags\"].split(\",\")]\n \n # 限制标签数量\n validated_content[\"tags\"] = validated_content[\"tags\"][:5]\n \n # 添加元数据\n validated_content[\"metadata\"] = {\n \"word_count\": len(validated_content[\"content\"]),\n \"tag_count\": len(validated_content[\"tags\"]),\n \"generated_for\": topic_info,\n \"generation_config\": self.task_model_config\n }\n \n return validated_content", "code_hash": "563d25f62c01c8605e21730c470242fe" }, { "name": "get_style_suggestions", "line_start": 501, "line_end": 530, "args": [ { "name": "self" }, { "name": "poster_type", "type_hint": "str" }, { "name": "target_audience", "type_hint": "str" } ], "return_type": "List[str]", "docstring": "根据海报类型和目标受众获取风格建议\n\nArgs:\n poster_type: 海报类型\n target_audience: 目标受众\n\nReturns:\n 风格建议列表", "is_async": false, "decorators": [], "code": " def get_style_suggestions(self, poster_type: str, target_audience: str) -> List[str]:\n \"\"\"\n 根据海报类型和目标受众获取风格建议\n\n Args:\n poster_type: 海报类型\n target_audience: 目标受众\n\n Returns:\n 风格建议列表\n \"\"\"\n style_mapping = {\n \"旅游宣传\": {\n \"年轻人\": [\"活泼有趣\", \"激情澎湃\", \"个性时尚\"],\n \"家庭\": [\"温馨感人\", \"亲切自然\", \"安全舒适\"],\n \"商务人士\": [\"优雅文艺\", \"简洁干练\", \"品质生活\"]\n },\n \"美食推荐\": {\n \"年轻人\": [\"诱人美味\", \"时尚潮流\", \"分享快乐\"],\n \"家庭\": [\"家常温馨\", \"营养健康\", \"团圆美好\"],\n \"美食爱好者\": [\"精致品味\", \"传统文化\", \"匠心工艺\"]\n },\n \"活动宣传\": {\n \"年轻人\": [\"活力四射\", \"激情参与\", \"社交互动\"],\n \"全年龄\": [\"欢乐共享\", \"文化体验\", \"意义深远\"],\n \"专业人士\": [\"高端品质\", \"网络建设\", \"知识分享\"]\n }\n }\n \n return style_mapping.get(poster_type, {}).get(target_audience, [\"活泼有趣\", \"简洁明快\"]) ", "code_hash": "31c20e0f78120979c69d8fbea46d5233" } ], "classes": [ { "name": "TextGenerator", "line_start": 19, "line_end": 530, "bases": [], "methods": [ { "name": "__init__", "line_start": 25, "line_end": 49, "args": [ { "name": "self" }, { "name": "config", "type_hint": "AlgorithmConfig" }, { "name": "ai_service", "type_hint": "AIService" }, { "name": "prompt_manager", "type_hint": "PromptManager" }, { "name": "json_processor", "type_hint": "JSONProcessor" } ], "return_type": null, "docstring": "初始化文本生成器\n\nArgs:\n config: 算法配置\n ai_service: AI服务\n prompt_manager: 提示词管理器\n json_processor: JSON处理器", "is_async": false, "decorators": [], "code": " def __init__(\n self, \n config: AlgorithmConfig, \n ai_service: AIService,\n prompt_manager: PromptManager,\n json_processor: JSONProcessor\n ):\n \"\"\"\n 初始化文本生成器\n\n Args:\n config: 算法配置\n ai_service: AI服务\n prompt_manager: 提示词管理器\n json_processor: JSON处理器\n \"\"\"\n self.config = config\n self.ai_service = ai_service\n self.prompt_manager = prompt_manager\n self.json_processor = json_processor\n \n # 获取任务特定的模型配置\n self.task_model_config = config.ai_model.get_task_config(\"poster_generation\")\n \n logger.info(\"海报文本生成器初始化完成\")", "code_hash": "15b338066890e13ec89a2fd8eda25792" }, { "name": "generate_poster_content", "line_start": 51, "line_end": 108, "args": [ { "name": "self" }, { "name": "topic_info", "type_hint": "str" }, { "name": "style", "type_hint": "str" }, { "name": "target_audience", "type_hint": "str" }, { "name": "poster_type", "type_hint": "str" } ], "return_type": "Dict[str, Any]", "docstring": "生成海报文案内容\n\nArgs:\n topic_info: 主题信息\n style: 文案风格\n target_audience: 目标受众\n poster_type: 海报类型\n **kwargs: 其他参数\n\nReturns:\n 生成的海报内容字典\n\nRaises:\n ContentGenerationError: 生成失败时抛出", "is_async": true, "decorators": [], "code": " async def generate_poster_content(\n self,\n topic_info: str,\n style: str = \"活泼有趣\",\n target_audience: str = \"年轻旅行者\",\n poster_type: str = \"旅游宣传\",\n **kwargs\n ) -> Dict[str, Any]:\n \"\"\"\n 生成海报文案内容\n\n Args:\n topic_info: 主题信息\n style: 文案风格\n target_audience: 目标受众\n poster_type: 海报类型\n **kwargs: 其他参数\n\n Returns:\n 生成的海报内容字典\n\n Raises:\n ContentGenerationError: 生成失败时抛出\n \"\"\"\n try:\n logger.info(f\"开始生成海报文案,主题: {topic_info}\")\n\n # 1. 构建提示词\n system_prompt = self._get_poster_system_prompt()\n user_prompt = self._build_user_prompt(\n topic_info=topic_info,\n style=style,\n target_audience=target_audience,\n poster_type=poster_type,\n **kwargs\n )\n\n # 2. 调用AI生成\n content, input_tokens, output_tokens, elapsed_time = await self.ai_service.generate_text(\n system_prompt=system_prompt,\n user_prompt=user_prompt,\n stage=\"海报文案生成\",\n **self.task_model_config\n )\n\n # 3. 解析结果\n poster_content = self._parse_poster_content(content)\n\n # 4. 验证和增强内容\n validated_content = self._validate_and_enhance_content(poster_content, topic_info)\n\n logger.info(\"海报文案生成完成\")\n return validated_content\n\n except Exception as e:\n error_msg = f\"海报文案生成失败: {str(e)}\"\n logger.error(error_msg, exc_info=True)\n raise ContentGenerationError(error_msg)", "code_hash": "331dbb63328ede729ea578c8b5986530" }, { "name": "generate_vibrant_content", "line_start": 110, "line_end": 156, "args": [ { "name": "self" }, { "name": "scenic_info", "type_hint": "str" }, { "name": "product_info", "type_hint": "str" }, { "name": "tweet_info", "type_hint": "str" } ], "return_type": "Dict[str, Any]", "docstring": "专门为Vibrant模板生成内容\n\nArgs:\n scenic_info: 景区信息\n product_info: 产品信息\n tweet_info: 推文信息\n **kwargs: 其他参数\n\nReturns:\n 符合Vibrant模板结构的内容字典\n\nRaises:\n ContentGenerationError: 生成失败时抛出", "is_async": true, "decorators": [], "code": " async def generate_vibrant_content(\n self,\n scenic_info: str,\n product_info: str,\n tweet_info: str = \"\",\n **kwargs\n ) -> Dict[str, Any]:\n \"\"\"\n 专门为Vibrant模板生成内容\n\n Args:\n scenic_info: 景区信息\n product_info: 产品信息\n tweet_info: 推文信息\n **kwargs: 其他参数\n\n Returns:\n 符合Vibrant模板结构的内容字典\n\n Raises:\n ContentGenerationError: 生成失败时抛出\n \"\"\"\n try:\n logger.info(\"开始生成Vibrant模板专用内容\")\n\n # 1. 构建Vibrant专用提示词\n system_prompt = self._get_vibrant_system_prompt()\n user_prompt = self._build_vibrant_user_prompt(scenic_info, product_info, tweet_info)\n\n # 2. 调用AI生成\n content, input_tokens, output_tokens, elapsed_time = await self.ai_service.generate_text(\n system_prompt=system_prompt,\n user_prompt=user_prompt,\n stage=\"Vibrant海报内容生成\",\n **self.task_model_config\n )\n\n # 3. 解析并验证Vibrant格式\n vibrant_content = self._parse_vibrant_content(content)\n\n logger.info(\"Vibrant模板内容生成完成\")\n return vibrant_content\n\n except Exception as e:\n error_msg = f\"Vibrant模板内容生成失败: {str(e)}\"\n logger.error(error_msg, exc_info=True)\n raise ContentGenerationError(error_msg)", "code_hash": "2f1ed3fc8f7368780c387f77d984a7d4" }, { "name": "_get_poster_system_prompt", "line_start": 158, "line_end": 177, "args": [ { "name": "self" } ], "return_type": "str", "docstring": "获取海报生成的系统提示词", "is_async": false, "decorators": [], "code": " def _get_poster_system_prompt(self) -> str:\n \"\"\"获取海报生成的系统提示词\"\"\"\n try:\n # 尝试从文件加载\n return self.prompt_manager.get_prompt(\"poster_generation\", \"system\")\n except:\n # 使用默认提示词\n return \"\"\"你是一个专业的海报文案创作者,专门为旅游、美食、生活方式等主题创作吸引人的海报文案。\n\n你的任务是根据给定的主题信息,创作适合海报展示的文案内容,包括:\n1. 吸引人的标题(简洁有力,15字以内)\n2. 核心内容描述(生动形象,突出亮点)\n3. 相关标签(3-5个关键词)\n4. 行动召唤语句(激发用户行动)\n\n要求:\n- 文案要有感染力和画面感\n- 适合目标受众的语言风格\n- 突出主题的独特价值\n- 符合海报的视觉传达需求\"\"\"", "code_hash": "020636f01d802e8b218c8759f9900dcb" }, { "name": "_get_vibrant_system_prompt", "line_start": 179, "line_end": 208, "args": [ { "name": "self" } ], "return_type": "str", "docstring": "获取Vibrant模板专用的系统提示词", "is_async": false, "decorators": [], "code": " def _get_vibrant_system_prompt(self) -> str:\n \"\"\"获取Vibrant模板专用的系统提示词\"\"\"\n return \"\"\"你是一名专业的海报设计师,专门设计宣传海报。你现在要根据用户提供的信息,生成适合Vibrant模板的海报内容。\n\n## Vibrant模板特点:\n- 单图背景,毛玻璃渐变效果\n- 两栏布局(左栏内容,右栏价格)\n- 适合展示套餐内容和价格信息\n\n## 你需要生成的数据结构包含以下字段:\n\n**必填字段:**\n1. `title`: 主标题(8-12字符,体现产品特色)\n2. `slogan`: 副标题/宣传语(10-20字符,吸引人的描述)\n3. `price`: 价格数字(纯数字,不含符号),如果材料中没有价格,则用\"欢迎咨询\"替代\n4. `ticket_type`: 票种类型(如\"成人票\"、\"套餐票\"、\"夜场票\"等)\n5. `content_button`: 内容按钮文字(通常为\"套餐内容\"、\"包含项目\"等)\n6. `content_items`: 套餐内容列表(3-5个项目,每项5-15字符,不要只包含项目名称,要做合适的美化,可以适当省略)\n\n**可选字段:**\n7. `remarks`: 备注信息(1-3条,每条10-20字符)\n8. `tag`: 标签(1条, 如\"#限时优惠\"等)\n9. `pagination`: 分页信息(如\"1/3\",可为空)\n\n## 内容创作要求:\n1. 套餐内容要具体实用:明确说明包含的服务、时间、数量\n2. 价格要有吸引力:突出性价比和优惠信息\n\n## 输出格式:\n请严格按照JSON格式输出,不要有任何额外内容。\"\"\"", "code_hash": "381b1b84d0827b5b7971483267f67d6a" }, { "name": "_build_user_prompt", "line_start": 210, "line_end": 249, "args": [ { "name": "self" }, { "name": "topic_info", "type_hint": "str" }, { "name": "style", "type_hint": "str" }, { "name": "target_audience", "type_hint": "str" }, { "name": "poster_type", "type_hint": "str" } ], "return_type": "str", "docstring": "构建用户提示词", "is_async": false, "decorators": [], "code": " def _build_user_prompt(\n self,\n topic_info: str,\n style: str,\n target_audience: str,\n poster_type: str,\n **kwargs\n ) -> str:\n \"\"\"构建用户提示词\"\"\"\n \n user_prompt_template = \"\"\"请为以下主题创作海报文案:\n\n### 主题信息\n{topic_info}\n\n### 创作要求\n- 文案风格:{style}\n- 目标受众:{target_audience}\n- 海报类型:{poster_type}\n\n### 额外要求\n{additional_requirements}\n\n请按照以下JSON格式输出:\n{\n \"title\": \"海报标题(15字以内)\",\n \"content\": \"主要内容描述\",\n \"tags\": [\"标签1\", \"标签2\", \"标签3\"],\n \"call_to_action\": \"行动召唤语句\"\n}\"\"\"\n\n additional_requirements = self._format_additional_requirements(kwargs)\n \n return user_prompt_template.format(\n topic_info=topic_info,\n style=style,\n target_audience=target_audience,\n poster_type=poster_type,\n additional_requirements=additional_requirements\n )", "code_hash": "84412467535b14d3540aec6efdb7b7db" }, { "name": "_build_vibrant_user_prompt", "line_start": 251, "line_end": 264, "args": [ { "name": "self" }, { "name": "scenic_info", "type_hint": "str" }, { "name": "product_info", "type_hint": "str" }, { "name": "tweet_info", "type_hint": "str" } ], "return_type": "str", "docstring": "构建Vibrant模板专用的用户提示词", "is_async": false, "decorators": [], "code": " def _build_vibrant_user_prompt(self, scenic_info: str, product_info: str, tweet_info: str) -> str:\n \"\"\"构建Vibrant模板专用的用户提示词\"\"\"\n return f\"\"\"请根据以下信息,生成适合在旅游海报上展示的文案:\n\n## 景区信息\n{scenic_info}\n\n## 产品信息\n{product_info}\n\n## 推文信息\n{tweet_info if tweet_info else \"无\"}\n\n请提取关键信息并整合成一个JSON对象,包含title、slogan、price、ticket_type、content_items、remarks和tag字段。\"\"\"", "code_hash": "3d5c1619b583f73645577dc7e23ea4c7" }, { "name": "_format_additional_requirements", "line_start": 266, "line_end": 286, "args": [ { "name": "self" }, { "name": "kwargs", "type_hint": "Dict[str, Any]" } ], "return_type": "str", "docstring": "格式化额外要求", "is_async": false, "decorators": [], "code": " def _format_additional_requirements(self, kwargs: Dict[str, Any]) -> str:\n \"\"\"格式化额外要求\"\"\"\n requirements = []\n \n if kwargs.get(\"color_theme\"):\n requirements.append(f\"- 配色主题:{kwargs['color_theme']}\")\n \n if kwargs.get(\"mood\"):\n requirements.append(f\"- 情感氛围:{kwargs['mood']}\")\n \n if kwargs.get(\"key_points\"):\n key_points = kwargs['key_points']\n if isinstance(key_points, list):\n requirements.append(f\"- 重点突出:{', '.join(key_points)}\")\n else:\n requirements.append(f\"- 重点突出:{key_points}\")\n \n if kwargs.get(\"length_preference\"):\n requirements.append(f\"- 文案长度:{kwargs['length_preference']}\")\n\n return \"\\n\".join(requirements) if requirements else \"无特殊要求\"", "code_hash": "b0a04b1118b2f21e03b4951e75cc6318" }, { "name": "_parse_poster_content", "line_start": 288, "line_end": 306, "args": [ { "name": "self" }, { "name": "raw_content", "type_hint": "str" } ], "return_type": "Dict[str, Any]", "docstring": "解析海报内容生成结果", "is_async": false, "decorators": [], "code": " def _parse_poster_content(self, raw_content: str) -> Dict[str, Any]:\n \"\"\"解析海报内容生成结果\"\"\"\n try:\n # 使用JSON处理器解析\n parsed_data = self.json_processor.parse_llm_output(\n raw_output=raw_content,\n expected_fields=[\"title\", \"content\", \"tags\", \"call_to_action\"],\n required_fields=[\"title\", \"content\"]\n )\n \n if isinstance(parsed_data, dict):\n return parsed_data\n else:\n logger.warning(\"解析结果不是字典格式,使用回退方案\")\n return self._extract_content_from_text(raw_content)\n \n except Exception as e:\n logger.warning(f\"JSON解析失败,使用文本提取: {e}\")\n return self._extract_content_from_text(raw_content)", "code_hash": "efaaad594972eb16fe02238f789cbed1" }, { "name": "_parse_vibrant_content", "line_start": 308, "line_end": 329, "args": [ { "name": "self" }, { "name": "raw_content", "type_hint": "str" } ], "return_type": "Dict[str, Any]", "docstring": "解析Vibrant模板专用内容", "is_async": false, "decorators": [], "code": " def _parse_vibrant_content(self, raw_content: str) -> Dict[str, Any]:\n \"\"\"解析Vibrant模板专用内容\"\"\"\n try:\n # 使用JSON处理器解析,指定Vibrant的字段\n expected_fields = [\"title\", \"slogan\", \"price\", \"ticket_type\", \"content_button\", \"content_items\"]\n required_fields = [\"title\", \"slogan\", \"price\", \"ticket_type\", \"content_items\"]\n \n parsed_data = self.json_processor.parse_llm_output(\n raw_output=raw_content,\n expected_fields=expected_fields + [\"remarks\", \"tag\", \"pagination\"],\n required_fields=required_fields\n )\n \n if isinstance(parsed_data, dict):\n return self._normalize_vibrant_content(parsed_data)\n else:\n logger.warning(\"解析结果不是字典格式,使用回退方案\")\n return self._create_fallback_vibrant_content()\n \n except Exception as e:\n logger.warning(f\"Vibrant内容解析失败,使用回退方案: {e}\")\n return self._create_fallback_vibrant_content()", "code_hash": "babcecb24f8b0ec4280825b32ca658c0" }, { "name": "_normalize_vibrant_content", "line_start": 331, "line_end": 360, "args": [ { "name": "self" }, { "name": "parsed_data", "type_hint": "Dict[str, Any]" } ], "return_type": "Dict[str, Any]", "docstring": "标准化Vibrant内容格式", "is_async": false, "decorators": [], "code": " def _normalize_vibrant_content(self, parsed_data: Dict[str, Any]) -> Dict[str, Any]:\n \"\"\"标准化Vibrant内容格式\"\"\"\n normalized = {\n # 必填字段\n \"title\": parsed_data.get(\"title\", \"精彩旅程\"),\n \"slogan\": parsed_data.get(\"slogan\", \"发现世界的美好\"),\n \"price\": str(parsed_data.get(\"price\", \"欢迎咨询\")),\n \"ticket_type\": parsed_data.get(\"ticket_type\", \"门票\"),\n \"content_button\": parsed_data.get(\"content_button\", \"套餐内容\"),\n \"content_items\": parsed_data.get(\"content_items\", [\"精彩体验项目\"]),\n \n # 可选字段\n \"remarks\": parsed_data.get(\"remarks\", []),\n \"tag\": parsed_data.get(\"tag\", \"\"),\n \"pagination\": parsed_data.get(\"pagination\", \"\")\n }\n \n # 确保content_items是列表\n if isinstance(normalized[\"content_items\"], str):\n normalized[\"content_items\"] = [normalized[\"content_items\"]]\n \n # 确保remarks是列表\n if isinstance(normalized[\"remarks\"], str):\n normalized[\"remarks\"] = [normalized[\"remarks\"]]\n \n # 限制列表长度\n normalized[\"content_items\"] = normalized[\"content_items\"][:5]\n normalized[\"remarks\"] = normalized[\"remarks\"][:3]\n \n return normalized", "code_hash": "d1d0680c8f3c18adea98d7865c839020" }, { "name": "_create_fallback_vibrant_content", "line_start": 362, "line_end": 378, "args": [ { "name": "self" } ], "return_type": "Dict[str, Any]", "docstring": "创建Vibrant模板的回退内容", "is_async": false, "decorators": [], "code": " def _create_fallback_vibrant_content(self) -> Dict[str, Any]:\n \"\"\"创建Vibrant模板的回退内容\"\"\"\n return {\n \"title\": \"精彩旅程体验\",\n \"slogan\": \"探索世界的无限可能\",\n \"price\": \"欢迎咨询\",\n \"ticket_type\": \"体验票\",\n \"content_button\": \"套餐内容\",\n \"content_items\": [\n \"专业导游服务\",\n \"精美旅游纪念品\",\n \"全程保险保障\"\n ],\n \"remarks\": [\"请提前预约\", \"节假日价格另议\"],\n \"tag\": \"#精彩体验\",\n \"pagination\": \"\"\n }", "code_hash": "8f8b25a2a9eb148e87d59918adb56a03" }, { "name": "_extract_content_from_text", "line_start": 380, "line_end": 413, "args": [ { "name": "self" }, { "name": "text", "type_hint": "str" } ], "return_type": "Dict[str, Any]", "docstring": "从文本中提取海报内容(回退方案)", "is_async": false, "decorators": [], "code": " def _extract_content_from_text(self, text: str) -> Dict[str, Any]:\n \"\"\"从文本中提取海报内容(回退方案)\"\"\"\n lines = text.strip().split('\\n')\n \n # 简单的文本解析逻辑\n title = \"\"\n content = \"\"\n tags = []\n call_to_action = \"\"\n \n for line in lines:\n line = line.strip()\n if not line:\n continue\n \n if len(line) <= 20 and not title:\n # 可能是标题\n title = line\n elif '#' in line:\n # 可能是标签\n tags = [tag.strip() for tag in line.replace('#', '').split() if tag.strip()]\n elif not content and len(line) > 10:\n # 可能是主要内容\n content = line\n elif len(line) <= 15 and ('!' in line or '!' in line):\n # 可能是行动召唤\n call_to_action = line\n\n return {\n \"title\": title or \"精彩旅程\",\n \"content\": content or text[:100],\n \"tags\": tags or [\"旅行\", \"探索\"],\n \"call_to_action\": call_to_action or \"立即体验!\"\n }", "code_hash": "763a2eec02d8d8e087f30dec4b6dac89" }, { "name": "_validate_and_enhance_content", "line_start": 415, "line_end": 445, "args": [ { "name": "self" }, { "name": "content", "type_hint": "Dict[str, Any]" }, { "name": "topic_info", "type_hint": "str" } ], "return_type": "Dict[str, Any]", "docstring": "验证和增强海报内容", "is_async": false, "decorators": [], "code": " def _validate_and_enhance_content(\n self, \n content: Dict[str, Any], \n topic_info: str\n ) -> Dict[str, Any]:\n \"\"\"验证和增强海报内容\"\"\"\n \n # 确保所有必需字段存在\n validated_content = {\n \"title\": content.get(\"title\", \"精彩旅程\")[:15], # 限制标题长度\n \"content\": content.get(\"content\", topic_info),\n \"tags\": content.get(\"tags\", [\"旅行\"]),\n \"call_to_action\": content.get(\"call_to_action\", \"立即体验!\")\n }\n \n # 确保标签是列表格式\n if isinstance(validated_content[\"tags\"], str):\n validated_content[\"tags\"] = [tag.strip() for tag in validated_content[\"tags\"].split(\",\")]\n \n # 限制标签数量\n validated_content[\"tags\"] = validated_content[\"tags\"][:5]\n \n # 添加元数据\n validated_content[\"metadata\"] = {\n \"word_count\": len(validated_content[\"content\"]),\n \"tag_count\": len(validated_content[\"tags\"]),\n \"generated_for\": topic_info,\n \"generation_config\": self.task_model_config\n }\n \n return validated_content", "code_hash": "563d25f62c01c8605e21730c470242fe" }, { "name": "generate_multiple_variations", "line_start": 447, "line_end": 499, "args": [ { "name": "self" }, { "name": "topic_info", "type_hint": "str" }, { "name": "num_variations", "type_hint": "int" }, { "name": "template_type", "type_hint": "str" } ], "return_type": "List[Dict[str, Any]]", "docstring": "生成多个文案变体\n\nArgs:\n topic_info: 主题信息\n num_variations: 变体数量\n template_type: 模板类型 (\"general\", \"vibrant\")\n **kwargs: 其他参数\n\nReturns:\n 文案变体列表", "is_async": true, "decorators": [], "code": " async def generate_multiple_variations(\n self,\n topic_info: str,\n num_variations: int = 3,\n template_type: str = \"general\",\n **kwargs\n ) -> List[Dict[str, Any]]:\n \"\"\"\n 生成多个文案变体\n\n Args:\n topic_info: 主题信息\n num_variations: 变体数量\n template_type: 模板类型 (\"general\", \"vibrant\")\n **kwargs: 其他参数\n\n Returns:\n 文案变体列表\n \"\"\"\n variations = []\n \n styles = [\"活泼有趣\", \"温馨感人\", \"激情澎湃\", \"优雅文艺\", \"简洁干练\"]\n \n for i in range(num_variations):\n try:\n # 使用不同的风格\n style = styles[i % len(styles)]\n \n if template_type == \"vibrant\":\n # 为Vibrant模板生成内容\n variation = await self.generate_vibrant_content(\n scenic_info=kwargs.get(\"scenic_info\", topic_info),\n product_info=kwargs.get(\"product_info\", \"\"),\n tweet_info=kwargs.get(\"tweet_info\", \"\"),\n **kwargs\n )\n else:\n # 通用海报内容\n variation = await self.generate_poster_content(\n topic_info=topic_info,\n style=style,\n **kwargs\n )\n \n variation[\"variation_id\"] = i + 1\n variation[\"style_used\"] = style\n variations.append(variation)\n \n except Exception as e:\n logger.error(f\"生成变体 {i+1} 失败: {e}\")\n continue\n \n return variations", "code_hash": "cbc98eca863ae6528a60314359f69de8" }, { "name": "get_style_suggestions", "line_start": 501, "line_end": 530, "args": [ { "name": "self" }, { "name": "poster_type", "type_hint": "str" }, { "name": "target_audience", "type_hint": "str" } ], "return_type": "List[str]", "docstring": "根据海报类型和目标受众获取风格建议\n\nArgs:\n poster_type: 海报类型\n target_audience: 目标受众\n\nReturns:\n 风格建议列表", "is_async": false, "decorators": [], "code": " def get_style_suggestions(self, poster_type: str, target_audience: str) -> List[str]:\n \"\"\"\n 根据海报类型和目标受众获取风格建议\n\n Args:\n poster_type: 海报类型\n target_audience: 目标受众\n\n Returns:\n 风格建议列表\n \"\"\"\n style_mapping = {\n \"旅游宣传\": {\n \"年轻人\": [\"活泼有趣\", \"激情澎湃\", \"个性时尚\"],\n \"家庭\": [\"温馨感人\", \"亲切自然\", \"安全舒适\"],\n \"商务人士\": [\"优雅文艺\", \"简洁干练\", \"品质生活\"]\n },\n \"美食推荐\": {\n \"年轻人\": [\"诱人美味\", \"时尚潮流\", \"分享快乐\"],\n \"家庭\": [\"家常温馨\", \"营养健康\", \"团圆美好\"],\n \"美食爱好者\": [\"精致品味\", \"传统文化\", \"匠心工艺\"]\n },\n \"活动宣传\": {\n \"年轻人\": [\"活力四射\", \"激情参与\", \"社交互动\"],\n \"全年龄\": [\"欢乐共享\", \"文化体验\", \"意义深远\"],\n \"专业人士\": [\"高端品质\", \"网络建设\", \"知识分享\"]\n }\n }\n \n return style_mapping.get(poster_type, {}).get(target_audience, [\"活泼有趣\", \"简洁明快\"]) ", "code_hash": "31c20e0f78120979c69d8fbea46d5233" } ], "docstring": "海报文本生成器\n使用AI模型为海报生成适合的文案内容,特别支持Vibrant模板的字段结构", "decorators": [], "code": "class TextGenerator:\n \"\"\"\n 海报文本生成器\n 使用AI模型为海报生成适合的文案内容,特别支持Vibrant模板的字段结构\n \"\"\"\n\n def __init__(\n self, \n config: AlgorithmConfig, \n ai_service: AIService,\n prompt_manager: PromptManager,\n json_processor: JSONProcessor\n ):\n \"\"\"\n 初始化文本生成器\n\n Args:\n config: 算法配置\n ai_service: AI服务\n prompt_manager: 提示词管理器\n json_processor: JSON处理器\n \"\"\"\n self.config = config\n self.ai_service = ai_service\n self.prompt_manager = prompt_manager\n self.json_processor = json_processor\n \n # 获取任务特定的模型配置\n self.task_model_config = config.ai_model.get_task_config(\"poster_generation\")\n \n logger.info(\"海报文本生成器初始化完成\")\n\n async def generate_poster_content(\n self,\n topic_info: str,\n style: str = \"活泼有趣\",\n target_audience: str = \"年轻旅行者\",\n poster_type: str = \"旅游宣传\",\n **kwargs\n ) -> Dict[str, Any]:\n \"\"\"\n 生成海报文案内容\n\n Args:\n topic_info: 主题信息\n style: 文案风格\n target_audience: 目标受众\n poster_type: 海报类型\n **kwargs: 其他参数\n\n Returns:\n 生成的海报内容字典\n\n Raises:\n ContentGenerationError: 生成失败时抛出\n \"\"\"\n try:\n logger.info(f\"开始生成海报文案,主题: {topic_info}\")\n\n # 1. 构建提示词\n system_prompt = self._get_poster_system_prompt()\n user_prompt = self._build_user_prompt(\n topic_info=topic_info,\n style=style,\n target_audience=target_audience,\n poster_type=poster_type,\n **kwargs\n )\n\n # 2. 调用AI生成\n content, input_tokens, output_tokens, elapsed_time = await self.ai_service.generate_text(\n system_prompt=system_prompt,\n user_prompt=user_prompt,\n stage=\"海报文案生成\",\n **self.task_model_config\n )\n\n # 3. 解析结果\n poster_content = self._parse_poster_content(content)\n\n # 4. 验证和增强内容\n validated_content = self._validate_and_enhance_content(poster_content, topic_info)\n\n logger.info(\"海报文案生成完成\")\n return validated_content\n\n except Exception as e:\n error_msg = f\"海报文案生成失败: {str(e)}\"\n logger.error(error_msg, exc_info=True)\n raise ContentGenerationError(error_msg)\n\n async def generate_vibrant_content(\n self,\n scenic_info: str,\n product_info: str,\n tweet_info: str = \"\",\n **kwargs\n ) -> Dict[str, Any]:\n \"\"\"\n 专门为Vibrant模板生成内容\n\n Args:\n scenic_info: 景区信息\n product_info: 产品信息\n tweet_info: 推文信息\n **kwargs: 其他参数\n\n Returns:\n 符合Vibrant模板结构的内容字典\n\n Raises:\n ContentGenerationError: 生成失败时抛出\n \"\"\"\n try:\n logger.info(\"开始生成Vibrant模板专用内容\")\n\n # 1. 构建Vibrant专用提示词\n system_prompt = self._get_vibrant_system_prompt()\n user_prompt = self._build_vibrant_user_prompt(scenic_info, product_info, tweet_info)\n\n # 2. 调用AI生成\n content, input_tokens, output_tokens, elapsed_time = await self.ai_service.generate_text(\n system_prompt=system_prompt,\n user_prompt=user_prompt,\n stage=\"Vibrant海报内容生成\",\n **self.task_model_config\n )\n\n # 3. 解析并验证Vibrant格式\n vibrant_content = self._parse_vibrant_content(content)\n\n logger.info(\"Vibrant模板内容生成完成\")\n return vibrant_content\n\n except Exception as e:\n error_msg = f\"Vibrant模板内容生成失败: {str(e)}\"\n logger.error(error_msg, exc_info=True)\n raise ContentGenerationError(error_msg)\n\n def _get_poster_system_prompt(self) -> str:\n \"\"\"获取海报生成的系统提示词\"\"\"\n try:\n # 尝试从文件加载\n return self.prompt_manager.get_prompt(\"poster_generation\", \"system\")\n except:\n # 使用默认提示词\n return \"\"\"你是一个专业的海报文案创作者,专门为旅游、美食、生活方式等主题创作吸引人的海报文案。\n\n你的任务是根据给定的主题信息,创作适合海报展示的文案内容,包括:\n1. 吸引人的标题(简洁有力,15字以内)\n2. 核心内容描述(生动形象,突出亮点)\n3. 相关标签(3-5个关键词)\n4. 行动召唤语句(激发用户行动)\n\n要求:\n- 文案要有感染力和画面感\n- 适合目标受众的语言风格\n- 突出主题的独特价值\n- 符合海报的视觉传达需求\"\"\"\n\n def _get_vibrant_system_prompt(self) -> str:\n \"\"\"获取Vibrant模板专用的系统提示词\"\"\"\n return \"\"\"你是一名专业的海报设计师,专门设计宣传海报。你现在要根据用户提供的信息,生成适合Vibrant模板的海报内容。\n\n## Vibrant模板特点:\n- 单图背景,毛玻璃渐变效果\n- 两栏布局(左栏内容,右栏价格)\n- 适合展示套餐内容和价格信息\n\n## 你需要生成的数据结构包含以下字段:\n\n**必填字段:**\n1. `title`: 主标题(8-12字符,体现产品特色)\n2. `slogan`: 副标题/宣传语(10-20字符,吸引人的描述)\n3. `price`: 价格数字(纯数字,不含符号),如果材料中没有价格,则用\"欢迎咨询\"替代\n4. `ticket_type`: 票种类型(如\"成人票\"、\"套餐票\"、\"夜场票\"等)\n5. `content_button`: 内容按钮文字(通常为\"套餐内容\"、\"包含项目\"等)\n6. `content_items`: 套餐内容列表(3-5个项目,每项5-15字符,不要只包含项目名称,要做合适的美化,可以适当省略)\n\n**可选字段:**\n7. `remarks`: 备注信息(1-3条,每条10-20字符)\n8. `tag`: 标签(1条, 如\"#限时优惠\"等)\n9. `pagination`: 分页信息(如\"1/3\",可为空)\n\n## 内容创作要求:\n1. 套餐内容要具体实用:明确说明包含的服务、时间、数量\n2. 价格要有吸引力:突出性价比和优惠信息\n\n## 输出格式:\n请严格按照JSON格式输出,不要有任何额外内容。\"\"\"\n\n def _build_user_prompt(\n self,\n topic_info: str,\n style: str,\n target_audience: str,\n poster_type: str,\n **kwargs\n ) -> str:\n \"\"\"构建用户提示词\"\"\"\n \n user_prompt_template = \"\"\"请为以下主题创作海报文案:\n\n### 主题信息\n{topic_info}\n\n### 创作要求\n- 文案风格:{style}\n- 目标受众:{target_audience}\n- 海报类型:{poster_type}\n\n### 额外要求\n{additional_requirements}\n\n请按照以下JSON格式输出:\n{\n \"title\": \"海报标题(15字以内)\",\n \"content\": \"主要内容描述\",\n \"tags\": [\"标签1\", \"标签2\", \"标签3\"],\n \"call_to_action\": \"行动召唤语句\"\n}\"\"\"\n\n additional_requirements = self._format_additional_requirements(kwargs)\n \n return user_prompt_template.format(\n topic_info=topic_info,\n style=style,\n target_audience=target_audience,\n poster_type=poster_type,\n additional_requirements=additional_requirements\n )\n\n def _build_vibrant_user_prompt(self, scenic_info: str, product_info: str, tweet_info: str) -> str:\n \"\"\"构建Vibrant模板专用的用户提示词\"\"\"\n return f\"\"\"请根据以下信息,生成适合在旅游海报上展示的文案:\n\n## 景区信息\n{scenic_info}\n\n## 产品信息\n{product_info}\n\n## 推文信息\n{tweet_info if tweet_info else \"无\"}\n\n请提取关键信息并整合成一个JSON对象,包含title、slogan、price、ticket_type、content_items、remarks和tag字段。\"\"\"\n\n def _format_additional_requirements(self, kwargs: Dict[str, Any]) -> str:\n \"\"\"格式化额外要求\"\"\"\n requirements = []\n \n if kwargs.get(\"color_theme\"):\n requirements.append(f\"- 配色主题:{kwargs['color_theme']}\")\n \n if kwargs.get(\"mood\"):\n requirements.append(f\"- 情感氛围:{kwargs['mood']}\")\n \n if kwargs.get(\"key_points\"):\n key_points = kwargs['key_points']\n if isinstance(key_points, list):\n requirements.append(f\"- 重点突出:{', '.join(key_points)}\")\n else:\n requirements.append(f\"- 重点突出:{key_points}\")\n \n if kwargs.get(\"length_preference\"):\n requirements.append(f\"- 文案长度:{kwargs['length_preference']}\")\n\n return \"\\n\".join(requirements) if requirements else \"无特殊要求\"\n\n def _parse_poster_content(self, raw_content: str) -> Dict[str, Any]:\n \"\"\"解析海报内容生成结果\"\"\"\n try:\n # 使用JSON处理器解析\n parsed_data = self.json_processor.parse_llm_output(\n raw_output=raw_content,\n expected_fields=[\"title\", \"content\", \"tags\", \"call_to_action\"],\n required_fields=[\"title\", \"content\"]\n )\n \n if isinstance(parsed_data, dict):\n return parsed_data\n else:\n logger.warning(\"解析结果不是字典格式,使用回退方案\")\n return self._extract_content_from_text(raw_content)\n \n except Exception as e:\n logger.warning(f\"JSON解析失败,使用文本提取: {e}\")\n return self._extract_content_from_text(raw_content)\n\n def _parse_vibrant_content(self, raw_content: str) -> Dict[str, Any]:\n \"\"\"解析Vibrant模板专用内容\"\"\"\n try:\n # 使用JSON处理器解析,指定Vibrant的字段\n expected_fields = [\"title\", \"slogan\", \"price\", \"ticket_type\", \"content_button\", \"content_items\"]\n required_fields = [\"title\", \"slogan\", \"price\", \"ticket_type\", \"content_items\"]\n \n parsed_data = self.json_processor.parse_llm_output(\n raw_output=raw_content,\n expected_fields=expected_fields + [\"remarks\", \"tag\", \"pagination\"],\n required_fields=required_fields\n )\n \n if isinstance(parsed_data, dict):\n return self._normalize_vibrant_content(parsed_data)\n else:\n logger.warning(\"解析结果不是字典格式,使用回退方案\")\n return self._create_fallback_vibrant_content()\n \n except Exception as e:\n logger.warning(f\"Vibrant内容解析失败,使用回退方案: {e}\")\n return self._create_fallback_vibrant_content()\n\n def _normalize_vibrant_content(self, parsed_data: Dict[str, Any]) -> Dict[str, Any]:\n \"\"\"标准化Vibrant内容格式\"\"\"\n normalized = {\n # 必填字段\n \"title\": parsed_data.get(\"title\", \"精彩旅程\"),\n \"slogan\": parsed_data.get(\"slogan\", \"发现世界的美好\"),\n \"price\": str(parsed_data.get(\"price\", \"欢迎咨询\")),\n \"ticket_type\": parsed_data.get(\"ticket_type\", \"门票\"),\n \"content_button\": parsed_data.get(\"content_button\", \"套餐内容\"),\n \"content_items\": parsed_data.get(\"content_items\", [\"精彩体验项目\"]),\n \n # 可选字段\n \"remarks\": parsed_data.get(\"remarks\", []),\n \"tag\": parsed_data.get(\"tag\", \"\"),\n \"pagination\": parsed_data.get(\"pagination\", \"\")\n }\n \n # 确保content_items是列表\n if isinstance(normalized[\"content_items\"], str):\n normalized[\"content_items\"] = [normalized[\"content_items\"]]\n \n # 确保remarks是列表\n if isinstance(normalized[\"remarks\"], str):\n normalized[\"remarks\"] = [normalized[\"remarks\"]]\n \n # 限制列表长度\n normalized[\"content_items\"] = normalized[\"content_items\"][:5]\n normalized[\"remarks\"] = normalized[\"remarks\"][:3]\n \n return normalized\n\n def _create_fallback_vibrant_content(self) -> Dict[str, Any]:\n \"\"\"创建Vibrant模板的回退内容\"\"\"\n return {\n \"title\": \"精彩旅程体验\",\n \"slogan\": \"探索世界的无限可能\",\n \"price\": \"欢迎咨询\",\n \"ticket_type\": \"体验票\",\n \"content_button\": \"套餐内容\",\n \"content_items\": [\n \"专业导游服务\",\n \"精美旅游纪念品\",\n \"全程保险保障\"\n ],\n \"remarks\": [\"请提前预约\", \"节假日价格另议\"],\n \"tag\": \"#精彩体验\",\n \"pagination\": \"\"\n }\n\n def _extract_content_from_text(self, text: str) -> Dict[str, Any]:\n \"\"\"从文本中提取海报内容(回退方案)\"\"\"\n lines = text.strip().split('\\n')\n \n # 简单的文本解析逻辑\n title = \"\"\n content = \"\"\n tags = []\n call_to_action = \"\"\n \n for line in lines:\n line = line.strip()\n if not line:\n continue\n \n if len(line) <= 20 and not title:\n # 可能是标题\n title = line\n elif '#' in line:\n # 可能是标签\n tags = [tag.strip() for tag in line.replace('#', '').split() if tag.strip()]\n elif not content and len(line) > 10:\n # 可能是主要内容\n content = line\n elif len(line) <= 15 and ('!' in line or '!' in line):\n # 可能是行动召唤\n call_to_action = line\n\n return {\n \"title\": title or \"精彩旅程\",\n \"content\": content or text[:100],\n \"tags\": tags or [\"旅行\", \"探索\"],\n \"call_to_action\": call_to_action or \"立即体验!\"\n }\n\n def _validate_and_enhance_content(\n self, \n content: Dict[str, Any], \n topic_info: str\n ) -> Dict[str, Any]:\n \"\"\"验证和增强海报内容\"\"\"\n \n # 确保所有必需字段存在\n validated_content = {\n \"title\": content.get(\"title\", \"精彩旅程\")[:15], # 限制标题长度\n \"content\": content.get(\"content\", topic_info),\n \"tags\": content.get(\"tags\", [\"旅行\"]),\n \"call_to_action\": content.get(\"call_to_action\", \"立即体验!\")\n }\n \n # 确保标签是列表格式\n if isinstance(validated_content[\"tags\"], str):\n validated_content[\"tags\"] = [tag.strip() for tag in validated_content[\"tags\"].split(\",\")]\n \n # 限制标签数量\n validated_content[\"tags\"] = validated_content[\"tags\"][:5]\n \n # 添加元数据\n validated_content[\"metadata\"] = {\n \"word_count\": len(validated_content[\"content\"]),\n \"tag_count\": len(validated_content[\"tags\"]),\n \"generated_for\": topic_info,\n \"generation_config\": self.task_model_config\n }\n \n return validated_content\n\n async def generate_multiple_variations(\n self,\n topic_info: str,\n num_variations: int = 3,\n template_type: str = \"general\",\n **kwargs\n ) -> List[Dict[str, Any]]:\n \"\"\"\n 生成多个文案变体\n\n Args:\n topic_info: 主题信息\n num_variations: 变体数量\n template_type: 模板类型 (\"general\", \"vibrant\")\n **kwargs: 其他参数\n\n Returns:\n 文案变体列表\n \"\"\"\n variations = []\n \n styles = [\"活泼有趣\", \"温馨感人\", \"激情澎湃\", \"优雅文艺\", \"简洁干练\"]\n \n for i in range(num_variations):\n try:\n # 使用不同的风格\n style = styles[i % len(styles)]\n \n if template_type == \"vibrant\":\n # 为Vibrant模板生成内容\n variation = await self.generate_vibrant_content(\n scenic_info=kwargs.get(\"scenic_info\", topic_info),\n product_info=kwargs.get(\"product_info\", \"\"),\n tweet_info=kwargs.get(\"tweet_info\", \"\"),\n **kwargs\n )\n else:\n # 通用海报内容\n variation = await self.generate_poster_content(\n topic_info=topic_info,\n style=style,\n **kwargs\n )\n \n variation[\"variation_id\"] = i + 1\n variation[\"style_used\"] = style\n variations.append(variation)\n \n except Exception as e:\n logger.error(f\"生成变体 {i+1} 失败: {e}\")\n continue\n \n return variations\n\n def get_style_suggestions(self, poster_type: str, target_audience: str) -> List[str]:\n \"\"\"\n 根据海报类型和目标受众获取风格建议\n\n Args:\n poster_type: 海报类型\n target_audience: 目标受众\n\n Returns:\n 风格建议列表\n \"\"\"\n style_mapping = {\n \"旅游宣传\": {\n \"年轻人\": [\"活泼有趣\", \"激情澎湃\", \"个性时尚\"],\n \"家庭\": [\"温馨感人\", \"亲切自然\", \"安全舒适\"],\n \"商务人士\": [\"优雅文艺\", \"简洁干练\", \"品质生活\"]\n },\n \"美食推荐\": {\n \"年轻人\": [\"诱人美味\", \"时尚潮流\", \"分享快乐\"],\n \"家庭\": [\"家常温馨\", \"营养健康\", \"团圆美好\"],\n \"美食爱好者\": [\"精致品味\", \"传统文化\", \"匠心工艺\"]\n },\n \"活动宣传\": {\n \"年轻人\": [\"活力四射\", \"激情参与\", \"社交互动\"],\n \"全年龄\": [\"欢乐共享\", \"文化体验\", \"意义深远\"],\n \"专业人士\": [\"高端品质\", \"网络建设\", \"知识分享\"]\n }\n }\n \n return style_mapping.get(poster_type, {}).get(target_audience, [\"活泼有趣\", \"简洁明快\"]) ", "code_hash": "fefa8ecc6e5c63c9d5cf088dde3fd727" } ], "imports": [ { "type": "import", "modules": [ "logging" ], "aliases": [] }, { "type": "from_import", "module": "typing", "names": [ "Dict", "Any", "Optional", "List" ], "aliases": [], "level": 0 }, { "type": "from_import", "module": "config", "names": [ "AlgorithmConfig" ], "aliases": [], "level": 2 }, { "type": "from_import", "module": "core", "names": [ "AIService", "PromptManager", "JSONProcessor" ], "aliases": [], "level": 2 }, { "type": "from_import", "module": "exceptions", "names": [ "ContentGenerationError" ], "aliases": [], "level": 2 } ], "constants": [], "docstring": "Text Generator for Posters\n海报文本生成器 - 负责生成海报所需的文案内容,支持Vibrant模板格式", "content_hash": "089a514f622542e62800299ecacf62c3" }