Skip to content

Repository files navigation

PortNOIE

Interface reproduzível para o PortNOIE, sistema de Open Information Extraction (Open IE) em português desenvolvido no doutorado de Bruno Souza Cabral com Marlo Vieira dos Santos e Souza e Daniela Barreiro Claro.

Esta distribuição oferece dois caminhos de inferência:

  • modern (padrão): migração experimental do núcleo neural em PyTorch, sem AllenNLP, Flair nem os dois arquivos externos de language model;
  • legacy: implementação AllenNLP histórica, preservada somente para comparações de compatibilidade.

Ambos usam o checkpoint histórico de bratao/PortNOIE no Hugging Face, baixado automaticamente e mantido em cache na primeira extração. A API normaliza a saída em triplas ARG0, V e ARG1 e remove pontuação marginal dos três campos.

O wheel instalado sem extras contém somente a API leve e as verificações de integridade; sozinho ele não executa inferência. Use o extra modern no comando de instalação da release abaixo para habilitar o backend padrão.

Não é o melhor BERT da tese. O model.th de 74.832.847 bytes é um artefato histórico/de referência: BiLSTM de uma camada, hidden size 384 e representações Flair Diário bidirecionais de 1024. O melhor modelo BERT descrito na tese será distribuído separadamente quando sua validação terminar.

Estado do backend moderno

O backend moderno reconstrói em PyTorch o grafo serializado no checkpoint. As 14 matrizes das duas LMs Flair presentes em model.th foram comparadas com os assets históricos: 14/14 eram idênticas com torch.equal. O checkpoint não guarda o dicionário de 287 caracteres; por isso a distribuição inclui o sidecar mínimo modern_data/flair_metadata.json, com proveniência e checksums dos arquivos dos quais ele foi derivado. Seu próprio SHA-256 é verificado antes do carregamento.

O caminho moderno usa torch.load(..., weights_only=True) e não abre model_params.pkl. Por segurança, ele exige Torch 2.10 ou mais novo; versões anteriores são bloqueadas por GHSA-63cw-57p8-fm3p. Ele executou uma frase anotada e também texto bruto com o modelo spaCy real, produzindo:

Maria | escreveu | um livro

Isso demonstra execução reproduzível sem AllenNLP/Flair em runtime, mas não prova equivalência ao legado. Ainda faltam comparação de logits e avaliação em corpus entre os dois pipelines. Até lá, o nome retornado pela API é PortNOIE-modern-experimental.

Instalação moderna

O pacote declara suporte a Python 3.10–3.13. Para o backend padrão, recomenda-se Python 3.11 ou mais novo:

python -m venv .venv
source .venv/bin/activate             # Windows: .venv\Scripts\activate
python -m pip install --upgrade pip
python -m pip install "portnoie[modern]"
portnoie download                    # opcional: antecipar o download do checkpoint
portnoie doctor --checkpoint-only

O wheel e o sdist não contêm os pesos. Não é necessário fornecer caminho de modelo: a primeira extração baixa o checkpoint de cerca de 75 MB para o cache Hugging Face, na revisão fixada na biblioteca, e verifica os hashes oficiais. PortNOIE() e a importação do pacote não fazem downloads.

Para texto bruto, se pt_core_news_lg estiver ausente, auto_download=True (padrão) também instala a wheel oficial pt_core_news_lg==3.8.0, de 568.207.147 bytes, via pip ou uv no mesmo Python que executa PortNOIE. A URL contém o SHA-256 fixado, verificado pelo instalador. Essa primeira chamada pode demorar e precisa de pip no ambiente ou de uv no PATH.

Em produção offline/controlada, execute portnoie download e instale previamente a wheel spaCy fixada por SHA-256. Depois use PortNOIE(local_files_only=True), PortNOIE(auto_download=False) ou portnoie extract --local-files-only; todas essas opções impedem os downloads automáticos tanto do checkpoint quanto do modelo spaCy.

Integrações que já possuem tokens, POS e dependências podem usar extract_annotated e não precisam do modelo spaCy.

API Python

from portnoie import PortNOIE

extractor = PortNOIE()  # backend="modern"
result = extractor.extract("Maria escreveu um livro.")

for triple in result.triples:
    print(triple.as_dict())
# {'ARG0': 'Maria', 'V': 'escreveu', 'ARG1': 'um livro'}

O objeto carrega os pesos e o pipeline spaCy de forma preguiçosa e os reutiliza nas chamadas seguintes. result.raw preserva tokens, anotações, tags BIO e o identificador explícito do backend. Por padrão, frames incompletos são descartados; use PortNOIE(strict=False) para mantê-los.

Para preparar o cache sem executar inferência:

from portnoie import download_model

download_model()  # baixa só o checkpoint oficial e verifica seus hashes
extractor = PortNOIE(local_files_only=True)  # requer spaCy pré-instalado para texto bruto

cache_dir é opcional; por padrão vale o cache padrão do Hugging Face, configurável por HF_HOME. revision permite selecionar outra revisão, mas não substitui os hashes oficiais ancorados no pacote.

Para anotações já calculadas:

result = extractor.extract_annotated(
    tokens=["Maria", "escreveu", "um", "livro", "."],
    pos_tags=["PROPN", "VERB", "DET", "NOUN", "PUNCT"],
    dependencies=["nsubj", "ROOT", "det", "obj", "punct"],
)

Como no leitor histórico, cada grupo contíguo de tokens VERB/AUX gera uma variação de indicador verbal. Labels de dependência desconhecidos usam o label de fallback dep do vocabulário preservado. Predicados multiword e frames com predicados sobrepostos são consolidados pelo mesmo algoritmo do preditor histórico. Dígitos viram 0 antes das LMs de caracteres, enquanto o word shape continua usando o token original.

Linha de comando e diagnóstico

portnoie download
portnoie doctor
portnoie extract "Maria escreveu um livro."
echo "Maria escreveu um livro." | portnoie extract --raw

portnoie doctor não carrega a rede neural nem acessa a rede para baixar arquivos. Ele verifica faixa de Python, hashes oficiais do checkpoint ancorados no pacote, sidecar, versão segura de Torch, spaCy e pt_core_news_lg. O relatório distingue:

  • modern.annotated_ready: grafo pronto para anotações fornecidas;
  • modern.raw_text_ready: também possui spaCy e pt_core_news_lg;
  • modern.raw_text_auto_download_available: pode instalar o modelo na primeira extração;
  • legacy.ready: ambiente histórico e assets externos completos.

Use portnoie doctor --checkpoint-only para validar apenas o checkpoint local ou em cache. Em uma instalação nova do wheel, o resultado esperado antes do primeiro download é checkpoint.status="not-cached", com código de saída 1. Execute portnoie download antes de repetir o diagnóstico. O comando completo também retorna status diferente de zero quando o backend selecionado não está pronto.

Um model_dir customizado é comparado aos hashes oficiais por padrão; o manifesto que estiver dentro dele não redefine essa raiz de confiança. Somente artefatos deliberadamente diferentes podem usar trust_custom_model=True. Esse opt-in confia no manifesto customizado para consistência, não para autenticidade, e é obrigatório ao pular integridade antes de carregar o pickle legado.

Backend legado, somente para comparação

O legado é explícito e limitado a Python 3.10 por causa de AllenNLP 2.10/Torch 1.12:

Não use em produção. Essa pilha está fora de suporte e contém dependências com vulnerabilidades conhecidas. Execute-a somente em ambiente descartável, isolado e offline, com os artefatos oficiais previamente baixados/verificados e sem dados não confiáveis.

python3.10 -m pip install -e ".[legacy]"
portnoie download
python3.10 -m spacy download pt_core_news_lg
portnoie doctor --backend legacy
portnoie extract --backend legacy "Maria escreveu um livro."

Os extras modern e legacy fixam linhas incompatíveis de Torch e devem ser instalados em ambientes virtuais separados.

Esse caminho ainda exige forward-1024.pt e backward-1024.pt. Informe cópias locais verificadas:

export PORTNOIE_FLAIR_FORWARD=/modelos/flair/forward-1024.pt
export PORTNOIE_FLAIR_BACKWARD=/modelos/flair/backward-1024.pt

O fallback histórico usa endpoints HTTP e fica desativado por padrão. O opt-in --allow-historical-download existe apenas para reprodução controlada; não é necessário nem consultado pelo backend moderno.

Docker

O container usa o backend moderno:

docker build -t portnoie .
docker run --rm portnoie doctor
docker run --rm portnoie extract "Maria escreveu um livro."

Também é possível executar docker compose run --rm portnoie doctor. O Dockerfile não instala AllenNLP/Flair nem baixa os assets Flair externos. Durante o build, baixa o checkpoint verificado para o cache do usuário não-root e instala pt_core_news_lg==3.8.0 pela URL com hash fixado; a imagem pronta pode executar sem acesso à rede.

Desenvolvimento

python -m pip install -e ".[modern,dev]"
portnoie download
ruff check src tests scripts
pytest
python -m build

Os testes leves não carregam a rede. Quando Torch está disponível, um teste offline carrega o checkpoint real e valida a frase anotada; outro percorre o fluxo de texto bruto com anotações spaCy simuladas. O teste com pt_core_news_lg real é executado quando esse modelo está instalado. A CI roda o backend moderno em Python 3.10, 3.11, 3.12 e 3.13.

src/portnoie/                 API, CLI, diagnóstico e núcleo moderno
src/portnoie/official.py       revisão e hashes oficiais ancorados no pacote
src/portnoie/modern_data/      sidecar mínimo com proveniência
src/portnoie/model_data/       cópia local opcional; excluída do wheel/sdist
multioie/                     implementação AllenNLP histórica
tests/                        testes unitários e validação offline
scripts/                      verificações de procedência e E2E

O relatório e o script reproduzível da comparação Flair 14/14 estão em docs/MODERN_VALIDATION.md. O guia de release descreve a publicação no PyPI/GitHub e os testes exigidos antes de cada tag.

Segurança, licença e citação

O backend moderno usa Torch ≥2.10 e carrega somente tensores com weights_only=True. O legado pode abrir o model_params.pkl, que é um pickle capaz de executar código; use somente a cópia oficial verificada contra os hashes oficiais do pacote. Consulte SECURITY.md.

Para trabalhos acadêmicos, cite o artigo associado (a referência também está em CITATION.cff):

@inproceedings{cabral2022portnoie,
  author = {Cabral, Bruno and Souza, Marlo and Claro, Daniela Barreiro},
  title = {PortNOIE: A Neural Framework for Open Information Extraction for the Portuguese Language},
  booktitle = {Computational Processing of the Portuguese Language (PROPOR 2022)},
  year = {2022},
  doi = {10.1007/978-3-030-98305-5_23}
}

A release usa GPL-3.0-only. O arquivo LICENCE original estava vazio e o metadata antigo dizia apenas GPL-3.; a autorização explícita do mantenedor para publicar o código, o checkpoint e as matrizes incorporadas foi registrada em 30/08/2026 no NOTICE.

About

Portuguese Open Information Extraction: historical PortNOIE checkpoint on Hugging Face, modern PyTorch API, automatic downloads and reproducible inference.

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages