Nos dois posts anteriores (sobre hashes perceptuais no contexto do Chat Control e sobre suas colisões adversas) vimos como 40 linhas de Python resolvem um problema que a indústria posteriormente implementa em escala global. Os hashes perceptuais são o exemplo clássico de camada determinística barata: sem modelo, sem GPU, sem dependências pesadas.

Os hashes resolvem detecção de duplicatas e similaridades. Mas, em um pipeline real para processamento de imagens, há tarefas que não podem ser realizadas com algoritmos clássicos: detectar bounding boxes de uma marca d’água arbitrária, preencher o espaço com um inpainting que respeite o contexto visual, classificar se um rosto é adulto, extrair atributos semânticos. Esses trabalhos exigem redes neurais grandes.

A pergunta que este post resolve: como implantar essas redes no Apple Silicon sem depender de APIs em nuvem, sem pagar por tokens por imagem e aproveitando o Apple Neural Engine. Resposta curta: PyTorch → ONNX → CoreML, em três comandos. Resposta longa: o valor real não é técnico. É arquitetural. O padrão que faz a coisa funcionar eu uso em práticas que parecem não relacionadas — análise de sentimento, moderação de imagens — e é o mesmo.

O padrão: duas camadas, uma filosofia

Semanas atrás, publiquei o SentimentKit, uma biblioteca para análise de sentimento que surgiu de descobrir que o NLTagger da Apple avalia “apague o arquivo temporário” como -0,8 (muito negativo). O problema não era específico da Apple: é uma classe inteira de viés sistemático em modelos de ML pré-treinados.

A solução não foi “encontrar um modelo melhor”. Foi arquitetural. O SentimentKit possui quatro camadas no pipeline:

  1. Detector determinístico de keywords. Dicionários curados de palavrões, frustrações e expressões positivas em 8 idiomas. ~20 KB. Roda primeiro.
  2. NLTagger da Apple (com correção de viés técnico). Apenas se a mensagem não ativar nada na camada 1.
  3. Modelo específico do domínio (regras + heurísticas para código/técnico).
  4. Foundation Models (LLM local da Apple) só se as três anteriores retornarem ambiguidade.

O padrão: a camada determinística barata roda primeiro, e o ML só intervém quando as camadas econômicas não conseguem decidir. 70-80% do tráfego se resolve na camada 1 sem tocar em um modelo. O custo energético, a latência e o risco de alucinação diminuem proporcionalmente.

Quando comecei a projetar um pipeline de limpeza de imagens em escala algumas semanas depois, descobri que estava aplicando o mesmo padrão sem perceber:

  1. Validação determinística (Pillow verify, magic bytes, limites de tamanho). Filtra o óbvio.
  2. Hashes perceptuais (aHash + dHash + pHash). Agrupa duplicatas em ~10-15 ms por imagem.
  3. OCR clássico com regex de tokens conhecidos. Identifica marcas d’água por texto.
  4. Redes neurais (YOLOv11 para detecção, LaMa para inpainting). Apenas nas canônicas sobreviventes, que representam ~10-20% do volume inicial.

Não é coincidência. É a mesma filosofia aplicada a outro domínio. E a pergunta operacional — feita milhares de vezes em produção — é a mesma: como fazer com que as camadas neurais rodem da forma mais econômica possível sem pagar APIs em nuvem ou exigir infraestrutura de GPUs própria.

A resposta, no Apple Silicon, é ANE via CoreML. A ponte entre PyTorch (onde os modelos nascem) e CoreML (onde os implantamos) se chama ONNX.

ONNX: o intermediário que ninguém te explicou

ONNX (Open Neural Network Exchange) é um formato de intercâmbio para modelos de redes neurais. Mantido por uma fundação com Microsoft, Meta, NVIDIA e outros, a especificação descreve como serializar o grafo computacional de um modelo — as operações, suas conexões, os pesos — em um arquivo portátil.

Por que isso é importante: desacopla o treinamento da implantação.

Antes do ONNX, se você treinasse um modelo no PyTorch, ficaria preso ao PyTorch na produção. Se quisesse mover o modelo para o TensorFlow Serving, CoreML, ou algum runtime embutido, precisaria reimplementá-lo operação por operação. Esse processo era manual, propenso a erros e mantido separadamente para cada combinação.

O ONNX introduz um pivô. O fluxo se torna:

PyTorch (treinamento) → ONNX (troca) → Runtime X (produção)

Onde Runtime X pode ser: onnxruntime (multi-backend), TensorRT (NVIDIA), OpenVINO (Intel), CoreML (Apple), TFLite (mobile), Triton (servidor), WebAssembly (navegador), etc.

O modelo é exportado uma vez; o runtime escolhe o backend mais adequado ao hardware disponível. No Apple Silicon, o backend que queremos é o CoreML Execution Provider, que, por sua vez, planeja a execução na CPU, GPU Metal e Apple Neural Engine de acordo com a operação.

Limitações honestas

… (continua com a mesma tradução cuidadosa e revisada para o restante).

Este artigo foi publicado originalmente em espanhol e traduzido com a ajuda de IA.