"""Geração de evidências legíveis para cada grupo de retakes. Produz uma lista estruturada ``{tipo, descricao, valor}`` que explica por que duas falas foram consideradas retake — pronto para a interface do painel descrever os motivos ao usuário. """ from __future__ import annotations from .modelos_de_retakes import AgrupamentoDeFalas, ClassificacaoDeRetake, EvidenciaDeRetake class GeradorDeEvidencias: """Monta as evidências de um grupo a partir do agrupamento e da categoria.""" def gerar( self, agrupamento: AgrupamentoDeFalas, classificacao: ClassificacaoDeRetake, ) -> list[EvidenciaDeRetake]: evidencias: list[EvidenciaDeRetake] = [] if not agrupamento.pares: return evidencias par = max(agrupamento.pares, key=lambda item: item.comparacao.similaridade_final) comp = par.comparacao estado = "É um retake provável." if classificacao.tipo == "retake_confirmado" else ( "Pode ser um retake." if classificacao.tipo == "possivel_retake" else "Repetição detectada.") evidencias.append(EvidenciaDeRetake( tipo="similaridade_textual", descricao=( f"As duas falas possuem {comp.similaridade_jaccard * 100:.0f}% " f"de palavras em comum e {comp.similaridade_final * 100:.0f}% de " f"similaridade textual geral." ), valor=comp.similaridade_final, )) if par.similaridade_semantica > 0: evidencias.append(EvidenciaDeRetake( tipo="similaridade_semantica", descricao=f"Semanticamente, as falas têm {par.similaridade_semantica * 100:.0f}% de afinidade.", valor=par.similaridade_semantica, )) if comp.similaridade_do_inicio >= 0.8: evidencias.append(EvidenciaDeRetake( tipo="repeticao_do_inicio", descricao="As duas falas começam com as mesmas palavras.", valor=comp.similaridade_do_inicio, )) evidencias.append(EvidenciaDeRetake( tipo="proximidade_temporal", descricao=( f"A segunda tentativa começa {par.intervalo.intervalo_em_segundos:.1f} " f"segundos após a primeira." ), valor=par.intervalo.proximidade_temporal, )) for sinal in agrupamento.sinais_de_reinicio: for detalhe in sinal.evidencias: evidencias.append(EvidenciaDeRetake( tipo="reinicio", descricao=detalhe, valor=sinal.intensidade, )) if par.mudanca_visual_proxima: evidencias.append(EvidenciaDeRetake( tipo="mudanca_visual_proxima", descricao=( "Há um corte visual próximo: as tentativas podem estar em " "tomadas diferentes, reforçando a hipótese de retake." ), valor=1.0, )) evidencias.append(EvidenciaDeRetake( tipo="classificacao", descricao=f"{estado} Confiança de {classificacao.confianca * 100:.0f}%.", valor=classificacao.confianca, )) return evidencias