Spaces:
Running
Running
# -*- coding: utf-8 -*- | |
import os | |
from dotenv import load_dotenv | |
import gradio as gr | |
import google.generativeai as genai # Importa Gemini | |
from datetime import datetime, timedelta # datetime è già qui | |
import re # Importa re per pulire l'output di Gemini a volte | |
# --- LOGGING CONFIGURATION (HOTEL TINTORETTO) --- | |
LOG_FILE_PATH_TINTORETTO = 'hotel_tintoretto_interactions.log' | |
def log_interaction_tintoretto(timestamp_str, personification, output_type, language, tones, narrative_arc, marketing_model, user_input, ai_output, image_prompt_output=None): | |
""" | |
Registra l'interazione in un formato user-friendly su un file di log per Hotel Tintoretto. | |
""" | |
log_entry = f"\n================ INTERAZIONE REGISTRATA (Hotel Tintoretto) ================ \n" | |
log_entry += f"Data e Ora: {timestamp_str}\n" | |
log_entry += f"Personificazione Utilizzata: {personification}\n" | |
log_entry += f"Tipo di Output Richiesto: {output_type}\n" | |
log_entry += f"Lingua: {language}\n" | |
log_entry += f"Toni: {tones}\n" # Sarà una stringa già formattata al momento della chiamata | |
log_entry += f"Arco Narrativo: {narrative_arc}\n" | |
log_entry += f"Modello Marketing: {marketing_model}\n" | |
log_entry += f"-------------------- INPUT UTENTE (Hotel Tintoretto) --------------------\n" | |
log_entry += f"{user_input}\n" | |
log_entry += f"-------------------- OUTPUT GENERATO (Hotel Tintoretto) -------------------\n" | |
log_entry += f"{ai_output}\n" | |
if image_prompt_output and image_prompt_output.strip() and image_prompt_output.lower() != "none": | |
log_entry += f"-------------------- PROMPT IMMAGINE (Hotel Tintoretto) -------------------\n" | |
log_entry += f"{image_prompt_output}\n" | |
log_entry += f"================ FINE INTERAZIONE (Hotel Tintoretto) ================ \n" | |
try: | |
with open(LOG_FILE_PATH_TINTORETTO, 'a', encoding='utf-8') as f: | |
f.write(log_entry) | |
except Exception as e: | |
# Stampa l'errore sulla console, che potrebbe essere visibile nei log di Hugging Face Spaces | |
print(f"CRITICAL: Errore durante la scrittura del log (Hotel Tintoretto): {e}") | |
import traceback | |
print(traceback.format_exc()) | |
# --- FINE LOGGING CONFIGURATION (HOTEL TINTORETTO) --- | |
# --- Lista Modelli Gemini Disponibili (al momento della scrittura) --- | |
# Puoi usare uno degli identificatori qui sotto nella variabile GEMINI_MODEL_TO_USE. | |
# Nota: 'Preview' o 'Esperimento' potrebbero cambiare o essere rimossi da Google. | |
# 'Stabile' o 'Legacy' sono generalmente più affidabili per uso continuativo. | |
# | |
# === Modelli Recenti/Preview === | |
# Gemini 2.5 Pro: 'gemini-2.5-pro-preview-03-25' - Preview/Esperimento - Modello più avanzato, eccellente per ragionamento e multimodalità. | |
# Gemini 2.5 Flash: 'gemini-2.5-flash-preview-04-17' - Preview/Esperimento - Versione ottimizzata per velocità e costi ridotti. | |
# Gemini 2.0 Flash-Live:'gemini-2.0-flash-live-preview-04-09' - Preview - Supporto streaming testo/audio in tempo reale. | |
# Gemini 2.0 Flash-Thinking: 'gemini-2.0-flash-thinking-exp-01-21' - Esperimento - Migliorato per ragionamento e spiegazione dei processi. | |
# | |
# === Modelli Stabili (Serie 2.0 / 1.5) === | |
# Gemini 2.0 Flash: 'gemini-2.0-flash-001' - Stabile - Ottimo bilanciamento tra velocità e capacità multimodale. | |
# Gemini 2.0 Flash-Lite:'gemini-2.0-flash-lite-001' - Stabile - Versione leggera, bassa latenza, alta efficienza. | |
# Gemini 1.5 Pro: 'gemini-1.5-pro-002' - Stabile - Fino a 2M token di contesto, ottimo per task complessi. (Potrebbe essere anche 'gemini-1.5-pro-latest') | |
# Gemini 1.5 Flash: 'gemini-1.5-flash-002' - Stabile - Veloce e versatile per molteplici task. (Potrebbe essere anche 'gemini-1.5-flash-latest') | |
# | |
# === Modelli Legacy (Serie 1.0) === | |
# Gemini 1.0 Pro: 'gemini-1.0-pro-002' - Legacy - Versione precedente, ancora accessibile. (Potrebbe essere anche 'gemini-pro') | |
# Gemini 1.0 Pro Vision:'gemini-1.0-pro-vision-001' - Legacy - Supporto input visivo. (Potrebbe essere anche 'gemini-pro-vision') | |
# --- Fine Lista Modelli --- | |
# --- Configurazione Iniziale --- | |
load_dotenv() | |
# !!! <<< SELEZIONA IL MODELLO GEMINI DA USARE QUI >>> !!! | |
GEMINI_MODEL_TO_USE = 'gemini-2.5-flash-preview-04-17' # Alternative: 'gemini-1.5-pro-latest', etc. | |
# !!! <<<===========================================>>> !!! | |
# Cerca la chiave API di Google | |
api_key = os.getenv('GOOGLE_API_KEY') | |
if not api_key: | |
api_key = os.getenv('OPENAI_API_KEY') # Fallback (con warning) | |
if api_key: | |
print("Warning: Using OPENAI_API_KEY environment variable for Google API Key. Please rename it to GOOGLE_API_KEY.") | |
else: | |
raise ValueError("Errore: GOOGLE_API_KEY non trovata nelle variabili d'ambiente.") | |
# Configura l'SDK di Google | |
genai.configure(api_key=api_key) | |
print(f"Using Google Gemini Model: {GEMINI_MODEL_TO_USE}") # Conferma il modello usato | |
# --- Variabili Globali Editabili: Nuances e Contesti --- | |
# Nuances Personificazioni | |
NUANCE_GABRIELLA = "meticolosa e attenta ai dettagli, pratica e organizzativa." | |
NUANCE_DANIELA = "calda, empatica e focalizzata sul comfort e benessere degli ospiti." | |
NUANCE_NICOLETTA = "efficiente, molto informata su Venezia, diretta e pratica." | |
NUANCE_CARLA = "calma, rassicurante e paziente, ottima per gestire richieste particolari." | |
NUANCE_RECEPTION_FRIENDLY = "esperta, amichevole e disponibile per accoglienza e info generali." | |
NUANCE_RECEPTION_FORMAL = "precisa, professionale e chiara per prenotazioni, amministrazione, problemi formali." | |
NUANCE_COACH = "orientato a migliorare performance team con neuroscienze applicate, copy efficace, strategie alberghiere semplici e motivanti." | |
NUANCE_INSPIRING_CREATIVE = "altamente creativa, focus su idee innovative per ospitalità, storytelling social, esperienze uniche e contenuti visuali." | |
NUANCE_NEUROSCIENTIST = "analitica e strategica, applica principi neuroscientifici (bias, framing, social proof) per ottimizzare comunicazione e persuasione marketing." | |
NUANCE_MANAGER = "manager senior con visione strategica, orientato a risultati e gestione efficiente team/operazioni." | |
NUANCE_BRAND = "voce ufficiale e impersonale dell'Hotel Tintoretto, comunicazione chiara e professionale." | |
NUANCE_TIKTOK_STRATEGIST = "un'esperta di neuromarketing e TikTok strategy nel travel. Identifica **trend audio/video ADATTABILI** in modo *originale* (non banale). Crea script brevi (15-60s) **realistici ma con potenziale virale**, suggerendo setting **facilmente realizzabili**, angolazioni **dinamiche e inaspettate** (POV, zoom rapidi, low angle), montaggio **ritmato con J-cuts/L-cuts**, e **neuro-hook ultra-rapidi** (pattern interrupt, curiosity gap, strong visual statement) per catturare l'attenzione nei primi 1-2 secondi. Usa neuro-copy per i testi overlay. Focus su autenticità, valore, umorismo situazionale (vita/viaggi a Venezia) e risoluzione problemi comuni del turista." | |
NUANCE_INSTAGRAM_STRATEGIST = "una visual storyteller e Instagram strategist esperta in **community building ed estetica raffinata**. Crea script per Reels (fino a 90s) con **storytelling emozionale e archi narrativi chiari**, idee **pronte all'uso** per **sequenze di Stories interattive e strategiche** (poll, quiz, Q&A mirati, sticker 'link' se appropriato), e concept per post/caroselli **esteticamente impeccabili** e coerenti con il brand (autentico, accogliente, dettagli curati). Punta a **ispirare il desiderio** di un'esperienza veneziana genuina, stimolare l'engagement **di qualità** e guidare azioni concrete (salvataggi, condivisioni, visite al sito)." | |
NUANCE_TIKTOK_CAMPAIGNER = "pianificatrice strategica di campagne TikTok per travel. Idea campagne tematiche (1-2 mesi) **realistiche, misurabili e creative**. Definisce concept **forte e originale**, target preciso, obiettivi (KPI chiari: es. % completamento video, click-through rate), **pilastri di contenuto differenzianti** con esempi video *specifici* (non generici), frequenza/mix formati **ottimizzato per l'algoritmo**, e strategia hashtag **a più livelli**." | |
NUANCE_INSTAGRAM_CAMPAIGNER = "pianificatrice strategica di campagne Instagram per travel. Idea campagne (1-2 mesi) focalizzate su **estetica distintiva, storytelling cross-format e crescita community**. Definisce concept, **visual moodboard dettagliato** (descrittivo), obiettivi (engagement rate, UGC di qualità, lead generation), **content mix strategico** (Reels per reach, Stories per engagement, Post per informazione/ispirazione, Guide), **piano di interazione proattivo** (risposte a commenti/DM, interazione con UGC), e **funnel di conversione** con CTA chiare." | |
# Clausola Privacy | |
privacy_clause = """ | |
Please note that data submitted by you shall be processed using electronic means in compliance with the principles set forth in applicable data privacy laws and regulations (EU Regulation n. 679, 2016), solely for the purpose of providing you with the information requested, and potentially for placing/confirming your booking of room(s) and other services/amenities. The complete privacy policy on processing methods and purposes is available at the following link www.hoteltintoretto.com/privacy-policy (Nota: Verificare URL esatto). If you are interested in receiving our newsletter / periodic updates on special rates and promotions (to be sent to an address supplied by you), you must provide explicit consent to the same. You may at any time thereafter revoke such consent, as noted in the policy. | |
""" | |
# --- FUNZIONE PER LINK BOOKING BASE --- | |
def generate_booking_link(language="English"): | |
"""Genera il link BASE alla pagina di disponibilità (senza date/ospiti).""" | |
base_url = "https://www.hoteltintoretto.com" | |
hotel_id = "SYN2595" | |
if language == "Italian": | |
path = "/disponibilita.html" | |
else: | |
path = "/EN/availability.html" | |
return f"{base_url}{path}?id_hotel={hotel_id}" | |
# --- Genera i link base ORA --- | |
link_base_it = generate_booking_link(language='Italian') | |
link_base_en = generate_booking_link(language='English') | |
# Contesto Principale Hotel Tintoretto | |
hotel_context="""" | |
--- Hotel Overview --- | |
Nome Hotel: Hotel Tintoretto | |
Stelle: 3 stelle | |
Ubicazione: Cannaregio, Venezia, Italia. Zona tranquilla e autentica, fuori dalle folle immediate ma comoda. Vicino a Strada Nova (shopping), Ghetto Ebraico, Ponte delle Guglie, fermata Vaporetto "Ponte delle Guglie" (linea 1, Alilaguna Blu per aeroporto). | |
Indirizzo: Santa Fosca, Cannaregio 2316, 30121 Venezia (VE) | |
Contatti: Tel +39 041 715030, Fax +39 041 715989, Email info@hoteltintoretto.com | |
Sito Web Ufficiale: www.hoteltintoretto.com | |
Descrizione Generale: Hotel accogliente e a gestione familiare situato in un palazzo storico veneziano con dependance. Atmosfera informale e amichevole. Offre un buon rapporto qualità-prezzo per Venezia. Non è un hotel di lusso, ma pulito, funzionale e ben posizionato per esplorare la vera Venezia. | |
Target Audience: Coppie, famiglie, viaggiatori singoli che cercano un'esperienza veneziana autentica, valore, convenienza e una base comoda per esplorare. Non ideale per chi cerca lusso moderno, spa, palestra o servizi business avanzati. Psicograficamente: tendenzialmente allocentrici (cercano esperienze autentiche locali) o mid-centrici (mix di comfort e scoperta). | |
Punti di Forza Chiave: | |
- Posizione: Strategica in Cannaregio, tranquilla ma vicina a trasporti e attrazioni. Permette di vivere un'esperienza veneziana più autentica. | |
- Staff: Amichevole, disponibile, multilingue. Spesso lodato nelle recensioni. | |
- Rapporto Qualità/Prezzo: Considerato buono per gli standard di Venezia. | |
- Atmosfera: Accogliente, informale, familiare. | |
- Pulizia: Generalmente buona e curata. | |
- Colazione: Buffet continentale standard (dolce/salato), adeguato per un 3 stelle. A volte descritta come 'essenziale' ma sufficiente. Inclusa nella tariffa della camera. Servita in sala dedicata. | |
- Deposito Bagagli: Gratuito prima del check-in e dopo il check-out. | |
Servizi Principali: | |
- Reception: Aperta 24h (verificare orari esatti se necessario per info specifiche). | |
- Wi-Fi: Gratuito in tutta la struttura (camere e aree comuni). | |
- Aria Condizionata / Riscaldamento: Presente nelle camere (regolabile). | |
- TV: Presente in tutte le camere. | |
- Bagno Privato: Tutte le camere hanno bagno privato con doccia o vasca, asciugacapelli e set di cortesia base. | |
- Ascensore: Presente nell'edificio principale (raggiunge la maggior parte delle camere, ma alcune potrebbero richiedere scale finali - specificare se richiesto). La dependance potrebbe non avere ascensore. | |
- Animali Domestici: Ammessi su richiesta, potrebbe essere applicato un supplemento. Specificare taglia piccola/media preferibilmente. | |
- Check-in: Dalle 14:00. | |
- Check-out: Entro le 11:00. | |
Limitazioni / Aspetti da gestire con trasparenza: | |
- Stile Arredamento: Classico veneziano, potrebbe apparire datato ad alcuni ospiti abituati a design moderno. Funzionale, non di lusso. | |
- Dimensioni Camere: Variabili, alcune camere (specialmente singole o economy) potrebbero essere piccole, tipico degli edifici storici veneziani. | |
- Rumore: Generalmente tranquillo, ma data la posizione centrale, rumori dalla strada/canale sono possibili. Camere interne più silenziose. | |
- Barriere Architettoniche: Essendo edificio storico, l'accessibilità per persone con mobilità ridotta potrebbe essere limitata. Verificare specifiche esigenze. L'ascensore potrebbe non servire tutti i piani/camere direttamente. | |
- Vista: Non tutte le camere hanno vista canale. Molte affacciano su cortili interni o strade laterali. | |
--- Prenotazioni & Offerte --- | |
- Booking Diretto: **Fortemente incoraggiato tramite il sito ufficiale www.hoteltintoretto.com per ottenere la migliore tariffa disponibile e offerte speciali.** | |
- (Nota per AI: Quando inviti a prenotare, suggerisci di visitare il sito www.hoteltintoretto.com o fornisci il link base appropriato alla lingua, spiegando che l'utente dovrà inserire date e ospiti. NON inserire date/ospiti nel link.) | |
- Link base IT: {link_it} | |
- Link base EN/Altro: {link_en} | |
- Pagina Offerte: Disponibile sul sito ufficiale. Controllare periodicamente per pacchetti (es. soggiorno lungo, prenota prima). | |
- Politiche Cancellazione: Variabili a seconda della tariffa (Standard vs Non Rimborsabile). Controllare sempre le condizioni specifiche al momento della prenotazione. | |
- Tassa di Soggiorno: Esclusa dalla tariffa, da pagare in hotel al check-out (importo variabile per legge comunale). | |
--- Hotel Partner (Alternativa se Tintoretto pieno) --- | |
Nome: Hotel Filù | |
Stelle: 3 stelle | |
Posizione: Vicino all'Hotel Tintoretto (Cannaregio 1431/B), leggermente più vicino alla stazione ferroviaria Santa Lucia. | |
Caratteristiche Simili: Buon rapporto qualità/prezzo, staff amichevole, stile veneziano (potrebbe essere leggermente più moderno del Tintoretto in alcune aree), colazione inclusa, Wi-Fi gratuito. | |
Differenze Potenziali: Potrebbe avere camere leggermente diverse, verificare disponibilità ascensore e accessibilità. | |
Contatti: Tel +39 041 524 2604, Email info@hotelfilu.com, Sito www.hotelfilu.com | |
(Nota per AI: Suggerire Hotel Filù SOLO se il Tintoretto è esplicitamente pieno o se l'utente chiede alternative nella stessa zona/fascia di prezzo.) | |
""".format(link_it=link_base_it, link_en=link_base_en) | |
# Dettagli Specifici Camere | |
room_details = """ | |
--- DETTAGLI TIPOLOGIE CAMERE HOTEL TINTORETTO --- | |
Nota Generale: Tutte le camere dispongono di bagno privato (con doccia o vasca, WC, bidet ove possibile, asciugacapelli, set cortesia base), aria condizionata/riscaldamento autonomo, TV LCD/LED, telefono, Wi-Fi gratuito, cassaforte (verificare se in tutte). L'arredamento è in stile classico veneziano (legno, tessuti damascati), funzionale e pulito, ma non moderno/design. Le dimensioni possono variare significativamente anche all'interno della stessa tipologia a causa della natura storica dell'edificio. Alcune camere sono nell'edificio principale (con ascensore che serve la maggior parte dei piani), altre nella dependance (potrebbe non avere ascensore). | |
1. **Camera Singola (Single Room):** | |
* Occupazione: 1 persona. | |
* Letto: Letto singolo standard. | |
* Dimensioni: Generalmente le più piccole (circa 8-12 mq). Essenziali e funzionali per chi viaggia da solo. | |
* Vista: Tipicamente su cortile interno o strada laterale (non garantita vista canale). | |
* Ideale per: Viaggiatori singoli con budget limitato, soggiorni brevi. | |
2. **Camera Matrimoniale/Doppia Uso Singola (Double for Single Use):** | |
* Occupazione: 1 persona. | |
* Letto: Letto matrimoniale standard (o due letti singoli uniti). | |
* Dimensioni: Più spaziosa di una Singola Standard (circa 12-16 mq). | |
* Vista: Variabile (cortile, strada laterale, raramente canale). | |
* Ideale per: Viaggiatori singoli che desiderano più spazio e comfort. | |
3. **Camera Matrimoniale Standard (Standard Double/Twin Room):** | |
* Occupazione: 2 persone. | |
* Letto: 1 letto matrimoniale (Double) OPPURE 2 letti singoli (Twin) - **specificare preferenza alla prenotazione, soggetta a disponibilità**. A volte il matrimoniale è composto da due singoli uniti (standard comune in molti hotel). | |
* Dimensioni: Variabili, generalmente 14-18 mq. Spazio adeguato per due persone, ma non ampie. | |
* Vista: Variabile (cortile interno, strada laterale). Alcune potrebbero avere affaccio parziale o laterale su canale (non garantito, specificare se è una richiesta). | |
* Ideale per: Coppie, amici. | |
4. **Camera Tripla (Triple Room):** | |
* Occupazione: 3 persone. | |
* Letto: Tipicamente 1 letto matrimoniale + 1 letto singolo, OPPURE 3 letti singoli. | |
* Dimensioni: Più grande di una doppia (circa 18-22 mq). | |
* Vista: Variabile, solitamente non con vista canale privilegiata. | |
* Ideale per: Piccole famiglie, gruppi di amici. | |
5. **Camera Quadrupla (Quadruple Room):** | |
* Occupazione: 4 persone. | |
* Letto: Combinazioni variabili, spesso 1 letto matrimoniale + 2 letti singoli, o 4 letti singoli, a volte letto a castello per ottimizzare spazio. Verificare configurazione specifica se disponibile. | |
* Dimensioni: Le più spaziose (circa 20-25 mq), ma lo spazio per i bagagli potrebbe essere comunque limitato con 4 occupanti. | |
* Vista: Variabile. | |
* Ideale per: Famiglie, gruppi. | |
6. **Camera Economy (Economy Room - se offerta):** | |
* Occupazione: 1 o 2 persone (verificare tipologia specifica). | |
* Caratteristiche: Simile alla Singola o Doppia Standard, ma potrebbe essere situata in una posizione meno favorevole (es. piano terra, dependance senza ascensore, vista limitata o interna) o avere dimensioni leggermente inferiori. Offerta a una tariffa più bassa. | |
* Ideale per: Ospiti molto attenti al budget a cui non interessano piccoli compromessi su posizione/vista/dimensioni. | |
**Note Addizionali Importanti:** | |
* **Letti Aggiuntivi/Culle:** Disponibili su richiesta e soggetti a disponibilità/supplemento. Da richiedere in anticipo. Non tutte le camere potrebbero essere abbastanza grandi per ospitare letti extra. | |
* **Preferenze (Letto, Posizione):** L'hotel cerca di soddisfare le richieste (es. letti separati, piano alto, camera silenziosa), ma non possono essere garantite e dipendono dalla disponibilità al momento dell'arrivo. | |
* **Foto:** Le foto sui siti web sono rappresentative della tipologia di camera, ma la camera specifica assegnata potrebbe differire leggermente in layout e decorazioni. | |
""" | |
# Informazioni Fattuali Addizionali | |
factual_info = """ | |
--- INFORMAZIONI FATTUALI AGGIUNTIVE --- | |
**Come Raggiungere l'Hotel:** | |
* **Dall'Aeroporto Marco Polo (VCE):** | |
* **Opzione 1 (Acqua - Consigliata):** Navetta acquea Alilaguna Linea Blu. Scendere alla fermata "Guglie". Da lì, l'hotel è a circa 5-7 minuti a piedi. Attraversare il Ponte delle Guglie, girare subito a sinistra lungo la Fondamenta di Cannaregio, poi a destra in Calle del Forno, dritto fino a Campo Santa Fosca. L'hotel è lì. (Costo indicativo: ~15€ a persona, durata ~40-50 min). | |
* **Opzione 2 (Terra + Vaporetto):** Autobus ACTV n. 5 (AeroBus) o ATVO per Piazzale Roma. Da Piazzale Roma, prendere il Vaporetto ACTV Linea 1 (direzione Rialto/Lido) e scendere alla fermata "San Marcuola". Da lì, 5 minuti a piedi. In alternativa, da Piazzale Roma si può camminare (circa 20-25 min, impegnativo con bagagli). | |
* **Opzione 3 (Taxi Acqueo Privato):** Soluzione più costosa (~120-150€) ma diretta. Chiedere di essere lasciati il più vicino possibile a Campo Santa Fosca / Ponte delle Guglie. | |
* **Dall'Aeroporto di Treviso (TSF):** | |
* Autobus navetta ATVO o Barzi Service per Piazzale Roma, Venezia. Da Piazzale Roma, seguire le indicazioni sopra (Vaporetto Linea 1 per "San Marcuola" o camminare). | |
* **Dalla Stazione Ferroviaria Santa Lucia:** | |
* **Opzione 1 (Piedi - Facile):** Uscire dalla stazione, girare a sinistra e seguire la strada principale (Lista di Spagna, poi Strada Nova). Dopo circa 10-15 minuti, superato il Ponte delle Guglie, girare a destra in Calle del Forno, dritto fino a Campo Santa Fosca. L'hotel è lì. Percorso quasi tutto dritto e pianeggiante (tranne il ponte). | |
* **Opzione 2 (Vaporetto):** Prendere Vaporetto ACTV Linea 1 (direzione Rialto/Lido) dalla fermata "Ferrovia" (di fronte alla stazione) e scendere alla fermata "San Marcuola" (1 fermata). Da lì, 5 minuti a piedi. | |
* **Da Piazzale Roma (Terminal Auto/Bus):** | |
* **Opzione 1 (Vaporetto):** Prendere Vaporetto ACTV Linea 1 (direzione Rialto/Lido) dalla fermata "Piazzale Roma" e scendere a "San Marcuola" (2 fermate). Da lì, 5 minuti a piedi. | |
* **Opzione 2 (Piedi):** Attraversare il Ponte della Costituzione (Calatrava), seguire le indicazioni per la Stazione Ferroviaria e poi per Strada Nova come descritto sopra. (Circa 20-25 min). | |
* **Dal Terminal Crociere (Stazione Marittima):** | |
* Prendere il People Mover fino a Piazzale Roma. Da lì, seguire le indicazioni da Piazzale Roma (Vaporetto Linea 1 o piedi). | |
**Parcheggio (Nota: Venezia centro è pedonale):** | |
* L'hotel NON dispone di parcheggio privato. | |
* Le auto devono essere lasciate nei parcheggi all'ingresso di Venezia: | |
* **Piazzale Roma:** Garage Comunale ASM, Garage San Marco. Sono i più vicini ma costosi. | |
* **Tronchetto:** Isola artificiale collegata da People Mover a Piazzale Roma. Parcheggi leggermente meno costosi (Venezia Tronchetto Parking). | |
* **Alternative più economiche:** Parcheggi a Mestre (vicino stazione FS) e poi prendere treno o bus per Venezia. | |
* **Costi:** Indicativamente 25-40€ al giorno, a seconda del garage e della stagione. Prenotazione online spesso consigliata e talvolta più conveniente. | |
* **Dai parcheggi:** Seguire le indicazioni per raggiungere l'hotel come da Piazzale Roma. | |
**Informazioni Locali Utili:** | |
* **Supermercato:** Nelle vicinanze (es. Coop in Strada Nova). Chiedere alla reception per indicazioni precise. | |
* **Farmacia:** Diverse in Strada Nova e dintorni. | |
* **Bancomat (ATM):** Presenti lungo Strada Nova. | |
* **Ristoranti/Bacari:** La zona di Cannaregio (specialmente Fondamenta della Misericordia e dintorni) è ricca di bacari (osterie tipiche veneziane) e ristoranti meno turistici rispetto all'area di San Marco. Lo staff può fornire ottimi consigli. | |
* **Mercato di Rialto:** Raggiungibile a piedi in circa 15-20 minuti. Famoso per pesce fresco e prodotti locali (mattina). | |
* **Vaporetto:** Acquistare biglietti singoli (costosi), giornalieri o plurigiornalieri (più convenienti per uso frequente) presso le biglietterie ACTV o i tabaccai autorizzati. La fermata più vicina è San Marcuola (Linea 1) o Guglie (Linea 1 + Alilaguna). | |
* **Gondola:** Stazi (punti di partenza) si trovano in vari punti della città, anche vicino a Campo Santa Fosca/Ponte delle Guglie. Tariffa ufficiale fissata dalla città (indicativamente 80€ per 30 min di giorno, di più la sera). | |
**Servizi Aggiuntivi (Su richiesta/Possibili):** | |
* Prenotazione taxi acqueo. | |
* Informazioni turistiche, mappe della città. | |
* Prenotazione tour/escursioni. | |
* Servizio lavanderia esterno (a pagamento). | |
**Politiche Specifiche:** | |
* **Fumo:** Generalmente vietato nelle camere e nelle aree comuni interne. Potrebbero esserci aree esterne designate. | |
* **Pagamenti:** Accettate le principali carte di credito (Visa, MasterCard, Amex - verificare). Contanti. | |
""" | |
# --- Funzioni Ausiliarie --- | |
# generate_narrative_arc (invariata) | |
def generate_narrative_arc(narrative_arc): | |
narrative_mapping = { | |
"Hero's Journey": "Using the \"Hero's Journey\" (a classic storytelling structure where the protagonist goes through departure, initiation, and return phases, facing challenges and undergoing transformation).", | |
"Story Cycle": "Using the \"Story Cycle\" (a recurring sequence of narrative events or situations that form a pattern, often seen in episodic or serial narratives).", | |
"Motivation Sequence": "Using the \"Motivation Sequence\" (a series of events or actions that drive the protagonist's desires, goals, and motivations, propelling the story forward).", | |
"Narrative Transportation": "Using the \"Narrative Transportation\" (the phenomenon where readers become immersed and transported into the narrative world, temporarily detaching from their real-world surroundings).", | |
"Narrative Persuasion": "Using the \"Narrative Persuasion\" (the use of storytelling to influence attitudes, beliefs, or behaviors by presenting arguments or perspectives through a narrative format).", | |
"Conciso": "Using the \"Concise Style\" (concise and extremely brief, conveying the essence of a narrative arc or structure in a highly condensed form)." | |
} | |
return narrative_mapping.get(narrative_arc, "") | |
# generate_marketing_model (invariata) | |
def generate_marketing_model(marketing_model): | |
instruction = "" | |
base_instructions = { | |
"PAS": "Problem Agitate Solve: Identify a problem, agitate the consequences, offer the solution.", | |
"AIDA": "Attention Interest Desire Action: Grab attention, generate interest, create desire, prompt action.", | |
"BAB": "Before After Bridge: Show the 'before' world, contrast with the 'after' world (problem solved), bridge with the solution.", | |
"4Cs": "Clear, Concise, Compelling, Credible: Ensure copy is easily understood, to the point, engaging, and trustworthy.", | |
"So What": "Focus on benefits, asking 'So what?' to emphasize user gains over features.", | |
"PPPP": "Problem, Promise, Proof, Proposal: Identify problem, promise solution, provide proof, end with proposal/CTA.", | |
"SSS": "Star, Story, Solution: Introduce protagonist (Star), narrate their journey/struggle (Story), present product as solution.", | |
"FAB": "Features, Advantages, Benefits: Highlight features, explain advantages over competitors, delineate user benefits.", | |
"SLAP": "Stop, Look, Action, Purchase: Grab attention (Stop), make them look (Look), encourage action (Action), guide to purchase (Purchase).", | |
"4Us": "Urgency, Uniqueness, Utility, Ultimatum: Create urgency, show uniqueness, describe utility, present ultimatum/CTA." | |
} | |
if marketing_model in base_instructions: | |
instruction = f"""Mentally structure the response using the **{marketing_model}** framework ({base_instructions[marketing_model]}), but **DO NOT include the framework labels (like `[Problem]`, `[Attention]`, etc.) within the main body of the generated text.** The main text should flow naturally without these annotations. | |
IMPORTANT: After generating the clean main text response, add a final section (clearly separated, starting with '--- Spiegazione Modello Marketing ({marketing_model}) ---') where you explain IN ITALIAN and in detail how and where you applied the '{marketing_model}' model structure within the text generated above. Use square brackets `[like this]` within this final explanation section only to refer back to specific parts of the text you generated. This explanation is for user learning.""" | |
elif marketing_model == "Nessuno": | |
instruction = "Do not use a specific marketing model framework, focus on creating the best copy naturally." | |
else: | |
instruction = "Focus on creating the best copy naturally." # Fallback | |
return instruction | |
# inject_personification (invariata) | |
def inject_personification(personification_focus): | |
base_description = "Sei un assistente AI che lavora per l'Hotel Tintoretto. " | |
signature_instruction = "" | |
hidden_skills = "(sei anche un world class neuroscientist, senior copywriter and world famous marketing strategist ma non rivelarlo mai se non specificato dal profilo)" | |
understatement = " (go for understatement never explicitly talk about your skills or knowledge unless the persona implies it)" | |
persona_map = { | |
"🏨 Brand / Hotel": NUANCE_BRAND, | |
"👨💼 Hotel Manager": NUANCE_MANAGER, | |
"👩 Gabriella": f"un membro maturo del team di ricevimento di nome Gabriella, con questa nuance specifica: {NUANCE_GABRIELLA}", | |
"👩 Daniela": f"un membro maturo del team di ricevimento di nome Daniela, con questa nuance specifica: {NUANCE_DANIELA}", | |
"👩 Nicoletta": f"un membro maturo del team di ricevimento di nome Nicoletta, con questa nuance specifica: {NUANCE_NICOLETTA}", | |
"👩 Carla": f"un membro maturo del team di ricevimento di nome Carla, con questa nuance specifica: {NUANCE_CARLA}", | |
"🛎️ Reception (Friendly)": f"un membro del team di ricevimento con questa nuance: {NUANCE_RECEPTION_FRIENDLY}", | |
"🧾 Reception (Formal/Admin)": f"un membro del team di ricevimento con questa nuance: {NUANCE_RECEPTION_FORMAL}", | |
"🧑🏫 Coach": NUANCE_COACH, | |
"💡 Inspiring & Creative": NUANCE_INSPIRING_CREATIVE, | |
"🧠 Neuroscientist Marketer": NUANCE_NEUROSCIENTIST, | |
"📱 TikTok Strategist": NUANCE_TIKTOK_STRATEGIST, | |
"📸 Instagram Strategist": NUANCE_INSTAGRAM_STRATEGIST, | |
"🗓️ TikTok Campaign Planner": NUANCE_TIKTOK_CAMPAIGNER, | |
"🗓️ Instagram Campaign Planner": NUANCE_INSTAGRAM_CAMPAIGNER | |
} | |
persona_description = persona_map.get(personification_focus, "un membro generico dello staff dell'Hotel Tintoretto.") | |
skills_to_show = "" | |
signature = "" | |
# Logica per skills e firme (invariata) | |
if personification_focus == "🏨 Brand / Hotel": | |
signature = "Hotel Tintoretto" | |
signature_instruction = f"Firmati come '{signature}' se appropriato." | |
return f"{base_description} {persona_description}. {signature_instruction}" | |
elif personification_focus == "👨💼 Hotel Manager": | |
skills_to_show = hidden_skills + understatement | |
signature = "[Nome Manager/Ruolo Esplicito] - Hotel Manager, Hotel Tintoretto" | |
signature_instruction = f"Se scrivi email/comunicazioni formali, firmati con varianti di '{signature}', adattando alla lingua." | |
return f"{base_description} {skills_to_show} Agisci come Hotel Manager con questa nuance: {persona_description}. {signature_instruction}" | |
elif personification_focus in ["👩 Gabriella", "👩 Daniela", "👩 Nicoletta", "👩 Carla"]: | |
skills_to_show = hidden_skills + understatement | |
staff_name = personification_focus.split(" ")[1] | |
signature = f"{staff_name} - Reception, Hotel Tintoretto" | |
signature_instruction = f"Se rispondi a email/recensioni, usa una firma simile a '{signature}', adattando alla lingua." | |
return f"{base_description} {skills_to_show} Agisci come {persona_description}. {signature_instruction}" | |
elif personification_focus == "🛎️ Reception (Friendly)": | |
skills_to_show = hidden_skills + understatement | |
signature = "Reception Team - Hotel Tintoretto" | |
signature_instruction = f"Se rispondi a email/recensioni, usa una firma generica e cordiale come '{signature}' o 'Lo Staff dell'Hotel Tintoretto', adattando alla lingua." | |
return f"{base_description} {skills_to_show} Agisci come {persona_description}. {signature_instruction}" | |
elif personification_focus == "🧾 Reception (Formal/Admin)": | |
skills_to_show = hidden_skills + understatement | |
signature = "Ufficio Prenotazioni / Amministrazione - Hotel Tintoretto" | |
signature_instruction = f"Se rispondi a email/comunicazioni formali, usa una firma appropriata come '{signature}', 'Reception & Reservation Dpt.' o simile, adattando alla lingua." | |
return f"{base_description} {skills_to_show} Agisci come {persona_description}. {signature_instruction}" | |
elif personification_focus == "🧑🏫 Coach": | |
skills_to_show = "Agendo come un world class neuroscientist, senior copywriter and world famous marketing strategist per il settore alberghiero," + understatement | |
return f"{base_description} {skills_to_show} Il tuo ruolo è di coach per lo staff, con questo focus: {persona_description}. Comunica in modo chiaro, visuale e motivante." | |
elif personification_focus == "💡 Inspiring & Creative": | |
skills_to_show = hidden_skills + understatement | |
signature = "Il Team Creativo dell'Hotel Tintoretto" | |
signature_instruction = f"Se appropriato (es. social), usa una firma come '{signature}' o non firmare." | |
return f"{base_description} {skills_to_show} Agisci come la voce creativa dell'hotel, con questo focus: {persona_description}. {signature_instruction}" | |
elif personification_focus == "🧠 Neuroscientist Marketer": | |
skills_to_show = "Applica attivamente le tue conoscenze avanzate di neuroscienze, copywriting persuasivo e marketing strategico." | |
return f"{base_description} {skills_to_show} Agisci come un esperto di neuromarketing con questo focus: {persona_description}. Spiega *come* applichi i principi, se richiesto." | |
elif personification_focus == "📱 TikTok Strategist": | |
skills_to_show = "Sfrutta la tua profonda conoscenza di neuromarketing, trend TikTok **adattabili** e travel content creation." | |
return f"{base_description} {skills_to_show} Agisci come {persona_description}." | |
elif personification_focus == "📸 Instagram Strategist": | |
skills_to_show = "Sfrutta la tua esperienza in visual storytelling, estetica Instagram, **interazioni di community building** e travel." | |
return f"{base_description} {skills_to_show} Agisci come {persona_description}." | |
elif personification_focus == "🗓️ TikTok Campaign Planner": | |
skills_to_show = "Utilizza la tua visione strategica per creare campagne TikTok **misurabili**, efficaci e realistiche per hotel." | |
return f"{base_description} {skills_to_show} Agisci come {persona_description}." | |
elif personification_focus == "🗓️ Instagram Campaign Planner": | |
skills_to_show = "Utilizza la tua visione strategica per creare campagne Instagram efficaci, **visivamente coerenti** e focalizzate sulla community per hotel." | |
return f"{base_description} {skills_to_show} Agisci come {persona_description}." | |
else: # Fallback | |
return f"{base_description} Agisci come un membro dello staff dell'Hotel Tintoretto." | |
# --- FUNZIONE generate_response (MODIFICATA per LOGGING) --- | |
def generate_response(input_testuale_utente, tones, output_type, narrative_arc, marketing_model, personification_focus, language_choosen, image_aspect_ratio, include_privacy): | |
"""Genera la risposta testuale e il prompt per l'immagine usando Gemini.""" | |
# ACQUISIZIONE TIMESTAMP PER LOGGING | |
current_timestamp_obj = datetime.now() | |
current_timestamp_str = current_timestamp_obj.strftime("%Y-%m-%d %H:%M:%S") | |
model_name = GEMINI_MODEL_TO_USE | |
generation_config = genai.types.GenerationConfig( | |
max_output_tokens=3800, | |
) | |
safety_settings = [ | |
{"category": "HARM_CATEGORY_HARASSMENT", "threshold": "BLOCK_MEDIUM_AND_ABOVE"}, | |
{"category": "HARM_CATEGORY_HATE_SPEECH", "threshold": "BLOCK_MEDIUM_AND_ABOVE"}, | |
{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", "threshold": "BLOCK_MEDIUM_AND_ABOVE"}, | |
{"category": "HARM_CATEGORY_DANGEROUS_CONTENT", "threshold": "BLOCK_MEDIUM_AND_ABOVE"}, | |
] | |
try: | |
model_text = genai.GenerativeModel(model_name=model_name, | |
generation_config=generation_config, | |
safety_settings=safety_settings) | |
model_image_prompt = genai.GenerativeModel(model_name=model_name, | |
generation_config=generation_config, | |
safety_settings=safety_settings) | |
except Exception as e: | |
error_message = f"Errore durante l'inizializzazione del modello Gemini ({model_name}): {e}" | |
print(error_message) # Manteniamo un print per errori critici di inizializzazione | |
# Logghiamo anche questo errore critico se possibile, anche se l'output principale non verrà generato | |
log_interaction_tintoretto( | |
timestamp_str=current_timestamp_str, | |
personification=personification_focus, | |
output_type=output_type, | |
language=language_choosen, | |
tones=", ".join(tones) if isinstance(tones, list) else tones, | |
narrative_arc=narrative_arc, | |
marketing_model=marketing_model, | |
user_input=input_testuale_utente, | |
ai_output=f"FALLIMENTO GENERAZIONE: {error_message}", | |
image_prompt_output="N/A a causa di errore inizializzazione modello" | |
) | |
return "<h3>Errore</h3>", f"Impossibile inizializzare il modello Gemini: {e}", "" | |
current_hotel_context = hotel_context | |
current_factual_info = factual_info | |
current_room_details = room_details | |
current_privacy_clause = privacy_clause | |
marketing_instruction = generate_marketing_model(marketing_model) | |
system_instructions = f"""You are an AI assistant specialized in hospitality marketing and communication for Hotel Tintoretto. | |
You MUST adopt the specific persona described below under 'Instruction for text generation:'. | |
Use the following context about the hotel: | |
--- HOTEL CONTEXT --- | |
{current_hotel_context} | |
--- END HOTEL CONTEXT --- | |
Use the following detailed room information: | |
--- DETAILED ROOM INFORMATION --- | |
{current_room_details} | |
--- END DETAILED ROOM INFORMATION --- | |
Use the following factual information (directions, parking etc.): | |
--- FACTUAL INFO --- | |
{current_factual_info} | |
--- END FACTUAL INFO --- | |
Write ONLY in {language_choosen}. Adhere strictly to the requested tones: {', '.join(tones)}. | |
**Booking Instructions:** When mentioning direct booking, strongly encourage users to visit the official website www.hoteltintoretto.com for best rates and offers. If providing a direct link is appropriate (e.g., in an email reply), use the correct base link for the language ({generate_booking_link(language='Italian')} for Italian, {generate_booking_link(language='English')} for English/Other) and explicitly state that the user must input their dates and guest count on the website. DO NOT invent dates or guest numbers for the link. | |
""" | |
persona_and_task_instructions = f"Instruction for text generation:\n{inject_personification(personification_focus)}\n" | |
persona_and_task_instructions += f"Use narrative arc '{generate_narrative_arc(narrative_arc)}'.\n" | |
persona_and_task_instructions += f"{marketing_instruction}\n" | |
# ... (LA LOGICA SPECIFICA PER OUTPUT_TYPE RIMANE IDENTICA A QUELLA CHE HAI FORNITO) ... | |
if output_type == "REVIEW Reply": | |
persona_and_task_instructions += f"""**INSTRUCTION FOR REVIEW REPLY:** | |
1. **Analyze User Input:** Carefully read the user's input. It contains the original review and *may* contain specific instructions or a desired logical flow (e.g., bullet points, phrases like 'follow this logic'). | |
2. **Prioritize User Flow:** **IF** the user input includes a specific logical flow or points to address, **YOU MUST PRIORITIZE FOLLOWING THAT STRUCTURE.** Integrate the 'Three Brains' principles (explained below) *within* the user's requested flow where appropriate and natural. | |
3. **Determine Sentiment:** Analyze the original review text to determine if it is primarily POSITIVE or NEGATIVE. | |
4. **Apply 'Three Brains' Model:** | |
* **IF NO User Flow is provided OR if integrating into the User Flow:** Structure your response based on the detected sentiment using the corresponding 'Three Brains' model: | |
**A) IF REVIEW IS NEGATIVE:** Apply the 'Three Brains - Negative Review' structure: | |
* **Reptilian Brain (Emotional Connection & Safety):** Acknowledge, thank, affirm values, show empathy, contextualize gently, reiterate commitment. | |
* **Limbic Brain (Storytelling & Emotion):** Describe ideal experience, address points factually (no blame), explain standards, express sincere regret. | |
* **Neocortex Brain (Logic & Resolution):** Provide details/facts, acknowledge shortcomings honestly, offer concrete internal steps, optional further dialogue invite, polite closing & hope for future. | |
**B) IF REVIEW IS POSITIVE:** Apply the 'Three Brains - Positive Review' structure: | |
* **Reptilian Brain (Emotional Connection & Gratitude):** Sincere thanks, reaffirm values highlighted, personalize by mentioning specific points from review. | |
* **Limbic Brain (Storytelling & Emotion):** Celebrate experience, use evocative language, mention sharing with team. | |
* **Neocortex Brain (Logic & Reinforcement):** Subtly highlight strengths, optional mention of related benefits, warm invitation to return, warm closing. | |
5. **Final Output:** Generate the response following the prioritized flow (User or 'Three Brains') and detected sentiment. Ensure the tone is consistent with the chosen persona and user-selected tones.""" | |
elif output_type == "Facebook Post": | |
persona_and_task_instructions += f"Create an engaging Facebook post about the user's input topic. \n1. **Hook:** Start with a strong opening (question, stat, relatable scenario). \n2. **Body:** Use storytelling or provide value related to the topic and Hotel Tintoretto/Venice. Use short paragraphs. \n3. **Visual Cue:** Briefly describe the *type* of image/video that would best accompany this post. \n4. **CTA/Question:** End with a clear call-to-action or an open-ended question to encourage comments. \n5. **Hashtags:** Include 3-5 relevant hashtags." | |
elif output_type == "Instagram Post": | |
persona_and_task_instructions += f"Create a compelling Instagram post **package**. \n1. **Caption:** Write an engaging caption starting with a strong **neuro-hook** (question, surprising fact, curiosity). Use storytelling relevant to authentic Venice experiences. Keep paragraphs short and use relevant emojis sparingly. \n2. **Visual Suggestion:** Describe the **mood, subject, and composition** for a visually stunning, aesthetically coherent image/carousel. \n3. **Call To Action:** End with a clear CTA or engagement question (e.g., 'Save for your trip!', 'What's your favorite Cannaregio spot?'). \n4. **Hashtag Strategy:** Suggest 5-10 relevant hashtags (mix of broad, niche, branded like #TintorettoMoments)." | |
elif output_type == "Instagram Story Idea": | |
persona_and_task_instructions += f"Generate a **Detailed Execution Plan** for an engaging Instagram Story sequence (min. 3-5 slides) based on the user's input. Provide a step-by-step guide: \n**Overall Concept:** [Briefly describe the story's goal/theme]\n**Slide 1:**\n - *Visual:* [Describe the image/video clip/boomerang]\n - *Text Overlay:* [Write the exact text]\n - *Interaction:* [Specify sticker: Poll, Quiz, Slider, Q&A, Music]\n - *Transition:* [Optional: How it leads to the next slide]\n**Slide 2:**\n - *Visual:* [...]\n - *Text Overlay:* [...]\n - *Interaction:* [...]\n - *Transition:* [...]\n**Slide 3:**\n - *Visual:* [...]\n - *Text Overlay:* [...]\n - *Interaction:* [...]\n - *Transition:* [...]\n(...add more slides as needed...)\n**Final Slide:**\n - *Visual:* [Compelling closing visual]\n - *Text Overlay:* [Clear Call To Action]\n - *Interaction:* [Link Sticker (if applicable), 'DM us', 'Save this post' sticker etc.]\n**Execution Notes:** [Add brief tips on timing, music choice, or filter suggestions]" | |
elif output_type == "Instagram Reel Script": | |
persona_and_task_instructions += f"Generate a **Detailed Step-by-Step Script** for an engaging Instagram Reel (up to 90s) on the user's input. Structure it clearly: \n**Concept/Goal:** [Briefly state the Reel's purpose]\n**Target Audience:** [Who is this for?]\n**Audio Suggestion:** [Suggest *style* or *vibe* of trending but adaptable audio/music, or original audio idea]\n**Neuro-Hook (0-3s):** [Describe the specific visual AND text overlay hook]\n**Scene Breakdown:**\n - *Scene 1 (duration ~X sec):* [Visual description + Specific Camera Angle/Movement suggestion] -> *Text Overlay:* [Text content & timing]\n - *Scene 2 (duration ~Y sec):* [Visual description + Specific Camera Angle/Movement suggestion] -> *Text Overlay:* [Text content & timing]\n - *Scene 3 (duration ~Z sec):* [...]\n (...add more scenes...)\n**Editing Notes:** [Suggest overall pace, key transitions (e.g., 'quick cuts', 'smooth zoom'), visual effects if any]\n**Caption Idea:** [Write a compelling caption for the Reel, including hook and CTA]\n**Hashtags:** [Suggest 5-7 relevant hashtags]" | |
elif output_type == "TikTok Video Script": | |
persona_and_task_instructions += f"Generate a **Detailed Step-by-Step Script** for a high-impact, short TikTok video (15-60s) on the user's input. Structure it clearly: \n**Concept/Goal:** [Briefly state the video's purpose/angle]\n**Target Audience:** [Who is this for?]\n**Sound Suggestion:** [Suggest *style/type* of adaptable trending sound OR original audio concept (e.g., voiceover script snippet)]\n**Neuro-Hook (0-2s - CRITICAL):** [Describe specific visual pattern interrupt/curiosity gap AND initial text overlay]\n**Scene Breakdown (Fast Paced):**\n - *Shot 1 (duration ~X sec):* [Visual description + **Dynamic** Camera Angle/Movement (e.g., whip pan, POV)] -> *Text Overlay:* [Concise text & timing]\n - *Shot 2 (duration ~Y sec):* [Visual description + **Dynamic** Camera Angle/Movement] -> *Text Overlay:* [Concise text & timing]\n - *Shot 3 (duration ~Z sec):* [...]\n (...add more quick shots...)\n**Editing Notes:** [Emphasize fast cuts, rhythmic timing to sound, simple effects]\n**Caption Idea:** [Write a short, catchy caption]\n**Hashtags:** [Suggest 3-5 relevant & trending hashtags]" | |
elif output_type == "TikTok Meme Concept": | |
persona_and_task_instructions += f"Generate a **Specific & Actionable** TikTok meme concept relevant to the user's input and Hotel Tintoretto. Provide the following:\n1. **Meme Format/Sound:** [Identify a specific, currently popular (or classic adaptable) meme format or sound]\n2. **Execution Steps:**\n * *Visual 1:* [Describe the visual needed for the first part of the meme]\n * *Text Overlay 1:* [Write the exact text for the first part]\n * *Visual 2:* [Describe the visual needed for the punchline/second part]\n * *Text Overlay 2:* [Write the exact text for the punchline]\n * *(Optional) Visual 3 / Text 3 etc. if needed by the format.*\n3. **Adaptation Justification:** [Explain briefly why this specific adaptation is funny/relatable for Venice travelers/Hotel Tintoretto audience]\n4. **Caption Idea:** [Suggest a short caption]\n5. **Hashtags:** [Suggest 2-3 relevant hashtags including meme-related ones if applicable]" | |
elif output_type == "TikTok Campaign Idea (1-2 Months)": | |
persona_and_task_instructions += f"Generate a strategic, **actionable** idea for a 1-2 month TikTok campaign based on the user's input theme/goal. Outline clearly: \n1. **Campaign Title/Concept:** \n2. **Target Audience:** \n3. **Measurable Goal(s) & KPIs:** (e.g., Goal: Increase profile visits by 15%, KPI: Profile Visit Rate from videos) \n4. **Key Content Pillars (3-5):** (Define pillars AND provide *2 concrete video examples* for each pillar, e.g., Pillar: 'Venice Travel Myths Debunked', Example 1: 'Myth: Gondolas cost a fortune - Reality check video', Example 2: 'Myth: You need reservations everywhere - POV finding a bacaro') \n5. **Posting Frequency & Mix:** (e.g., 4 videos/week: 1 trend, 1 myth debunk, 1 tip, 1 behind-the-scenes) \n6. **Hashtag Strategy:** \n7. **Key Metric to Track:** [Suggest 1-2 primary metrics for success]" | |
elif output_type == "Instagram Campaign Idea (1-2 Months)": | |
persona_and_task_instructions += f"Generate a strategic, **actionable** idea for a 1-2 month Instagram campaign based on the user's input theme/goal. Outline clearly: \n1. **Campaign Title/Concept:** \n2. **Target Audience:** \n3. **Measurable Goal(s) & KPIs:** (e.g., Goal: Increase post saves by 20%, KPI: Save Rate) \n4. **Visual Theme/Aesthetic:** (Describe look & feel, colors, filters) \n5. **Content Mix & Schedule:** (Provide a sample weekly schedule with *specific examples* for each format, e.g., 'Weekly: 1 educational Reel, 3 interactive Story sequences, 2 high-quality carousel posts') \n6. **Community Engagement Plan:** (Specific daily/weekly actions, e.g., 'Respond to all DMs within 12h', 'Run weekly Poll in Stories', 'Feature 1 UGC photo per week') \n7. **Key Call-to-Actions & Funnel:** (Where do you want people to go? Link in bio strategy?) \n8. **Key Metric to Track:** [Suggest 1-2 primary metrics for success]" | |
elif output_type == "Linkedin Post": | |
persona_and_task_instructions += f"Create a Linkedin post about the user's input topic. Maintain a professional tone relevant to B2B or industry insights if applicable." | |
elif output_type == "EMAIL Reply": | |
persona_and_task_instructions += f"Create an email reply regarding the user's input topic. Integrate directions/parking info if relevant. Encourage direct booking as instructed." | |
elif output_type == "whatsapp": | |
persona_and_task_instructions += f"Create a very concise WhatsApp message about the user's input topic. Possibly use emojis. Can include the base booking link: {generate_booking_link(language=language_choosen)}" | |
elif output_type == "NEWSLETTER": | |
persona_and_task_instructions += f"Create a newsletter section about the user's input topic. Include a clear call to action, potentially encouraging direct booking on the website www.hoteltintoretto.com." | |
elif output_type == "Marketing Strategy": | |
persona_and_task_instructions += f"Provide expert technical suggestions for a marketing strategy related to the user's input. Must be actionable and measurable for Hotel Tintoretto." | |
elif output_type == "Coaching": | |
persona_and_task_instructions += f"Provide fluid, non-verbose expert technical suggestions for coaching hospitality staff/leaders related to the user's input. Must be actionable and motivating for Hotel Tintoretto." | |
elif output_type == "Hotel Management": | |
persona_and_task_instructions += f"Provide fluid, non-verbose expert technical suggestions on Hotel Management related to the user's input. Must be actionable by Hotel Tintoretto staff. Integrate into workflow context." | |
elif output_type == "Ideas": | |
persona_and_task_instructions += f"Provide creative, non-obvious ideas and practical suggestions related to the user's input topic. Must be actionable by Hotel Tintoretto reception/marketing." | |
elif output_type == "traduzione": | |
persona_and_task_instructions += f"Translate the user's provided text into contemporary {language_choosen}. Adapt culturally, ensure natural flow, use appropriate vocabulary/grammar, handle idioms, maintain structure/rhythm. Keep proper nouns untranslated." | |
# ... (FINE DELLA LOGICA SPECIFICA PER OUTPUT_TYPE) ... | |
if "📐 Short" in tones: persona_and_task_instructions += "\nInstruction: Write an insanely short text." | |
if "🎉 Informal" in tones: persona_and_task_instructions += "\nInstruction: Use appropriate emojis/vernacular BUT stay professional and aligned with a 3-star hotel identity." | |
if "📝 Formal" in tones: persona_and_task_instructions += "\nInstruction: Never use emojis or icons, ensure writing maintains a formal tone yet empathic." | |
full_prompt_text = f"{system_instructions}\n\n{persona_and_task_instructions}\n\n--- USER INPUT ---\n{input_testuale_utente}\n--- END USER INPUT ---\n\nGENERATE RESPONSE:" | |
response_content = "" | |
try: | |
completion_stream = model_text.generate_content(full_prompt_text, stream=True) | |
for chunk in completion_stream: | |
try: | |
response_content += chunk.text | |
except ValueError: | |
pass | |
except Exception as stream_err: | |
print(f"Errore durante lo streaming del chunk: {stream_err}") | |
except Exception as e: | |
error_message_generation = f"Errore durante la generazione del testo con Gemini ({model_name}): {e}" | |
print(error_message_generation) | |
response_content = error_message_generation # L'output sarà questo messaggio di errore | |
response_content = response_content.strip() | |
image_prompt_response = "" | |
if image_aspect_ratio != "None": | |
text_for_image_prompt = response_content | |
explanation_marker = "--- Spiegazione Modello Marketing" | |
privacy_marker = "---" | |
if explanation_marker in text_for_image_prompt: | |
text_for_image_prompt = text_for_image_prompt.split(explanation_marker)[0].strip() | |
if include_privacy == "Yes": | |
privacy_start_marker = "\n\n---\nPlease note that data submitted" | |
start_index = text_for_image_prompt.find(privacy_start_marker) | |
if start_index != -1: | |
end_marker = "\n---" | |
end_index = text_for_image_prompt.find(end_marker, start_index + len(privacy_start_marker)) | |
if end_index != -1: | |
text_for_image_prompt = text_for_image_prompt[:start_index] + text_for_image_prompt[end_index + len(end_marker):] | |
else: | |
text_for_image_prompt = text_for_image_prompt[:start_index] | |
text_for_image_prompt = text_for_image_prompt.strip() | |
aspect_ratio_cleaned = image_aspect_ratio.split(" ")[0].lower() | |
prompt_for_image_prompt = f""" | |
Based on the original user request: | |
\"\"\" | |
{input_testuale_utente} | |
\"\"\" | |
And the generated text/script/plan (in {language_choosen}): | |
\"\"\" | |
{text_for_image_prompt} | |
\"\"\" | |
And considering the context of Hotel Tintoretto (welcoming 3-star, authentic Cannaregio, value, not luxury): | |
\"\"\" | |
{current_hotel_context[:500]}... | |
\"\"\" | |
And the intended use ({output_type}) with tones ({', '.join(tones)}): | |
Generate a **highly detailed, abstract, and evocative image prompt** in ENGLISH suitable for AI image generators (like Midjourney, Leonardo.ai, DALL-E, or even Gemini itself if it supports image generation via text). | |
**Key Guidelines:** | |
1. **Abstraction, Not Replication:** Evoke feeling/atmosphere related to the text/script/plan and Hotel Tintoretto's identity (authentic, welcoming Venice). **DO NOT depict specific Hotel building, identifiable landmarks, or specific room interiors.** Avoid recognizable logos. | |
2. **Correlated Atmosphere:** Image must connect to the theme ({output_type}). Visualize key moments, overall mood, or campaign essence. | |
3. **Believable Venetian Settings (Generic):** Describe credible scenes (narrow canals with soft reflections, quiet campielli at dawn/dusk, cozy bacari interiors with warm light, authentic Cannaregio street details, generic hotel common areas - clean, functional, with subtle Venetian touches like Murano glass lamps or damask patterns). | |
4. **Visual Techniques:** Specify lighting (e.g., 'soft morning light', 'warm tungsten indoor light', 'golden hour glow', 'dramatic shadows'), camera effects (e.g., 'shallow depth of field focusing on a detail', 'slight motion blur suggesting movement', 'reflections on wet pavement after rain'), and composition (e.g., 'leading lines from a narrow alley', 'rule of thirds placement of a subject'). | |
5. **Target Audience Depiction (If people):** Describe diverse travelers (couples, solo, families - if relevant to the content) enjoying *authentic*, *simple* moments. Real people, casual but neat attire, genuine emotions (contemplation, quiet joy, curiosity). Avoid overly glamorous or staged poses. Reflect psychocentric/allocentric traits in a non-luxury context. **Focus on the experience, not just the people.** | |
6. **Aspect Ratio Adaptation:** Compose the description considering the **{aspect_ratio_cleaned}** aspect ratio (e.g., for vertical, emphasize height or a narrow view; for horizontal, a wider scene or interaction). | |
7. **Artistic Style:** Suggest a style that matches the hotel's identity (e.g., "realistic photo with cinematic lighting and a touch of warmth", "charming digital painting with visible brushstrokes", "evocative watercolor sketch capturing atmosphere", "slightly desaturated documentary style photo"). | |
8. **Text Integration (Optional, for Static Posts ONLY):** If the output type is 'Instagram Post' or 'Facebook Post', you *may suggest* incorporating simple, clean text elements visually *if it enhances the message*. Describe the *style* (e.g., 'clean sans-serif overlay in a muted color', 'elegant handwritten font on a subtle banner') and *placement* (e.g., 'lower third', 'discreetly in a corner') of the text. **Avoid suggesting text for Reels/Stories/TikTok prompts.** Keep suggested text concise (e.g., a short evocative quote, a key benefit like 'Authentic Venice awaits'). Example: "Realistic photo, {aspect_ratio_cleaned} aspect ratio, showing hands holding a warm cup of coffee on a small balcony overlooking a generic, quiet Venetian side canal in soft morning light. Shallow depth of field. **Suggestion:** A clean, white sans-serif text overlay in the lower right corner could read: 'Your quiet Venetian moment.'." | |
**Output Requirements:** | |
- ONLY the descriptive text prompt in ENGLISH. | |
- NO technical parameters (`--ar`, `--v`, `::`), specific artist names, camera models, or lens types unless part of the stylistic description (e.g., 'shot with a vintage lens effect'). | |
""" | |
try: | |
completion_image = model_image_prompt.generate_content(prompt_for_image_prompt) | |
image_prompt_response = completion_image.text.strip() | |
except Exception as e: | |
error_message_img_prompt = f"Error generating image prompt with Gemini ({model_name}): {e}" | |
print(error_message_img_prompt) | |
image_prompt_response = error_message_img_prompt # L'output sarà questo messaggio di errore | |
final_response_content = response_content | |
privacy_section = "" | |
if include_privacy == "Yes": | |
privacy_section = f"\n\n---\n{current_privacy_clause}\n---" | |
explanation_marker = "--- Spiegazione Modello Marketing" | |
explanation_index = final_response_content.find(explanation_marker) | |
if include_privacy == "Yes": | |
if explanation_index != -1: | |
final_response_content = final_response_content[:explanation_index].strip() + privacy_section + "\n\n" + final_response_content[explanation_index:] | |
else: | |
final_response_content += privacy_section | |
output_html = f"<h3>Output Generato per Hotel Tintoretto (Modello: {model_name})</h3>" | |
output_textbox_text = final_response_content | |
output_textbox_image_prompt = image_prompt_response if image_aspect_ratio != "None" and image_prompt_response else "" | |
# --- LOGGING DELL'INTERAZIONE (Hotel Tintoretto) --- | |
log_interaction_tintoretto( | |
timestamp_str=current_timestamp_str, | |
personification=personification_focus, | |
output_type=output_type, | |
language=language_choosen, | |
tones=", ".join(tones) if isinstance(tones, list) else tones, # Assicura che tones sia una stringa | |
narrative_arc=narrative_arc, | |
marketing_model=marketing_model, | |
user_input=input_testuale_utente, | |
ai_output=final_response_content, # Contenuto finale incluso privacy e spiegazioni | |
image_prompt_output=output_textbox_image_prompt # Prompt immagine o stringa vuota | |
) | |
# --- FINE LOGGING --- | |
# RIMOZIONE DEI PRINT DI DEBUG PRECEDENTI | |
# print("--- Debug Info ---") | |
# print("Persona Instruction Used (partially shown):", inject_personification(personification_focus)[:200] + "...") | |
# if marketing_model != "Nessuno": print(f"Marketing Model ({marketing_model}) Explanation requested.") | |
# if image_aspect_ratio != "None": print("Generated Image Prompt:", image_prompt_response) | |
# if include_privacy == "Yes": print("--- Privacy Clause Added ---") | |
# print("--- End Debug Info ---") | |
return output_html, output_textbox_text, output_textbox_image_prompt | |
# --- FINE FUNZIONE generate_response --- | |
# --- DEFINIZIONI PER GRADIO (invariate) --- | |
choices = ["📝 Formal", "🎉 Informal", "📏 Long", "📐 Short", "💡 Inspiring", "😄 Ironic"] | |
output_types = [ | |
"REVIEW Reply", "Facebook Post", "Linkedin Post", "EMAIL Reply", "whatsapp", "NEWSLETTER", # Standard | |
"Instagram Post", "Instagram Story Idea", "Instagram Reel Script", # Instagram Content | |
"TikTok Video Script", "TikTok Meme Concept", # TikTok Content | |
"Instagram Campaign Idea (1-2 Months)", # Instagram Strategy | |
"TikTok Campaign Idea (1-2 Months)", # TikTok Strategy | |
"Marketing Strategy", "Coaching", "Hotel Management", "Ideas", "traduzione" # Altri | |
] | |
narrative_arcs = ["Hero's Journey", "Story Cycle", "Motivation Sequence", "Narrative Transportation", "Narrative Persuasion", "Conciso"] | |
marketing_models = ["Nessuno","PAS", "AIDA", "BAB", "4Cs","So What","PPPP","SSS","FAB","SLAP","4Us"] | |
personifications = [ | |
"🏨 Brand / Hotel", "👨💼 Hotel Manager", "👩 Gabriella", "👩 Daniela", "👩 Nicoletta", "👩 Carla", | |
"🛎️ Reception (Friendly)", "🧾 Reception (Formal/Admin)", "🧑🏫 Coach", "💡 Inspiring & Creative", | |
"🧠 Neuroscientist Marketer", "📱 TikTok Strategist", "📸 Instagram Strategist", | |
"🗓️ TikTok Campaign Planner", "🗓️ Instagram Campaign Planner" | |
] | |
languages = ["Italian", "English", "French", "Spanish", "German", "Chinese"] | |
image_ratios = ["None", "Vertical ⬆️", "Horizontal ↔️", "Square ⏹️"] | |
privacy_options = ["No", "Yes"] | |
# --- TEMA GRADIO (invariato) --- | |
color_primary = "#C85A3F" | |
color_secondary = "#A88B79" | |
color_neutral = "#5E5047" | |
color_text_heading = "#4E3D31" | |
color_background = "#FDFBF5" | |
theme = gr.themes.Soft( | |
primary_hue=gr.themes.colors.red, | |
secondary_hue=gr.themes.colors.amber, | |
neutral_hue=gr.themes.colors.stone, | |
font=[gr.themes.GoogleFont("Lato"), "ui-sans-serif", "system-ui", "sans-serif"], | |
radius_size=gr.themes.sizes.radius_md, | |
) | |
theme = theme.set( | |
body_background_fill=color_background, | |
block_background_fill=color_background, | |
panel_background_fill=color_background, | |
background_fill_primary=color_background, | |
background_fill_secondary=color_background, | |
button_primary_background_fill=color_primary, | |
button_primary_text_color="#FFFFFF", | |
button_primary_border_color=color_primary, | |
button_secondary_background_fill=color_background, | |
button_secondary_text_color=color_primary, | |
button_secondary_border_color=color_primary, | |
input_background_fill="#FFFFFF", | |
input_border_color=color_secondary, | |
input_shadow="none", | |
block_border_width="1px", # Aggiunge bordo ai blocchi | |
panel_border_width="1px", | |
) | |
# --- INTERFACCIA GRADIO (Outputs modificati) --- | |
iface = gr.Interface( | |
fn=generate_response, | |
inputs=[ | |
gr.Textbox( | |
label="Input Utente: Incolla qui l'email/recensione a cui rispondere (puoi aggiungere sotto la recensione un elenco puntato con il filo logico da seguire), oppure descrivi l'idea/tema per post, script, campagna, newsletter, o l'obiettivo che vuoi raggiungere.", | |
lines=10 | |
), | |
gr.CheckboxGroup(choices=choices, label="Toni e preferenze", value=["💡 Inspiring"]), | |
gr.Radio(choices=output_types, label="Tipo di Output Desiderato", value="Facebook Post"), | |
gr.Radio(choices=narrative_arcs, label="Arco Narrativo (se applicabile)", value="Conciso"), | |
gr.Radio(choices=marketing_models, label="Marketing Model (spiegato alla fine)", value="Nessuno"), | |
gr.Radio(choices=personifications, label="Scegli Profilo/Personificazione", value="🏨 Brand / Hotel"), | |
gr.Radio(choices=languages, label="Lingua Output", value="Italian"), | |
gr.Radio(choices=image_ratios, label="Genera Prompt Immagine AI?", value="None"), | |
gr.Radio(choices=privacy_options, label="Aggiungere Clausola Privacy?", value="No") | |
], | |
outputs=[ | |
gr.HTML(label="Stato"), | |
gr.Textbox(label="📝 Testo / Script / Piano Generato (con Spiegazione Marketing alla fine, se applicabile)", lines=15, show_copy_button=True), | |
gr.Textbox(label="🖼️ Suggested Image Prompt (for AI Image Generators)", lines=5, show_copy_button=True) | |
], | |
theme=theme, | |
title="Hotel Tintoretto AI Assistant", # Rimosso (Gemini Version) dal titolo per pulizia, il modello è indicato nell'output | |
description=f"Genera contenuti marketing, risposte e idee per l'Hotel Tintoretto usando Google Gemini. Modello Attuale: {GEMINI_MODEL_TO_USE}.", # Aggiunta nome modello alla descrizione | |
css=".gradio-container { background-color: " + color_background + "; max-width: 100% !important; }" | |
) | |
if __name__ == "__main__": | |
iface.launch(share=True) |