12 papers de IA que mudaram tudo: explicação detalhada com exemplos

Este artigo tem um vídeo curto:TikTok

1. Visão geral

A maioria dos sistemas de IA que você usa todos os dias — ChatGPT, Midjourney, Google Search com AI Overview — ficam de pé nos ombros de cerca de uma dúzia de papers de pesquisa. Este artigo passa por esses 12 papers, explica as ideias centrais em linguagem fácil de entender, e ilustra cada ideia com um trecho de código Java curto. Após ler, você entenderá por que Transformer “dominou” todo o mundo do NLP, por que RAG consegue resolver hallucinations, e por que um prompt “vamos pensar passo a passo” é tão poderoso.

2. AlexNet (2012) — deep learning começa a “enxergar”

Antes do AlexNet, visão computacional era baseada em engenharia manual de features. AlexNet usou convolutional neural network (CNN) com ativação ReLU e dropout, treinado em GPU, e derrotou todos os concorrentes no ImageNet 2012 com erro quase 10 pontos percentuais menor. Este foi o boom que marcou o início da era do deep learning.

public class ConvOutputSizeCalculator {

    public static int outputSize(int inputSize, int kernelSize, int stride, int padding) {
        return (inputSize - kernelSize + 2 * padding) / stride + 1;
    }

    public static void main(String[] args) {
        // Imagem de entrada do AlexNet: 227x227, kernel 11x11, stride 4
        int size = outputSize(227, 11, 4, 0);
        System.out.println(size);
    }
}
55

outputSize calcula o tamanho do feature map após uma camada conv. Com entrada 227×227 e kernel 11×11 stride 4, a saída é 55×55×96 — exatamente o tamanho da primeira camada do AlexNet. ReLU ajuda o gradiente a não “morrer” como em sigmoid, então redes mais profundas ainda conseguem treinar.

3. GAN (2014) — duas redes em confronto para gerar imagens realistas

Generative Adversarial Network coloca duas redes em posição de confronto: o gerador tenta criar imagens falsas para enganar o discriminador, e o discriminador tenta distinguir imagens reais/falsas. Ambos melhoram a cada rodada de treinamento.

public record GanLosses(double discriminatorLoss, double generatorLoss) {}

public class GanLossCalculator {

    public static GanLosses compute(double probReal, double probFake) {
        double dLoss = -(Math.log(probReal) + Math.log(1 - probFake));
        double gLoss = -Math.log(probFake);
        return new GanLosses(dLoss, gLoss);
    }
}

probReal é a probabilidade do discriminador adivinhar corretamente a imagem real, probFake é a probabilidade de ser enganado pelo gerador. O discriminador quer probReal → 1 e probFake → 0; o gerador quer o oposto. Este é um jogo de soma zero típico.

Lembrete: GAN é famoso por ser difícil de treinar — é fácil encontrar mode collapse (o gerador cria apenas alguns tipos de imagens repetidas). Modelos de difusão posteriores são muito mais estáveis, então a maioria dos sistemas modernos de geração de imagens (DALL·E, Stable Diffusion) não usam mais GAN.

4. Transformer (2017) — “Attention Is All You Need”

Transformer abandona completamente RNN/LSTM, substituindo-os por self-attention: cada token olha diretamente para todos os outros tokens na frase para calcular relevância, sem necessidade de processamento sequencial. Esta é a arquitetura base do GPT, Claude, Llama e BERT.

public class ScaledDotProductAttention {

    public static double[] attendFirstToken(double[][] query, double[][] key) {
        int seqLen = key.length;
        int dim = query[0].length;
        double scale = Math.sqrt(dim);
        double[] scores = new double[seqLen];
        for (int j = 0; j < seqLen; j++) {
            double dot = 0;
            for (int k = 0; k < dim; k++) dot += query[0][k] * key[j][k];
            scores[j] = dot / scale;
        }
        return softmax(scores);
    }

    private static double[] softmax(double[] row) {
        double max = Arrays.stream(row).max().orElse(0);
        double sum = 0;
        double[] exps = new double[row.length];
        for (int i = 0; i < row.length; i++) {
            exps[i] = Math.exp(row[i] - max);
            sum += exps[i];
        }
        for (int i = 0; i < exps.length; i++) exps[i] /= sum;
        return exps;
    }
}

A linha dot / scale divide o produto escalar por sqrt(dim) para evitar que valores muito grandes saturem o softmax. O resultado do softmax são os pesos de atenção — tokens que se relacionam muito com o token em questão terão pesos altos, usados para combinar os value vectors.

5. Scaling Laws (2020) — loss diminui segundo uma lei de potência

OpenAI descobriu: aumentar o número de parâmetros, dados ou compute exponencialmente faz a loss diminuir ao longo de uma curva de lei de potência bastante suave e previsível — não há “magia”, basta escalar corretamente.

public class ScalingLawEstimator {

    // L(N) = (Nc / N)^alpha — N: número de bilhões de parâmetros, Nc, alpha: constantes empíricas
    public static double estimateLoss(double paramsBillion, double nc, double alpha) {
        return Math.pow(nc / paramsBillion, alpha);
    }
}

Com nc e alpha fixos a partir de dados empíricos, aumentar paramsBillion faz estimateLoss diminuir gradualmente, mas mais lentamente (diminishing returns). Esta é a razão pela qual labs de IA investem centenas de milhões de dólares em compute: a redução de loss é previsível, não é uma aposta.

Lembrete: Scaling laws não são infinitas. Após certo ponto, para diminuir a loss um pouco mais é necessário aumentar compute exponencialmente de forma gigantesca — essa é a razão pela qual a indústria está se voltando para melhorar dados e arquitetura em vez de apenas “ficar maior”.

6. GPT-3 (2020) — escala cria novas capacidades

GPT-3 com 175 bilhões de parâmetros demonstra: se grande o suficiente, um modelo pode fazer few-shot learning — basta alguns exemplos no prompt, sem necessidade de ajustar pesos novamente.

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
    <version>1.0.0</version>
</dependency>
@Service
public class FewShotClassifier {

    private final ChatClient chatClient;

    public FewShotClassifier(ChatClient.Builder builder) {
        this.chatClient = builder.build();
    }

    public String classifySentiment(String review) {
        String prompt = """
                Avaliação: "Produto bom, entrega rápida" -> Positivo
                Avaliação: "Produto com defeito, não funciona" -> Negativo
                Avaliação: "%s" ->
                """.formatted(review);
        return chatClient.prompt(prompt).call().content();
    }
}

Dois exemplos no prompt servem para “ensinar” o modelo o formato da resposta diretamente no contexto — sem necessidade de treinar novamente. Esta é precisamente a habilidade emergente que modelos menores não conseguem fazer bem.

7. InstructGPT & RLHF (2022) — transformar LLM bruto em assistente útil

GPT-3 original prevê bem o próximo token, mas não “obedece” — pode responder fora do tópico ou de forma prejudicial. InstructGPT usa Reinforcement Learning from Human Feedback (RLHF): humanos classificam respostas, treinam um modelo de recompensa a partir disso, e usam o modelo de recompensa para otimizar a policy com PPO.

public record Completion(String text, double rewardScore) {}

public class RewardBasedSelector {

    public Completion pickBest(List<Completion> candidates) {
        return candidates.stream()
                .max(Comparator.comparingDouble(Completion::rewardScore))
                .orElseThrow();
    }
}

O código acima apenas ilustra o passo final: selecionar a conclusão com maior recompensa de acordo com a avaliação do modelo de recompensa. Na prática, PPO atualiza os pesos do modelo de policy gradualmente para que ele gere respostas de alta pontuação desde o início, sem necessidade de filtragem posterior.

Lembrete: RLHF requer uma grande quantidade de dados rotulados por humanos (ranking), caro e tendencioso de acordo com o viés do avaliador. Técnicas como DPO (Direct Preference Optimization) surgiram depois para reduzir esse custo.

8. ViT (2020) — imagem também é uma “frase”

Vision Transformer divide a imagem em pequenos patches (por exemplo, 16×16 pixels), achata cada patch em um vetor, e os trata como tokens enviados para um encoder Transformer — a arquitetura é idêntica ao processamento de texto.

public class PatchEmbeddingCalculator {

    public static int numPatches(int imageSize, int patchSize) {
        int gridSize = imageSize / patchSize;
        return gridSize * gridSize;
    }
}

Com uma imagem 224×224 e patches 16×16, numPatches retorna 196 — equivalente a uma “frase” de 196 tokens enviada para o Transformer. Dessa forma, ViT reutiliza todas as técnicas de atenção já comprovadas em NLP para tarefas de visão, e supera CNN quando os dados de treinamento são grandes o suficiente.

9. DDPM (2020) — adicionar ruído e aprender a remover

Denoising Diffusion Probabilistic Model estabelece a base para todos os modelos de difusão modernos: o processo forward adiciona ruído Gaussiano gradualmente à imagem ao longo de muitas etapas, o processo reverse aprende a prever e remover esse ruído para reconstruir a imagem original.

public class ForwardDiffusion {

    public static double[] addNoise(double[] x0, double alphaBarT, Random random) {
        double[] xt = new double[x0.length];
        for (int i = 0; i < x0.length; i++) {
            double noise = random.nextGaussian();
            xt[i] = Math.sqrt(alphaBarT) * x0[i] + Math.sqrt(1 - alphaBarT) * noise;
        }
        return xt;
    }
}

alphaBarT controla a proporção de imagem original retida em relação ao ruído no passo t: próximo a 1 significa que ainda está perto da imagem original, próximo a 0 significa que é quase ruído puro. O modelo gerador aprende o processo inverso — começando de ruído puro, remove gradualmente o ruído a cada etapa para gerar uma imagem significativa.

10. Latent Diffusion (2021) — denoising em espaço comprimido

Executar difusão diretamente em pixels consome muito compute. Latent Diffusion comprime a imagem para um espaço latente menor usando um autoencoder, executa todo o processo de denoising lá, e depois decodifica de volta para imagem — este é o design por trás do Stable Diffusion.

public class LatentCompressionCalculator {

    public static long pixelCount(int width, int height, int channels) {
        return (long) width * height * channels;
    }
}
pixelCount(512, 512, 3) = 786_432   // espaço de pixel
pixelCount(64, 64, 4)   = 16_384    // espaço latente

A taxa de compressão de cerca de 48 vezes ajuda a difusão a rodar muito mais rápido enquanto mantém a qualidade da imagem, porque a maioria das informações “redundantes” no espaço de pixel (áreas de cor uniforme, pequenos detalhes) foram removidas pelo autoencoder durante a compressão.

11. CLIP (2021) — ligar imagem e texto em um espaço comum

CLIP treina aprendizado contrastivo em centenas de milhões de pares (imagem, caption): pares corretos têm embeddings próximos, pares incorretos têm embeddings distantes. O resultado é um espaço comum que permite comparar texto e imagem usando similaridade do cosseno.

@Service
public class ImageTextMatcher {

    private final EmbeddingModel embeddingModel;

    public ImageTextMatcher(EmbeddingModel embeddingModel) {
        this.embeddingModel = embeddingModel;
    }

    public double similarity(String caption, float[] imageEmbedding) {
        float[] textEmbedding = embeddingModel.embed(caption);
        return cosine(textEmbedding, imageEmbedding);
    }

    private double cosine(float[] a, float[] b) {
        double dot = 0, normA = 0, normB = 0;
        for (int i = 0; i < a.length; i++) {
            dot += a[i] * b[i];
            normA += a[i] * a[i];
            normB += b[i] * b[i];
        }
        return dot / (Math.sqrt(normA) * Math.sqrt(normB));
    }
}

similarity retorna um valor próximo a 1 se a legenda corresponde ao conteúdo da imagem, próximo a 0 ou negativo se não estiver relacionada. Este é o mecanismo por trás da busca de imagens por descrição de texto natural (text-to-image search) que muitos produtos de e-commerce estão usando.

12. Chain-of-Thought (2022) — uma frase de prompt libera o raciocínio

Basta adicionar a frase “vamos pensar passo a passo” ao prompt, e LLMs grandes automaticamente quebram o problema complexo em passos pequenos, reduzindo significativamente erros de cálculo e lógica em comparação com respostas diretas.

public String solveWithReasoning(ChatClient chatClient, String question) {
    String prompt = """
            Vamos pensar passo a passo antes de responder.
            Pergunta: %s
            Raciocínio:
            """.formatted(question);
    return chatClient.prompt(prompt).call().content();
}

Pedir ao modelo para “raciocinar” antes de finalizar a resposta força a gerar tokens intermediários que servem como suporte — assim como as pessoas rabiscam antes de responder uma pergunta difícil.

Lembrete: Chain-of-Thought aumenta o número de tokens gerados, resultando em custo e latência mais altos. Para perguntas simples (busca de fato direto), forçar CoT apenas torna mais lento sem melhorar a precisão.

13. RAG (2020) — recuperar depois gerar, sem mais invenção

Retrieval-Augmented Generation acopla um LLM com uma etapa de recuperação de documentos reais antes de gerar a resposta, ajudando a reduzir alucinações e permitindo respostas baseadas em dados atualizados fora do escopo de treinamento original.

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-pgvector-store-spring-boot-starter</artifactId>
    <version>1.0.0</version>
</dependency>
@Service
public class DocumentAnsweringService {

    private final VectorStore vectorStore;
    private final ChatClient chatClient;

    public DocumentAnsweringService(VectorStore vectorStore, ChatClient.Builder builder) {
        this.vectorStore = vectorStore;
        this.chatClient = builder.build();
    }

    public String answer(String question) {
        List<Document> relevant = vectorStore.similaritySearch(
                SearchRequest.query(question).withTopK(3));

        String context = relevant.stream()
                .map(Document::getContent)
                .collect(Collectors.joining("\n---\n"));

        String prompt = """
                Com base nos documentos a seguir, responda à pergunta. Se não houver informação, diga "Não sei".
                Documentos:
                %s

                Pergunta: %s
                """.formatted(context, question);

        return chatClient.prompt(prompt).call().content();
    }
}

similaritySearch recupera os 3 trechos de documentos mais semanticamente próximos da pergunta, insere-os no prompt como contexto, e força o modelo a responder baseado nesse contexto em vez de “lembrar” vagamente do treinamento.

class DocumentAnsweringServiceTest {

    @Test
    void shouldReturnUnknownWhenNoRelevantDocument() {
        VectorStore emptyStore = mock(VectorStore.class);
        when(emptyStore.similaritySearch(any())).thenReturn(List.of());

        ChatClient stubClient = mock(ChatClient.class, RETURNS_DEEP_STUBS);
        when(stubClient.prompt(anyString()).call().content()).thenReturn("Não sei");

        ChatClient.Builder builder = mock(ChatClient.Builder.class);
        when(builder.build()).thenReturn(stubClient);

        DocumentAnsweringService service = new DocumentAnsweringService(emptyStore, builder);

        String result = service.answer("Quando a empresa foi fundada?");

        assertThat(result).contains("Não sei");
    }
}

O teste confirma que quando nenhum documento relevante é encontrado, a resposta deve admitir “Não sei” em vez de inventar uma resposta — exactamente o objetivo de grounding do RAG.

Lembrete: Se seu repositório de documentos tiver apenas algumas dezenas de páginas, colocar tudo diretamente na janela de contexto é mais simples e barato do que construir um pipeline RAG completo com vector store. RAG só vale a pena usar quando os dados são grandes ou mudam frequentemente.

14. Conclusão

Esses 12 papers não são independentes — eles se constroem um sobre o outro: Transformer é a base para GPT-3 e ViT; scaling laws explicam por que GPT-3 funciona; RLHF transforma GPT-3 em ChatGPT; DDPM é a base do Latent Diffusion; CLIP é a ponte para que modelos de difusão entendam prompts de texto. Entender cada peça do quebra-cabeça ajuda você a ler novos papers mais rapidamente, porque a maioria das ideias “novas” atualmente são variações ou combinações dessas bases.

llmdeep-learningtransformerragai