Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

1 Commit

Folders and files

Repository files navigation

TensionMeter

Sistema de inteligência geopolítica baseado em NLP que monitora o conflito Irã × EUA × Israel em fontes abertas, produzindo um Índice de Tensão (TI) multidimensional com escala DEFCON visual, grafo de co-ocorrência de atores e detecção automática de fases e narrativas do conflito.

Disciplina: Modelagem de Dados Não Estruturados (MDNE) — Reposição Etapa 3
Instituição: UFPB — 2026


Resultado atual

Métrica Valor
Documentos analisados 193
Fontes RSS 8
Período coberto 27/03/2026 → 07/04/2026
Sentimento negativo 72,0%
Fase dominante escalation (73,6%)
Tension Index médio 35,85 / 100
DEFCON atual 4 — Tensão Moderada

Visão geral

O TensionMeter automatiza o monitoramento de tensão geopolítica em três etapas:

Fontes RSS (feedparser)
       ↓
Pré-processamento (spaCy en_core_web_lg)
  Tokenização · Lematização · POS · NER · Noun Chunks
       ↓
Análise de Sentimento (XLM-RoBERTa)
  cardiffnlp/twitter-xlm-roberta-base-sentiment
       ↓
Classificação Zero-Shot (BART)
  facebook/bart-large-mnli → fases do conflito + narrativas
       ↓
Tension Index
  TI = 0,35·S + 0,30·P + 0,20·H + 0,15·C → DEFCON 1–5

Fórmula do Tension Index

TI = 0,35 × S + 0,30 × P + 0,20 × H + 0,15 × C

S  Negatividade do sentimento      (0–100)
P  Severidade da fase do conflito  escalation=100 · retaliation=80 · provocation=60
                                   diplomacy=20 · truce=10
H  Hostilidade entre atores        pares hostis detectados × 25 (máx 100)
C  Clickbait / alarmismo           palavras-gatilho no texto × 6,25 (máx 100)

DEFCON  81–100 = 1  |  61–80 = 2  |  41–60 = 3  |  21–40 = 4  |  0–20 = 5

Stack

Camada Tecnologia
Linguagem Python ≥ 3.12
Gerenciamento de deps uv
Coleta RSS feedparser
NLP estrutural spaCy — en_core_web_lg
Sentimento cardiffnlp/twitter-xlm-roberta-base-sentiment
Classificação zero-shot facebook/bart-large-mnli
Benchmark vaderSentiment
Data pandas + pyarrow (Parquet)
Visualização plotly + matplotlib + seaborn + wordcloud
Dashboard streamlit + folium
API fastapi + uvicorn
Notebooks jupyterlab + ipykernel
Testes pytest
Linting ruff

Estrutura do projeto

tensionmeter/
├── src/
│   ├── main.py                    # Entrypoint: uvicorn + CLI
│   ├── core/
│   │   └── config.py              # Settings via pydantic-settings
│   └── app/
│       ├── server.py              # FastAPI app factory
│       ├── container.py           # Dependency injection
│       ├── conflict/
│       │   ├── router.py          # Endpoints /api/v1/conflict/*
│       │   ├── schemas.py         # DTOs Pydantic
│       │   └── use_cases.py       # Lógica de negócio
│       └── infrastructure/
│           ├── collectors/
│           │   ├── rss_collector.py
│           │   └── reddit_collector.py
│           └── nlp/
│               ├── preprocessor.py    # spaCy: tokenização, lemas, POS, NER
│               ├── ner_extractor.py   # Actor graph + role classification
│               ├── sentiment.py       # XLM-RoBERTa
│               ├── classifier.py      # BART zero-shot
│               └── tension_index.py   # Cálculo do TI ponderado
├── notebooks/
│   ├── 01_exploracao.ipynb        # Coleta + EDA + wordcloud
│   ├── 02_modelagem.ipynb         # Pipeline NLP completo
│   └── 03_avaliacao.ipynb         # Benchmark + métricas + gráficos finais
├── dashboard/
│   └── app.py                     # Streamlit — DEFCON ao vivo
├── data/
│   ├── raw/
│   │   ├── corpus_raw.parquet     # Corpus bruto (193 docs)
│   │   └── wordcloud_corpus.png
│   └── processed/
│       ├── corpus_nlp.parquet     # Corpus com todas as features NLP
│       ├── metricas_finais.csv    # Métricas consolidadas
│       └── fig_*.png              # 17 visualizações geradas
├── tests/
│   ├── conftest.py
│   ├── test_preprocessor.py
│   └── test_tension_index.py
├── CLAUDE.md                      # Guia de contexto para agentes de IA
├── RELATORIO_APRESENTACAO.md      # Síntese completa de todos os resultados
├── LOVABLE_PROMPT.md              # Prompt para gerar apresentação interativa
├── pyproject.toml
├── uv.lock
└── .env.example

Instalação e execução

Pré-requisitos

  • Python ≥ 3.12
  • uv instalado (pip install uv ou brew install uv)

Setup

# 1. Instalar dependências
uv sync

# 2. Baixar modelo spaCy
uv run python -m spacy download en_core_web_lg

# 3. Configurar variáveis de ambiente
cp .env.example .env
# Editar .env com suas credenciais Reddit (opcional)

Executar os notebooks (fluxo principal)

Os notebooks devem ser executados nessa ordem:

uv run jupyter lab
Notebook Gera Depende de
01_exploracao.ipynb data/raw/corpus_raw.parquet —
02_modelagem.ipynb data/processed/corpus_nlp.parquet corpus_raw.parquet
03_avaliacao.ipynb fig_*.png + metricas_finais.csv corpus_nlp.parquet

Rodar a API

uv run python src/main.py
# ou diretamente:
uv run uvicorn src.app.server:app --reload --port 8000

Documentação interativa disponível em http://localhost:8000/docs.

Rodar o dashboard

uv run streamlit run dashboard/app.py

Rodar os testes

uv run pytest tests/ -v

Coleta manual de dados

# Com a API rodando:
curl -X POST http://localhost:8000/api/v1/conflict/collect

Endpoints da API

Método Endpoint Descrição
GET /health Status do sistema
POST /api/v1/conflict/analyze Analisa um texto avulso
GET /api/v1/conflict/tension TI atual + histórico
GET /api/v1/conflict/actors Grafo de atores agregado
GET /api/v1/conflict/feed Últimas notícias processadas
POST /api/v1/conflict/collect Dispara coleta manual

Variáveis de ambiente

# Reddit API (opcional — obter em reddit.com/prefs/apps)
REDDIT_CLIENT_ID=your_client_id
REDDIT_CLIENT_SECRET=your_client_secret
REDDIT_USER_AGENT=tensionmeter:v1.0

# API
API_HOST=0.0.0.0
API_PORT=8000
DEBUG=false

# Paths
DATA_DIR=data
RAW_DIR=data/raw
PROCESSED_DIR=data/processed

Resultados do pipeline NLP

Corpus (Notebook 01)

  • 193 documentos coletados de 8 feeds RSS internacionais
  • Período: 27/03/2026 → 07/04/2026 (11 dias)
  • 0 duplicatas · 317,8 palavras médias por documento
  • Fontes: axios_world (91) · middle_east_eye (20) · aljazeera (17) · foreign_policy (17) · defense_one (15) · times_of_israel (13) · bbc_world (10) · the_hill_intl (10)

NLP estrutural — spaCy (Notebook 02)

  • 426,0 tokens médios por documento · 82.222 tokens totais
  • 34,1 entidades NER por documento · 10.052 lemas únicos
  • Entidades mais frequentes: Iran (340) · Trump (322) · U.S. (294) · Israeli (88)

Sentimento — XLM-RoBERTa (Notebook 02)

Label Docs %
negative 139 72,0%
neutral 51 26,4%
positive 3 1,6%

Fases do conflito — BART (Notebook 02)

Fase Docs %
escalation 142 73,6%
truce 22 11,4%
provocation 19 9,8%
retaliation 7 3,6%
diplomacy 3 1,6%

Tension Index (Notebook 02)

Métrica Valor
TI médio 35,85
TI máximo 67,08 (DEFCON 2)
TI mínimo 4,10 (DEFCON 5)
DEFCON predominante 4 — Tensão Moderada

Benchmark VADER vs XLM-RoBERTa (Notebook 03)

Métrica Valor
Concordância direta 56,0%
Cohen's Kappa (κ) 0,135
Interpretação Fraca — modelos divergem fundamentalmente

O VADER classificou 30,6% dos documentos como positivos contra 1,6% do XLM-RoBERTa — evidência de que o modelo léxico não captura ameaças e jargão militar-diplomático. O XLM-RoBERTa é a escolha correta para este domínio.


Grafo de co-ocorrência de atores

Par Co-ocorrências TI médio
Iran ↔ USA 81 docs 42,6
Israel ↔ USA 32 docs 44,6
Iran ↔ Israel 31 docs 46,4 ← maior TI

USA presente em 70,5% dos documentos — papel central como ator e mediador.


Erros conhecidos e soluções

Erro Causa Solução
praw 401 Unauthorized Credenciais Reddit ausentes Criar app em reddit.com/prefs/apps
OSError: [E050] spaCy model not found Modelo não baixado uv run python -m spacy download en_core_web_lg
Feed RSS retorna 0 artigos URL desatualizada Testar URL no browser
CUDA out of memory no BART Modelo grande demais Adicionar device="cpu" no pipeline HuggingFace
HTML residual nos lemas Texto dos feeds não limpo Usar beautifulsoup4 antes do spaCy
Noun chunks únicos = 171 (baixo) HTML interfere nos spans Mesma solução acima

Licença

Projeto acadêmico — UFPB 2026. Uso educacional.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages