Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| from docling.document_converter import DocumentConverter | |
| import google.generativeai as genai | |
| import re | |
| import os | |
| import logging | |
| import json | |
| from typing import Dict, List, Tuple | |
| from datetime import datetime | |
| from transformers import AutoModelForTokenClassification, AutoTokenizer | |
| import torch | |
| import spacy | |
| # Configuração de logging | |
| logging.basicConfig( | |
| level=logging.INFO, | |
| format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', | |
| handlers=[ | |
| logging.FileHandler(f'contract_analyzer_{datetime.now().strftime("%Y%m%d")}.log'), | |
| logging.StreamHandler() | |
| ] | |
| ) | |
| logger = logging.getLogger(__name__) | |
| # Configuração da API do Gemini | |
| GOOGLE_API_KEY = os.getenv("GOOGLE_API_KEY") | |
| if not GOOGLE_API_KEY: | |
| logger.error("GOOGLE_API_KEY não encontrada nas variáveis de ambiente") | |
| raise ValueError("GOOGLE_API_KEY não configurada") | |
| genai.configure(api_key=GOOGLE_API_KEY) | |
| logger.info("API Gemini configurada com sucesso") | |
| # Carregar o modelo NER e tokenizador | |
| model_name = "dominguesm/ner-legal-bert-base-cased-ptbr" | |
| logger.info(f"Carregando o modelo NER: {model_name}") | |
| ner_model = AutoModelForTokenClassification.from_pretrained(model_name) | |
| tokenizer = AutoTokenizer.from_pretrained(model_name) | |
| logger.info("Modelo NER e tokenizador carregados com sucesso") | |
| # Funções do App 1 (Gemini) | |
| def extract_json_from_response(response_text: str) -> str: | |
| json_content = response_text.strip() | |
| if json_content.startswith('```'): | |
| json_content = json_content.split('\n', 1)[1] | |
| if json_content.endswith('```'): | |
| json_content = json_content.rsplit('\n', 1)[0] | |
| return json_content.strip() | |
| def extract_legal_representatives_gemini(contract_text: str) -> Dict: | |
| logger.info("Iniciando extração de representantes legais com Gemini") | |
| try: | |
| model = genai.GenerativeModel('gemini-pro') | |
| prompt = """ | |
| Analise o seguinte contrato social e extraia: | |
| 1. Todos os sócios e seus percentuais de participação | |
| 2. Todos os administradores mencionados | |
| Formate a resposta como um dicionário JSON com as seguintes chaves: | |
| - "socios": lista de dicionários com "nome" e "participacao" | |
| - "administradores": lista de nomes | |
| Contrato Social: | |
| {contract_text} | |
| """ | |
| response = model.generate_content(prompt.format(contract_text=contract_text)) | |
| json_content = extract_json_from_response(response.text) | |
| result = json.loads(json_content) | |
| return result | |
| except Exception as e: | |
| logger.error(f"Erro na análise Gemini: {str(e)}") | |
| return { | |
| "socios": [], | |
| "administradores": [], | |
| "erro": str(e) | |
| } | |
| # Funções do App 2 (NER) | |
| def extract_entities(text: str) -> List[Tuple[str, str]]: | |
| logger.debug("Iniciando extração de entidades com NER") | |
| inputs = tokenizer(text, max_length=512, truncation=True, return_tensors="pt") | |
| tokens = inputs.tokens() | |
| with torch.no_grad(): | |
| outputs = ner_model(**inputs).logits | |
| predictions = torch.argmax(outputs, dim=2) | |
| entities = [] | |
| for token, prediction in zip(tokens, predictions[0].numpy()): | |
| entity_label = ner_model.config.id2label[prediction] | |
| if entity_label != "O": | |
| entities.append((token, entity_label)) | |
| return entities | |
| def extract_representatives_ner(entities: List[Tuple[str, str]]) -> List[str]: | |
| representatives = [] | |
| current_person = "" | |
| current_organization = "" | |
| for token, label in entities: | |
| if label in ["B-PESSOA", "I-PESSOA"]: | |
| current_person += token.replace("##", "") | |
| else: | |
| if current_person: | |
| representatives.append(current_person) | |
| current_person = "" | |
| if label in ["B-ORGANIZACAO", "I-ORGANIZACAO"]: | |
| current_organization += token.replace("##", "") | |
| else: | |
| if current_organization: | |
| representatives.append(current_organization) | |
| current_organization = "" | |
| if current_person: | |
| representatives.append(current_person) | |
| if current_organization: | |
| representatives.append(current_organization) | |
| return representatives | |
| def format_output_gemini(analysis_result: Dict) -> str: | |
| output = "ANÁLISE DO CONTRATO SOCIAL (Gemini)\n\n" | |
| output += "SÓCIOS:\n" | |
| for socio in analysis_result.get("socios", []): | |
| participacao = socio.get('participacao', 'Não especificada') | |
| participacao_str = f"{participacao}%" if participacao is not None else "Participação não especificada" | |
| output += f"- {socio['nome']}: {participacao_str}\n" | |
| output += "\nADMINISTRADORES:\n" | |
| for admin in analysis_result.get("administradores", []): | |
| output += f"- {admin}\n" | |
| if "erro" in analysis_result: | |
| output += f"\nERRO: {analysis_result['erro']}" | |
| return output | |
| def format_output_ner(representatives: List[str]) -> str: | |
| output = "ANÁLISE DO CONTRATO SOCIAL (NER)\n\n" | |
| output += "REPRESENTANTES IDENTIFICADOS:\n" | |
| for rep in representatives: | |
| output += f"- {rep}\n" | |
| return output | |
| # Função principal que processa o documento | |
| def analyze_contract(file, analysis_type: str): | |
| logger.info(f"Iniciando análise do arquivo usando {analysis_type}: {file.name}") | |
| try: | |
| converter = DocumentConverter() | |
| result = converter.convert(file.name) | |
| document_text = result.document.export_to_markdown() | |
| if analysis_type == "Gemini": | |
| analysis_result = extract_legal_representatives_gemini(document_text) | |
| output = format_output_gemini(analysis_result) | |
| else: # NER | |
| entities = extract_entities(document_text) | |
| representatives = extract_representatives_ner(entities) | |
| output = format_output_ner(representatives) | |
| return document_text, output | |
| except Exception as e: | |
| logger.error(f"Erro durante análise do contrato: {str(e)}") | |
| return "", f"Erro ao processar o arquivo: {str(e)}" | |
| # Criar interface Gradio | |
| try: | |
| logger.info("Iniciando configuração da interface Gradio") | |
| iface = gr.Interface( | |
| fn=analyze_contract, | |
| inputs=[ | |
| "file", | |
| gr.Radio( | |
| choices=["Gemini", "NER"], | |
| label="Tipo de Análise", | |
| value="Gemini" | |
| ) | |
| ], | |
| outputs=[ | |
| gr.Textbox(label="Texto do Contrato"), | |
| gr.Textbox(label="Resultado da Análise") | |
| ], | |
| title="Analisador de Contratos Sociais", | |
| description="Este aplicativo analisa contratos sociais usando Gemini ou NER para identificar representantes legais.", | |
| ) | |
| logger.info("Interface Gradio configurada com sucesso") | |
| except Exception as e: | |
| logger.error(f"Erro ao configurar interface Gradio: {str(e)}") | |
| raise | |
| if __name__ == "__main__": | |
| logger.info("Iniciando aplicação") | |
| iface.launch() |