Pular para o conteúdo

Plataformas e apps

Hemeroteca digital

Acervo privado de jornais em PDF com OCR, busca full-text em italiano, busca por significado e um assistente de IA que cita as fontes.

TipoPlataformas e apps

Uma hemeroteca digital para uma coleção particular: edições de jornal em PDF viram um acervo onde qualquer matéria pode ser encontrada por palavra, por significado ou fazendo uma pergunta, sempre com a fonte citada.

O problema

O cliente tinha uma coleção de edições de jornais em arquivos PDF. Encontrar um artigo significava abrir os arquivos um por um, e muitas páginas eram digitalizações sem texto. O acervo também precisava continuar privado: só podiam entrar as pessoas convidadas pelo administrador.

O que eu construí: uma hemeroteca digital

Construí um acervo web privado em que cada edição é armazenada como título do jornal, data e PDF, e cada página se torna pesquisável.

  • Extração de texto com OCR como fallback: uma página mantém a própria camada de texto quando tem uma. Páginas com menos de 40 caracteres são renderizadas a 220 DPI e lidas com o Tesseract. Assim, até as digitalizações antigas ficam pesquisáveis.
  • Busca full-text em italiano: a busca usa stemming italiano e ignora acentos, então “citta” encontra “città”. Frases exatas aparecem primeiro, com trechos destacados.
  • Busca por significado: o texto das páginas é dividido em blocos sobrepostos e convertido em vetores de 768 dimensões com um modelo multilíngue. Os leitores encontram artigos mesmo sem saber as palavras exatas.
  • Assistente com citações: o leitor faz uma pergunta em linguagem comum. O sistema recupera até 8 trechos, por significado e por palavra-chave, e o Claude responde apenas com base nesses trechos, citando título, data e página. Ele é ativado no painel de administração com a chave Anthropic do próprio cliente.
  • Upload em lote a partir de uma pasta: o administrador seleciona uma pasta de PDFs e a data é lida do nome de cada arquivo. Duplicatas são ignoradas por título e data ou pela impressão digital SHA-256, então um upload pode ser repetido com segurança.
  • Acesso só por convite: dois perfis, administrador e leitor. O painel gerencia usuários, títulos, a chave de IA e os backups.

Os números

  • Limite de memória de 8 GB no serviço de embeddings, com reinício diário. Antes do limite, ele havia crescido até cerca de 15 GB e travado a fila por uma semana.
  • Backup noturno às 03:30: um dump compactado do banco de dados, mantendo os 14 mais recentes, além de um espelho incremental dos PDFs.
  • Jobs travados recuperados automaticamente: um job que fica rodando por mais de 20 minutos volta para a fila, até 6 tentativas.

Com o que foi feito

Python 3.11 e FastAPI para a aplicação web. PostgreSQL 16 com pgvector, unaccent e pg_trgm para dados, busca textual e vetores. PyMuPDF e Tesseract para texto e OCR. Sentence-transformers com o modelo multilingual-e5-base para os embeddings, rodando como um serviço local separado. A API da Anthropic para o assistente. Tudo roda como serviços systemd atrás de um proxy reverso Apache.

Por que foi feito assim

Mantive a fila de jobs dentro do PostgreSQL em vez de adicionar o Redis. Os workers pegam os jobs com FOR UPDATE SKIP LOCKED, então vários workers rodam em paralelo e nunca processam a mesma edição duas vezes. O servidor também hospeda outros sites, então ter um serviço a menos para rodar e proteger foi um ganho real.

Tem uma ideia?
Vamos conversar.

Seja um site, um app, um vídeo, uma música ou algo maior, estou pronto para ajudar você a realizá-lo.

Entre em contato
  • Nápoles
  • Ideias
  • Projetos
  • Pessoas
  • Sempre em frente