Aller au contenu principal

Campaigns : Annotation à Grande Échelle

Passer de l’évaluation unitaire à l’échelle

Vous avez créé et validé un Judge. Maintenant, vous voulez l’appliquer non pas sur 20 événements, mais sur 5 000. C’est le rôle des Campaigns : elles orchestrent l’annotation batch du trafic de production en utilisant vos Judges.

Une Campaign prend un Judge, un ensemble de filtres, et annote automatiquement chaque événement correspondant. Les résultats sont sauvegardés directement dans l’Explorer, associés aux événements d’origine.

Cas d’usage des Campaigns

Détecter les comportements problématiques

Vous soupçonnez que votre chatbot de support est parfois sec ou hors-sujet. Lancez une Campaign avec un Judge de classification “ton professionnel” sur le trafic de la semaine :

Filtre : timestamp >= 7 derniers jours
         AND model_name = "mistral-medium-2508"
Judge  : Qualité du ton (professional / needs_improvement / rude)

Tagger le trafic pour analyse

Votre équipe produit veut comprendre la répartition des types de requêtes :

Filtre : timestamp >= 30 derniers jours
Judge  : Classification thématique (code / search / general / troubleshooting)

Construire des Datasets annotés

Vous préparez des données pour le fine-tuning. Vous voulez des exemples de réponses “excellentes” validées par un Judge :

Filtre : timestamp >= 90 derniers jours
         AND total_time_elapsed < 3
Judge  : Qualité globale (excellent / acceptable / poor)
Export : Événements annotés "excellent" -> Dataset de fine-tuning

Créer une Campaign via le SDK

from mistralai import Mistral

client = Mistral(api_key="votre-clé-api")

# Créer la Campaign
campaign = client.beta.observability.campaigns.create(
    name="Revue qualité support - Semaine 13",
    judge_id="judge-456",  # ID du Judge créé précédemment
    search_params={
        "filters": {
            "AND": [
                {
                    "field": "timestamp",
                    "op": "gte",
                    "value": "2026-03-24T00:00:00Z"
                },
                {
                    "field": "timestamp",
                    "op": "lt",
                    "value": "2026-03-31T00:00:00Z"
                },
                {
                    "field": "model_name",
                    "op": "eq",
                    "value": "mistral-medium-2508"
                }
            ]
        }
    },
    max_nb_events=5000
)

print(f"Campaign lancée : {campaign.id}")
print(f"Statut : {campaign.status}")

Monitorer la progression

Les Campaigns s’exécutent de manière asynchrone. Suivez leur progression :

import time


def monitor_campaign(client, campaign_id, poll_interval=30):
    """Suit la progression d'une Campaign."""
    while True:
        status = client.beta.observability.campaigns.fetch_status(
            campaign_id=campaign_id
        )

        total = status.total_events
        processed = status.processed_events
        pct = (processed / total * 100) if total > 0 else 0

        print(f"Progression : {processed}/{total} ({pct:.1f}%)")
        print(f"Statut : {status.status}")

        if status.status in ("COMPLETED", "FAILED"):
            return status

        time.sleep(poll_interval)


# Lancer le monitoring
final_status = monitor_campaign(client, campaign.id)

Analyser les résultats

Une fois la Campaign terminée, explorez les résultats :

# Récupérer les événements annotés
events = client.beta.observability.campaigns.list_events(
    campaign_id=campaign.id,
    page_size=100
)

# Compter les résultats par catégorie
from collections import Counter

categories = Counter()
for event in events.data:
    annotation = event.annotation_value
    categories[annotation] += 1

print("=== Répartition des annotations ===")
for cat, count in categories.most_common():
    pct = count / sum(categories.values()) * 100
    print(f"  {cat}: {count} ({pct:.1f}%)")

Filtrer par annotation dans l’Explorer

Après une Campaign, les annotations sont visibles dans l’Explorer. Vous pouvez filtrer le trafic par valeur d’annotation pour identifier précisément les événements problématiques :

# Trouver les réponses "poor" annotées par la Campaign
poor_events = client.beta.observability.chat_completion_events.search(
    search_params={
        "filters": {
            "AND": [
                {
                    "field": "annotation.judge_name",
                    "op": "eq",
                    "value": "Qualité des réponses support"
                },
                {
                    "field": "annotation.value",
                    "op": "eq",
                    "value": "poor"
                }
            ]
        }
    },
    page_size=50
)

Gestion des Campaigns

# Lister toutes les Campaigns
campaigns = client.beta.observability.campaigns.list(page_size=20)
for c in campaigns.data:
    print(f"{c.name} - {c.status} - {c.created_at}")

# Supprimer une Campaign (les annotations restent dans Explorer)
client.beta.observability.campaigns.delete(
    campaign_id="campaign-old-123"
)

Point important : supprimer une Campaign ne supprime pas les annotations. Elles persistent dans l’Explorer et restent exploitables.

Contraintes

  • Un seul Judge par Campaign — Si vous voulez évaluer plusieurs critères, créez plusieurs Campaigns
  • Limite de 10 000 événements — Pour des volumes supérieurs, contactez le support Mistral
  • Les filtres se verrouillent au lancement — Vous ne pouvez pas modifier les critères en cours de route

Points clés à retenir

  • Les Campaigns appliquent un Judge sur une tranche de trafic filtrée, à grande échelle
  • L’exécution est asynchrone : suivez la progression via fetch_status()
  • Les annotations persistent dans l’Explorer même après suppression de la Campaign
  • Un seul Judge par Campaign, avec un maximum de 10 000 événements
  • Les résultats annotés peuvent être filtrés dans l’Explorer et exportés vers des Datasets