import gradio as gr import torch import spaces import time from transformers import AutoTokenizer, AutoModelForCausalLM # Load model and tokenizer @spaces.GPU def load_model(): model_name = "arthrod/tucano_voraz_cwb-com-prompts-apr-04" tokenizer = AutoTokenizer.from_pretrained(model_name) tokenizer.padding_side = 'left' model = AutoModelForCausalLM.from_pretrained( model_name, torch_dtype=torch.float16, device_map="auto" ) return model, tokenizer model, tokenizer = load_model() # Main prediction function with the exact format you specified @spaces.GPU def predict(message, history): # Apply chat template messages = [{"role": "user", "content": message}] inputs = tokenizer.apply_chat_template( messages, tokenize=False, add_generation_prompt=True ) # Tokenize inputs model_inputs = tokenizer(inputs, padding=True, return_tensors="pt").to(model.device) # Create a streaming effect partial_message = "" input_length = model_inputs.input_ids.shape[1] # Generate without sampling for deterministic output with torch.no_grad(): generated_ids = model.generate( **model_inputs, max_new_tokens=512, do_sample=False, temperature=None, # Remove temperature top_p=None, # Remove top_p top_k=None ) # Extract just the generated part (not the input) generated_part = generated_ids[0, input_length:] # Decode the output output = tokenizer.decode(generated_part, skip_special_tokens=True) # Simulate streaming for better user experience for i in range(min(len(output), 100)): # Limit to reasonable length partial_message = output[:i+1] time.sleep(0.02) # Small delay for streaming effect yield partial_message # Yield the complete message yield output # Example texts demonstrating different PII types examples = [ "Meu nome é Ricardo Almeida e moro na Rua das Flores, 123, em Curitiba. Meu CPF é 123.456.789-00 e meu telefone é (41) 98765-4321.", "A paciente Maria da Silva, nascida em 15/03/1980, apresentou resultados alterados no exame de sangue. Favor contatar pelo celular 11 99876-5432.", "O funcionário José Roberto Santos, portador do RG 12.345.678-9, está autorizado a acessar o prédio da empresa Tecnologia Brasil LTDA.", "Declaração de Imposto de Renda do contribuinte Roberto Carlos Magalhães, CPF 987.654.321-00, residente na Av. Paulista, 1578, São Paulo-SP.", "Segue o número do cartão de crédito para o pagamento: 5432-1098-7654-3210, titular Ana Beatriz Oliveira, validade 12/25, código 123." ] # PII types with explanations pii_types = [ {"name": "CPF/CNPJ", "tag": "SSN_CPF", "example": "123.456.789-00 → [SSN_CPF]"}, {"name": "RG", "tag": "ID_RG", "example": "12.345.678-9 → [ID_RG]"}, {"name": "Nome", "tag": "FIRST_NAME/MIDDLE_NAME/LAST_NAME", "example": "João Silva → [FIRST_NAME] [LAST_NAME]"}, {"name": "Endereço", "tag": "STREET_NAME/BUILDING_NB", "example": "Rua Aurora, 123 → [STREET_NAME], [BUILDING_NB]"}, {"name": "Bairro", "tag": "NEIGHBORHOOD", "example": "Jardim Paulista → [NEIGHBORHOOD]"}, {"name": "Cidade", "tag": "CITY", "example": "São Paulo → [CITY]"}, {"name": "Estado", "tag": "STATE/STATE_ABBR", "example": "São Paulo/SP → [STATE]/[STATE_ABBR]"}, {"name": "CEP", "tag": "ZIPCODE_CEP", "example": "01234-567 → [ZIPCODE_CEP]"}, {"name": "Telefone", "tag": "PHONE", "example": "(11) 98765-4321 → [PHONE]"}, {"name": "Data de nascimento", "tag": "BIRTHDATE", "example": "15/03/1980 → [BIRTHDATE]"}, {"name": "Cartão de crédito", "tag": "CREDITCARD", "example": "5432-1098-7654-3210 → [CREDITCARD]"}, {"name": "PIS/PASEP", "tag": "SOCIAL_NB_PIS", "example": "123.45678.90-1 → [SOCIAL_NB_PIS]"}, {"name": "Dados médicos", "tag": "MEDICAL_DATA", "example": "Diagnóstico de hipertensão → [MEDICAL_DATA]"}, {"name": "Opinião política", "tag": "POLITICAL_OPINION", "example": "Apoiador do partido X → [POLITICAL_OPINION]"}, {"name": "Convicção religiosa", "tag": "RELIGIOUS_CONVICTION", "example": "Praticante de religião Y → [RELIGIOUS_CONVICTION]"} ] # Create Gradio Interface with gr.Blocks(css=""" .gradio-container {max-width: 1200px !important; margin-left: auto !important; margin-right: auto !important;} .examples {margin-top: 10px !important;} .pii-table {margin-top: 20px !important; margin-bottom: 20px !important;} .footer {text-align: center; margin-top: 20px !important; padding: 10px !important; border-top: 1px solid #eee !important;} .pii-card {background-color: #f9f9f9; border-radius: 8px; padding: 15px; margin-bottom: 10px;} .header-image {display: block; margin: 0 auto; max-width: 120px; margin-bottom: 10px;} .assistant-message {border-left: 3px solid #ffd700 !important; background-color: #fffdf7 !important;} .user-message {background-color: #f5f5f5 !important; border-left: 3px solid #6c757d !important;} """) as demo: gr.HTML("""
Tucano Voraz Logo

Tucano Voraz

Sistema de Anonimização e Remoção de Dados Sensíveis

by Arthur Souza Rodrigues

""") with gr.Row(): with gr.Column(scale=2): gr.Markdown(""" ## Sobre o Projeto **Tucano Voraz** é uma ferramenta de anonimização de texto projetada para identificar e remover informações pessoais sensíveis (PII) de documentos em português. Em um mundo onde vazamentos de dados são cada vez mais comuns, proteger informações pessoais tornou-se essencial. ### Como Funciona: 1. Cole seu texto contendo dados sensíveis 2. O modelo identificará automaticamente PIIs 3. Receberá o texto com os dados sensíveis substituídos por tags ### Aplicações: - Conformidade com LGPD e regulamentos de privacidade - Compartilhamento seguro de documentos - Preparação de dados para processamento por terceiros - Publicação de documentos em ambientes públicos """) with gr.Accordion("📋 Tipos de Dados Sensíveis Detectados", open=False): pii_html = "
" for pii in pii_types: pii_html += f"""

{pii['name']}

Tag: {pii['tag']}
Exemplo: {pii['example']}
""" pii_html += "
" gr.HTML(pii_html) chat_interface = gr.ChatInterface( fn=predict, type="messages", examples=examples, title="", chatbot=gr.Chatbot( height=500, bubble_full_width=False, show_share_button=True, show_copy_button=True, layout="bubble", avatar_images=(None, "https://i.imgur.com/Ptd2AoL.png") ), textbox=gr.Textbox( placeholder="Insira seu texto para anonimização...", lines=3, max_lines=10, show_copy_button=True, container=False, scale=7 ) ) gr.HTML(""" """) # Launch the app if __name__ == "__main__": demo.launch()