"""마케터 단계 — 전환율 강화 + 브랜드커넥트 링크 삽입.""" import json import logging from datetime import date from typing import Any, Dict, List, Optional import anthropic from .config import ANTHROPIC_API_KEY, CLAUDE_MODEL from .db import get_template logger = logging.getLogger(__name__) _client: Optional[anthropic.Anthropic] = None def _get_client() -> anthropic.Anthropic: global _client if _client is None: _client = anthropic.Anthropic(api_key=ANTHROPIC_API_KEY) return _client def _call_claude(prompt: str, max_tokens: int = 8192) -> str: client = _get_client() today = date.today().isoformat() resp = client.messages.create( model=CLAUDE_MODEL, max_tokens=max_tokens, system=f"현재 날짜는 {today}입니다. 모든 콘텐츠는 이 날짜 기준으로 작성하세요.", messages=[{"role": "user", "content": prompt}], ) return resp.content[0].text def enhance_for_conversion( post_body: str, post_title: str, brand_links: List[Dict[str, Any]], keyword: str, ) -> Dict[str, str]: """초안에 제휴 링크를 자연스럽게 삽입하고 전환율을 강화. Args: post_body: 작가 초안 HTML 본문 post_title: 작가 초안 제목 brand_links: 브랜드커넥트 링크 리스트 keyword: 타겟 키워드 Returns: {"title": str, "body": str, "excerpt": str} Raises: ValueError: 브랜드 링크가 없을 때 """ if not brand_links: raise ValueError("브랜드커넥트 링크가 필요합니다") template = get_template("marketer_enhance") if not template: raise RuntimeError("marketer_enhance 템플릿이 없습니다") brand_links_text = "" for i, link in enumerate(brand_links, 1): brand_links_text += ( f"{i}. 상품명: {link.get('product_name', '')}\n" f" 설명: {link.get('description', '')}\n" f" URL: {link.get('url', '')}\n" f" 배치 힌트: {link.get('placement_hint', '자연스럽게')}\n\n" ) prompt = template.format( draft_body=post_body[:6000], keyword=keyword, brand_links_info=brand_links_text, ) prompt += ( "\n\n---\n" "응답은 반드시 아래 JSON 형식으로 해주세요 (JSON만 출력):\n" '{"title": "개선된 제목", "body": "개선된 HTML 본문", "excerpt": "2줄 요약"}' ) raw = _call_claude(prompt) try: text = raw.strip() if text.startswith("```"): lines = text.split("\n") lines = [l for l in lines if not l.strip().startswith("```")] text = "\n".join(lines) result = json.loads(text) return { "title": result.get("title", post_title), "body": result.get("body", post_body), "excerpt": result.get("excerpt", ""), } except (json.JSONDecodeError, KeyError): logger.warning("Marketer JSON parse failed, using raw text") return { "title": post_title, "body": raw, "excerpt": raw[:200], }