Stratégies de journalisation et de documentation
Enregistrez les versions des prompts, les entrées et les sorties pour rendre le débogage reproductible.
Stratégies de journalisation et de documentation est une leçon AI Prompt Engineering gratuite sur CoddyKit. Ceci est la leçon 4 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage AI Prompt Engineering, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours AI Prompt Engineering comprend 4 leçons au total.
Pourquoi la journalisation des invites est importante
Sans journalisation, les échecs des invites restent invisibles jusqu’à ce qu’un utilisateur les signale. Grâce à la journalisation, vous pouvez :
- Détecter les régressions dès qu’elles se produisent
- Reproduire exactement tout échec passé
- Mesurer l’amélioration au fil du temps, à mesure que les invites évoluent
- Auditer le comportement du modèle pour vérifier sa conformité ou sa sécurité
La journalisation n’est pas facultative pour les systèmes d’invites en production : elle constitue le fondement d’applications LLM fiables.
L’entrée minimale viable du journal
Chaque interaction avec une invite doit au minimum consigner les champs suivants :
timestamp: ISO 8601 UTCprompt_id: modèle d’invite utilisémodel: nom et version exacts du modèletemperature: paramètre d’échantillonnageinput: message utilisateur (ou un hachage si PII)output: réponse du modèlelatency_ms: temps de réponsetokens_used: jetons d’entrée + de sortie
import time, json
from datetime import datetime, timezone
def logged_call(prompt_id, system_prompt, user_message, model='gpt-4o', temperature=0.7):
start = time.time()
resp = client.chat.completions.create(
model=model,
messages=[
{'role': 'system', 'content': system_prompt},
{'role': 'user', 'content': user_message}
],
temperature=temperature
)
latency = int((time.time() - start) * 1000)
output = resp.choices[0].message.content
log_entry = {
'timestamp': datetime.now(timezone.utc).isoformat(),
'prompt_id': prompt_id,
'model': model,
'temperature': temperature,
'input': user_message,
'output': output,
'latency_ms': latency,
'input_tokens': resp.usage.prompt_tokens,
'output_tokens': resp.usage.completion_tokens
}
append_log(log_entry)
return outputFormat de journalisation structuré
Utilisez du JSON délimité par des retours à la ligne (JSONL) pour les fichiers journaux. Chaque ligne constitue un objet JSON complet et valide. Ce format est :
- Facile à compléter sans verrouillage
- Lisible par jq, pandas et tous les agrégateurs de journaux
- Compatible avec le traitement en flux — chaque ligne peut être traitée dès sa réception
import json
LOG_FILE = 'prompt_logs.jsonl'
def append_log(entry):
with open(LOG_FILE, 'a') as f:
f.write(json.dumps(entry) + '\n')
def read_logs():
with open(LOG_FILE) as f:
return [json.loads(line) for line in f if line.strip()]
# Query: all entries for prompt_id 'summarize_v3'
logs = read_logs()
summarize_logs = [e for e in logs if e['prompt_id'] == 'summarize_v3']
print(f'Total calls to summarize_v3: {len(summarize_logs)}')Gestion des versions des invites
Les invites évoluent avec le temps. Sans gestion des versions, vous ne pouvez pas reproduire les comportements passés ni comparer les sorties du modèle entre les versions de l’invite. Utilisez un identifiant de version dans chaque entrée du journal.
Gestion simple des versions : une chaîne de version sémantique (par ex. v1.2.3) ou le hachage d’un commit git. Conservez les versions des invites dans un fichier dédié afin de pouvoir récupérer n’importe quelle version pour la rejouer.
PROMPTS = {
'summarize': {
'v1': 'Summarize the following text.',
'v2': 'Summarize the following text in 3 sentences.',
'v3': 'Summarize the following text in exactly 3 sentences. '
'Start each sentence on a new line. No bullet points.'
}
}
CURRENT_VERSIONS = {'summarize': 'v3'}
def get_prompt(prompt_id):
version = CURRENT_VERSIONS[prompt_id]
return version, PROMPTS[prompt_id][version]
version, prompt = get_prompt('summarize')
log_entry['prompt_version'] = versionGestion des PII dans les journaux
Les entrées utilisateur peuvent contenir des informations permettant d’identifier une personne (PII). La journalisation des entrées brutes peut enfreindre le GDPR ou le CCPA. Options :
- Hachage : stockez le SHA-256 de l’entrée — reproductible pour la déduplication, mais pas pour la relecture
- Masquage : utilisez une expression régulière ou un modèle NER avec replace pour remplacer les PII avant la journalisation
- Stockage séparé : journalisez les PII dans un espace chiffré avec des contrôles d’accès ; ne journalisez dans le journal principal qu’un ID de référence
import hashlib, re
def redact_pii(text):
# Redact email addresses
text = re.sub(r'[\w.-]+@[\w.-]+\.\w+', '[EMAIL]', text)
# Redact phone numbers (US format)
text = re.sub(r'\b\d{3}[-.]\d{3}[-.]\d{4}\b', '[PHONE]', text)
return text
def hash_input(text):
return hashlib.sha256(text.encode()).hexdigest()[:16]
log_entry['input'] = redact_pii(user_message)
log_entry['input_hash'] = hash_input(user_message)Suivi de la latence et des coûts
Les journaux permettent de créer des tableaux de bord des coûts et de la latence. Suivez les métriques par version d’invite afin de détecter les régressions de performance ou de coût après une modification de l’invite :
def compute_cost(entry, price_per_1m_input=5.0, price_per_1m_output=15.0):
input_cost = entry['input_tokens'] / 1_000_000 * price_per_1m_input
output_cost = entry['output_tokens'] / 1_000_000 * price_per_1m_output
return input_cost + output_cost
def prompt_stats(prompt_id, version):
logs = [e for e in read_logs()
if e['prompt_id'] == prompt_id and e.get('prompt_version') == version]
if not logs:
return
avg_latency = sum(e['latency_ms'] for e in logs) / len(logs)
total_cost = sum(compute_cost(e) for e in logs)
print(f'{prompt_id} {version}: {len(logs)} calls, avg {avg_latency:.0f}ms, total ${total_cost:.4f}')Journalisation de l’évaluation des sorties
En plus des journaux bruts, stockez les résultats d’évaluation avec chaque entrée du journal. Cela permet une analyse des tendances : la qualité des sorties s’améliore-t-elle entre les versions de l’invite ?
def evaluated_call(prompt_id, system_prompt, user_message, evaluator_fn):
output = logged_call(prompt_id, system_prompt, user_message)
score = evaluator_fn(user_message, output)
# Update the last log entry with the evaluation score
logs = read_logs()
last = logs[-1]
last['eval_score'] = score
last['eval_pass'] = score >= 0.8
# Rewrite the last line
with open(LOG_FILE, 'a') as f:
# In practice, use a DB or separate eval log
pass
return output, scoreDocumentation des invites
Chaque modèle d’invite doit être accompagné d’une entrée de documentation couvrant :
- Objectif : quelle tâche cette invite exécute
- Variables : quels espaces réservés existent et ce qu’ils attendent
- Limitations connues : entrées avec lesquelles elle échoue
- Historique des versions : ce qui a changé dans chaque version et pourquoi
- Cas de test : lien vers la suite de tests de cette invite
PROMPT_DOCS = {
'summarize': {
'purpose': 'Summarize a single text passage into 3 sentences.',
'variables': {'text': 'The passage to summarize (max 2000 tokens)'},
'known_limitations': [
'Fails to preserve numbers accurately for texts with many statistics',
'May not summarize correctly for non-English text'
],
'versions': {
'v1': 'Initial version — vague length instruction',
'v2': 'Added 3-sentence limit',
'v3': 'Added line-break and no-bullet formatting fix'
},
'test_suite': 'tests/test_summarize.py'
}
}Utiliser des services de journalisation centralisés
Pour les systèmes en production, écrivez les journaux dans un service centralisé plutôt que dans des fichiers locaux :
- LangSmith : plateforme native de traçage et d’évaluation de LangChain
- Weights and Biases Prompts : suivi des expériences pour les invites
- Datadog / Grafana : tableaux de bord d’exploitation standard avec des métriques personnalisées
- Supabase / PostgreSQL : interroger les journaux avec SQL pour des analyses ponctuelles
Le schéma est identique ; seule la destination change.
# Example: writing to Supabase
from supabase import create_client
supabase = create_client('https://xxx.supabase.co', 'your-anon-key')
def log_to_supabase(entry):
supabase.table('prompt_logs').insert(entry).execute()
# Now query with SQL:
# SELECT prompt_id, prompt_version, AVG(latency_ms), COUNT(*)
# FROM prompt_logs
# WHERE timestamp > NOW() - INTERVAL '7 days'
# GROUP BY prompt_id, prompt_version
# ORDER BY COUNT(*) DESC;Alertes en cas de pics d’échec
Configurez des alertes lorsque les taux d’échec dépassent un seuil. Par exemple : si plus de 10 % des appels à une instruction renvoient un JSON invalide sur une période de 5 minutes, envoyez une alerte.
from collections import deque
from datetime import datetime, timezone, timedelta
recent_results = deque(maxlen=100) # sliding window
def track_and_alert(prompt_id, success, alert_fn, threshold=0.10):
recent_results.append({'success': success, 'time': datetime.now(timezone.utc)})
window = [
r for r in recent_results
if r['time'] > datetime.now(timezone.utc) - timedelta(minutes=5)
]
if not window:
return
fail_rate = sum(1 for r in window if not r['success']) / len(window)
if fail_rate > threshold:
alert_fn(f'ALERT: {prompt_id} failure rate {fail_rate:.0%} in last 5 min')Conservation et archivage
Définissez une politique de conservation des journaux :
- Journaux bruts des appels : 30 jours (période glissante) — volume élevé, nécessaires pour déboguer les problèmes récents
- Métriques agrégées : 1 an — nécessaires pour analyser les tendances et prévoir les coûts
- Journaux d’échec : indéfiniment — nécessaires pour identifier les schémas liés aux causes profondes
Compressez et archivez les journaux bruts après 30 jours. Ne supprimez jamais les journaux d’échec : ils constituent la mémoire collective de votre organisation pour l’ingénierie des instructions.
Vérification des connaissances
Quel est l’avantage principal du format JSON délimité par des retours à la ligne (JSONL) pour les journaux d’instructions, par rapport à un seul grand tableau JSON ?
Récapitulatif : journalisation et documentation
Bonnes pratiques essentielles pour la journalisation et la documentation des instructions :
- Journalisez chaque appel : horodatage, identifiant_instruction, version, modèle, température, entrée, sortie, latence, jetons
- Utilisez le format JSONL : facile à compléter, interrogeable avec des outils standards
- Versionnez les instructions : chaque modification reçoit une nouvelle version ; les journaux font référence à cette version
- Gérez les PII : masquez ou hachez les entrées sensibles avant la journalisation
- Suivez les coûts et la latence : détectez les régressions après les mises à jour des instructions
- Déclenchez des alertes en cas de pics d’échec : surveillance du taux d’échec sur une période glissante
Cette section conclut le cours 17 sur le débogage des échecs d’instructions. Ensuite : injection d’instructions et défense.
Questions Fréquemment Posées
La leçon « Stratégies de journalisation et de documentation » est-elle gratuite ?
Oui — le texte complet de « Stratégies de journalisation et de documentation » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours AI Prompt Engineering, passe à CoddyKit PRO. Le cours AI Prompt Engineering comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « Stratégies de journalisation et de documentation » ?
Enregistrez les versions des prompts, les entrées et les sorties pour rendre le débogage reproductible. Tu pratiques AI Prompt Engineering avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer AI Prompt Engineering ?
Aucune expérience préalable n'est requise. AI Prompt Engineering sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 4 sur 4.
Combien de temps prend la leçon « Stratégies de journalisation et de documentation » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon AI Prompt Engineering ?
Oui. Chaque leçon AI Prompt Engineering inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- Diagnostiquer les sorties inattendues
- Analyse des causes profondes des problèmes d’invites
- Approche systématique du débogage
- Stratégies de journalisation et de documentation