Visão Geral da Arquitetura
A arquitetura do ContraDito foi desenhada com foco em resiliência absoluta e simplicidade estrutural, separando rigorosamente o processamento de inteligência artificial da entrega de dados ao usuário final.
1. Visão Arquitetural: C4 Model
Para garantir clareza e transparência no fluxo de processamento e arquitetura do ContraDito, utilizamos o modelo C4 para documentar os diferentes níveis de abstração do sistema.
Nível 1: C4 Context (Sistema e Usuário)
O diagrama de Contexto mostra a visão de "helicóptero" de como a plataforma interage com o usuário final e sistemas externos (governamentais).
C4Context
title Nível 1: Contexto de Sistemas - ContraDito
Person(cidadao, "Cidadão / Eleitor / Jornalista", "Busca dados")
System(contradito, "ContraDito", "Exibe dados")
System_Ext(camara, "API da Câmara", "Deputados e dados relacionados")
System_Ext(senado, "API do Senado", "Senadores e dados relacionados")
Rel_D(cidadao, contradito, "Acessa vitrine", "Web")
Rel_D(contradito, camara, "Extrai", "REST")
Rel_D(contradito, senado, "Extrai", "REST")
UpdateElementStyle(cidadao, $bgColor="#08427b", $fontColor="#ffffff", $borderColor="#052e56")
UpdateElementStyle(contradito, $bgColor="#1168bd", $fontColor="#ffffff", $borderColor="#0b4884")
UpdateElementStyle(camara, $bgColor="#374151", $fontColor="#ffffff", $borderColor="#4b5563")
UpdateElementStyle(senado, $bgColor="#374151", $fontColor="#ffffff", $borderColor="#4b5563")
UpdateLayoutConfig($c4ShapeInRow="2", $c4BoundaryInRow="1")
Nível 2: C4 Container (Aplicações e Dados)
O diagrama de Container detalha a Plataforma ContraDito em seus serviços independentes, evidenciando o padrão arquitetural CQRS que isola leitura de processamento, e especificando que os bancos relacional e vetorial residem na nuvem como serviços gerenciados.
C4Container
title Nível 2: Diagrama de Container - ContraDito
Person(cidadao, "Cidadão / Eleitor / Jornalista", "Acessa portal e documentação")
System_Ext(gov_apis, "APIs do Governo", "Câmara/Senado")
ContainerDb(supabase, "Banco Relacional (Supabase - Nuvem)", "PostgreSQL", "Armazena dados cadastrais de políticos, votos, discursos e resumos")
ContainerDb(qdrant, "Banco Vetorial (Qdrant - Nuvem)", "Qdrant Cloud", "Armazena embeddings e chunks de discursos/proposições")
Container_Boundary(c1, "ContraDito") {
Container(frontend, "Front-end Web", "Next.js", "Interface e Vitrine")
Container(fastapi, "API de Leitura", "FastAPI", "Endpoints View_Query")
Container(worker, "Worker NLP / Scripts ETL", "Python", "Processa View_Command, extração e vetorização")
Container(mkdocs, "Servidor de Documentação", "MkDocs (Material Theme)", "Disponibiliza a documentação do projeto")
}
Rel_D(cidadao, frontend, "Navega", "HTTPS")
Rel_D(cidadao, mkdocs, "Consulta documentação", "HTTPS")
Rel_D(frontend, fastapi, "Consome", "JSON")
Rel_D(fastapi, supabase, "Lê dados", "SQL")
Rel_R(worker, gov_apis, "Extrai dados", "HTTPS")
Rel_U(worker, supabase, "Lê/Escreve dados relacionais", "SQL")
Rel_U(worker, qdrant, "Escreve embeddings", "gRPC/HTTP")
UpdateElementStyle(cidadao, $bgColor="#08427b", $fontColor="#ffffff", $borderColor="#052e56")
UpdateElementStyle(gov_apis, $bgColor="#374151", $fontColor="#ffffff", $borderColor="#4b5563")
UpdateElementStyle(frontend, $bgColor="#2563eb", $fontColor="#ffffff", $borderColor="#93c5fd")
UpdateElementStyle(fastapi, $bgColor="#2563eb", $fontColor="#ffffff", $borderColor="#93c5fd")
UpdateElementStyle(worker, $bgColor="#2563eb", $fontColor="#ffffff", $borderColor="#93c5fd")
UpdateElementStyle(mkdocs, $bgColor="#2563eb", $fontColor="#ffffff", $borderColor="#93c5fd")
UpdateElementStyle(supabase, $bgColor="#059669", $fontColor="#ffffff", $borderColor="#6ee7b7")
UpdateElementStyle(qdrant, $bgColor="#059669", $fontColor="#ffffff", $borderColor="#6ee7b7")
UpdateLayoutConfig($c4ShapeInRow="2", $c4BoundaryInRow="1")
Nível 3: C4 Component (Worker NLP)
Focando nos scripts e pipelines de processamento do backend — o Worker NLP / Scripts ETL —, este diagrama ilustra o fluxo de dados em formato de Pipe and Filter para a extração de dados, sumarização, fragmentação, vetorização e vinculação de proximidade semântica.
C4Component
title Nível 3: Diagrama de Componentes - Worker NLP / ETL
ContainerDb(supabase, "Supabase (Nuvem)", "PostgreSQL", "Armazena dados cadastrais, proposições, votos, discursos e vínculos")
ContainerDb(qdrant, "Qdrant (Nuvem)", "Qdrant Cloud", "Armazena embeddings e chunks de discursos/proposições")
System_Ext(gov_apis, "APIs do Governo", "Câmara e Senado")
Container_Boundary(worker_nlp, "Worker NLP / ETL Pipeline") {
Component(extrator, "1: Extrator", "Python Scripts", "Extrai dados brutos de parlamentares, discursos, proposições e votos")
Component(sumarizador, "2: Sumarizador", "Llama 3.1 / Gemini", "Gera resumos executivos temáticos das proposições")
Component(chunker, "3: Chunker", "Python Scripts", "Fragmenta discursos longos em blocos textuais menores")
Component(vetorizador, "4: Vetorizador", "SBERT / BGE-M3", "Gera embeddings para blocos de discurso e resumos")
Component(vinculador, "5: Vinculador de Chunks", "Python (run_vinculo_chunks)", "Calcula similaridade via Qdrant e vincula chunks de discursos a votos correspondentes")
}
Rel_D(extrator, gov_apis, "Extrai via REST", "HTTPS")
Rel_D(extrator, supabase, "Salva dados relacionais", "SQL")
Rel_D(sumarizador, supabase, "Lê proposições", "SQL")
Rel_D(sumarizador, supabase, "Salva resumos", "SQL")
Rel_D(chunker, supabase, "Lê discursos", "SQL")
Rel_D(chunker, vetorizador, "Repassa chunks", "Memória")
Rel_D(vetorizador, qdrant, "Salva embeddings", "gRPC/HTTP")
Rel_D(vinculador, qdrant, "Busca vizinhos semânticos", "gRPC/HTTP")
Rel_D(vinculador, supabase, "Lê votos e salva vínculos de proximidade", "SQL")
UpdateElementStyle(supabase, $bgColor="#059669", $fontColor="#ffffff", $borderColor="#6ee7b7")
UpdateElementStyle(qdrant, $bgColor="#059669", $fontColor="#ffffff", $borderColor="#6ee7b7")
UpdateElementStyle(gov_apis, $bgColor="#374151", $fontColor="#ffffff", $borderColor="#4b5563")
UpdateElementStyle(extrator, $bgColor="#1d4ed8", $fontColor="#ffffff", $borderColor="#60a5fa")
UpdateElementStyle(sumarizador, $bgColor="#1d4ed8", $fontColor="#ffffff", $borderColor="#60a5fa")
UpdateElementStyle(chunker, $bgColor="#1d4ed8", $fontColor="#ffffff", $borderColor="#60a5fa")
UpdateElementStyle(vetorizador, $bgColor="#1d4ed8", $fontColor="#ffffff", $borderColor="#60a5fa")
UpdateElementStyle(vinculador, $bgColor="#1d4ed8", $fontColor="#ffffff", $borderColor="#60a5fa")
UpdateLayoutConfig($c4ShapeInRow="2", $c4BoundaryInRow="1")
Nível 4: C4 Code (Diagrama de Classes de Domínio)
O modelo de classes a seguir apresenta as principais estruturas de domínio que trafegam pelo motor NLP até persistirem no banco de dados para consumo posterior.
classDiagram
class Politico {
+UUID id
+String nome
+String partido
+String estado
}
class Proposicao {
+UUID id
+String ementa_oficial
+String resumo_executivo
+String tema
}
class Discurso {
+UUID id
+UUID politico_id
+String texto
+Date data
}
class ChunkDiscurso {
+UUID id
+UUID discurso_id
+String texto
+Date data
+Vector_1024 embedding_bge_m3
}
class Voto {
+UUID id
+UUID politico_id
+UUID proposicao_id
+Enum tipo_voto
}
Politico "1" *-- "many" Discurso : Realiza
Politico "1" *-- "many" Voto : Efetua
Discurso "1" *-- "many" ChunkDiscurso : Possui
Voto "many" -- "1" Proposicao : Pertence a
2. Macroarquitetura: CQRS
O sistema é dividido física e logicamente em dois lados independentes que não realizam chamadas diretas ou comunicação síncrona entre si, utilizando o Supabase (PostgreSQL) e o Qdrant (Banco Vetorial) como meios de persistência e acoplamento indireto de dados.
| Lado de Leitura (Query — FastAPI) | Lado de Escrita (Command — Worker/ETL) | |
|---|---|---|
| Tipo | API REST para consultas e agregação de métricas em tempo de execução | Conjunto de scripts e pipelines Python executados em contêiner isolado |
| Responsabilidades | Ler dados consolidados do Supabase e entregar JSONs estruturados ao front-end | Extração das APIs governamentais, fragmentação de textos, geração de embeddings com SBERT e geração de resumos executivos via Google GenAI |
| Cache | Opera com respostas cacheadas em memória (FastAPICache) | Não se aplica (persistência direta nos bancos de dados) |
| Resiliência | Continua servindo o portal mesmo se o Worker/ETL estiver inativo ou falhar | As falhas do pipeline ficam restritas ao contêiner do Worker, sem qualquer impacto na API principal |
3. Microarquitetura do Worker: Pipe and Filter
Para o processamento interno do Worker NLP, a arquitetura abandona abstrações complexas e segue um fluxo procedural, determinístico e linear. O pacote de dados trafega de forma unidirecional por 6 estágios sequenciais:
- Filtro 1 — Extração (API): Consumo das APIs federais para capturar perfis, proposições validadas e discursos.
- Filtro 2 — Sumarização: Submissão da proposição legislativa para a API do Google GenAI para geração de um resumo executivo coeso.
- Filtro 3 — Fragmentação (Chunking): Divisão dos discursos limpos em chunks textuais com sobreposição, preparando a carga para modelos com limite de contexto estrito.
- Filtro 4 — Vetorização: Geração de embeddings com SBERT ( BAAI/bge-m3 ) para chunks e resumos.
- Filtro 5 — Armazenamento Vetorial: Envio e indexação dos chunks com seus vetores no Qdrant.
- Filtro 6 — Vinculação de Chunks a Votos: Execução do mecanismo de similaridade vetorial comparando discursos do Qdrant e associando-os aos votos no Supabase.
4. Stack Tecnológica
A tabela a seguir consolida as principais tecnologias que compõem o ecossistema do ContraDito, agrupadas por camada de atuação:
| Camada / Componente | Tecnologia | Função |
|---|---|---|
| Front-end | React, Next.js, Tailwind CSS | Interface interativa, roteamento da aplicação web e estilização visual. |
| API de Leitura | FastAPI | Camada REST para entrega rápida e cacheada dos dados (CQRS - Query). |
| Banco de Dados | Supabase (PostgreSQL), Qdrant Cloud | Supabase para persistência relacional de políticos/votos/discursos e Qdrant para armazenamento/busca vetorial de embeddings. |
| Extração e Processamento (ETL) | Regex, BeautifulSoup4, pdfplumber |
Coleta governamental, limpeza textual rigorosa e extração de PDFs legislativos. |
| Inteligência Artificial | Google GenAI (Gemini), BAAI/bge-m3 (SBERT) |
Google GenAI para sumarização temática de proposições e SBERT para vetorização de textos e busca semântica. |