CERCON / modules /memorial_generator.py
carlosh10's picture
feat: Adiciona gerador de memorial descritivo PSCIP
2ac47b0 verified
"""
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))