IntermédiaireCas Pratiques
30 min de lecture19 vues

Analyse de Sentiment sur des Tweets Français

Comparez les performances de GPT-4o, Claude et Gemini sur la classification de sentiment de tweets français avec un dataset Kaggle réel.

Objectif du TP

Les benchmarks standards (MMLU, HumanEval) sont en anglais. Mais comment les modèles se comportent-ils en français ? Dans ce cas pratique, vous allez tester et comparer plusieurs LLMs sur une tâche concrète : la classification de sentiment de tweets français.

Prérequis

  • Python 3.8+, Pandas
  • Accès gratuit à ChatGPT, Claude ou Gemini
  • Optionnel : une clé API OpenRouter pour automatiser les tests

Dataset

French Twitter Sentiment Analysis – Kaggle

1,5 million de tweets français étiquetés positif/négatif. Nous n''en utiliserons qu''un échantillon.

Exercice 1 : Préparer les Données de Test

import pandas as pd

# Charger un échantillon
df = pd.read_csv("french_tweets.csv", nrows=500)

print(f"Colonnes : {df.columns.tolist()}")
print(f"Taille : {len(df)}")
print(df.head())

# Distribution des sentiments
print("\nDistribution :")
print(df["label"].value_counts())

# Sélectionner 30 tweets de test (équilibrés)
positifs = df[df["label"] == 1].sample(15, random_state=42)
negatifs = df[df["label"] == 0].sample(15, random_state=42)
test_set = pd.concat([positifs, negatifs]).sample(frac=1, random_state=42)

print(f"\nDataset de test : {len(test_set)} tweets")
test_set.to_csv("test_tweets.csv", index=False)

Exercice 2 : Générer les Prompts

Créez les prompts standardisés que vous enverrez à chaque modèle.

# Charger le dataset de test
test_set = pd.read_csv("test_tweets.csv")

# Template de prompt
prompt_template = """Tu es un expert en analyse de sentiment.
Classe le sentiment du tweet suivant en EXACTEMENT un mot : "positif" ou "négatif".

Tweet : "{tweet}"

Sentiment :"""

# Générer et afficher les prompts
prompts = []
for idx, row in test_set.iterrows():
    prompt = prompt_template.format(tweet=row["text"])
    prompts.append({
        "id": idx,
        "tweet": row["text"],
        "vrai_sentiment": "positif" if row["label"] == 1 else "négatif",
        "prompt": prompt
    })

# Sauvegarder
prompts_df = pd.DataFrame(prompts)
prompts_df.to_csv("prompts_test.csv", index=False)

print(f"{len(prompts)} prompts générés.")
print("\n--- Exemple de prompt ---")
print(prompts[0]["prompt"])

Conseil : Le prompt est volontairement simple et directif. En production, vous testeriez aussi l''impact de prompts plus détaillés (few-shot, chain-of-thought).

Exercice 3 : Tester Manuellement (Sans API)

Si vous n''avez pas de clé API, testez manuellement sur les interfaces gratuites.

Protocole :

  1. Ouvrez 3 onglets : ChatGPT, Claude, Gemini
  2. Pour chaque tweet, copiez le prompt dans les 3 interfaces
  3. Notez la réponse dans un tableur :
TweetVraiGPT-4oClaudeGemini
"J''adore ce film !"positifpositifpositifpositif
"Service client horrible"négatifnégatifnégatifpositif

Testez au moins 15-20 tweets pour avoir des résultats significatifs. C''est fastidieux manuellement, d''où l''intérêt d''automatiser (exercice suivant).

Exercice 4 : Automatiser avec l''API OpenRouter

Si vous avez une clé API, automatisez les tests.

import requests
import time

OPENROUTER_API_KEY = "sk-or-..."  # Votre clé

def ask_model(prompt, model_id):
    """Envoie un prompt à un modèle via OpenRouter."""
    response = requests.post(
        "https://openrouter.ai/api/v1/chat/completions",
        headers={
            "Authorization": f"Bearer {OPENROUTER_API_KEY}",
            "Content-Type": "application/json"
        },
        json={
            "model": model_id,
            "messages": [{"role": "user", "content": prompt}],
            "max_tokens": 10,
            "temperature": 0
        }
    )
    result = response.json()
    return result["choices"][0]["message"]["content"].strip().lower()

# Modèles à tester
models = {
    "GPT-4o-mini": "openai/gpt-4o-mini",
    "Claude Haiku": "anthropic/claude-3-haiku",
    "Gemini Flash": "google/gemini-flash-1.5",
}

# Tester chaque prompt sur chaque modèle
results = []
for _, row in prompts_df.iterrows():
    result = {"tweet": row["tweet"], "vrai": row["vrai_sentiment"]}
    for name, model_id in models.items():
        try:
            answer = ask_model(row["prompt"], model_id)
            # Normaliser la réponse
            if "positif" in answer:
                result[name] = "positif"
            elif "négatif" in answer or "negatif" in answer:
                result[name] = "négatif"
            else:
                result[name] = answer  # Réponse inattendue
        except Exception as e:
            result[name] = f"erreur: {e}"
        time.sleep(0.5)  # Respecter les rate limits
    results.append(result)

results_df = pd.DataFrame(results)
results_df.to_csv("resultats_sentiment.csv", index=False)
print("Tests terminés !")
print(results_df.head(10))

Coût estimé : Avec des modèles "mini/haiku/flash", 30 tweets coûtent moins de 0,01€. Avec GPT-4o ou Claude Opus, comptez environ 0,10€.

Exercice 5 : Analyser les Résultats

results_df = pd.read_csv("resultats_sentiment.csv")

print("=== Résultats de l''Analyse de Sentiment ===\n")

for model_name in ["GPT-4o-mini", "Claude Haiku", "Gemini Flash"]:
    if model_name not in results_df.columns:
        continue

    correct = (results_df[model_name] == results_df["vrai"]).sum()
    total = len(results_df)
    accuracy = correct / total * 100

    # Détail par classe
    positifs = results_df[results_df["vrai"] == "positif"]
    negatifs = results_df[results_df["vrai"] == "négatif"]

    acc_pos = (positifs[model_name] == positifs["vrai"]).mean() * 100
    acc_neg = (negatifs[model_name] == negatifs["vrai"]).mean() * 100

    print(f"--- {model_name} ---")
    print(f"  Précision globale : {accuracy:.0f}% ({correct}/{total})")
    print(f"  Précision positifs : {acc_pos:.0f}%")
    print(f"  Précision négatifs : {acc_neg:.0f}%")

    # Exemples d''erreurs
    errors = results_df[results_df[model_name] != results_df["vrai"]]
    if len(errors) > 0:
        print(f"  Erreurs ({len(errors)}) :")
        for _, err in errors.head(3).iterrows():
            print(f"    Tweet: \"{err['tweet'][:60]}...\"")
            print(f"    Attendu: {err['vrai']} → Réponse: {err[model_name]}")
    print()

Observations typiques :

  • Les modèles ont souvent plus de mal avec le sarcasme et l''argot français
  • Les tweets courts et ambigus génèrent le plus d''erreurs
  • La précision sur les négatifs est souvent inférieure à celle sur les positifs

Pour Aller Plus Loin

  • Testez avec des prompts few-shot (donner 3 exemples dans le prompt) et comparez la précision
  • Essayez le dataset Allociné Reviews pour tester sur des critiques de films (textes plus longs)
  • Calculez le coût par prédiction pour chaque modèle et déterminez le meilleur rapport précision/coût

Specialiste IA — Master Intelligence Artificielle

Diplome d'un Master en Intelligence Artificielle, je travaille au quotidien sur des projets IA en entreprise. J'ai cree IwanttolearnAI pour rendre l'apprentissage de l'IA accessible a tous, gratuitement.