12 papiers IA qui ont tout changé : explications détaillées avec exemples

Cet article a une courte vidéo :TikTok

1. Aperçu

La plupart des systèmes d’IA que vous utilisez au quotidien — ChatGPT, Midjourney, Google Search avec AI Overview — reposent sur les épaules d’une dizaine de papiers de recherche. Cet article parcourt ces 12 papiers, explique les idées centrales dans un langage accessible, et illustre chaque concept par un court extrait de code Java. À la fin, vous comprendrez pourquoi Transformer « domine » tout l’univers du NLP, pourquoi RAG résout les hallucinations, et pourquoi un prompt « réfléchis étape par étape » est si puissant.

2. AlexNet (2012) — deep learning bắt đầu “nhìn thấy”

Avant AlexNet, la vision par ordinateur reposait sur de l’ingénierie des caractéristiques manuelle. AlexNet utilisait un réseau de neurones convolutifs (CNN) avec activation ReLU et dropout, entraîné sur GPU, et a surpassé tous ses concurrents sur ImageNet 2012 avec une erreur plus faible de près de 10 points de pourcentage. C’était l’explosion qui a ouvert l’ère du 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) {
        // Image d'entrée AlexNet : 227x227, kernel 11x11, stride 4
        int size = outputSize(227, 11, 4, 0);
        System.out.println(size);
    }
}
55

outputSize calcule la taille de la feature map après une couche conv. Avec une entrée 227×227 et un kernel 11×11 stride 4, la sortie est 55×55×96 — exactement la taille de la première couche d’AlexNet. ReLU aide le gradient à ne pas « mourir » comme avec sigmoid, donc les réseaux plus profonds restent entraînables.

3. GAN (2014) — deux mạng đối đầu pour générer des images réalistes

Generative Adversarial Network place deux réseaux dans une position antagoniste : le générateur essaie de créer des images fausses pour tromper le discriminateur, le discriminateur essaie de distinguer les vraies images des fausses. Les deux s’améliorent à chaque tour d’entraînement.

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 est la probabilité que le discriminator devine correctement l’image réelle, probFake est la probabilité qu’il soit trompé par le générateur. Le discriminateur veut probReal → 1 et probFake → 0 ; le générateur veut l’inverse. C’est un jeu à somme nulle classique.

Remarque : Les GAN sont réputés difficiles à entraîner — ils souffrent souvent d’effondrement de mode (le générateur ne crée que quelques types d’images répétées). Les modèles de diffusion sont beaucoup plus stables par la suite, donc la plupart des systèmes de génération d’images modernes (DALL·E, Stable Diffusion) n’utilisent plus les GAN.

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

Transformer abandonne complètement les RNN/LSTM, en les remplaçant par l’auto-attention : chaque token regarde directement tous les autres tokens de la phrase pour calculer leur pertinence, sans traitement séquentiel. C’est l’architecture sous-jacente de GPT, Claude, Llama, 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;
    }
}

La ligne dot / scale divise le produit scalaire par sqrt(dim) pour éviter que les valeurs soient trop grandes et ne saturent la softmax. Le résultat softmax donne les poids d’attention — les tokens très pertinents par rapport au token considéré auront un poids élevé, utilisés pour pondérer les vecteurs de valeur.

5. Scaling Laws (2020) — loss diminue selon une loi de puissance

OpenAI a découvert : chaque fois qu’on augmente le nombre de paramètres, de données ou de puissance de calcul de manière exponentielle, la loss diminue selon une loi de puissance lisse et prévisible — pas de « magie », il suffit de scaler correctement.

public class ScalingLawEstimator {

    // L(N) = (Nc / N)^alpha — N : nombre de milliards de paramètres, Nc, alpha : constantes empiriques
    public static double estimateLoss(double paramsBillion, double nc, double alpha) {
        return Math.pow(nc / paramsBillion, alpha);
    }
}

Avec nc et alpha fixés à partir des données empiriques, augmenter paramsBillion fait diminuer estimateLoss progressivement mais plus lentement (rendements décroissants). C’est pourquoi les labos d’IA investissent des centaines de millions dans le compute : la diminution de la loss est prévisible, pas une question de pari.

Remarque : Les lois de scaling ne sont pas infinies. Au-delà d’un certain seuil, pour réduire la loss un peu plus, il faudrait augmenter le compute de manière exponentielle géante — c’est pourquoi l’industrie se tourne vers l’amélioration des données et de l’architecture plutôt que simplement « grandir ».

6. GPT-3 (2020) — l’ampleur génère de nouvelles capacités

GPT-3 avec 175 milliards de paramètres a montré : s’il est assez grand, un modèle peut faire du few-shot learning — il suffit de quelques exemples dans le prompt, sans besoin de fine-tuner les poids.

<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 = """
                Avis : "Produit bon, livraison rapide" -> Positif
                Avis : "Marchandise défectueuse, inutilisable" -> Négatif
                Avis : "%s" ->
                """.formatted(review);
        return chatClient.prompt(prompt).call().content();
    }
}

Les deux exemples dans le prompt « enseignent » au modèle le format de réponse directement dans le contexte — pas besoin de réentraîner. C’est exactement la capacité émergente que les modèles plus petits ne reproduisent pas bien.

7. InstructGPT & RLHF (2022) — transformer un LLM brut en assistant utile

Le GPT-3 original prédit bien le token suivant, mais ne « vous écoute pas » — il peut répondre hors sujet ou être nuisible. InstructGPT utilise Reinforcement Learning from Human Feedback (RLHF) : les humains classent les réponses, ce qui entraîne un modèle de récompense, puis ce dernier est utilisé pour optimiser la politique avec 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();
    }
}

Le code ci-dessus illustre juste l’étape finale : choisir la completion avec la plus haute récompense selon l’évaluation du modèle de récompense. En pratique, PPO met à jour les poids du modèle de politique progressivement pour qu’il génère lui-même des réponses à haut score dès le départ, sans nécessiter de sélection ultérieure.

Remarque : RLHF nécessite une grande quantité de données annotées par des humains (classements), coûteux et sujet aux biais des annotateurs. Des techniques comme DPO (Direct Preference Optimization) sont apparues par la suite pour réduire ce coût.

8. ViT (2020) — les images peuvent aussi être une “phrase”

Vision Transformer divise une image en petits patches (par exemple 16×16 pixels), aplatit chaque patch en un vecteur, puis les traite comme des tokens dans un encodeur Transformer — une architecture identique au traitement du texte.

public class PatchEmbeddingCalculator {

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

Avec une image 224×224 et des patches 16×16, numPatches retourne 196 — équivalent à une « phrase » de 196 tokens envoyée à Transformer. De cette façon, ViT réutilise toute la mécanique d’attention éprouvée du NLP pour la vision, et surpasse les CNN quand les données d’entraînement sont suffisamment volumineuses.

9. DDPM (2020) — ajouter du bruit puis apprendre à le supprimer

Denoising Diffusion Probabilistic Model pose les bases de tous les modèles de diffusion modernes : le processus forward ajoute progressivement du bruit gaussien à une image sur plusieurs étapes, le processus reverse apprend à prédire et supprimer ce bruit pour reconstruire l’image originale.

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 contrôle la proportion d’image originale conservée par rapport au bruit à l’étape t : proche de 1 signifie proche de l’image originale, proche de 0 signifie presque du bruit pur. Le modèle génératif apprend l’inverse de ce processus — en commençant par du bruit pur, « débruitant » étape par étape pour produire une image significative.

10. Latent Diffusion (2021) — débruiter dans un espace compressé

Exécuter la diffusion directement sur les pixels est très coûteux. Latent Diffusion compresse l’image dans un espace latent plus petit à l’aide d’un autoencoder, exécute tout le processus de débruitage là-bas, puis décode pour retrouver l’image — c’est la conception derrière 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   // espace pixel
pixelCount(64, 64, 4)   = 16_384    // espace latent

Un ratio de compression de près de 48× permet à la diffusion de s’exécuter bien plus rapidement tout en conservant la qualité de l’image, car la plupart des informations « redondantes » dans l’espace pixel (zones de couleur uniforme, petits détails) sont supprimées par l’autoencoder lors de la compression.

11. CLIP (2021) — relier images et texte dans un même espace

CLIP entraîne l’apprentissage contrastif sur des centaines de millions de paires (image, caption) : les vraies paires ont des embeddings proches, les fausses paires les ont éloignés. Le résultat est un espace partagé qui permet de comparer le texte et l’image via la similarité cosinus.

@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 retourne une valeur proche de 1 si le caption correspond au contenu de l’image, proche de 0 ou négatif s’ils ne sont pas liés. C’est le mécanisme derrière la recherche d’image par description textuelle (text-to-image search) que de nombreuses plateformes de e-commerce utilisent.

12. Chain-of-Thought (2022) — un prompt “réfléchis étape par étape” déverrouille le raisonnement

Il suffit d’ajouter la phrase « réfléchis étape par étape » au prompt, et les grands LLM décomposent automatiquement les problèmes complexes en étapes plus petites, réduisant considérablement les erreurs de calcul et de logique par rapport à une réponse directe.

public String solveWithReasoning(ChatClient chatClient, String question) {
    String prompt = """
            Réfléchis étape par étape avant de répondre.
            Question : %s
            Raisonnement :
            """.formatted(question);
    return chatClient.prompt(prompt).call().content();
}

Le fait de demander au modèle de « raisonner » avant de conclure le force à générer des tokens intermédiaires comme support — comme les humains qui rédigent un brouillon avant de répondre à une question difficile.

Remarque : Chain-of-Thought augmente le nombre de tokens générés, entraînant des coûts et une latence plus élevés. Pour les questions simples (lookup direct de faits), forcer CoT ralentit juste sans améliorer la précision.

13. RAG (2020) — récupérer puis générer, pas d’hallucinations

Retrieval-Augmented Generation couple un LLM avec une étape de récupération de documents réels avant de générer la réponse, ce qui aide à réduire les hallucinations et permet de répondre en fonction de données mises à jour en dehors du corpus d’entraînement d’origine.

<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 = """
                En fonction des documents suivants, répondez à la question. Si l'information n'est pas disponible, dites "Je ne sais pas".
                Documents :
                %s

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

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

similaritySearch récupère les 3 documents les plus proches sémantiquement de la question, les insère dans le prompt comme contexte, puis force le modèle à répondre sur la base de ce contexte plutôt que de compter sur des souvenirs vagues de l’entraînement.

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("Je ne sais pas");

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

        DocumentAnsweringService service = new DocumentAnsweringService(emptyStore, builder);

        String result = service.answer("En quelle année l'entreprise a-t-elle été fondée ?");

        assertThat(result).contains("Je ne sais pas");
    }
}

Le test confirme que quand aucun document pertinent n’est trouvé, la réponse doit avouer « Je ne sais pas » au lieu de fabriquer une réponse — c’est l’objectif exact du grounding de RAG.

Remarque : Si votre corpus de documents n’est que quelques dizaines de pages, les injecter directement dans la context window est plus simple et moins cher que de construire un pipeline RAG complet avec vector store. RAG ne vaut le coup que si les données sont volumineuses ou changent fréquemment.

14. Conclusion

Ces 12 papiers ne sont pas indépendants — ils s’appuient les uns sur les autres : Transformer est la base de GPT-3 et ViT ; les scaling laws expliquent pourquoi GPT-3 fonctionne ; RLHF transforme GPT-3 en ChatGPT ; DDPM est l’origine de Latent Diffusion ; CLIP est le lien pour que les modèles de diffusion comprennent les prompts textuels. Comprendre chaque pièce du puzzle vous aide à lire plus rapidement de nouveaux papiers, car la plupart des idées « nouvelles » aujourd’hui sont des variantes ou des combinaisons de ces fondations.

llmdeep-learningtransformerragai