0Pricing
AI Prompt Engineering · Leçon

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 UTC
  • prompt_id : modèle d’invite utilisé
  • model : nom et version exacts du modèle
  • temperature : paramètre d’échantillonnage
  • input : message utilisateur (ou un hachage si PII)
  • output : réponse du modèle
  • latency_ms : temps de réponse
  • tokens_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 output

Format 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'] = version

Gestion 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, score

Documentation 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

  1. Diagnostiquer les sorties inattendues
  2. Analyse des causes profondes des problèmes d’invites
  3. Approche systématique du débogage
  4. Stratégies de journalisation et de documentation
← Retour à AI Prompt Engineering