Skip to content
Tutoriels6 min de lecture

Créer une tâche d'analyse de sentiment

Construisez une tâche complète de classification de sentiment avec des boutons radio, des infobulles et des raccourcis clavier pour un étiquetage efficace.

Potato Team

L'analyse de sentiment est l'une des tâches de NLP les plus courantes, et collecter des étiquettes propres pour cette tâche dans Potato est simple. Ce tutoriel construit une interface d'annotation de sentiment que vous pouvez réellement mettre entre les mains des annotateurs, avec les raccourcis clavier et les contrôles qualité qui accélèrent l'étiquetage.

Aperçu du projet

Nous annotons des publications de réseaux sociaux. L'interface comprend :

  • Une classification de sentiment en trois classes (Positive, Negative, Neutral)
  • Une note de confiance pour chaque annotation
  • Des explications textuelles optionnelles
  • Des raccourcis clavier pour aller plus vite
  • Des mesures de contrôle qualité

Configuration complète

Voici le fichier config.yaml complet :

yaml
annotation_task_name: "Social Media Sentiment Analysis"
 
# Data configuration
data_files:
  - "data/tweets.json"
 
item_properties:
  id_key: id
  text_key: text
 
# Annotation interface
annotation_schemes:
  # Primary sentiment label
  - annotation_type: radio
    name: sentiment
    description: "What is the overall sentiment of this post?"
    labels:
      - name: Positive
        tooltip: "Expresses happiness, satisfaction, or approval"
        key_value: "1"
      - name: Negative
        tooltip: "Expresses sadness, frustration, or disapproval"
        key_value: "2"
      - name: Neutral
        tooltip: "Factual, objective, or lacks emotional content"
        key_value: "3"
    label_requirement:
      required: true
 
  # Confidence rating
  - annotation_type: likert
    name: confidence
    description: "How confident are you in your sentiment label?"
    size: 5
    min_label: "Not confident"
    max_label: "Very confident"
    label_requirement:
      required: true
 
  # Optional explanation
  - annotation_type: text
    name: explanation
    description: "Why did you choose this label? (Optional)"
    rows: 4
    label_requirement:
      required: false
    placeholder: "Explain your reasoning..."
 
# Guidelines
annotation_instructions: |
  ## Sentiment Annotation Guidelines
 
  ### Your Task
  Classify the sentiment expressed in each social media post.
 
  ### Labels
 
  **Positive**: The author expresses positive emotions or opinions
  - Happiness, excitement, gratitude
  - Praise, recommendations, approval
  - Examples: "Love this!", "Best day ever!", "Highly recommend"
 
  **Negative**: The author expresses negative emotions or opinions
  - Anger, frustration, sadness
  - Complaints, criticism, disapproval
  - Examples: "Terrible service", "So disappointed", "Worst experience"
 
  **Neutral**: Factual or lacking clear sentiment
  - News, announcements, questions
  - Mixed or balanced opinions
  - Examples: "The store opens at 9am", "Has anyone tried this?"
 
  ### Tips
  - Focus on the author's sentiment, not the topic
  - Sarcasm should be labeled based on intended meaning
  - When unsure, lower your confidence rating
 
# User management
automatic_assignment:
  on: true
  sampling_strategy: random
  labels_per_instance: 1
  instance_per_annotator: 100

Format des données d'exemple

Créez data/tweets.json :

json
{"id": "t001", "text": "Just got my new laptop and I'm absolutely loving it! Best purchase of the year! #happy"}
{"id": "t002", "text": "Waited 2 hours for customer service and they still couldn't help me. Never shopping here again."}
{"id": "t003", "text": "The new coffee shop on Main Street opens tomorrow at 7am."}
{"id": "t004", "text": "This movie was okay I guess. Some good parts, some boring parts."}
{"id": "t005", "text": "Can't believe how beautiful the sunset was tonight! Nature is amazing."}

Lancer la tâche

Démarrez le serveur d'annotation :

bash
potato start config.yaml

Ouvrez http://localhost:8000 et connectez-vous pour commencer à annoter.

Voici ce que voient vos annotateurs une fois le serveur lancé :

Interface d'annotation d'analyse de sentiment avec des boutons radio pour les étiquettes Positive, Negative et NeutralL'interface de classification de sentiment avec les étiquettes en boutons radio, l'échelle de confiance et le champ d'explication optionnel

Comprendre l'interface

Zone d'annotation principale

L'interface affiche :

  1. Le texte à annoter (avec les URLs, mentions et hashtags surlignés)
  2. Les boutons radio de sentiment avec infobulles
  3. L'échelle de Likert de confiance
  4. La zone de texte d'explication optionnelle

Flux de travail au clavier

Une fois que les annotateurs ont pris le rythme, la boucle la plus rapide est la suivante :

  1. Lire le texte
  2. Appuyer sur 1, 2 ou 3 pour le sentiment
  3. Cliquer sur le niveau de confiance (ou utiliser la souris)
  4. Appuyer sur Enter pour soumettre

Suivi de la progression

L'interface affiche :

  • La progression actuelle (par ex. « 15 / 100 »)
  • Le temps restant estimé
  • Les statistiques de session

Format de sortie

Le travail de chaque annotateur est enregistré dans <output_annotation_dir>/<user>/user_state.json, quelle que soit la valeur de export_annotation_format. Ce paramètre ajoute un export périodique à côté, de sorte qu'avec jsonl le fichier combiné est <output_annotation_dir>/exports/jsonl/annotations.jsonl, avec un enregistrement par annotateur et par instance :

json
{
  "instance_id": "t001",
  "user_id": "john_doe",
  "labels": {
    "sentiment": {"Positive": "true"},
    "confidence": {"5": "true"},
    "explanation": {"text_box": "Clear expression of happiness with the purchase"}
  },
  "spans": {},
  "links": {}
}

Ajouter un contrôle qualité

Vérifications d'attention

Ajoutez des items de référence (gold standard) pour vérifier l'attention des annotateurs. Pour l'ensemble des options des schémas radio et likert utilisés ici, consultez la documentation source.

yaml
attention_checks:
  enabled: true
  frequency: 10          # Every 10th item
  items_file: data/attention_checks.json
  failure_handling:
    warn_threshold: 2
    block_threshold: 5

Les items se trouvent dans items_file plutôt que directement dans la configuration, et chacun porte la réponse qu'il doit recevoir :

json
[
  {
    "id": "chk1",
    "text": "I am extremely happy and satisfied! This is the best!",
    "expected_answer": { "sentiment": "Positive" }
  },
  {
    "id": "chk2",
    "text": "This is absolutely terrible and I hate it completely.",
    "expected_answer": { "sentiment": "Negative" }
  }
]

Les items gold standard utilisent gold_label au lieu de expected_answer et se placent dans gold_standards.items_file. Notez que les deux blocs se placent au niveau supérieur. Potato lit attention_checks à la racine de la configuration, donc le glisser dans un bloc quality_control: fait qu'il n'est pas lu, sans qu'aucune erreur ne soit signalée.

Accord inter-annotateurs

Pour les projets de recherche, activez les annotations multiples :

yaml
automatic_assignment:
  on: true
  sampling_strategy: random
  labels_per_instance: 3  # Each item annotated by 3 people
  instance_per_annotator: 50

Analyser les résultats

Exportez et analysez vos annotations :

python
import json
from collections import Counter
 
records = []
with open('annotation_output/exports/jsonl/annotations.jsonl') as f:
    for line in f:
        records.append(json.loads(line))
 
def chosen(record, scheme):
    """The label picked for a single-choice scheme: the key whose value is "true"."""
    for name, value in record["labels"].get(scheme, {}).items():
        if value == "true":
            return name
    return None
 
sentiments = Counter(chosen(r, "sentiment") for r in records)
print(f"Sentiment distribution: {dict(sentiments)}")
 
# A likert stores its scale position the same way, as the label name
points = [int(p) for r in records if (p := chosen(r, "confidence"))]
print(f"Average confidence: {sum(points)/len(points):.2f}")

Prochaines étapes


Découvrez d'autres types d'annotation dans notre documentation.