Files
web-page-backend/blog-lab/app/marketer.py
gahusb 14674c4e9a fix(blog-lab): AI 생성 콘텐츠에 현재 날짜 컨텍스트 추가
Claude API 호출 시 시스템 프롬프트에 현재 날짜를 포함하여
2024년이 아닌 실제 날짜 기준으로 콘텐츠가 생성되도록 수정.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 02:09:49 +09:00

106 lines
3.1 KiB
Python

"""마케터 단계 — 전환율 강화 + 브랜드커넥트 링크 삽입."""
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],
}