리포트/플랜에 브랜드·영문채널 반영
- overrides에 brandAssets·영문 인스타/페북 audit 보장 (채널별 빌더 분리) - logoRules·other_channels·channel_scores 프롬프트 수정, 스키마 입력 필드 추가 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>insta-data
parent
4855d44381
commit
163e9d1c02
|
|
@ -15,6 +15,11 @@ class PlanInput(BaseModel):
|
|||
market_keywords: str | None = None
|
||||
market_trend: str | None = None
|
||||
market_target_audience: str | None = None
|
||||
tiktok: str | None = None
|
||||
instagram_en: str | None = None
|
||||
facebook_en: str | None = None
|
||||
channel_logos: str | None = None
|
||||
brand_assets: str | None = None
|
||||
|
||||
|
||||
# --- BrandGuide ---
|
||||
|
|
|
|||
|
|
@ -321,6 +321,12 @@ class ReportInput(BaseModel):
|
|||
market_keywords: str | None = None
|
||||
market_trend: str | None = None
|
||||
market_target_audience: str | None = None
|
||||
branding: str | None = None
|
||||
brand_assets: str | None = None
|
||||
tiktok: str | None = None
|
||||
instagram_en: str | None = None
|
||||
facebook_en: str | None = None
|
||||
channel_logos: str | None = None
|
||||
|
||||
|
||||
# --- MarketingReport ---
|
||||
|
|
|
|||
|
|
@ -32,19 +32,47 @@
|
|||
## 분석 리포트
|
||||
{report}
|
||||
|
||||
## 추가 채널 데이터 (틱톡 / 인스타그램 EN / 페이스북 EN)
|
||||
아래에 데이터가 있는 채널은 channelStrategies와 channelBranding에 **반드시 포함**하세요 (틱톡, 영문 인스타그램, 영문 페이스북). null이면 제외.
|
||||
|
||||
### 틱톡 (TikTok)
|
||||
{tiktok}
|
||||
|
||||
### 인스타그램 (영문 계정)
|
||||
{instagram_en}
|
||||
|
||||
### 페이스북 (영문 페이지)
|
||||
{facebook_en}
|
||||
|
||||
## 채널별 로고 분석 (Gemini Vision) — 채널룰/일관성의 근거
|
||||
{channel_logos}
|
||||
- 위 channel_logos[]의 각 항목: channel(채널명), logo_description(프로필이 어떻게 생겼는지), is_official(공식 로고와 일치 여부).
|
||||
- **channelBranding[]를 이 데이터로 채우세요**: 채널별로 profilePhoto=해당 채널의 logo_description, currentStatus=is_official이 true면 "correct" / false면 "incorrect" (데이터 없는 채널은 "missing"). bannerSpec은 권장 배너 규격(크기/디자인)을 작성.
|
||||
- **brandInconsistencies[]에 "로고" 항목을 반드시 만드세요**: values[]에 채널마다 channel(채널명) / value(logo_description 그대로) / is_correct(is_official 값) 세 필드를 넣고, impact는 inconsistency_summary, recommendation은 channel_logos.recommendation 기반으로 작성 (공식 로고로 통일 권고 포함).
|
||||
|
||||
## 브랜드 자산 (홈페이지 CSS에서 추출 — 결정적 데이터)
|
||||
{brand_assets}
|
||||
- brand_assets.color_palette[]의 hex와 brand_assets.brand_colors(primary/accent/text)는 **홈페이지 CSS에서 실제로 추출한 값**입니다.
|
||||
- **brandGuide.colors의 hex는 반드시 이 추출값을 그대로 사용하세요. hex를 새로 지어내거나 변형하지 마세요** (매 실행마다 동일해야 함). name/usage 설명은 의미있게 써도 되지만 hex 값 자체는 추출값으로 고정.
|
||||
|
||||
## 섹션별 작성 지침
|
||||
|
||||
### Section 1: brandGuide
|
||||
- colors: 병원 아이덴티티에 맞는 컬러 팔레트 3~5개 (hex + 사용 가이드)
|
||||
- colors: **brand_assets.color_palette / brand_colors의 hex를 그대로 사용** (홈페이지 CSS 추출값, 지어내기 금지). 3~5개, 각 hex에 name/usage 부여
|
||||
- fonts: 제목/본문/캡션용 폰트 시스템 (한글/영문 포함)
|
||||
- logoRules: DO/DON'T 형식의 로고 사용 규칙 4~6개
|
||||
- logoRules: 로고 사용 규칙 4~6개. 각 항목은 rule / description / correct 3개 필드로 구성:
|
||||
- rule: 규칙을 요약한 **구체적인 제목**. "DO"·"DON'T" 같은 단어를 그대로 넣지 말 것. 실제 규칙 내용을 쓸 것 (예: "보라색+골드 깃털 로고 통일 사용", "모델 사진 프로필 금지", "비공식 변형 로고 사용 금지", "로고 주변 여백 확보").
|
||||
- description: 해당 규칙의 상세 설명.
|
||||
- correct: 권장 규칙(DO)이면 true, 금지/지양 규칙(DON'T)이면 false. 권장(true)과 금지(false)를 섞어서 작성.
|
||||
- toneOfVoice: 브랜드 성격 키워드, 커뮤니케이션 스타일, 권장/지양 표현 예시
|
||||
- channelBranding: 리포트에 존재하는 채널별 브랜딩 적용 규칙
|
||||
- brandInconsistencies: 채널 간 브랜딩 불일치 항목 및 개선 권고
|
||||
|
||||
### Section 2: channelStrategies
|
||||
- 리포트에 데이터가 있는 채널만 포함
|
||||
- 각 채널의 우선순위(P0/P1/P2), 목표, 콘텐츠 유형, 게시 빈도, 포맷 가이드라인 작성
|
||||
- **currentStatus는 현재 채널 상태를 실제 수치로 서술** (예: "14,047 팔로워, Reels 0개", "104K 구독자, 주 2~3회 업로드"). `excellent`/`warning`/`good` 같은 등급·평가어를 절대 쓰지 마세요.
|
||||
- targetGoal은 구체적 목표 수치로 작성 (예: "50K 팔로워, Reels 주 5개")
|
||||
- 각 채널의 우선순위(P0/P1/P2), 콘텐츠 유형, 게시 빈도, 포맷 가이드라인 작성
|
||||
- customerJourneyStage는 해당 채널의 주요 기여 단계로 설정
|
||||
|
||||
### Section 3: contentStrategy
|
||||
|
|
|
|||
|
|
@ -12,6 +12,17 @@
|
|||
- 시술: {services}
|
||||
- 의료진: {doctors}
|
||||
|
||||
## 브랜드 자산 (홈페이지에서 자동 추출)
|
||||
|
||||
### Firecrawl branding (로고 URL / 색상 / 폰트)
|
||||
{branding}
|
||||
|
||||
### 추출된 브랜드 자산 (로고 묘사 + CSS 색상 팔레트)
|
||||
{brand_assets}
|
||||
|
||||
⚠️ clinic_snapshot.logo_images / brand_colors는 위 추출값(brand_assets.logo_images, brand_assets.brand_colors)을 **그대로** 사용하세요. hex나 로고 URL을 절대 추측하지 마세요. 추출값이 null이면 해당 필드도 null로 두세요.
|
||||
로고에 대한 정성 평가(심볼/워드마크/톤)는 brand_assets.logo_description을 근거로 하고, 채널 프로필 이미지가 공식 로고와 일치하는지 판단할 때도 이 묘사를 기준으로 삼으세요.
|
||||
|
||||
## 시장 분석 데이터
|
||||
|
||||
### 경쟁 병원
|
||||
|
|
@ -43,9 +54,45 @@
|
|||
### 강남언니
|
||||
{gangnam_unni}
|
||||
|
||||
### 틱톡 (TikTok)
|
||||
{tiktok}
|
||||
|
||||
### 인스타그램 (영문 계정)
|
||||
{instagram_en}
|
||||
|
||||
### 페이스북 (영문 페이지)
|
||||
{facebook_en}
|
||||
|
||||
### 채널별 로고 분석 (Gemini Vision)
|
||||
{channel_logos}
|
||||
- channel_logos.channel_logos[]에 각 채널의 로고 설명(logo_description)과 공식 로고 일치 여부(is_official)가 있습니다.
|
||||
- **facebook_audit.pages[].logo** 는 짧은 판정 타이틀로: is_official=true면 `"일치 (공식 로고)"`, false면 `"불일치 (비공식 변형)"`. 그리고 **facebook_audit.pages[].logo_description** 에 해당 채널의 logo_description(설명문)을 넣으세요.
|
||||
- **instagram_audit.accounts[].profile_photo** 는 해당 채널 로고를 짧게 서술 (예: `"모델 사진 (브랜드 로고 아님)"`, `"VIEW 골드 로고"`). 긴 문장 말고 짧게.
|
||||
- 위 값들은 channel_logos 데이터 기반으로만 작성하고 추측하지 마세요.
|
||||
- 채널 간 로고 불일치(is_official=false)는 brand 일관성 진단(problem_diagnosis/weaknesses)에 반영하세요.
|
||||
|
||||
## clinic_snapshot / 채널 audit 작성 지침 (수집 데이터 그대로, 추측 금지)
|
||||
- clinic_snapshot.name 은 {clinic_name} 을 **그대로** 사용 (강남언니 표기명 '-본원' 등으로 바꾸지 말 것).
|
||||
- clinic_snapshot 의 overall_rating/total_reviews/staff_count/location/certifications/lead_doctor 는 강남언니({gangnam_unni}) 데이터의 값을 그대로 사용.
|
||||
- instagram_audit.accounts: KR 인스타({instagram})·영문 인스타({instagram_en}) 데이터가 있으면 **각각 별도 계정**으로 넣고, handle/followers/posts/following 은 그 데이터 수치를 그대로. KR=language "KR"·label "인스타그램 KR", EN=language "EN"·label "인스타그램 EN".
|
||||
- facebook_audit.pages: KR 페북({facebook})·영문 페북({facebook_en}) 데이터가 있으면 **각각 별도 페이지**로 넣고, url/page_name/followers 등은 그 데이터 그대로. language/label 동일 규칙.
|
||||
- 위 수치·URL·이름은 제공된 데이터에서 그대로 쓰고 절대 지어내지 마세요.
|
||||
|
||||
## 기타 채널 현황 (other_channels) 작성 지침
|
||||
- other_channels에는 메인 audit(YouTube/Instagram/Facebook/Website)에 **포함되지 않은** 채널만 넣으세요.
|
||||
- 위 '채널 데이터'에 **실제 수집된 데이터가 있는 채널만** status=active와 실제 url로 일관되게 포함: 네이버 블로그, 강남언니, 틱톡, 영문 인스타그램({instagram_en}), 영문 페이스북({facebook_en}).
|
||||
- **영문 인스타그램·영문 페이스북은 KR 메인 audit(Instagram/Facebook)과 별개 계정이므로, 데이터가 있으면 반드시 other_channels에 "Instagram EN" / "Facebook EN"으로 각각 포함하세요 (절대 누락 금지).**
|
||||
- **수집 데이터에 없는 채널(카카오톡/네이버플레이스/네이버카페/Threads 등)은 절대 임의로 만들지 마세요.** 데이터 없으면 그 채널은 생략 (랜덤 생성·추측 금지).
|
||||
- url은 수집 데이터의 실제 URL만 사용. 없으면 빈 문자열.
|
||||
|
||||
## 분석 지침
|
||||
|
||||
- 점수는 0~100 기준입니다.
|
||||
- **channel_scores(채널 종합도)에는 데이터가 있는 모든 채널을 각각 별도 항목으로 만드세요. 같은 플랫폼이라도 한국 계정과 영문 계정을 절대 하나로 합치지 마세요:**
|
||||
- 인스타그램 KR → channel "Instagram", 영문 인스타그램({instagram_en}) 데이터가 있으면 → channel "Instagram EN" (별도 항목)
|
||||
- 페이스북 KR → channel "Facebook", 영문 페이스북({facebook_en}) 데이터가 있으면 → channel "Facebook EN" (별도 항목)
|
||||
- 틱톡({tiktok}) 데이터가 있으면 → channel "TikTok" (별도 항목)
|
||||
- 데이터가 null인 계정은 항목을 만들지 마세요. icon은 instagram/facebook/video 등 플랫폼에 맞게 설정.
|
||||
- strengths와 weaknesses는 각 3개 이상 작성하세요.
|
||||
- roadmap은 우선순위 순으로 실행 가능한 액션으로 작성하세요.
|
||||
- kpis는 실제 수집된 수치 기반으로 현실적인 측정 가능 지표로 작성하세요.
|
||||
|
|
|
|||
|
|
@ -119,7 +119,8 @@ class VisionClient:
|
|||
' "logo_text": "로고에 보이는 워드마크 텍스트 그대로 (한글/영문). 없으면 빈 문자열",\n'
|
||||
' "logo_colors_desc": "로고에 쓰인 색감을 사람이 부르는 이름으로 서술 (예: \'딥네이비 + 골드\'). 정확한 hex는 출력하지 말 것"\n'
|
||||
"}\n"
|
||||
"주의: 색상 hex 값이나 logo URL 같은 필드는 출력하지 마세요 (별도 추출 로직이 처리)."
|
||||
"주의: 색상 hex 값이나 logo URL 같은 필드는 출력하지 마세요 (별도 추출 로직이 처리).\n"
|
||||
"모든 설명/텍스트 값은 반드시 한국어로 작성하세요 (영어 금지)."
|
||||
)
|
||||
result = await self._ask(urls, prompt)
|
||||
if not result:
|
||||
|
|
@ -166,6 +167,7 @@ class VisionClient:
|
|||
' "channel_logos": [{"channel": "...", "logo_description": "...", "is_official": true}],\n'
|
||||
' "inconsistency_summary": "채널 간 로고 일관성 1~2문장 요약",\n'
|
||||
' "recommendation": "통합 권고 1문장"\n'
|
||||
"}"
|
||||
"}\n"
|
||||
"모든 logo_description·inconsistency_summary·recommendation은 반드시 한국어로 작성하세요 (영어 금지)."
|
||||
)
|
||||
return await self._ask(urls, prompt)
|
||||
|
|
|
|||
|
|
@ -39,6 +39,12 @@ async def generate_report(analysis_run_id: str) -> ReportOutput:
|
|||
"market_keywords": _json(market.get("keywords")),
|
||||
"market_trend": _json(market.get("trend")),
|
||||
"market_target_audience": _json(market.get("target_audience")),
|
||||
"branding": _json(clinic.get("branding")),
|
||||
"brand_assets": _json(clinic.get("brandAssets")),
|
||||
"tiktok": _json(clinic.get("tiktok")),
|
||||
"instagram_en": _json(clinic.get("instagramEn")),
|
||||
"facebook_en": _json(clinic.get("facebookEn")),
|
||||
"channel_logos": _json(clinic.get("channelLogos")),
|
||||
**{
|
||||
channel: _json(data)
|
||||
for channel, data in raw.items()
|
||||
|
|
@ -78,6 +84,11 @@ async def generate_plan(analysis_run_id: str) -> PlanOutput:
|
|||
"market_keywords": _json(market.get("keywords")),
|
||||
"market_trend": _json(market.get("trend")),
|
||||
"market_target_audience": _json(market.get("target_audience")),
|
||||
"tiktok": _json(clinic.get("tiktok")),
|
||||
"instagram_en": _json(clinic.get("instagramEn")),
|
||||
"facebook_en": _json(clinic.get("facebookEn")),
|
||||
"channel_logos": _json(clinic.get("channelLogos")),
|
||||
"brand_assets": _json(clinic.get("brandAssets")),
|
||||
}
|
||||
|
||||
return await LLMService(provider="perplexity").generate(plan_prompt, input_data)
|
||||
|
|
|
|||
Loading…
Reference in New Issue