feat(01-02): costanti dominio, schemas Pydantic, FormatSelector
- backend/constants.py: CANVA_FIELDS (33 col locked), PERSUASION_DISTRIBUTION (13), SCHWARTZ_DISTRIBUTION (13) - backend/schemas/calendar.py: CalendarSlot, CalendarRequest, CalendarResponse - backend/schemas/generate.py: SlideContent, GeneratedPost, TopicResult, GenerateRequest, PostResult, GenerateResponse - backend/data/format_mapping.json: matrice 6 tipi x 5 livelli (30 combinazioni) - backend/services/format_selector.py: FormatSelector con select_format e fallback PAS - fix .gitignore: backend/data/prompts/ e format_mapping.json non erano ignorabili
This commit is contained in:
108
backend/schemas/calendar.py
Normal file
108
backend/schemas/calendar.py
Normal file
@@ -0,0 +1,108 @@
|
||||
"""Pydantic schemas per il calendario editoriale.
|
||||
|
||||
Questi modelli rappresentano il piano di pubblicazione dei 13 slot PN
|
||||
generato da CalendarService, prima della generazione LLM del contenuto.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class CalendarSlot(BaseModel):
|
||||
"""Un singolo slot del calendario editoriale con metadati strategici."""
|
||||
|
||||
indice: int = Field(
|
||||
...,
|
||||
ge=0,
|
||||
lt=13,
|
||||
description="Indice 0-based dello slot nel ciclo di 13 post",
|
||||
)
|
||||
tipo_contenuto: str = Field(
|
||||
...,
|
||||
description="Tipo Persuasion Nurturing: valore, storytelling, news, "
|
||||
"riprova_sociale, coinvolgimento, promozione",
|
||||
)
|
||||
livello_schwartz: str = Field(
|
||||
...,
|
||||
description="Livello di consapevolezza del pubblico: L1-L5",
|
||||
)
|
||||
formato_narrativo: str = Field(
|
||||
...,
|
||||
description="Formato narrativo selezionato: PAS, AIDA, BAB, Listicle, "
|
||||
"Storytelling, Dato_Implicazione, Obiezione_Risposta",
|
||||
)
|
||||
funzione: str = Field(
|
||||
...,
|
||||
description="Funzione editoriale: Intrattenere, Educare, Persuadere, Convertire",
|
||||
)
|
||||
fase_campagna: str = Field(
|
||||
...,
|
||||
description="Fase del funnel: Attira, Cattura, Coinvolgi, Converti",
|
||||
)
|
||||
target_nicchia: str = Field(
|
||||
...,
|
||||
description="Nicchia target: es. generico, dentisti, avvocati, ecommerce",
|
||||
)
|
||||
data_pub_suggerita: str = Field(
|
||||
...,
|
||||
description="Data di pubblicazione suggerita in formato YYYY-MM-DD",
|
||||
)
|
||||
topic: Optional[str] = Field(
|
||||
default=None,
|
||||
description="Topic specifico del post. None finché non generato dall'LLM "
|
||||
"o specificato dall'utente.",
|
||||
)
|
||||
|
||||
|
||||
class CalendarRequest(BaseModel):
|
||||
"""Richiesta per generare un calendario editoriale."""
|
||||
|
||||
obiettivo_campagna: str = Field(
|
||||
...,
|
||||
min_length=10,
|
||||
description="Obiettivo principale della campagna (es. 'Acquisire nuovi "
|
||||
"clienti dentisti nel Nord Italia')",
|
||||
)
|
||||
settimane: int = Field(
|
||||
default=2,
|
||||
ge=1,
|
||||
le=12,
|
||||
description="Durata del ciclo in settimane (default: 2 settimane per 13 post)",
|
||||
)
|
||||
nicchie: Optional[list[str]] = Field(
|
||||
default=None,
|
||||
description="Lista di nicchie target. Se None, usa NICCHIE_DEFAULT. "
|
||||
"'generico' viene sempre incluso automaticamente.",
|
||||
)
|
||||
frequenza_post: int = Field(
|
||||
default=3,
|
||||
ge=1,
|
||||
le=7,
|
||||
description="Numero di post a settimana (default: 3 — lun, mer, ven)",
|
||||
)
|
||||
data_inizio: Optional[str] = Field(
|
||||
default=None,
|
||||
description="Data di inizio del calendario in formato YYYY-MM-DD. "
|
||||
"Se None, usa la data corrente.",
|
||||
)
|
||||
|
||||
|
||||
class CalendarResponse(BaseModel):
|
||||
"""Risposta con il calendario editoriale generato."""
|
||||
|
||||
campagna: str = Field(
|
||||
...,
|
||||
description="Riepilogo sintetico dell'obiettivo campagna",
|
||||
)
|
||||
slots: list[CalendarSlot] = Field(
|
||||
...,
|
||||
description="Lista di 13 slot del calendario ordinati per sequenza campagna "
|
||||
"(Attira → Cattura → Coinvolgi → Converti)",
|
||||
)
|
||||
totale_post: int = Field(
|
||||
...,
|
||||
description="Numero totale di slot generati (sempre 13 per ciclo completo)",
|
||||
)
|
||||
Reference in New Issue
Block a user