← Retour
Module 01

Fondations LLM

Comprendre comment fonctionnent les Large Language Models, de l'architecture Transformer au fine-tuning. Le socle sur lequel tout le reste repose.

01

Pourquoi ce module ?

Avant de construire un chatbot, un agent vocal, ou un pipeline RAG, il faut comprendre la machine qui est au coeur de tout : le Large Language Model.

Un LLM n'est pas magique. C'est un programme mathematique qui prend du texte en entree, calcule des probabilites, et produit du texte en sortie. Tout le reste — agents, RAG, tool calling — n'est que de la plomberie autour de ce mecanisme.

Analogie

Imagine un musicien de jazz. Il ne sait pas ce qu'il va jouer a l'avance, mais a chaque note, il "predit" la prochaine en se basant sur toutes les notes qu'il a entendues dans sa vie. Un LLM fait exactement ca, mais avec des mots.

A la fin de ce module, tu sauras expliquer a n'importe qui comment un LLM fonctionne, ce qu'est un token, ce que fait l'attention, et pourquoi la temperature change le comportement du modele. C'est le socle.

02

Les tokens — l'alphabet des LLMs

Un LLM ne lit pas des lettres ni des mots entiers. Il lit des . C'est la premiere chose a comprendre.

Concept cle

Qu'est-ce qu'un token ?

Un token est un morceau de texte que le modele traite comme une unite. Le processus qui decoupe le texte en tokens s'appelle la tokenization.

Prenons un exemple concret. La phrase :

texte
"Bonjour, je cherche un contrat d'electricite"

Pourrait etre decoupee en tokens comme ca (ca depend du tokenizer) :

tokens
["Bon", "jour", ",", " je", " cherche", " un", " contrat", " d", "'", "elect", "ric", "ite"]

Remarque : certains mots sont coupes en morceaux ("electricite" → 3 tokens). C'est parce que le tokenizer a appris que "elect", "ric" et "ite" sont des sous-unites frequentes.

python — tokenizer en pratique
import tiktoken  # tokenizer d'OpenAI (pip install tiktoken)

enc = tiktoken.encoding_for_model("gpt-4o")
tokens = enc.encode("Bonjour, je cherche un contrat d'electricite")
print(f"{len(tokens)} tokens")  # → 12 tokens
print(enc.decode_single_token_bytes(t) for t in tokens])

# Avec Hugging Face Transformers (PyTorch)
from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("mistralai/Mistral-7B-v0.1")
result = tokenizer("Bonjour, je cherche un contrat d'electricite")
print(result["input_ids"])        # → [1, 9038, 28725, ...]
print(len(result["input_ids"]))   # → 13 tokens (different ! chaque modele a son tokenizer)

Attention

Pourquoi c'est important en pratique ?Parce que tu payes a l'API au nombre de tokens, pas au nombre de mots. Et le context window (la "memoire" du modele) est mesure en tokens aussi. Un texte en francais consomme ~30% plus de tokens que le meme texte en anglais.

ConceptExempleImpact pratique
1 token"hello"Les mots courants = 1 token
Multi-token"electricite" → 3 tokensLes mots longs ou rares coutent plus
Token special"<|endoftext|>"Signale la fin d'une sequence au modele
~100 tokens~75 mots en anglaisRegle rapide pour estimer les couts

Quiz

La phrase 'Bonjour le monde' contient combien de tokens approximativement ?

03

Les embeddings — donner du sens aux mots

OK, le modele a decoupes le texte en tokens. Mais un ordi ne comprend pas les mots — il comprend les nombres. Comment on passe de "chat" a quelque chose qu'un ordinateur peut manipuler ?

Concept cle

L'embedding

Chaque token est converti en un vecteur — une liste de nombres (par exemple 768 ou 4096 nombres). Ce vecteur capture le sens du token. Des mots similaires ont des vecteurs proches.

Analogie

Imagine une carte du monde, mais pour les mots. "Paris" et "Lyon" seraient proches (deux villes francaises). "Paris" et "banane" seraient loin. Un embedding, c'est la position GPS d'un mot sur cette carte — sauf que la carte a 768 dimensions au lieu de 2.

Voici a quoi ca ressemble en simplifie :

python — embeddings avec PyTorch
import torch
from transformers import AutoTokenizer, AutoModel

# Charger un modele d'embeddings (sentence-transformers)
tokenizer = AutoTokenizer.from_pretrained("sentence-transformers/all-MiniLM-L6-v2")
model = AutoModel.from_pretrained("sentence-transformers/all-MiniLM-L6-v2")

# Embedder des mots
phrases = ["roi", "reine", "banane"]
inputs = tokenizer(phrases, padding=True, return_tensors="pt")

with torch.no_grad():
    outputs = model(**inputs)
    # Mean pooling sur les tokens → un vecteur par phrase
    embeddings = outputs.last_hidden_state.mean(dim=1)

print(embeddings.shape)  # → torch.Size([3, 384])  (3 phrases, 384 dimensions)

# Similarite cosinus
from torch.nn.functional import cosine_similarity
print(cosine_similarity(embeddings[0], embeddings[1], dim=0))  # roi↔reine  → 0.72 (proche !)
print(cosine_similarity(embeddings[0], embeddings[2], dim=0))  # roi↔banane → 0.11 (loin)

La propriete magique des embeddings, c'est qu'on peut faire de l'arithmetique dessus :

arithmetique vectorielle
roi - homme + femme ≈ reine

Ce n'est pas une metaphore — ca marche vraiment avec les vecteurs. Le modele a appris ces relations en lisant des milliards de textes.

Attention

Lien avec RAG (Module 3) :les embeddings sont la base du RAG. Quand tu chercheras des documents "similaires" a une question, tu compareras des embeddings. On y reviendra.

04

L'attention — le coeur du Transformer

C'est LE concept qui a revolutionne le NLP en 2017 avec le papier "Attention Is All You Need". Avant l'attention, les modeles lisaient le texte mot par mot, de gauche a droite (RNN). Le probleme : pour des phrases longues, le modele "oubliait" le debut.

Concept cle

Le mecanisme d'attention

L'attention permet a chaque token de "regarder" tous les autres tokens de la sequence et de decider lesquels sont importants pour lui. C'est un systeme de ponderation dynamique.

Prenons une phrase :

exemple
"Le chat dort sur le canape car il est fatigue"

Quand le modele traite le mot "il", l'attention lui permet de "regarder en arriere" et de comprendre que "il" se refere a "chat", pas a "canape". Il attribue un poids eleve a "chat" et un poids faible a "canape".

Mecanisme d'attention simplifie

Lechatdortsurlecanapecarilestfatigue
        ↑↑↑↑↑↑↑↑ forte attention          ↑ regard

"il" donne un poids fort a "chat" (0.72) et faible a "canape" (0.03)

En pratique, le Transformer utilise du multi-head attention: plusieurs "tetes" d'attention en parallele, chacune specialisee dans un type de relation (syntaxe, semantique, coreference...).

Le calcul mathematique (simplifie) :

mathematiques
Attention(Q, K, V) = softmax(Q * K^T / sqrt(d_k)) * V

Q = Query   → "Qu'est-ce que je cherche ?" (le token actuel)
K = Key     → "Qu'est-ce que je contiens ?" (chaque autre token)
V = Value   → "Quelle information je donne ?" (le contenu a transmettre)

Le softmax normalise les poids pour qu'ils somment a 1.
sqrt(d_k) empeche les valeurs de devenir trop grandes.
python — attention avec NumPy
import numpy as np

def attention(Q, K, V):
    """Self-attention en 4 lignes de NumPy."""
    d_k = Q.shape[-1]
    scores = Q @ K.T / np.sqrt(d_k)    # similarite entre Q et K
    weights = np.exp(scores) / np.exp(scores).sum(axis=-1, keepdims=True)  # softmax
    return weights @ V                   # moyenne ponderee des valeurs

# Exemple : 4 tokens, dimension 8
np.random.seed(42)
Q = np.random.randn(4, 8)  # 4 tokens, chacun un vecteur de dim 8
K = np.random.randn(4, 8)
V = np.random.randn(4, 8)

output = attention(Q, K, V)
print(output.shape)  # → (4, 8)  — chaque token recoit un vecteur "enrichi"

# En PyTorch, c'est une seule ligne :
import torch
import torch.nn.functional as F
attn_output = F.scaled_dot_product_attention(
    torch.randn(4, 8), torch.randn(4, 8), torch.randn(4, 8)
)  # PyTorch gere le scaling et le softmax pour toi

Analogie

Imagine une salle de classe. L'attention, c'est comme si chaque eleve (Q) pouvait poser une question silencieuse, et chaque autre eleve (K) repondait avec un signal d'intensite variable. L'eleve recoit l'info (V) proportionnellement a l'intensite de chaque signal.

Quiz

Pourquoi le mecanisme d'attention est-il superieur aux RNN pour les longues sequences ?

05

Architecture complete d'un Transformer

Maintenant qu'on a les briques (tokens, embeddings, attention), assemblons le puzzle complet.

1

Tokenization

Le texte brut est decoupe en tokens numeriques.

2

Embedding + Positional Encoding

Chaque token recoit un vecteur (embedding) + une information de position. Sans la position, le modele ne saurait pas l'ordre des mots.

3

N couches de Transformer

Chaque couche contient : multi-head attention → normalisation → feed-forward network → normalisation. GPT-4 a ~120 couches. Claude ~96. Chaque couche raffine la comprehension.

4

Couche de sortie (logits)

Le dernier vecteur est projete sur le vocabulaire entier (~100k tokens). Chaque token recoit un score (logit). Plus le score est haut, plus le modele pense que ce token est la bonne suite.

5

Sampling

Les logits sont convertis en probabilites (softmax), puis un token est choisi selon une strategie (greedy, top-k, top-p...). Ce token est ajoute a la sequence, et on recommence a l'etape 1.

Pipeline simplifie d'un LLM


  "Bonjour, je"
       |
  [ Tokenizer ]
       |
  [82, 4521, 29]
       |
  [ Embedding + Position ]
       |
  [ 0.21, -0.3, ... ] x 3 tokens
       |
  ┌──────────────────────┐
  │  Transformer Layer 1 │ ← attention + feed-forward
  │  Transformer Layer 2 │
  │        ...           │
  │  Transformer Layer N │
  └──────────────────────┘
       |
  [ Projection → vocabulaire ]
       |
  "cherche" (probabilite: 0.12)
  "veux"    (probabilite: 0.08)
  "suis"    (probabilite: 0.07)
       |
  [ Sampling ] → "cherche"
       |
  Output: "Bonjour, je cherche"
  → on recommence avec cette nouvelle sequence

Concept cle

Autoregressive generation

Le modele genere UN SEUL token a la fois, puis le rajoute a l'entree pour generer le suivant. C'est pour ca que les reponses arrivent mot par mot quand tu utilises le streaming. Et c'est pour ca que la generation est lente : chaque token necessite un passage complet dans le reseau.

06

Comment le modele genere du texte

Quand le modele a calcule les probabilites pour le prochain token, comment choisit-il ? Il y a plusieurs strategies :

StrategiePrincipeUsage
GreedyToujours choisir le token le plus probableRapide mais repetitif et ennuyeux
Top-kChoisir parmi les k tokens les plus probablesPlus de variete, mais k est arbitraire
Top-p (nucleus)Choisir parmi les tokens dont la proba cumulee atteint pLe plus utilise — s'adapte au contexte
TemperatureAplatit ou accentue les probabilites avant samplingControle la 'creativite' globale

En pratique, on combine temperature + top-p. C'est ce que tu controles quand tu appelles l'API.

07

Temperature, top-p, top-k

Ces trois parametres sont les boutons que tu tournes le plus souvent quand tu utilises un LLM. Comprends-les bien.

Concept cle

Temperature

La temperature controle la "confiance" du modele. T=0 : le modele choisit toujours le token le plus probable (deterministe). T=1 : distribution naturelle. T>1 : plus aleatoire, plus creatif.

intuition
Temperature = 0.0 → "Le chat est sur le tapis."
                       Toujours la meme reponse. Factuel.

Temperature = 0.7 → "Le chat somnole paisiblement sur le tapis."
                       Un peu de variete. Bon equilibre.

Temperature = 1.5 → "Le chat cosmique danse sur un tapis de nebuleuses."
                       Creatif mais peut delirer.

Concept cle

Top-p (nucleus sampling)

Au lieu de considerer TOUS les tokens possibles, on ne garde que ceux dont la probabilite cumulee atteint p. Avec p=0.9, on garde les tokens qui representent 90% de la masse de probabilite.

python — temperature et sampling avec PyTorch
import torch
import torch.nn.functional as F

# Logits bruts du modele (scores avant softmax)
logits = torch.tensor([2.0, 1.5, 0.8, 0.3, -0.5])  # 5 tokens candidats
labels = ["chat", "chien", "oiseau", "dragon", "dinosaure"]

# Temperature = 1.0 (distribution naturelle)
probs_t1 = F.softmax(logits / 1.0, dim=0)
print(dict(zip(labels, probs_t1.tolist())))
# → {'chat': 0.42, 'chien': 0.25, 'oiseau': 0.13, 'dragon': 0.08, 'dinosaure': 0.03}

# Temperature = 0.3 (quasi-deterministe)
probs_t03 = F.softmax(logits / 0.3, dim=0)
# → {'chat': 0.89, 'chien': 0.09, ...}  ← "chat" domine

# Temperature = 2.0 (tres aleatoire)
probs_t2 = F.softmax(logits / 2.0, dim=0)
# → {'chat': 0.28, 'chien': 0.23, ...}  ← distribution aplatie

# Top-p sampling (nucleus)
def top_p_sample(logits, p=0.9):
    probs = F.softmax(logits, dim=0)
    sorted_probs, sorted_idx = torch.sort(probs, descending=True)
    cumsum = torch.cumsum(sorted_probs, dim=0)
    mask = cumsum - sorted_probs < p    # garder jusqu'a cumsum >= p
    filtered = sorted_probs * mask
    return torch.multinomial(filtered / filtered.sum(), 1)  # echantillonner
ParamValeur basseValeur hauteRecommandation
temperature0 = deterministe2 = tres aleatoire0.7 pour du general, 0 pour de l'extraction
top_p0.1 = tres restrictif1.0 = tout garder0.9 pour du general
top_k1 = greedy100+ = large choixSouvent ignore, top-p suffit

Attention

Regle pratique :pour du tool calling et de l'extraction de donnees (ce qu'on fera chez Selectra), utilise temperature=0 et top_p=1. Tu veux des reponses deterministes et fiables, pas de la creativite.

Quiz

Pour un agent vocal Selectra qui doit collecter une adresse, quelle temperature utiliser ?

08

Le context window — la memoire de travail

Le est la quantite de texte que le modele peut "voir" en meme temps. C'est sa memoire de travail.

Concept cle

Input + Output = Context Window

Le context window inclut TOUT : ton system prompt, l'historique de conversation, les documents fournis, ET la reponse du modele. Si ton prompt fait 100k tokens et que le window est de 128k, il ne reste que 28k pour la reponse.

ModeleContext windowEn mots (~)Equivalent
GPT-3.54k tokens~3 000 mots~6 pages A4
GPT-4o128k tokens~96 000 motsUn roman entier
Claude 3.5 Sonnet200k tokens~150 000 mots2 romans
Claude Opus 41M tokens~750 000 mots10 romans
Gemini 2.51M tokens~750 000 mots10 romans

Attention

Context window ≠ memoire long terme.Le modele "oublie" tout entre deux requetes API. Si tu veux qu'il se souvienne d'une conversation, tu dois renvoyer tout l'historique a chaque appel. C'est pour ca que les couts explosent dans les chatbots — chaque message renvoie tout ce qui precede.

Analogie

Le context window, c'est comme la table de travail d'un artisan. Tu peux y poser beaucoup de choses (200k tokens), mais une fois que tu quittes l'atelier et reviens le lendemain, la table est vide. Pas de memoire permanente.

09

Panorama des modeles (2024-2026)

Le paysage evolue tres vite. Voici les acteurs majeurs :

FamilleModelesForcesFaiblesses
OpenAI (GPT)GPT-4o, GPT-5, o1, o3Polyvalent, bon en code, large ecosystemeClosed-source, cher sur les gros modeles
Anthropic (Claude)Claude 3.5 Sonnet, Claude Opus 4Excellent en analyse longue, suivi d'instructions, ethiqueClosed-source, pas de fine-tuning public
Google (Gemini)Gemini 2.5 Flash/ProMultimodal natif, context 1M, bon rapport qualite/prixMoins bon en code complexe
Meta (Llama)Llama 3.3, Llama 4Open-source, deployable en local, fine-tunableMoins bon que les closed-source sur le raisonnement
MistralMixtral, Mistral LargeFrancais ! Open-source, bon en multilingueEcosysteme plus petit

Concept cle

Open-source vs Closed-source

Closed-source (GPT, Claude) : tu appelles une API, tu ne vois pas les poids du modele. Plus performant mais dependance au fournisseur.
Open-source (Llama, Mistral) : tu peux telecharger et faire tourner le modele toi-meme. Moins performant sur les gros benchmarks, mais libre et fine-tunable.

Pour ton stage chez Selectra, tu utiliseras probablement un modele closed-source (GPT ou Claude) via API pour l'agent vocal. La latence et la qualite du raisonnement comptent plus que le cout pour une demo.

10

Utiliser un LLM via API — premier appel

Assez de theorie. Voici comment on parle a un LLM en vrai. On utilise le Vercel AI SDK— c'est la librairie standard pour faire de l'IA en TypeScript.

1

Installer les dependances

terminal
npm install ai @ai-sdk/react
2

Creer la route API (serveur)

typescript — app/api/chat/route.ts
import { streamText, convertToModelMessages } from "ai";

export async function POST(req: Request) {
  const { messages } = await req.json();

  const result = streamText({
    model: "anthropic/claude-sonnet-4.6",     // via AI Gateway
    system: "Tu es un assistant Selectra. Tu aides les clients a trouver le meilleur contrat d'energie.",
    messages: await convertToModelMessages(messages),
  });

  return result.toUIMessageStreamResponse();
}
3

Creer le composant client (UI)

typescript — app/page.tsx
"use client";
import { useChat, DefaultChatTransport } from "@ai-sdk/react";

const transport = new DefaultChatTransport({ api: "/api/chat" });

export default function Chat() {
  const { messages, status, sendMessage } = useChat({ transport });
  const [input, setInput] = useState("");

  return (
    <div>
      {messages.map((m) => (
        <div key={m.id}>
          <strong>{m.role}:</strong>
          {m.parts.map((part, i) =>
            part.type === "text" ? <span key={i}>{part.text}</span> : null
          )}
        </div>
      ))}
      <form onSubmit={(e) => {
        e.preventDefault();
        sendMessage({ text: input });
        setInput("");
      }}>
        <input value={input} onChange={(e) => setInput(e.target.value)} />
      </form>
    </div>
  );
}

Concept cle

System prompt

Le system promptest une instruction invisible pour l'utilisateur mais visible par le modele. C'est la que tu definis le role, le ton, et les contraintes de ton assistant. Pour Selectra : "Tu es un agent de qualification Selectra. Tu collectes l'adresse, le fournisseur actuel, et le numero PDL."

Attention

streamText vs generateText : utilise streamText pour les interfaces utilisateur (les mots apparaissent un par un) et generateTextpour le traitement en arriere-plan (tu veux la reponse complete d'un coup).

11

Quiz final

Verifions que les fondations sont solides avant de passer au Module 2.

Quiz

Quel est l'ordre correct du pipeline d'un LLM ?

Quiz

Pourquoi le context window est-il un facteur limitant pour les chatbots ?

Quiz

Que fait le mecanisme d'attention ?

Module 01 termine

Tu connais maintenant les fondations : tokens, embeddings, attention, architecture Transformer, parametres de generation, et comment faire ton premier appel API. Prochain module : Prompt Engineering — l'art de parler aux LLMs.