""" Gerador de Memorial Descritivo - PSCIP NT-01/2025 CBMGO Gera texto estruturado do memorial com todos os sistemas exigidos. Com LLM (cbmgo/memorial-generator) ou template local (fallback). """ import os import re from datetime import datetime from typing import Dict, List try: from transformers import pipeline HAS_TRANSFORMERS = True except ImportError: HAS_TRANSFORMERS = False class MemorialGenerator: """ Gerador de memorial descritivo para projetos PSCIP. Usa LLM fine-tunado ou template estruturado como fallback. """ def __init__(self, model_id="cbmgo/memorial-generator", use_llm=False): self.model_id = model_id self.use_llm = use_llm and HAS_TRANSFORMERS self._pipe = None def _load_llm(self): if self._pipe is None and self.use_llm: print(f"Carregando modelo: {self.model_id}") self._pipe = pipeline("text-generation", model=self.model_id, device_map="auto", max_new_tokens=1500, temperature=0.2) def gerar_llm(self, dados: Dict) -> str: self._load_llm() prompt = self._montar_prompt_llm(dados) saida = self._pipe(prompt)[0]["generated_text"] # Extrair apenas a parte gerada (apos o prompt) if "MEMORIAL DESCRITIVO" in saida: idx = saida.find("MEMORIAL DESCRITIVO") return saida[idx:] return saida def _montar_prompt_llm(self, d: Dict) -> str: exig = ", ".join(d.get("exigencias", [])) return f"""Gere memorial descritivo completo de prevencao de incendio: Edificacao: {d.get("nome_edificacao","Edificio")} Uso/Ocupacao: {d.get("ocupacao","comercial")} Grupo NT-01: {d.get("grupo","D")} | Divisao: {d.get("divisao","D-1")} Area total: {d.get("area_m2",0):.1f} m2 Altura: {d.get("altura_m",0):.1f} m Numero de pavimentos: {d.get("pavimentos",1)} Lotacao estimada: {d.get("lotacao",50)} pessoas Sistemas exigidos: {exig} MEMORIAL DESCRITIVO - PSCIP:""" def gerar_template(self, dados: Dict) -> str: """Gera memorial usando template estruturado (sem LLM).""" d = dados nome = d.get("nome_edificacao", "Edificacao") ocupacao = d.get("ocupacao", "Comercial").title() grupo = d.get("grupo", "D") divisao = d.get("divisao", "D-1") area = d.get("area_m2", 0) altura = d.get("altura_m", 0) pavimentos = d.get("pavimentos", 1) lotacao = d.get("lotacao", 0) exigencias = d.get("exigencias", []) qtd_ext = d.get("qtd_extintores", max(1, int(area / 400))) cap_ext = d.get("capacidade_extintor", "2-A:20-B:C") sist_hid = d.get("sistema_hidrante", "Coluna Seca") vazao = d.get("vazao_lpm", 300) reserva = d.get("reserva_m3", round(vazao * 60 / 1000, 1)) rt_nome = d.get("rt_nome", "___________________________") rt_crea = d.get("rt_crea", "_______________") data_hoje = datetime.now().strftime("%d/%m/%Y") # Construir secoes condicionalmente sec_ilum = "" if "iluminacao_emergencia" in exigencias: sec_ilum = f""" 6. ILUMINACAO DE EMERGENCIA Sistema de iluminacao de emergencia instalado nas rotas de fuga, saidas de emergencia e areas criticas. - Autonomia minima: 1 (uma) hora - Nivel de iluminamento rota de fuga: >= 3 lux - Nivel de iluminamento areas de acesso: >= 10 lux - Blocos autonomos com bateria selada, recarregavel - Conforme ABNT NBR 10898 Ref: NT-01/2025 CBMGO Art. 20 """ sec_spda = "" if "spda" in exigencias: sec_spda = f""" 7. SPDA - SISTEMA DE PROTECAO CONTRA DESCARGAS ATMOSFERICAS SPDA obrigatorio para esta edificacao (area > 1.000m2). - Nivel de protecao: a definir conforme ABNT NBR 5419 - Sistema captacao, descida e aterramento independente - Projeto especifico assinado por profissional habilitado Ref: NT-01/2025 CBMGO Art. 25 | ABNT NBR 5419 """ sec_alarme = "" if "alarme_incendio" in exigencias: sec_alarme = f""" 8. SISTEMA DE ALARME E DETECCAO DE INCENDIO Sistema de alarme de incendio com: - Central de alarme endereçavel - Acionadores manuais nas saidas de emergencia (espacamento <= 30m) - Detectores de fumaca nos ambientes cobertos - Sirenes audiovisuais Conforme ABNT NBR 17240 Ref: NT-01/2025 CBMGO Art. 22 """ sec_chuveiros = "" if "chuveiros_automaticos" in exigencias: sec_chuveiros = f""" 9. SISTEMA DE CHUVEIROS AUTOMATICOS (SPRINKLERS) Sistema de chuveiros automaticos cobrindo toda a area edificada. - Tipo: Resposta rapida, temperatura de ativacao 68 graus C - Densidade minima: 5 mm/min - Area de atuacao: 144 m2 - Reservatorio exclusivo para incendio Conforme ABNT NBR 10897 Ref: NT-01/2025 CBMGO """ memorial = f"""MEMORIAL DESCRITIVO SISTEMA DE PREVENCAO E COMBATE A INCENDIO E PANICO - PSCIP Data de elaboracao: {data_hoje} Referencia normativa principal: NT-01/2025 - Procedimentos Administrativos CBMGO ============================================================ 1. IDENTIFICACAO DA EDIFICACAO ============================================================ Denominacao: {nome} Uso/Ocupacao: {ocupacao} Classificacao NT-01/2025: Grupo {grupo} - Divisao {divisao} Endereco: _______________________________________________ Area total construida: {area:.2f} m2 Altura da edificacao: {altura:.2f} m Numero de pavimentos: {pavimentos} Lotacao maxima estimada: {lotacao} pessoas ============================================================ 2. BASE LEGAL E NORMATIVA ============================================================ - NT-01/2025 - Procedimentos Administrativos - CBMGO - ABNT NBR 12693:2013 - Sistemas de protecao por extintores - ABNT NBR 13714:2003 - Sistemas de hidrantes e mangotinhos - ABNT NBR 13434:2004 - Sinalizacao de seguranca contra incendio - ABNT NBR 10898:2013 - Iluminacao de emergencia - ABNT NBR 5419:2015 - SPDA - ABNT NBR 17240:2010 - Deteccao e alarme de incendio - ABNT NBR 9077:2001 - Saidas de emergencia - Codigo de Obras e Postura Municipal vigente ============================================================ 3. SISTEMAS DE PROTECAO EXIGIDOS ============================================================ Conforme classificacao Grupo {grupo} - NT-01/2025, para edificacao com area de {area:.0f} m2 e altura de {altura:.1f} m, sao exigidos os seguintes sistemas de protecao: {chr(10).join([' - ' + e.replace('_',' ').title() for e in exigencias])} ============================================================ 4. EXTINTORES PORTATEIS ============================================================ Quantidade minima instalada: {qtd_ext} (unidades) Capacidade extintora: {cap_ext} Distribuicao: instalados em locais visiveis, sinalizados e de facil acesso, com distancia maxima de 15 metros entre eles. Altura de instalacao: entre 1,0m e 1,60m do piso ao manometro. Manutencao: anual conforme ABNT NBR 12962. Conforme ABNT NBR 12693 e NT-01/2025 Anexo B - Grupo {grupo.upper()} ============================================================ 5. SISTEMA DE HIDRANTES E MANGOTINHOS ============================================================ Sistema instalado: {sist_hid} Vazao minima: {vazao} L/min por hidrante Pressao dinamica minima: 15 mca no hidrante mais desfavoravel Reserva tecnica de incendio: {reserva} m3 (exclusiva para incendio) Tubulacao: aco galvanizado/PRFV, DN 65mm (rede principal) Registro de recalque externo para CBMGO Conforme ABNT NBR 13714 e NT-01/2025 Art. 18 {sec_ilum}{sec_spda}{sec_alarme}{sec_chuveiros} ============================================================ {len([e for e in exigencias if e not in ['iluminacao_emergencia','spda','alarme_incendio','chuveiros_automaticos']]) + 6}. SINALIZACAO DE EMERGENCIA ============================================================ Sinalizacao fotoluminescente instalada em: - Saidas de emergencia (indicacao de saida e seta direcional) - Rotas de fuga em todos os corredores - Localizacao dos extintores e hidrantes - Instrucoes de emergencia e prohibicoes - Planta de localizacao com rotas de evacuacao Conforme ABNT NBR 13434 Partes 1, 2 e 3 ============================================================ ASSINATURAS ============================================================ Responsavel Tecnico: {rt_nome} CREA/CAU N.: {rt_crea} Empresa: _____________________________________________ Data: {data_hoje} Profissional habilitado conforme resolucao CONFEA/CREA. Este memorial e parte integrante do projeto de PSCIP e deve ser lido em conjunto com as pranchas tecnicas. ============================================================ FIM DO MEMORIAL DESCRITIVO ============================================================ """ return memorial def gerar(self, dados: Dict) -> str: """Interface principal: LLM se disponivel, template caso contrario.""" if self.use_llm and self._pipe is not None: return self.gerar_llm(dados) return self.gerar_template(dados) _memorial_gen = None def get_memorial_generator(use_llm=False): global _memorial_gen if _memorial_gen is None: _memorial_gen = MemorialGenerator(use_llm=use_llm) return _memorial_gen if __name__ == "__main__": gen = MemorialGenerator() dados = { "nome_edificacao": "Edificio Comercial Exemplo", "ocupacao": "comercial", "grupo": "D", "divisao": "D-1", "area_m2": 1200, "altura_m": 8, "pavimentos": 2, "lotacao": 120, "exigencias": ["extintores_portateis", "hidrantes", "sinalizacao_emergencia", "alarme_incendio", "spda"], "qtd_extintores": 4, "capacidade_extintor": "2-A:20-B:C", "sistema_hidrante": "Coluna Seca", "vazao_lpm": 300, "reserva_m3": 18.0, "rt_nome": "Eng. Carlos Silva", "rt_crea": "GO-12345" } print(gen.gerar(dados))