Download app.py from timestampgroup/demo-email-classifier: direct link, hf CLI and curl.
- Browser
- Download file 22.2 kB
-
https://huggingface.co/spaces/timestampgroup/demo-email-classifier/resolve/main/app.py
- Command line
-
hf download hf://spaces/timestampgroup/demo-email-classifier/app.py
-
curl -L -o app.py https://huggingface.co/spaces/timestampgroup/demo-email-classifier/resolve/main/app.py
22.2 kB
| import os | |
| import email | |
| from email import policy | |
| from dotenv import load_dotenv | |
| import openai | |
| import json | |
| import gradio as gr | |
| load_dotenv() | |
| client = openai.OpenAI( | |
| api_key=os.environ.get("GROQ_API_KEY"), | |
| base_url="https://api.groq.com/openai/v1" | |
| ) | |
| CATEGORIES = [ | |
| "Reserva – Novos pedidos de reserva, alterações ou cancelamentos.", | |
| "Check-in/Check-out – Informações sobre chegadas, saidas ou procedimentos.", | |
| "Reclamação – Queixas ou problemas reportados por hóspedes.", | |
| "Elogio – Feedback positivo ou agradecimentos de hóspedes.", | |
| "Pagamento – Questões sobre faturação, pagamentos ou reembolsos.", | |
| "Serviços – Pedidos de serviços adicionais (room service, spa, transfers, etc.).", | |
| "Fornecedores – Comunicações com fornecedores de produtos ou serviços.", | |
| "Eventos – Reservas ou informações sobre eventos, conferências ou casamentos.", | |
| "RH – Questões de recursos humanos e gestão de pessoal.", | |
| "Manutenção – Problemas técnicos ou pedidos de manutenção das instalações.", | |
| "Marketing – Parcerias, promoções ou campanhas publicitárias.", | |
| "Outros – Se nenhuma das anteriores se aplicar." | |
| ] | |
| SYSTEM_PROMPT = ''' | |
| És um assistente especializado em processar e estruturar emails recebidos por um hotel. A tua tarefa é analisar o email e devolver uma resposta em **JSON** com cinco campos principais: | |
| 1. **classification**: A categoria do email (escolhida de uma lista fixa). | |
| 2. **TL;DR**: Um resumo muito curto (2-5 palavras). | |
| 3. **description**: Uma descrição clara e concisa do conteúdo do email. | |
| 4. **structured_data**: Um objeto com campos específicos relevantes para a categoria — preenche **apenas os campos que forem mencionados ou inferíveis com segurança no email**. Se não houver informação suficiente, deixa o campo ausente ou com valor `null`. | |
| 5. **automated_reply**: Uma resposta profissional e personalizada ao email recebido, adaptada à categoria e ao contexto específico. | |
| ### Lista de categorias e campos esperados em `structured_data`: | |
| - **Reserva**: | |
| ```json | |
| { | |
| "guest_name": "string (nome completo do hóspede)", | |
| "email": "string (email de contacto)", | |
| "phone": "string (telefone de contacto)", | |
| "número do CC ": "String", | |
| "nif_cc": "string (NIF)", | |
| "check_in_date": "YYYY-MM-DD", | |
| "check_out_date": "YYYY-MM-DD", | |
| "nights": "número (calculado automaticamente se possível)", | |
| "room_type": "string (ex: 'duplo', 'suite', 'familiar')", | |
| "guests": "número (total de pessoas)", | |
| "adults": "número", | |
| "children": "número", | |
| "special_requests": "string (pedidos especiais, alergias, etc.)", | |
| "meal_plan": "string (ex: 'pequeno-almoço', 'meia-pensão', 'pensão completa')", | |
| "estimated_arrival_time": "HH:MM" | |
| } | |
| ``` | |
| - **Check-in/Check-out**: | |
| ```json | |
| { | |
| "check_in_time": "HH:MM", | |
| "check_out_time": "HH:MM", | |
| "guest_name": "string", | |
| "email": "string", | |
| "phone": "string", | |
| "reservation_id": "string", | |
| "early_checkin": "boolean", | |
| "late_checkout": "boolean", | |
| "special_requests": "string" | |
| } | |
| ``` | |
| - **Reclamação**: | |
| ```json | |
| { | |
| "guest_name": "string", | |
| "reservation_id": "string", | |
| "room_number": "string", | |
| "issue_type": "string (ex: 'limpeza', 'barulho', 'equipamento', 'atendimento')", | |
| "urgency": "Baixa/Média/Alta", | |
| "affected_service": "string", | |
| "date_of_incident": "YYYY-MM-DD", | |
| "compensation_requested": "boolean" | |
| } | |
| ``` | |
| - **Elogio**: | |
| ```json | |
| { | |
| "guest_name": "string", | |
| "highlighted_service": "string", | |
| "staff_member": "string", | |
| "department": "string", | |
| "reservation_id": "string" | |
| } | |
| ``` | |
| - **Pagamento**: | |
| ```json | |
| { | |
| "guest_name": "string", | |
| "invoice_number": "string", | |
| "reservation_id": "string", | |
| "amount": "string (ex: '€250.00')", | |
| "payment_method": "string (ex: 'transferência', 'MB WAY', 'cartão')", | |
| "payment_status": "string (ex: 'pago', 'pendente', 'reembolso')", | |
| "due_date": "YYYY-MM-DD", | |
| "nif": "string (para faturação)" | |
| } | |
| ``` | |
| - **Serviços**: | |
| ```json | |
| { | |
| "requested_service": "string (ex: 'room service', 'spa', 'transfer', 'babysitting')", | |
| "service_datetime": "YYYY-MM-DDTHH:MM", | |
| "guest_name": "string", | |
| "room_number": "string", | |
| "location": "string", | |
| "number_of_people": "número", | |
| "special_requirements": "string" | |
| } | |
| ``` | |
| - **Fornecedores**: | |
| ```json | |
| { | |
| "supplier_name": "string", | |
| "contact_person": "string", | |
| "product_or_service": "string", | |
| "delivery_date": "YYYY-MM-DD", | |
| "delivery_time": "HH:MM", | |
| "order_number": "string", | |
| "quantity": "string" | |
| } | |
| ``` | |
| - **Eventos**: | |
| ```json | |
| { | |
| "event_type": "string (ex: 'casamento', 'conferência', 'aniversário')", | |
| "event_date": "YYYY-MM-DD", | |
| "event_time": "HH:MM", | |
| "expected_guests": "número", | |
| "contact_person": "string", | |
| "email": "string", | |
| "phone": "string", | |
| "budget_range": "string", | |
| "catering_required": "boolean", | |
| "accommodation_required": "boolean", | |
| "special_requirements": "string" | |
| } | |
| ``` | |
| - **RH**: | |
| ```json | |
| { | |
| "topic": "string (ex: 'férias', 'folga', 'recrutamento', 'formação')", | |
| "employee_name": "string", | |
| "department": "string", | |
| "start_date": "YYYY-MM-DD", | |
| "end_date": "YYYY-MM-DD", | |
| "urgency": "Baixa/Média/Alta" | |
| } | |
| ``` | |
| - **Manutenção**: | |
| ```json | |
| { | |
| "location": "string (ex: 'quarto 312', 'receção', 'piscina')", | |
| "issue_description": "string", | |
| "issue_type": "string (ex: 'elétrico', 'canalização', 'ar condicionado', 'mobiliário')", | |
| "urgency": "Baixa/Média/Alta", | |
| "reported_by": "string", | |
| "affects_guests": "boolean" | |
| } | |
| ``` | |
| - **Marketing**: | |
| ```json | |
| { | |
| "campaign_name": "string", | |
| "partner": "string", | |
| "contact_person": "string", | |
| "start_date": "YYYY-MM-DD", | |
| "end_date": "YYYY-MM-DD", | |
| "campaign_type": "string (ex: 'redes sociais', 'email marketing', 'parceria')", | |
| "budget": "string" | |
| } | |
| ``` | |
| - **Outros**: | |
| ```json | |
| { | |
| "topic": "string", | |
| "requires_follow_up": "boolean" | |
| } | |
| ``` | |
| ### Instruções para `automated_reply`: | |
| Regra Principal: | |
| - **Deteta automaticamente o idioma do email original (português ou inglês)**. | |
| - **Se o email estiver em inglês**, todos os campos de texto gerados devem estar **em português profissional**, o campo "automated_reply" deve vir em inglês adaptado culturalmente (ex: “Dear Mr. Smith”). | |
| - **Se o email estiver em português**, mantém o português europeu formal e cordial. | |
| - Usa sempre o nome do remetente, se disponível. | |
| - **Reserva**: | |
| - Se TODOS os campos obrigatórios estiverem presentes (nome, contacto, datas, tipo de quarto, NIF/CC): confirma a receção do pedido e informa que será processado. | |
| - Se FALTAREM dados obrigatórios: solicita educadamente as informações em falta. Campos obrigatórios: `guest_name`, `email` ou `phone`, `nif_cc`, `check_in_date`, `check_out_date`, `room_type`, `guests`. | |
| - **Check-in/Check-out**: Confirma o pedido e informa sobre políticas ou procedimentos relevantes. | |
| - **Reclamação**: Pede desculpa pelo incómodo, assegura que a situação será analisada com prioridade, e agradece o feedback. | |
| - **Elogio**: Agradece calorosamente o feedback positivo e transmite os elogios à equipa mencionada. | |
| - **Pagamento**: Confirma receção do pedido e informa sobre os próximos passos ou envia documentação solicitada. | |
| - **Serviços**: Confirma o pedido de serviço e informa disponibilidade ou solicita confirmação adicional. | |
| - **Fornecedores**: Confirma receção da comunicação e próximos passos. | |
| - **Eventos**: Agradece o interesse, solicita informações adicionais se necessário, ou confirma disponibilidade. | |
| - **RH**: Confirma receção e informa sobre processo de aprovação. | |
| - **Manutenção**: Confirma que a situação foi registada e será tratada com a devida urgência. | |
| - **Marketing**: Agradece a proposta e indica interesse em explorar a parceria. | |
| - **Outros**: Resposta genérica confirmando receção e indicando que será dado seguimento. | |
| **Tom da resposta**: Profissional, cordial, empático, em português europeu. Usa o nome do hóspede/contacto quando disponível. Mantém um tom caloroso mas profissional. | |
| ### Instruções importantes: | |
| - **NÃO inventes dados**. Só preenche campos se o email contiver informação clara ou se for uma inferência óbvia. | |
| - Se não houver dados suficientes para um campo, **omite-o** ou usa `null`. | |
| - **Mantém tudo em português europeu**. | |
| - **Responde apenas com um objeto JSON válido**, sem explicações adicionais, markdown ou texto extra. | |
| - A data atual é **3 de novembro de 2025** — podes usar isto para interpretar expressões como "amanhã", "na próxima semana", etc. | |
| - Para reservas, se faltarem campos obrigatórios, a `automated_reply` DEVE solicitar essas informações específicas de forma clara e educada. | |
| ### Exemplo de resposta válida (Reserva completa): | |
| ```json | |
| { | |
| "classification": "Reserva", | |
| "TL;DR": "Nova reserva", | |
| "description": "Pedido de reserva de quarto duplo para duas pessoas de 15 a 17 de novembro com vista para o mar.", | |
| "structured_data": { | |
| "guest_name": "Miguel Ferreira", | |
| "check_in_date": "2025-11-15", | |
| "check_out_date": "2025-11-17", | |
| "nights": 2, | |
| "room_type": "duplo", | |
| "guests": 2, | |
| "special_requests": "vista para o mar" | |
| }, | |
| "automated_reply": "Exmo. Sr. Miguel Ferreira,\n\nAgradecemos o seu contacto e interesse no nosso hotel.\n\nPara procedermos com a sua reserva de um quarto duplo com vista para o mar de 15 a 17 de novembro (2 noites), necessitamos de alguns dados adicionais:\n\n• Número de telefone ou email de contacto\n• Número do Cartão de Cidadão ou NIF (obrigatório para registo)\n• Hora prevista de chegada\n• Preferência de regime alimentar (apenas pequeno-almoço, meia-pensão, etc.)\n\nAssim que recebermos estas informações, teremos todo o prazer em confirmar a sua reserva.\n\nFicamos ao dispor para qualquer esclarecimento adicional.\n\nCom os melhores cumprimentos,\nEquipa de Reservas" | |
| } | |
| ``` | |
| ### Exemplo de resposta válida (Reclamação): | |
| ```json | |
| { | |
| "classification": "Reclamação", | |
| "TL;DR": "Barulho noturno", | |
| "description": "Hóspede reclama de barulho excessivo no corredor durante a madrugada no quarto 203.", | |
| "structured_data": { | |
| "guest_name": "Tiago Mendes", | |
| "room_number": "203", | |
| "issue_type": "barulho", | |
| "urgency": "Média", | |
| "affected_service": "descanso noturno" | |
| }, | |
| "automated_reply": "Exmo. Sr. Tiago Mendes,\n\nLamentamos profundamente o incómodo causado durante a sua estadia no quarto 203.\n\nA situação que nos reporta relativamente ao barulho no corredor durante a madrugada é inaceitável e será imediatamente analisada pela nossa equipa de gestão. Estamos a tomar medidas para garantir que situações semelhantes não voltem a ocorrer.\n\nO seu conforto e descanso são a nossa prioridade máxima. Gostaríamos de contactá-lo pessoalmente para apresentar as nossas desculpas e encontrar uma solução adequada.\n\nAgradecemos por nos ter alertado para esta situação.\n\nCom os melhores cumprimentos,\nDireção do Hotel" | |
| } | |
| ``` | |
| ''' | |
| def summarize_and_classify(email_body: str): | |
| response = client.responses.create( | |
| model="openai/gpt-oss-120b", | |
| input=[ | |
| {"role": "system", "content": SYSTEM_PROMPT}, | |
| {"role": "user", "content": email_body} | |
| ] | |
| ) | |
| return response.output_text.strip() | |
| def classify_email(email_body: str): | |
| if not email_body.strip(): | |
| return "Nenhuma entrada fornecida", "", "", "" | |
| summary_text = summarize_and_classify(email_body) | |
| try: | |
| summary_json = json.loads(summary_text) | |
| classification = summary_json.get("classification", "Classificação Manual") | |
| tldr = summary_json.get("TL;DR", "N/A") | |
| description = summary_json.get("description", "N/A") | |
| json_output = json.dumps(summary_json.get("structured_data", {}), indent=2, ensure_ascii=False) | |
| automatic_answer = summary_json.get("automated_reply", "N/A") | |
| except json.JSONDecodeError: | |
| classification = "⚠️ Erro ao analisar JSON" | |
| tldr = "" | |
| description = summary_text | |
| json_output = "" | |
| automatic_answer= "" | |
| return classification, tldr, description, json_output, automatic_answer | |
| def exemplo_email(tipo): | |
| exemplos = { | |
| "reserva": "Assunto: Pedido de reserva para o fim de semana\n\nBom dia,\nGostaria de reservar um quarto duplo para duas pessoas de 15 a 17 de novembro.\nPreferencialmente com vista para o mar.\nPodem confirmar a disponibilidade, por favor?\nCumprimentos,\nMiguel Ferreira", | |
| "checkin": "Assunto: Pedido de check-out tardio\n\nBoa tarde,\nTenho uma reserva para amanhã (nº RES-2025-345).\nSerá possível fazer o check-out pelas 14h, em vez das 11h?\nObrigado,\nCarla Ramos", | |
| "reclamacao": "Assunto: Reclamação sobre barulho durante a noite\n\nBoa noite,\nDurante a minha estadia no quarto 203, houve muito barulho no corredor até às 3h da manhã.\nPeço que revejam esta situação, pois foi bastante incómodo.\nCumprimentos,\nTiago Mendes", | |
| "elogio": "Assunto: Agradecimento pela estadia maravilhosa\n\nOlá,\nGostaria de agradecer a toda a equipa pela simpatia e profissionalismo, especialmente à Sra. Joana da receção.\nO serviço foi impecável!\nCom os melhores cumprimentos,\nInês Oliveira", | |
| "pagamento": "Assunto: Fatura pendente — reserva #2025-0021\n\nBoa tarde,\nPodem enviar-me a fatura referente à minha estadia de outubro?\nO pagamento foi feito por transferência bancária, no valor de €420,00.\nObrigada,\nRita Santos", | |
| "servicos": "Assunto: Pedido de massagem e jantar no quarto\n\nBoa noite,\nEstou hospedado no quarto 507 e gostaria de agendar uma massagem para amanhã às 17h, e o jantar no quarto pelas 20h.\nCumprimentos,\nHugo Matos", | |
| "fornecedores": "Assunto: Entrega de vinhos — Quinta da Serra\n\nBom dia,\nConfirmamos a entrega dos vinhos tintos reserva para dia 6 de novembro, pelas 10h.\nCumprimentos,\nAntónio Silva\nQuinta da Serra Lda.", | |
| "eventos": "Assunto: Pedido de orçamento para casamento\n\nOlá,\nGostaríamos de saber se o vosso hotel organiza casamentos.\nPretendemos realizar o evento no dia 20 de junho de 2026, para cerca de 120 convidados.\nO contacto principal será a noiva, Marta Lopes.\nObrigada!", | |
| "rh": "Assunto: Pedido de férias — dezembro\n\nBom dia,\nVenho solicitar férias de 16 a 30 de dezembro.\nAgradeço confirmação.\nCumprimentos,\nPaulo Costa\nDepartamento de Manutenção", | |
| "manutencao": "Assunto: Ar condicionado avariado — quarto 312\n\nBoa tarde,\nO ar condicionado do quarto 312 não está a funcionar corretamente.\nEstá a emitir um ruído forte e não arrefece.\nAgradeço reparação urgente.\nObrigado,\nReceção", | |
| "marketing": "Assunto: Proposta de parceria — Influenciadora de viagens\n\nOlá,\nSou a Carolina Sousa, criadora de conteúdo na área de viagens.\nGostaria de propor uma parceria para divulgação do vosso hotel nas minhas redes sociais durante novembro.\nPosso enviar proposta detalhada.\nObrigada,\nCarolina Sousa", | |
| "outros": "Assunto: Pedido de informações gerais\n\nBoa tarde,\nGostaria de saber se o vosso hotel aceita animais de estimação e se existe estacionamento gratuito.\nCumprimentos,\nJoão Almeida", | |
| } | |
| return exemplos[tipo] | |
| with gr.Blocks(theme=gr.themes.Ocean(), title="Classificador de Emails", css=""" | |
| .main-title {text-align: center;} | |
| .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; | |
| } | |
| .category-box { | |
| display: inline-block; | |
| padding: 6px 12px; | |
| margin: 4px; | |
| background-color: #f5f0ef; | |
| border-radius: 12px; | |
| font-size: 0.85em; | |
| color: #8b7a77; | |
| font-weight: 500; | |
| border: 1px solid #8b7a77; | |
| } | |
| .category-container { | |
| text-align: center; | |
| flex-wrap: wrap; | |
| display: flex; | |
| justify-content: center; | |
| margin-bottom: 2rem; | |
| } | |
| /* Custom button colors */ | |
| .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 { | |
| display: inline-block !important; | |
| padding: 6px 12px !important; | |
| margin: 4px !important; | |
| background-color: #f5f0ef !important; | |
| background: #f5f0ef !important; | |
| border-radius: 12px !important; | |
| font-size: 0.85em !important; | |
| color: #8b7a77 !important; | |
| font-weight: 500 !important; | |
| border: 1px solid #8b7a77 !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-color: #f5f0ef; | |
| color: #8b7a77; | |
| border: 1px solid #8b7a77; | |
| }""") as demo: | |
| 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("# 📧 Classificação e Resposta Automática a E-mails", elem_classes="main-title") | |
| gr.Markdown( | |
| """ | |
| Este agente utiliza inteligência artificial para analisar, categorizar e propor respostas automáticas a emails recebidos por estabelecimentos hoteleiros. O sistema identifica com precisão o tipo de email, as entidades, fornece resumos executivos, classificando cada email nas seguintes categorias: | |
| """, | |
| elem_classes="subtitle" | |
| ) | |
| categories_html = "".join([ | |
| f'<div class="category-box">{cat.split(" – ")[0]}</div>' | |
| for cat in CATEGORIES | |
| ]) | |
| gr.HTML(f'<div class="category-container">{categories_html}</div>') | |
| with gr.Row(): | |
| with gr.Column(scale=2): | |
| gr.Markdown("### 📥 Email de Entrada") | |
| email_input = gr.Textbox( | |
| lines=8, | |
| label="Conteúdo do Email", | |
| placeholder="Cole aqui o conteúdo do email ou use um exemplo abaixo...", | |
| show_label=False | |
| ) | |
| gr.Markdown("### 🎯 Exemplos Rápidos") | |
| with gr.Row(): | |
| btn_reserva = gr.Button("🏨 Reserva", variant="secondary", size="sm") | |
| btn_checkin = gr.Button("🕓 Check-in/Out", variant="secondary", size="sm") | |
| with gr.Row(): | |
| btn_reclamacao = gr.Button("😡 Reclamação", variant="secondary", size="sm") | |
| btn_pagamento = gr.Button("💳 Pagamento", variant="secondary", size="sm") | |
| with gr.Row(): | |
| btn_elogio = gr.Button("😊 Elogio", variant="secondary", size="sm") | |
| btn_servicos = gr.Button("🛎️ Serviços", variant="secondary", size="sm") | |
| with gr.Row(): | |
| btn_fornecedores = gr.Button("📦 Fornecedores", variant="secondary", size="sm") | |
| btn_eventos = gr.Button("🎉 Eventos", variant="secondary", size="sm") | |
| with gr.Row(): | |
| btn_rh = gr.Button("👥 RH", variant="secondary", size="sm") | |
| btn_manutencao = gr.Button("🔧 Manutenção", variant="secondary", size="sm") | |
| with gr.Row(): | |
| btn_marketing = gr.Button("📢 Marketing", variant="secondary", size="sm") | |
| btn_outros = gr.Button("❓ Outros", variant="secondary", size="sm") | |
| classify_btn = gr.Button("🔍 Classificar Email", variant="primary", size="lg") | |
| with gr.Column(scale=3): | |
| gr.Markdown("### 📊 Resultados da Classificação") | |
| with gr.Row(): | |
| classification_output = gr.Textbox( | |
| label="📌 Classificação", | |
| lines=1, | |
| interactive=False | |
| ) | |
| tldr_output = gr.Textbox( | |
| label="🎯 Tema", | |
| lines=1, | |
| interactive=False | |
| ) | |
| description_output = gr.Textbox( | |
| label="📝 Resumo", | |
| lines=1, | |
| max_lines=3, | |
| interactive=True | |
| ) | |
| json_output = gr.JSON( | |
| label="Recolha de Entidades (JSON)" | |
| ) | |
| automated_reply_output = gr.Textbox( | |
| label="✉️ Resposta Automática Sugerida", | |
| lines=2, | |
| max_lines=40, | |
| interactive=True | |
| ) | |
| gr.HTML(""" | |
| <div style=' | |
| text-align:center; | |
| padding:20px; | |
| margin-top:30px; | |
| font-size:0.95em; | |
| color:#555; | |
| border-top:1px solid #ddd; | |
| '> | |
| © 2025 Timestamp — Todos os direitos reservados | |
| </div> | |
| """) | |
| # Button event handlers | |
| for btn, tipo in [ | |
| (btn_reserva, "reserva"), | |
| (btn_checkin, "checkin"), | |
| (btn_reclamacao, "reclamacao"), | |
| (btn_elogio, "elogio"), | |
| (btn_pagamento, "pagamento"), | |
| (btn_servicos, "servicos"), | |
| (btn_fornecedores, "fornecedores"), | |
| (btn_eventos, "eventos"), | |
| (btn_rh, "rh"), | |
| (btn_manutencao, "manutencao"), | |
| (btn_marketing, "marketing"), | |
| (btn_outros, "outros") | |
| ]: | |
| btn.click( | |
| lambda t=tipo: exemplo_email(t), | |
| None, | |
| email_input | |
| ) | |
| classify_btn.click( | |
| fn=classify_email, | |
| inputs=email_input, | |
| outputs=[classification_output, tldr_output, description_output, json_output, automated_reply_output] | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch(share=True) |