import os import json import gradio as gr from dotenv import load_dotenv import openai from datetime import datetime load_dotenv() client = openai.OpenAI( api_key=os.environ.get("GROQ_API_KEY"), base_url="https://api.groq.com/openai/v1" ) # Hotel information HOTEL_INFO = """ **AP Hotel & Resorts** ☎️ **Contacto**: +351 289 540 100 (Chamada para a Rede Fixa Nacional) | book@ap-hotelsresorts.com ** Hoteis do grupo **: - AP Adriana Beach Resort | Albufeira - AP Cabanas Beach & Nature | Tavira - AP Eva Senses | Faro - AP Oriental Beach | Portimão - AP Maria Nova Lounge | Tavira - AP Victoria Sports & Beach | Albufeira - AP Dona Aninhas | Viana do Castelo - AP Lago Montargil Conference & Spa | Montargil - AP Sines | Costa Alentejana 🏨 **Quartos Disponiveis**: - Quantidade: 1, 2 ou 3. - Quantos Adultos: 1 a 8. - Quantas Crianças: 0 a 4. - Quantos Bébes: 0 a 2. **Tipos de Reservas** - Alojamento e Pequeno Almoço. - Meia-Pensão (includes Breakfast and Dinner (Beverages not included). Set Menu (Chef's Suggestion)). - Pensão-Completa (includes breakfast, lunch, and dinner (drinks not included). Set Menu (chef's suggestion)). 🎯 **Serviços e Comodidades**: - Wi-Fi grátis em todo o resort - 2 piscinas exteriores para adultos - 2 piscinas exteriores para crianças - Acesso direto à praia - Campo de futebol, basquete, tiro ao arco, vólei de praia, ténis, minigolfe e petanca. - Ginásio com acesso grátis - SPA - Música ao vivo - Espetáculos - Clube infantil ⏰ **Horários**: - Check-in: 14:00 - Check-out: 11h00 - Pequeno-almoço: 07:30 - 10:30 🐕 **Animais**: Aceites em certas áreas de alguns hóteis. """ CHATBOT_SYSTEM_PROMPT = f""" És um agente de Inteligência Aritificial do grupo AP Hotels & Resorts, especializado em ajudar clientes com informações e reservas. *** Princípio Fundamental e Regras Inquebráveis *** 1. **REGRA DE OURO: A tua única fonte de verdade é a "Informação do Hotel" fornecida abaixo de `Informação do Hotw`.** És estritamente e absolutamente proibido de usar qualquer conhecimento externo ou pré-treinado. 2. **SE A RESPOSTA NÃO ESTIVER NO CONTEXTO:** Se um cliente perguntar algo cuja resposta não se encontra explicitamente no `{{context}}`, a tua resposta OBRIGATÓRIA deve ser uma variação de: "Peço desculpa, mas não encontro essa informação específica nos detalhes que tenho sobre o hotel. Posso ajudar com outra questão, talvez sobre os nossos tipos de quarto ou regimes de pensão?" Nunca inventes ou faças suposições. 3. **NÃO FAÇAS PROMESSSAS EXTERNAS:** Não menciones serviços, parcerias ou eventos que não estejam listados no `{{context}}`. **Informação do Hotel**: {{context}} **Tuas Responsabilidades**: 1. Responder a perguntas sobre o hotel, serviços, etc. 2. Ajudar com simulações de reservas (sempre confirma disponibilidade primeiro) 3. Fornecer informações sobre preços, tipos de quartos e comodidades 4. Ser cordial, profissional e prestável em português europeu 5. Se não souberes algo, admite e oferece alternativas **Formato de Conversação**: - Usa emojis ocasionalmente para tornar a conversa mais amigável - Quando falares de reservas, pede sempre: datas, tipo de quarto, número de pessoas - Se o cliente quiser fazer uma reserva, recolhe TODOS os dados necessários antes de confirmar: * Nome completo * Email * Telefone * NIF ou CC * Hotel * Data check-in e check-out * Numero de noites * Quantas pessoas * Número de crianças * Pedidos especiais (opcional) * Board (esclarecendo sempre os 3 tipos de board) **Regras Importantes**: - Baseia as tuas respostas no contexto fornecido acima - Se perguntarem sobre disponibilidade, simula uma verificação e confirma (para fins de demo) - Calcula automaticamente o número de noites e o preço total - A data atual é {datetime.now().strftime('%d de %B de %Y')} - Oferece sempre upgrades ou serviços adicionais quando relevante **Tom**: Profissional, caloroso, prestável e eficiente. """ WELCOME_MESSAGE = """👋 **Bem-vindo ao AP Hotel & Resorts!** Sou o teu agente de IA e estou aqui para ajudar-te com: • 🏨 Informações sobre quartos e preços • 📅 Disponibilidade e reservas • 🍽️ Restaurantes e serviços • 🎯 Comodidades do hotel **Como posso ajudá-lo hoje?**""" def chat_with_bot(message, history): """Process chat messages with the hotel bot""" if not message or message.strip() == "": return history try: context = HOTEL_INFO # Build conversation history messages = [ {"role": "system", "content": CHATBOT_SYSTEM_PROMPT.format(context=context)} ] # Add chat history (skip the welcome message) for user_msg, assistant_msg in history: if user_msg: messages.append({"role": "user", "content": user_msg}) messages.append({"role": "assistant", "content": assistant_msg}) # Add current message messages.append({"role": "user", "content": message}) # Get response from LLM response = client.chat.completions.create( model="openai/gpt-oss-120b", messages=messages, temperature=0.4, max_tokens=1000 ) bot_response = response.choices[0].message.content history.append((message, bot_response)) return history except Exception as e: error_message = f"❌ Desculpe, ocorreu um erro: {str(e)}" history.append((message, error_message)) return history # Create Gradio Interface with gr.Blocks( theme=gr.themes.Ocean(), title="AP Hotel & Resorts", css=""" .main-title {text-align: center; margin-bottom: 0.5rem;} .subtitle { text-align: center; margin: 0 auto 0 auto; font-size: 1.05em; line-height: 1.6; width: 80%; color: var(--body-text-color); } .logo-image { margin: 0 auto; display: block; } .chatbot-container { border-radius: 12px; } .info-box { background-color: #f0f4f8; padding: 1.5rem; border-radius: 12px; border-left: 4px solid #8b7a77; margin: 1rem 0; } .info-box h3 { margin-top: 0; color: #8b7a77; } /* Custom button colors - More specific selectors */ .primary, button.primary, .gradio-button.primary { background: #8b7a77 !important; background-color: #8b7a77 !important; border-color: #8b7a77 !important; color: white !important; } .primary:hover, button.primary:hover, .gradio-button.primary:hover { background: #7a6966 !important; background-color: #7a6966 !important; border-color: #7a6966 !important; } .secondary, button.secondary, .gradio-button.secondary { background: #8b7a77 !important; background-color: #8b7a77 !important; border-color: #8b7a77 !important; color: white !important; } .secondary:hover, button.secondary:hover, .gradio-button.secondary:hover { background: #7a6966 !important; background-color: #7a6966 !important; border-color: #7a6966 !important; } /* Targeting all buttons to ensure color change */ button[variant="primary"] { background: #8b7a77 !important; background-color: #8b7a77 !important; border-color: #8b7a77 !important; } button[variant="secondary"] { background: #8b7a77 !important; background-color: #8b7a77 !important; border-color: #8b7a77 !important; } """ ) as demo: # Header logo = gr.Image( value="logo-ap.png", label="", show_label=False, show_download_button=False, show_share_button=False, show_fullscreen_button=False, height=100, container=False, elem_classes="logo-image" ) gr.Markdown("# 🏨 Agente de IA", elem_classes="main-title") gr.Markdown( """ Este é um agente de inteligência artificial demonstrativo. Ele utiliza a informação disponível sobre o hotel para responder de forma inteligente às tuas perguntas. Testa as suas capacidades! """, elem_classes="subtitle" ) # Tabs with gr.Tabs(): # Tab 1: Chatbot with gr.Tab("💬 Agente de IA"): chatbot = gr.Chatbot( height=500, label="", avatar_images=("logo-ap.png", "logo-ap.png"), type="tuples", elem_classes="chatbot-container", show_label=False, value=[(None, WELCOME_MESSAGE)] ) with gr.Row(): msg = gr.Textbox( placeholder="💬 Escreve a tua mensagem aqui...", show_label=False, scale=9, container=False ) submit_btn = gr.Button("Enviar", variant="primary", scale=1, elem_classes="primary") clear_btn = gr.Button("🗑️ Limpar Conversa", variant="secondary", size="sm", elem_classes="secondary") # Tab 2: Hotel Information with gr.Tab("📋 Informações do Hotel"): gr.Markdown("## 🏨 AP Hotel & Resorts") gr.Markdown("""

📍 Contacto

Telefone: +351 289 540 100 (Chamada para a Rede Fixa Nacional)

Email: book@ap-hotelsresorts.com

""") gr.Markdown("""

🏨 Hotéis do Grupo

🏖️ AP Adriana Beach Resort | Albufeira

🌿 AP Cabanas Beach & Nature | Tavira

AP Eva Senses | Faro

🌊 AP Oriental Beach | Portimão

🎭 AP Maria Nova Lounge | Tavira

AP Victoria Sports & Beach | Albufeira

🏰 AP Dona Aninhas | Viana do Castelo

🏞️ AP Lago Montargil Conference & Spa | Montargil

🌅 AP Sines | Costa Alentejana

""") gr.Markdown("""

🏨 Quartos Disponíveis

Quantidade: 1, 2 ou 3 quartos

Adultos: 1 a 8 pessoas

Crianças: 0 a 4

Bebés: 0 a 2

""") gr.Markdown("""

🍽️ Tipos de Reservas

🛏️ Alojamento e Pequeno Almoço
Inclui pequeno-almoço

🍴 Meia Pensão
Inclui pequeno-almoço e jantar (bebidas não incluídas). Menu do dia (sugestão do Chef)

🍽️ Pensão Completa
Inclui pequeno-almoço, almoço e jantar (bebidas não incluídas). Menu do dia (sugestão do Chef)

""") gr.Markdown("""

⏰ Horários

Check-in: 14:00

Check-out: 11:00

Pequeno-almoço: 07:30 - 10:30

""") gr.Markdown("""

🎯 Serviços e Comodidades

📶 Wi-Fi grátis em todo o resort

🏊 2 piscinas exteriores para adultos

👶 2 piscinas exteriores para crianças

🏖️ Acesso direto à praia

⚽ Campo de futebol

🏀 Basquete

🎯 Tiro ao arco

🏐 Vólei de praia

🎾 Ténis

⛳ Minigolfe

🎱 Petanca

🏋️ Ginásio com acesso grátis

💆 SPA

🎵 Música ao vivo

🎭 Espetáculos

🎪 Clube infantil

""") gr.Markdown("""

🐕 Política de Animais

Animais aceites em certas áreas de alguns hotéis.

* Consulte condições específicas na receção do hotel escolhido

""") gr.HTML("""
© 2025 Timestamp — Todos os direitos reservados
""") # Event handlers - Submit message msg.submit( chat_with_bot, [msg, chatbot], [chatbot] ).then( lambda: "", None, [msg] ) submit_btn.click( chat_with_bot, [msg, chatbot], [chatbot] ).then( lambda: "", None, [msg] ) clear_btn.click(lambda: [(None, WELCOME_MESSAGE)], None, chatbot) if __name__ == "__main__": demo.launch(share=True)