o2o-infinith-backend/app/integrations/llm/schemas/plan.py

211 lines
4.6 KiB
Python

from typing import Literal
from pydantic import BaseModel
class PlanInput(BaseModel):
clinic_name: str | None = None
clinic_name_en: str | None = None
address: str | None = None
phone: str | None = None
slogan: str | None = None
services: str | None = None
doctors: str | None = None
report: str | None = None
market_competitors: str | None = None
market_keywords: str | None = None
market_trend: str | None = None
market_target_audience: str | None = None
# --- BrandGuide ---
class ColorSwatch(BaseModel):
name: str
hex: str
usage: str
class FontSpec(BaseModel):
family: str
weight: str
usage: str
sample_text: str
class LogoUsageRule(BaseModel):
rule: str
description: str
correct: bool
class ToneOfVoice(BaseModel):
personality: list[str]
communication_style: str
do_examples: list[str]
dont_examples: list[str]
class ChannelBrandingRule(BaseModel):
channel: str
icon: str
profile_photo: str
banner_spec: str
bio_template: str
current_status: Literal["correct", "incorrect", "missing"]
class BrandPlanInconsistencyValue(BaseModel):
channel: str
value: str
is_correct: bool
class BrandPlanInconsistency(BaseModel):
field: str
values: list[BrandPlanInconsistencyValue]
impact: str
recommendation: str
class BrandGuide(BaseModel):
colors: list[ColorSwatch]
fonts: list[FontSpec]
logo_rules: list[LogoUsageRule]
tone_of_voice: ToneOfVoice
channel_branding: list[ChannelBrandingRule]
brand_inconsistencies: list[BrandPlanInconsistency]
# --- ChannelStrategy ---
class ChannelStrategyCard(BaseModel):
channel_id: str
channel_name: str
icon: str
current_status: str
target_goal: str
content_types: list[str]
posting_frequency: str
tone: str
format_guidelines: list[str]
priority: Literal["P0", "P1", "P2"]
customer_journey_stage: Literal["awareness", "interest", "consideration", "conversion", "loyalty"] | None = None
# --- ContentStrategy ---
class ContentPillar(BaseModel):
title: str
description: str
related_usp: str
example_topics: list[str]
color: str
class ContentTypeRow(BaseModel):
format: str
channels: list[str]
frequency: str
purpose: str
class WorkflowStep(BaseModel):
step: int
name: str
description: str
owner: str
duration: str
class RepurposingOutput(BaseModel):
format: str
channel: str
description: str
class ContentStrategyData(BaseModel):
pillars: list[ContentPillar]
type_matrix: list[ContentTypeRow]
workflow: list[WorkflowStep]
repurposing_source: str
repurposing_outputs: list[RepurposingOutput]
# --- Calendar ---
class CalendarEntry(BaseModel):
day_of_week: int
channel: str
channel_icon: str
content_type: Literal["video", "blog", "social", "ad"]
title: str
id: str | None = None
description: str | None = None
pillar: str | None = None
status: Literal["draft", "approved", "published"] | None = None
is_manual_edit: bool | None = None
ai_prompt_seed: str | None = None
class CalendarWeek(BaseModel):
week_number: int
label: str
entries: list[CalendarEntry]
class ContentCountSummary(BaseModel):
type: Literal["video", "blog", "social", "ad"]
label: str
count: int
color: str
class CalendarData(BaseModel):
weeks: list[CalendarWeek]
monthly_summary: list[ContentCountSummary]
# --- AssetCollection ---
class AssetCard(BaseModel):
id: str
source: Literal["homepage", "naver_place", "blog", "social", "youtube"]
source_label: str
type: Literal["photo", "video", "text"]
title: str
description: str
repurposing_suggestions: list[str]
status: Literal["collected", "pending", "needs_creation"]
class YouTubeRepurposeItem(BaseModel):
title: str
views: int
type: Literal["Short", "Long"]
repurpose_as: list[str]
class AssetCollectionData(BaseModel):
assets: list[AssetCard]
youtube_repurpose: list[YouTubeRepurposeItem]
# --- Repurposing ---
class RepurposingProposalItem(BaseModel):
source_video: YouTubeRepurposeItem
outputs: list[RepurposingOutput]
estimated_effort: Literal["low", "medium", "high"]
priority: Literal["high", "medium", "low"]
# --- PlanOutput ---
class PlanOutput(BaseModel):
brand_guide: BrandGuide
channel_strategies: list[ChannelStrategyCard]
content_strategy: ContentStrategyData
calendar: CalendarData
asset_collection: AssetCollectionData
repurposing_proposals: list[RepurposingProposalItem] | None = None