Serigy Sapiens — FakeNews BR
Pesos do Serigy Sapiens (v1.1), treinados em notícias em português (FakeBR), e as instruções de
uso pela SDK serigy. O modelo responde a perguntas tipadas sobre um
texto, Escolha, Indice e Verdadeiro, e cada resposta traz confidence, para decidir, e
uncertainty, para saber se o texto é terreno conhecido.
Arquivos
| Arquivo | Função |
|---|---|
comite/comite.json |
Manifesto do modelo: sensores, encoder, temperatura e referências da uncertainty |
comite/membro_{0..9}.safetensors · .json |
As dez partes treinadas do modelo (~0,9 M de parâmetros cada) |
comite/csem.safetensors |
Projeção do sinal semântico usado na uncertainty |
figuras/ |
Scorecard e figuras do modelo |
notebook_quick_start_with_Serigy.ipynb |
Quick start: perguntas tipadas sobre seis textos, de notícias de 2026 a textos fora do domínio |
São ~41 MB de pesos treinados. Os LLMs congelados que o modelo lê (Manacá-1B e Tucano-1b1) e o encoder MiniLM multilíngue não são redistribuídos aqui: a SDK os baixa dos repositórios originais na primeira execução. Este repositório não contém código de inferência; o uso é pela SDK.
Instalação
pip install "serigy>=0.3" # backend torch (CUDA → MPS → CPU)
pip install "serigy[mlx]>=0.3" # opcional: GPU do Mac (Apple Silicon)
Não é preciso token: este repositório e os modelos congelados que a SDK baixa são públicos.
Uso
Para começar rápido, abra o notebook_quick_start_with_Serigy.ipynb:
ele carrega o modelo e faz as mesmas três perguntas sobre seis textos, de notícias de 2026 a textos fora
do domínio (inglês, código, receita), mostrando como a uncertainty sobe quando o texto sai do que o
modelo conhece.
Perguntas tipadas (system_one)
from serigy import SerigyModel, Escolha, Indice, Verdadeiro
model = SerigyModel("wendellperbar/serigy-fake-news-br")
perguntas = {
"tema": Escolha(
instructions="Qual o tema da notícia?",
criteria={"politica": None, "tv_celebridades": None, "sociedade_cotidiano": None},
),
"gravidade": Indice(instructions="Quão grave?", criteria=["Baixa", "Média", "Alta"]),
"falsa": Verdadeiro(instructions="A notícia é falsa?"),
}
result = model.system_one(
"BOMBA!!! Apresentador famoso da Globo é preso em 2026 e a emissora paga milhões para "
"esconder o caso. Veja o vídeo antes que tirem do ar!",
perguntas,
leitura=True,
)
tema = result.answers["tema"]
print(tema.escolha, tema.confidence, tema.uncertainty, tema.leitura)
# tv_celebridades 0.82 0.08 pode_apostar
print(result.answers["falsa"].verdadeiro)
# 0.997
print(result.as_public_dict()) # JSON público
As mesmas três perguntas sobre os seis textos do notebook de quick start:
| Texto | "A notícia é falsa?" (P(sim) · leitura) | Tema (confidence · leitura) | uncertainty (falsa · tema) |
|---|---|---|---|
| Boato de celebridade (2026) | sim, 1,00 · pode_apostar |
tv_celebridades 0,82 · pode_apostar |
0,13 · 0,08 |
| Boato de saúde (2026) | sim, 0,96 · pode_apostar |
tv_celebridades 0,48 · nao_sei |
0,67 · 0,96 |
| Nota de política (2026) | não, 0,00 · pode_apostar |
politica 0,70 · nao_sei |
0,14 · 0,21 |
| Texto em inglês | não, 0,17 · nao_me_comprometo |
tv_celebridades 0,42 · nao_sei |
1,00 · 1,00 |
| Código Python | sim, 0,63 · nao_sei |
tv_celebridades 0,46 · nao_sei |
1,00 · 1,00 |
| Receita de bolo | não, 0,12 · pode_apostar |
tv_celebridades 0,51 · nao_sei |
0,89 · 0,92 |
Nas notícias, a uncertainty fica baixa ou média; nos textos fora do domínio, vai a 0,89–1,00. Ela
sobe, mas nem sempre o bastante para barrar a resposta: na receita, o "é falsa?" ainda sai como
pode_apostar.
| Primitiva | O que responde | Resposta |
|---|---|---|
Escolha |
Qual opção? (2–6 opções, chaves livres, descrição opcional) | escolha, probabilities, confidence, uncertainty |
Indice |
Em que ponto da escala? (2–10 níveis ordenados) | indice (Σ k·P(k)), legend, probabilities, confidence, uncertainty |
Verdadeiro |
A proposição é verdadeira? | verdadeiro (P(sim)), uncertainty |
As perguntas e as opções são texto livre: paráfrases e perguntas novas funcionam sem re-treino, inclusive
com a polaridade invertida ("a notícia é verdadeira?"). Quando a lista de opções pode não cobrir o texto,
inclua uma opção de escape como nenhuma_das_anteriores. O texto é lido uma vez, e cada pergunta a mais
sobre ele custa ~1,5 ms.
Atalho de fake news (predict)
out = model.predict(
"A Câmara dos Deputados aprovou nesta terça-feira, em votação simbólica, o projeto que altera "
"regras do orçamento para 2026. O texto segue agora para análise do Senado."
)
# falsa=False, p_falsa=0.005, uncertainty=0.14, leitura="pode_apostar"; tema "politica"
# {"falsa": bool, "p_falsa": float, "confidence": float, "uncertainty": float,
# "leitura": "pode_apostar" | "nao_me_comprometo" | "nao_sei",
# "tema": {"escolha": str, "probabilities": {...}, "confidence": float, "uncertainty": float, "leitura": ...},
# "usage": {"input_tokens": int}}
São as duas perguntas do treino ("A notícia é falsa?" e o tema: politica, tv_celebridades,
sociedade_cotidiano) numa leitura só do texto.
CLI
serigy --model wendellperbar/serigy-fake-news-br "texto da notícia..." # predict
serigy --model wendellperbar/serigy-fake-news-br --json '{"state":"…","questions":{…}}' --leitura # system_one
serigy --model wendellperbar/serigy-fake-news-br --backend mlx --dtype bfloat16 "texto..." # GPU do Mac, metade da memória
Opções do SerigyModel
| Argumento | Padrão | Uso |
|---|---|---|
repo_or_path (1º argumento) |
wendellperbar/serigy-fake-news-br |
O repositório dos pesos no Hub ("wendellperbar/<nome-do-modelo>") ou uma pasta local com comite.json (uso offline) |
revision |
o pin da versão da SDK | Fixar um commit deste repo (ou env SERIGY_HUB_REVISION) |
backend |
"torch" |
"mlx" na GPU do Mac (serigy[mlx]) |
device |
automático (CUDA → MPS → CPU) | Só no torch, por exemplo "cpu" |
dtype |
"auto" (bf16 na GPU, fp32 na CPU) |
"float32" ou "bfloat16"; o bf16 usa metade da memória, e a decisão foi igual em 100% num teste de paridade |
Para uso offline, baixe a pasta comite/ e passe o caminho:
from huggingface_hub import snapshot_download
pasta = snapshot_download("wendellperbar/serigy-fake-news-br", allow_patterns=["comite/*"])
model = SerigyModel(pasta)
Como ler confidence e uncertainty
confidence(a maior probabilidade, calibrada) serve para decidir: aja quando passar de um limiar que vem do custo do erro no seu caso. NoVerdadeiro, ela émax(verdadeiro, 1 − verdadeiro).uncertainty(0–1) diz se o texto é terreno conhecido: um valor alto significa um texto diferente daqueles em que o modelo aprendeu. Em textos como os do treino, metade das respostas fica abaixo de ~0,4 e 90% abaixo de ~0,95.
Com leitura=True, cada resposta ganha o campo leitura:
leitura |
Quando | Em palavras |
|---|---|---|
pode_apostar |
confidence ≥ tau e uncertainty ≤ o quantil q de referência |
"a resposta é X e pode apostar" |
nao_me_comprometo |
confidence ≥ tau, mas uncertainty acima do quantil |
"a resposta é X, mas não quero me comprometer" |
nao_sei |
confidence < tau |
"não sei" |
O padrão é tau=0.8 e q=0.9. Os quantis disponíveis são 0.5, 0.8, 0.9 e 0.95:
model.system_one(texto, perguntas, leitura=True, tau=0.9, q=0.8).
Como o Serigy chegou até aqui
Cada passo foi decidido por um teste; o relatório técnico (em breve) traz os números de cada um.
- Três sinais de confiança (
serigy-jev, até a 0.2.0). O ponto de partida foi o trabalho de Nandakishor M. (2025) sobre sinais de confiança lidos de um LLM antes da geração: similaridade semântica (C_sem), convergência entre as camadas e uma confiança aprendida, fundidos num escore único que classificava a notícia como verdadeira, falsa ou incerta. - Primeiras perguntas tipadas (
serigy-golpes-br). No modelo de golpes, o escore único deu lugar a heads que recebem a pergunta como entrada, com as respostas tipadasEscolha,IndiceeVerdadeiro. - A pergunta modula a leitura do texto (FiLM). Somada ao texto, a pergunta quase não pesava: o modelo acertava 0,95 no "é falsa?" e 0,05 no "é verdadeira?". Com FiLM, a pergunta escala cada traço do texto, e o modelo passou a responder às duas polaridades e a paráfrases que nunca viu.
confidenceé a probabilidade da resposta. A temperatura, ajustada na validação, passou a fazer parte do modelo, e o índice de confiança herdado, que não era uma probabilidade, deu lugar ao max P.- Um comitê de dois leitores. Heads sobre o mesmo LLM erram juntas; heads sobre o Manacá-1B e o
Tucano-1b1 concordam dentro do domínio e divergem fora dele. A discordância entre as dez heads virou a
uncertainty. - Controle do tamanho do texto. O reconhecimento de domínio media, em boa parte, o tamanho do texto. O treino passou a incluir versões cortadas (8–40 palavras), e o C_sem voltou como segunda leitura de domínio, somado à discordância.
- Opções abertas (v1.1, este modelo). O tema passou a aceitar chaves livres, descrições opcionais e uma opção de escape, escolhida em 83–100% dos casos em que o tema certo não está na lista.
O nome vem de Homo sapiens sapiens, "o que sabe que sabe": além de decidir, o Serigy aprende a reconhecer quando não sabe.
Treinamento
| Dados | FakeBR (Monteiro et al., 2018): "a notícia é falsa?" e tema com 3 opções; FACTCK.BR (Moreno & Bressan, 2019): escala de veracidade de 4 níveis |
| Textos | Pares falsa/verdadeira cortados no comprimento do mais curto, mais versões cortadas (8–40 palavras); pares nunca divididos entre splits |
| Perguntas | Banco de paráfrases, metade com a polaridade invertida; opções com chaves livres, distratores e opção de escape (receita aberto) |
| Modelo | 10 partes treinadas (5 seeds × 2 LLMs congelados), ~10,8 M de parâmetros treinados; os LLMs não são ajustados |
| Calibração | Temperatura única do modelo, ajustada na validação |
Resultados no teste do FakeBR (1.434 notícias):
| Métrica | Valor |
|---|---|
| Acerto "a notícia é falsa?" | 0,954 |
| ECE (erro de calibração) | 0,020 |
| Acerto com 80% de cobertura | 0,993 |
| Pergunta invertida nunca vista: acerto · coerência | 0,938 · 0,955 |
| Acerto no tema (3 opções) | 0,678 |
| AUROC de texto fora do domínio (comprimento casado: FACTCK.BR · golpes · prompt injection) | 0,64–0,67 · 0,83–0,85 · 0,81–0,83 |
| Latência por texto (GPU de um Mac) | ~423 ms |
Scorecard
Serigy × Jev (TypeSafe AI, API) × Laya (Convai), com as mesmas perguntas, textos e código de métricas, no teste do FakeBR e no FACTCK.BR (fora do domínio). Jev e Laya são zero-shot; o Serigy foi treinado no FakeBR, então parte da vantagem no domínio vem do treino. Fora do domínio, o Jev é mais bem calibrado.
O relatório técnico, com o método, os testes e as comparações completas, sai em breve.
Limites
- Treinado em um único domínio (notícias em português, 2016–2018). Fora dele, o modelo tem pouco sinal
sobre a veracidade, e a
uncertaintysobe, mas não o bastante para barrar tudo: cerca de metade das respostas ainda sai comopode_apostar. Não é um verificador de fatos para produção. - Os dois LLMs ocupam ~9 GB de memória em fp32 (metade em bf16).
- Por segurança, a SDK só baixa modelos de uma allowlist (
allow_custom_models=Truepara sair dela). Em serviços HTTP, fixe o modelo no servidor.
Versões
| Modelo | Versão do serigy |
|---|---|
wendellperbar/serigy-fake-news-br (este, padrão) |
a partir da 0.3.0 |
wendellperbar/serigy-jev, serigy-golpes-br, serigy-trex (formato antigo) |
até a 0.2.0 (pip install "serigy<0.3") |
Licença e créditos
Pesos sob Apache-2.0. Os modelos congelados mantêm as próprias licenças: Manacá-1B (CC-BY-4.0), Tucano-1b1 (Apache-2.0) e MiniLM multilíngue (Apache-2.0). Dados de treino: FakeBR (Monteiro et al., 2018), citado conforme pedido dos autores, e FACTCK.BR (Moreno & Bressan, 2019, MIT).
Ao usar, cite:
@misc{barreto2026serigy,
title = {Serigy Sapiens: um modelo que decide e aprende a reconhecer quando n{\~a}o sabe},
author = {Barreto, Wendell Pereira},
year = {2026},
month = {10},
howpublished = {\url{https://huggingface.co/wendellperbar/serigy-fake-news-br}},
note = {Modelo Serigy Sapiens v1.1, Hugging Face}
}