Files
postgenerator/backend/schemas/calendar.py
Michele 67769dd68d feat(03-02): topic_overrides in CalendarRequest + pipeline wiring
- Aggiunto campo topic_overrides: Optional[dict[int, str]] a CalendarRequest
- GenerationPipeline._run_generation ora controlla request.topic_overrides
  prima di chiamare LLM per generare il topic
- Slot con override saltano la chiamata LLM per il topic
- Log informativo quando un override viene applicato
- Slot senza override continuano a funzionare come prima
2026-03-09 00:30:47 +01:00

114 lines
3.6 KiB
Python

"""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.",
)
topic_overrides: Optional[dict[int, str]] = Field(
default=None,
description="Override topic per slot specifici. Chiave: indice slot (0-12), valore: topic. "
"Gli slot con override skipperanno la generazione topic LLM.",
)
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)",
)