English Previous slide Next slide Toggle fullscreen Toggle overview view Open presenter view
title: "Claude API : plongée en profondeur"
subtitle: "Applied AI — Niveau Avancé · Session 1"
author: "Yann Isola"
theme: "ink #1A2230 / teal #0F7A6C / copper #B4612A / light-teal #E9F6F3 / bg #F4F7F6"
Slide 1 — Titre
Claude API : plongée en profondeur
Applied AI — Niveau Avancé · Session 1
Yann Isola · Préparation Claude Certified Architect
Slide 2 — Objectifs de la session
Construire une requête API complète et justifier chaque paramètre
Interpréter les 4 valeurs de stop_reason → logique applicative
Raisonner sur la fenêtre de contexte comme mémoire de travail
Maîtriser le prompt caching (cache_control) et son ROI
Implémenter le streaming SSE (SSE = Server-Sent Events)
Arbitrer synchrone / streaming / Batches API
Concevoir la gestion d'erreurs : 429, backoff, retry-after
Slide 3 — Le contrat minimal
Trois champs obligatoires : model, max_tokens, messages
curl https://api.anthropic.com/v1/messages \
-H "x-api-key: $ANTHROPIC_API_KEY " \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"model": "claude-sonnet-4-5",
"max_tokens": 1024,
"messages": [{"role": "user", "content": "Bonjour"}]
}'
Noms de modèles volatils — toujours vérifier docs.anthropic.com
Slide 5 — L'appel via SDK Python
import anthropic
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-sonnet-4-5" ,
max_tokens=1024 ,
temperature=0.2 ,
stop_sequences=["FIN_RAPPORT" ],
system="Analyste financier. Français, concis." ,
messages=[{"role" : "user" , "content" : "..." }],
)
print (response.content[0 ].text)
print (response.usage, response.stop_reason)
Slide 6 — Paramètres d'échantillonnage
Paramètre
Rôle
Reco architecte
temperature 0–1
aléa
0–0.3 extraction · 0.7–1 créatif
top_p
nucleus sampling
ne pas combiner avec temperature
top_k
k tokens les + probables
cas avancés uniquement
stop_sequences
arrêts personnalisés
sorties délimitées
Piège certif : temperature: 0 ≠ déterminisme parfait
Slide 7 — Trois rôles, trois privilèges
system — canal privilégié (hors du tableau messages)
→ persona, règles, politique de sortie. Pas « un premier message déguisé »
user — l'appelant : questions, documents, tool_result
assistant — le modèle… et le prefilling
Règle : alternance stricte, premier message = user
Deux rôles identiques consécutifs → 400
Slide 8 — Prefilling : mettre des mots dans la bouche du modèle
messages=[
{"role" : "user" , "content" : "Liste 3 risques en JSON." },
{"role" : "assistant" , "content" : "{" }
]
Le modèle continue à partir de {
Supprime les préambules (« Bien sûr ! Voici… »)
Le prefill n'est pas dans la réponse → re-préfixer côté client
Slide 9 — stop_reason : les 4 signaux
stop_reason
Signification
Réaction
end_turn
fin naturelle
nominal
max_tokens
tronqué (HTTP 200 !)
alerter / relancer
stop_sequence
séquence rencontrée
lire response.stop_sequence
tool_use
outil demandé
exécuter → tool_result → boucler
Slide 10 — Le garde-fou canonique
match response.stop_reason:
case "end_turn" :
return extract_text(response)
case "max_tokens" :
raise TruncatedResponseError(partial=...)
case "stop_sequence" :
return parse_delimited(..., response.stop_sequence)
case "tool_use" :
return handle_tool_loop(response)
case _:
raise UnexpectedStopReason(...)
Slide 11 — La fenêtre de contexte = mémoire de travail
~200 000 tokens (certains modèles : 1M en bêta)
Contient TOUT : system + historique + docs + outils + résultats
Ce n'est pas « une limite » — c'est ce que le modèle sait pour cette requête
3 conséquences : coût linéaire · lost in the middle · latence (TTFT)
Slide 12 — Coût : la conversation qui devient quadratique
API sans état → l'historique complet est refacturé à chaque tour
total = sum (cout(30_000 , 500 ) for _ in range (20 ))
× 10 000 utilisateurs/jour → sujet de direction technique
Parades : résumé · troncature glissante · prompt caching
Slide 13 — « Lost in the middle »
Rappel de l'information selon sa position dans le contexte :
DÉBUT ████████████ excellent
MILIEU ██████ dégradé ← ne rien enterrer ici
FIN ███████████ excellent
Placement stratégique :
Documents volumineux → en tête
Instructions critiques + question → en fin
Consigne clé au milieu de 80k tokens de logs →
Slide 14 — Prompt caching : le principe
Réutiliser un préfixe déjà traité via cache_control
Économie (volatile) :
Lecture (hit) : ~10 % du tarif → −90 %
Écriture : surcoût ~25 %
TTL ~5 min , rafraîchi à chaque hit (option 1 h )
Rentable dès 2 requêtes : 1,25 + 0,10 = 1,35 < 2,00
Slide 15 — cache_control : syntaxe
system=[{
"type" : "text" ,
"text" : GROS_CONTEXTE,
"cache_control" : {"type" : "ephemeral" }
}]
u = response.usage
u.cache_creation_input_tokens
u.cache_read_input_tokens
u.input_tokens
Slide 16 — Règles d'invalidation du cache
Préfixe exact : un octet modifié en amont → invalidé
Ordre : tools → system → messages
Minimum cachable : 1 024 tokens (sinon ignoré silencieusement )
Max 4 breakpoints par requête
Design cible : stable en tête, variable en queue
Slide 17 — Anti-pattern : le cache qui coûte plus cher
system = f"[{datetime.now()} ] Tu es un assistant..."
Horodatage en tête → préfixe jamais identique
0 % de hit + surcoût d'écriture 25 % à chaque appel
Résultat : on paie plus cher que sans cache
Slide 18 — Compter avant de payer : count_tokens
count = client.messages.count_tokens(
model="claude-sonnet-4-5" ,
system="..." ,
messages=[{"role" : "user" , "content" : doc}],
)
print (count.input_tokens)
Chaque famille de modèles a son tokenizer
Ne jamais réutiliser un comptage tiktoken (OpenAI) pour Claude
Ordres de grandeur : ~3,5–4 car./token (anglais), un peu plus dense en français
Slide 19 — Streaming : pourquoi
UX : premier token en ~1 s au lieu d'attendre 30 s
Longues générations : indispensable (timeouts HTTP)
SSE = Server-Sent Events : flux HTTP unidirectionnel text/event-stream
event: content_block_delta
data: {"delta":{"type":"text_delta","text":"Le"}}
Slide 20 — Le cycle d'événements SSE
message_start ← id, model, usage d'ENTRÉE
content_block_start ← ouverture bloc 0
content_block_delta ×n ← les morceaux de texte
content_block_stop ← fermeture bloc 0
message_delta ← stop_reason + output_tokens ★
message_stop ← fin du flux
(+ ping keep-alive, + error possible en cours de flux)
★ Piège certif : les métadonnées finales sont dans message_delta
Slide 21 — Streaming : implémentation
with client.messages.stream(
model="claude-sonnet-4-5" , max_tokens=1024 ,
messages=[...],
) as stream:
for text in stream.text_stream:
print (text, end="" , flush=True )
final = stream.get_final_message()
print (final.stop_reason)
Version bas niveau : stream=True + boucle sur event.type
→ exigée en certification (exercice 2)
Slide 22 — Batches API : le 3e mode d'exécution
Mode
Latence
Coût
Usage
Synchrone
secondes
100 %
interactif
Streaming
TTFT ~1 s
100 %
interactif long
Batch
SLA 24 h
−50 %
masse, non urgent
Jusqu'à 100 000 requêtes / ~256 Mo par batch
En pratique : souvent < 1 h
Résultats non ordonnés → corrélation par custom_id obligatoire
Slide 23 — Batch : code
batch = client.messages.batches.create(requests=[
{"custom_id" : f"doc-{i} " ,
"params" : {"model" : "claude-haiku-4-5" ,
"max_tokens" : 512 ,
"messages" : [...]}}
for i, doc in enumerate (documents)
])
for r in client.messages.batches.results(batch.id ):
if r.result.type == "succeeded" : traiter(r.custom_id, ...)
else : rejouer(r.custom_id, r.result)
Slide 25 — Backoff exponentiel avec jitter
except anthropic.RateLimitError as e:
retry_after = e.response.headers.get("retry-after" )
if retry_after:
delai = float (retry_after)
else :
delai = min (60 , 2 **tentative) * random.uniform(0.5 , 1.5 )
time.sleep(delai)
retry-after prime sur votre formule
Jitter obligatoire (effet « thundering herd »)
Le SDK retry déjà 2× par défaut → attention aux couches multiplicatives
Slide 26 — Arbre de décision de l'architecte
Besoin temps réel ?
├── OUI → réponse longue ? → streaming SSE
│ réponse courte ? → synchrone
└── NON → volume massif ? → Batches API (−50 % )
+ petit modèle
+ prompt caching si préfixe commun
Toujours : garde stop_reason + backoff 429 + log de usage
Slide 27 — Les 7 pièges de certification vus aujourd'hui
max_tokens obligatoire, sans valeur par défaut
Troncature = HTTP 200 + stop_reason: "max_tokens"
Le prefill n'est pas inclus dans la réponse
temperature: 0 ≠ déterminisme parfait
Cache : préfixe exact, tools → system → messages
stop_reason final en streaming → message_delta
Résultats batch non ordonnés → custom_id
Slide 28 — Prochaines étapes
Exercices : client robuste · streaming bas niveau · pipeline batch 80k emails
Quiz : 10 QCM certification (seuil 7/10)
Page interactive : constructeur de requête + visualiseur SSE + compteur de tokens (offline)
Session 2 : tool use & agents — la boucle tool_use → tool_result en profondeur
Réflexe permanent : revalider tarifs, limites et noms de modèles sur docs.anthropic.com
Notes: Cadrer d'emblée — cette session n'est pas du prompting, c'est de l'architecture. Contrat d'API, économie de tokens, modes de défaillance.
Notes: 7 objectifs = 7 blocs. Tout est évalué en QCM certification.
Notes: `anthropic-version` épingle le contrat d'API. Sans lui → erreur. `max_tokens` n'a PAS de défaut (piège Q1 du quiz).
Notes: Anecdote terrain : systèmes en prod livrant des JSON tronqués pendant des semaines faute de tester stop_reason. Transition vers slide 8.
Notes: SDK = Software Development Kit. Insister : logger `usage` systématiquement (observabilité des coûts). `content` est un TABLEAU de blocs.
Notes: Formulation correcte : « réduit fortement la variabilité ». Non-déterminisme numérique résiduel.
Notes: Le system prompt est traité avec une priorité particulière par le modèle — résistance accrue aux contournements dans les tours user. API sans état : tout est renvoyé à chaque appel.
Notes: Démo live : même question avec/sans prefill. JSON = JavaScript Object Notation. Autre usage : forcer un choix de QCM avec prefill « La réponse est ( ».
Notes: LE slide certification. Un architecte écrit une branche par valeur. max_tokens n'est PAS une erreur HTTP — état métier à détecter soi-même.
Notes: Le `case _` protège contre les futures valeurs de l'API. À faire écrire en exercice 1.
Notes: TTFT = Time To First Token. Changement de mental model : de « contrainte » à « ressource à architecturer ».
Notes: Somme des préfixes = croissance quadratique. Transition naturelle vers le caching.
Notes: Question au groupe : « RAG avec 40 chunks — où va la question utilisateur ? » Réponse : après les docs, éventuellement répétée.
Notes: TTL = Time To Live. Faire faire le calcul de rentabilité au groupe avant de donner la réponse.
Notes: Trois compteurs distincts dans usage — les montrer, c'est ce qui permet de vérifier que le cache fonctionne réellement en prod.
Notes: Piège Q7 du quiz : modifier le dernier message user N'invalide PAS le cache (il est après le breakpoint).
Notes: Cas réel fréquent. Idem avec un ID de session, un nonce, un compteur. Tout ce qui varie va APRÈS le breakpoint.
Notes: Usages : valider la fenêtre AVANT de payer, dimensionner max_tokens, chargeback interne. Passer la requête COMPLÈTE (system+messages+tools).
Notes: UX = User eXperience. SSE ≠ WebSocket : unidirectionnel, simple HTTP, compatible proxys (sauf buffering — voir exercice 2C).
Notes: Démo : visualiseur de la page web de session (offline). Lancer la version « troncature » pour montrer stop_reason=max_tokens en streaming.
Notes: Même en streaming, la troncature max_tokens existe. Un front qui affiche joliment un texte tronqué reste un bug.
Notes: SLA = Service Level Agreement. Cas d'usage à faire trouver : classification nocturne, enrichissement CRM, éval massive de prompts.
Notes: États finaux : succeeded / errored / expired / canceled — une politique de rejeu pour chacun. Bonus : batch + caching se CUMULENT (hits non garantis).
Notes: Trois compteurs de rate limit indépendants — on peut être limité en tokens de sortie tout en étant sous la limite de requêtes.
Notes: Bonus : en-têtes `anthropic-ratelimit-*-remaining` pour throttling PROACTIF. Rappeler la question d'ouverture du cours (qui a vécu un 429 ?).
Notes: Synthèse opérationnelle. Les trois réflexes du bas s'appliquent aux TROIS modes.
Notes: Faire relire cette liste à voix haute par un participant. C'est la check-list de révision.
Notes: Distribuer les exit tickets (5 questions, 3 min). Ramasser à la sortie — ils calibrent l'ouverture de la session 2.