baodan/api/insurance/poster/copy_generator.py

92 lines
3.5 KiB
Python
Raw Normal View History

2026-07-23 15:04:16 +08:00
"""文案生成器 — 模板模式 + AI 模式双模式。"""
import re
import json
import logging
logger = logging.getLogger(__name__)
class CopyGenerator:
"""文案生成器。"""
def generate_template_copy(self, template_content: str, product_rules: dict, customer_data: dict) -> dict:
"""模板模式:本地变量替换。
参数:
template_content: {{变量}} 占位符的文案模板
product_rules: 产品规则manual_parsed_rules
customer_data: 客户数据confirmed_data
返回:
{"headline": "...", "body": "...", "call_to_action": "..."}
"""
# 构建变量映射
variables = {}
# 产品信息
if product_rules:
2026-07-29 12:19:26 +08:00
for key, value in product_rules.items():
if isinstance(value, (str, int, float)):
variables[key] = str(value)
2026-07-23 15:04:16 +08:00
features = product_rules.get("features", [])
for i, feat in enumerate(features[:3], 1):
variables[f"feature_{i}_title"] = feat.get("title", "")
variables[f"feature_{i}_summary"] = feat.get("summary", "")
variables["currency_options"] = ", ".join(product_rules.get("currency_options", []))
# 客户数据
if customer_data:
2026-07-29 12:19:26 +08:00
for key, value in customer_data.items():
if isinstance(value, (str, int, float)):
variables[key] = str(value)
2026-07-23 15:04:16 +08:00
# 替换占位符
result = template_content
for key, value in variables.items():
result = result.replace("{{" + key + "}}", value)
# 尝试按段落拆分为 headline/body/call_to_action
lines = [l.strip() for l in result.split("\n") if l.strip()]
return {
"headline": lines[0] if lines else "",
"body": "\n".join(lines[1:-1]) if len(lines) > 2 else lines[1] if len(lines) > 1 else "",
"call_to_action": lines[-1] if len(lines) > 1 else "",
}
async def generate_ai_copy(self, product_rules: dict, customer_data: dict, style: str = "专业") -> dict:
"""AI 模式:调用 LLM 生成营销文案。
返回:
{"headline": "...", "body": "...", "call_to_action": "..."}
"""
from insurance.ppt.llm_client import poster_llm_client
2026-07-23 15:04:16 +08:00
system_prompt = f"""你是一位专业的保险营销文案撰写人。
根据以下产品信息和客户数据生成一张保险营销海报的文案
要求
1. 标题headline简短有力8字以内
2. 正文body突出产品亮点与客户需求的匹配50-100
3. 行动号召call_to_action引导客户咨询15字以内
4. 风格{style}
5. 必须基于真实数据不得虚构收益数字
JSON 格式返回不要包含 markdown 代码块标记"""
user_prompt = f"""
产品信息{json.dumps(product_rules, ensure_ascii=False)}
客户数据{json.dumps(customer_data, ensure_ascii=False)}"""
result, _response = await poster_llm_client.structured_output(
2026-07-23 15:04:16 +08:00
user_prompt, system_prompt,
schema={
"type": "object",
"properties": {
"headline": {"type": "string"},
"body": {"type": "string"},
"call_to_action": {"type": "string"},
},
"required": ["headline", "body", "call_to_action"],
},
)
return result