- 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
195 lines
6.2 KiB
Python
195 lines
6.2 KiB
Python
"""Costanti di dominio LOCKED per PostGenerator.
|
|
|
|
ATTENZIONE: Queste costanti sono fondamentali per la coerenza del sistema.
|
|
Non modificare CANVA_FIELDS, PERSUASION_DISTRIBUTION o SCHWARTZ_DISTRIBUTION
|
|
senza aggiornare anche il CSV builder e tutti i prompt LLM.
|
|
"""
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Configurazione ciclo editoriale
|
|
# ---------------------------------------------------------------------------
|
|
|
|
POST_PER_CICLO: int = 13
|
|
"""Numero fisso di post per ciclo editoriale completo."""
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Distribuzione Persuasion Nurturing (PN) — 13 slot per ciclo
|
|
# ---------------------------------------------------------------------------
|
|
|
|
PERSUASION_DISTRIBUTION: dict[str, int] = {
|
|
"valore": 4,
|
|
"storytelling": 2,
|
|
"news": 2,
|
|
"riprova_sociale": 3,
|
|
"coinvolgimento": 1,
|
|
"promozione": 1,
|
|
}
|
|
"""Distribuzione tipo_contenuto per ciclo di 13 post.
|
|
|
|
Totale: sum(values) == 13
|
|
"""
|
|
|
|
# Verifica a load-time
|
|
assert sum(PERSUASION_DISTRIBUTION.values()) == POST_PER_CICLO, (
|
|
f"PERSUASION_DISTRIBUTION deve sommare a {POST_PER_CICLO}, "
|
|
f"ora somma a {sum(PERSUASION_DISTRIBUTION.values())}"
|
|
)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Distribuzione livelli Schwartz — 13 slot per ciclo
|
|
# ---------------------------------------------------------------------------
|
|
|
|
SCHWARTZ_DISTRIBUTION: dict[str, int] = {
|
|
"L5": 3, # Inconsapevole del problema — storytelling + news
|
|
"L4": 3, # Consapevole del problema — valore + news
|
|
"L3": 4, # Consapevole della soluzione — valore + riprova_sociale
|
|
"L2": 2, # Consapevole del prodotto — riprova_sociale + coinvolgimento
|
|
"L1": 1, # Pronto all'acquisto — promozione
|
|
}
|
|
"""Distribuzione livelli consapevolezza Schwartz per ciclo di 13 post.
|
|
|
|
L5+L4 = 6 (fase Attira/Cattura — top of funnel)
|
|
L3 = 4 (fase Coinvolgi — middle of funnel)
|
|
L2+L1 = 3 (fase Converti — bottom of funnel)
|
|
Totale: sum(values) == 13
|
|
"""
|
|
|
|
# Verifica a load-time
|
|
assert sum(SCHWARTZ_DISTRIBUTION.values()) == POST_PER_CICLO, (
|
|
f"SCHWARTZ_DISTRIBUTION deve sommare a {POST_PER_CICLO}, "
|
|
f"ora somma a {sum(SCHWARTZ_DISTRIBUTION.values())}"
|
|
)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Colonne CSV per Canva Bulk Create — LOCKED
|
|
# ---------------------------------------------------------------------------
|
|
|
|
CANVA_FIELDS: list[str] = [
|
|
# --- Metadati slot (8 colonne) ---
|
|
"campagna",
|
|
"fase_campagna",
|
|
"tipo_contenuto",
|
|
"formato_narrativo",
|
|
"funzione",
|
|
"livello_schwartz",
|
|
"target_nicchia",
|
|
"data_pub_suggerita",
|
|
# --- Cover slide (3 colonne) ---
|
|
"cover_title",
|
|
"cover_subtitle",
|
|
"cover_image_keyword",
|
|
# --- Slide 2 (3 colonne) ---
|
|
"s2_headline",
|
|
"s2_body",
|
|
"s2_image_keyword",
|
|
# --- Slide 3 (3 colonne) ---
|
|
"s3_headline",
|
|
"s3_body",
|
|
"s3_image_keyword",
|
|
# --- Slide 4 (3 colonne) ---
|
|
"s4_headline",
|
|
"s4_body",
|
|
"s4_image_keyword",
|
|
# --- Slide 5 (3 colonne) ---
|
|
"s5_headline",
|
|
"s5_body",
|
|
"s5_image_keyword",
|
|
# --- Slide 6 (3 colonne) ---
|
|
"s6_headline",
|
|
"s6_body",
|
|
"s6_image_keyword",
|
|
# --- Slide 7 (3 colonne) ---
|
|
"s7_headline",
|
|
"s7_body",
|
|
"s7_image_keyword",
|
|
# --- CTA slide (3 colonne) ---
|
|
"cta_text",
|
|
"cta_subtext",
|
|
"cta_image_keyword",
|
|
# --- Extra (1 colonna) ---
|
|
"caption_instagram",
|
|
]
|
|
"""Lista ORDINATA di tutte le colonne del CSV per Canva Bulk Create.
|
|
|
|
Struttura:
|
|
- 8 metadati slot
|
|
- 24 campi slide (8 slide x 3 campi: headline/title, body/subtitle, image_keyword)
|
|
Nota: image_keyword contiene parole chiave testuali (NON URL).
|
|
Gli URL Unsplash verranno aggiunti in Phase 4.
|
|
- 1 caption Instagram
|
|
Totale: 33 colonne
|
|
|
|
LOCKED: Non aggiungere/rimuovere colonne senza aggiornare tutti i prompt LLM
|
|
e il CSV builder.
|
|
"""
|
|
|
|
# Verifica a load-time
|
|
_expected_count = 8 + 24 + 1 # 33
|
|
assert len(CANVA_FIELDS) == _expected_count, (
|
|
f"CANVA_FIELDS deve avere {_expected_count} elementi, "
|
|
f"ne ha {len(CANVA_FIELDS)}"
|
|
)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Formati narrativi disponibili (7 formati)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
FORMATI_NARRATIVI: list[str] = [
|
|
"PAS", # Problema → Agitazione → Soluzione
|
|
"AIDA", # Attenzione → Interesse → Desiderio → Azione
|
|
"BAB", # Before → After → Bridge
|
|
"Listicle", # Lista numerata di punti/consigli
|
|
"Storytelling", # Narrativa emotiva di trasformazione
|
|
"Dato_Implicazione", # Dato/statistica → Implicazione → Azione
|
|
"Obiezione_Risposta", # Obiezione comune → Confutazione → Soluzione
|
|
]
|
|
"""I 7 formati narrativi supportati per i caroselli Instagram."""
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Funzioni contenuto (4 macro-funzioni editoriali)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
FUNZIONI_CONTENUTO: list[str] = [
|
|
"Intrattenere",
|
|
"Educare",
|
|
"Persuadere",
|
|
"Convertire",
|
|
]
|
|
"""Le 4 macro-funzioni editoriali di ogni post."""
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Fasi campagna (funnel AIDA semplificato)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
FASI_CAMPAGNA: list[str] = [
|
|
"Attira", # Top of funnel — inconsapevoli (L5)
|
|
"Cattura", # Upper middle — consapevoli del problema (L4+L3)
|
|
"Coinvolgi", # Lower middle — consapevoli della soluzione (L3+L2)
|
|
"Converti", # Bottom of funnel — pronti all'acquisto (L1+L2)
|
|
]
|
|
"""Le 4 fasi del funnel di acquisizione clienti."""
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Nicchie target predefinite
|
|
# ---------------------------------------------------------------------------
|
|
|
|
NICCHIE_DEFAULT: list[str] = [
|
|
"generico",
|
|
"dentisti",
|
|
"avvocati",
|
|
"ecommerce",
|
|
"local_business",
|
|
"agenzie",
|
|
]
|
|
"""Lista di nicchie target predefinite.
|
|
|
|
"generico" è sempre incluso e viene usato per il 50% degli slot.
|
|
Le altre nicchie vengono ruotate per il restante 50%.
|
|
"""
|