Solo Mode: Wie ein einzelner Annotator 10.000 Beispiele beschriften kann
Schritt-für-Schritt-Tutorial zu Potatos Solo Mode: eine Startmenge selbst beschriften, den Rest von einem LLM beschriften lassen und anhand der Genauigkeitsprüfungen entscheiden, wann das Ergebnis gut genug ist, um aufzuhören.
Sie haben 10.000 Produktbewertungen nach Stimmung (Positiv, Neutral, Negativ) zu beschriften. Wenn drei Annotatoren alle davon beschriften, dauert das Wochen und kostet Tausende von Dollar. Mit Solo Mode erreicht ein einzelner Domänenexperte vergleichbare Qualität, indem er nur 500-1.000 Instanzen beschriftet. Ein LLM übernimmt den Rest, und der Mensch prüft alles, bei dem sich das LLM unsicher ist.
Dieses Tutorial geht den gesamten Prozess durch.
Was Sie benötigen
- Potato 2.3.0 oder neuer, mit den KI-Extras für die LLM-Anbieter:
pip install potato-annotation[ai] - Einen OpenAI- oder Anthropic-API-Schlüssel (für die LLM-Komponente)
- Ihren Datensatz im JSONL-Format
- Einen sachkundigen Annotator (das können Sie selbst sein)
Schritt 1: Daten vorbereiten
Erstellen Sie data/reviews.jsonl mit einer Bewertung pro Zeile:
{"id": "rev_001", "text": "Absolutely love this product! Best purchase I've made all year.", "source": "amazon"}
{"id": "rev_002", "text": "It works fine. Nothing special but gets the job done.", "source": "amazon"}
{"id": "rev_003", "text": "Broke after two weeks. Complete waste of money.", "source": "amazon"}
{"id": "rev_004", "text": "The quality is decent for the price point. I might buy again.", "source": "amazon"}
{"id": "rev_005", "text": "Arrived damaged and customer service was unhelpful.", "source": "amazon"}Stellen Sie sich für dieses Tutorial vor, dass diese Datei 10.000 Bewertungen enthält.
Schritt 2: Die Konfiguration erstellen
Erstellen Sie config.yaml:
annotation_task_name: "Product Review Sentiment (Solo Mode)"
task_dir: "."
data_files:
- "data/reviews.jsonl"
item_properties:
id_key: id
text_key: text
# --- Solo Mode Configuration ---
solo_mode:
enabled: true
# The model that labels. A list, so you can give fallbacks.
labeling_models:
- endpoint_type: openai
model: "gpt-4o"
api_key: ${OPENAI_API_KEY}
temperature: 0.1
max_tokens: 1024
embedding:
model_name: "all-MiniLM-L6-v2"
uncertainty:
strategy: direct_confidence
# When you are allowed to stop labeling
thresholds:
end_human_annotation_agreement: 0.93
minimum_validation_sample: 50
confidence_low: 0.5
confidence_high: 0.85
periodic_review_interval: 100
# What decides which instance you see next
instance_selection:
low_confidence_weight: 0.30
disagreement_weight: 0.25
diversity_weight: 0.20
llm_predicted_weight: 0.15
random_weight: 0.10
batches:
llm_labeling_batch: 25
max_parallel_labels: 200
labeling_functions:
enabled: true
auto_extract: true
max_functions: 15
min_confidence: 0.92
min_coverage: 3
edge_case_rules:
enabled: true
auto_extract_on_labeling: true
confusion_analysis:
enabled: true
min_instances_for_pattern: 3
max_patterns: 20
prompt_optimization:
enabled: true
target_accuracy: 0.93
refinement_loop:
enabled: true
trigger_interval: 50
min_improvement: 0.02
max_cycles: 3
state_dir: "solo_state_reviews"
# --- Annotation Schema ---
annotation_schemes:
- annotation_type: radio
name: sentiment
description: "What is the overall sentiment of this review?"
labels:
- "Positive"
- "Neutral"
- "Negative"
label_requirement:
required: true
sequential_key_binding: true
output_annotation_dir: "output/"
export_annotation_format:
- jsonl
- parquetSchritt 3: Den Server starten
potato start config.yaml -p 8000Öffnen Sie http://localhost:8000 und melden Sie sich an. Das Solo-Mode-Dashboard erscheint. Es zeigt das Projekt in der Einrichtung, bereit dafür, dass Sie den von ihm synthetisierten Prompt prüfen.
Schritt 4: Parallele Annotation, Ihre ersten 50
Potato hat mithilfe von embedding-basiertem Clustering 50 unterschiedliche Bewertungen ausgewählt. Sie sind nicht zufällig, sondern so gewählt, dass sie Ihre Datenverteilung möglichst breit abdecken.
Beschriften Sie jede einzelne. Diese Phase ist die wichtigste, denn die Qualität Ihrer Seed-Labels setzt die Obergrenze dessen, was das LLM lernen kann. Nehmen Sie sich Zeit und bleiben Sie konsistent.
Zeitschätzung: 15-25 Minuten bei 20-30 Sekunden pro Instanz.
Sobald genug davon beschriftet sind, beginnt das LLM ohne Aufforderung, parallel zu Ihnen zu beschriften.
Schritt 5: Das LLM holt auf
Diese Phase läuft von selbst. Potato sendet dem LLM einen Batch von 200 Instanzen mit Ihren 50 Seed-Labels als Few-Shot-Beispiele und vergleicht die Vorhersagen dann mit 10 zurückgehaltenen Seed-Labels, um die Basisgenauigkeit zu schätzen.
Im Dashboard erscheint ein Fortschrittsindikator. Das dauert je nach LLM-Anbieter meist 1-2 Minuten.
Typisches Ergebnis: Das LLM landet bei der ersten Kalibrierung bei 75-85 % Genauigkeit. Das ist zu erwarten. Es hat Ihren Annotationsstil noch nicht gelernt.
Schritt 6: Konfusionsanalyse
Potato zeigt eine Konfusionsmatrix, aus der hervorgeht, wo das LLM von Ihren Labels abweicht. Eine typische Ausgabe:
Confusion Analysis (Round 1)
============================
Overall Accuracy: 0.82 (target: 0.93)
Top Confusion Pairs:
Neutral -> Positive: 14 instances (7.0%)
Negative -> Neutral: 9 instances (4.5%)
Positive -> Neutral: 4 instances (2.0%)
Das zeigt die Hauptschwäche des LLM in diesem Fall: Es stuft neutrale Bewertungen immer wieder zu positiv hoch. Das kommt häufig vor, weil LLMs zum Positiven neigen.
Ihre Aktion: Sehen Sie die Konfusionspaare durch. Klicken Sie auf jedes Paar, um die konkreten Instanzen zu sehen, bei denen das LLM falsch lag. So verstehen Sie am schnellsten, wie es scheitert.
Schritt 7: Zurück zur Prompt-Prüfung
Auf Grundlage der Konfusionsanalyse entwirft Potato verfeinerte Leitfäden für das LLM und zeigt sie nebeneinander an: auf der einen Seite den aktuellen Prompt, auf der anderen die konkreten Änderungen, die es aus den Fehlermustern ableitet.
Potato könnte zum Beispiel vorschlagen, Folgendes hinzuzufügen:
"Bewertungen, die ein Produkt ohne starke Emotion als 'in Ordnung', 'okay' oder 'ordentlich' beschreiben, sollten als Neutral beschriftet werden, auch wenn sie einen erneuten Kauf erwähnen."
Gehen Sie jede vorgeschlagene Änderung durch und genehmigen, ändern oder verwerfen Sie sie. Sie können auch eigene Klarstellungen ergänzen.
Zeitschätzung: 5-10 Minuten.
Schritt 8: Labeling-Funktionen
Potato erzeugt aus Mustern in Ihren Seed-Labels programmatische Labeling-Funktionen. Das sind schnelle, deterministische Regeln, die einfache Fälle abdecken:
Generated Labeling Functions:
LF1: Strong positive words (love, amazing, best, excellent)
Precision: 0.97, Coverage: 0.06
LF2: Strong negative words (terrible, awful, worst, waste)
Precision: 0.95, Coverage: 0.04
LF3: Exclamation + positive adjective
Precision: 0.94, Coverage: 0.03
LF4: Return/refund mention + negative context
Precision: 0.92, Coverage: 0.02
...
Total coverage: 0.18 (1,800 of 10,000 instances)
Die Labeling-Funktionen decken 18 % Ihres Datensatzes mit einer Präzision von über 92 % ab. Diese Instanzen werden automatisch beschriftet, sodass LLM und Mensch sich um die schwierigeren Fälle kümmern können.
Ihre Aktion: Sehen Sie die erzeugten Funktionen durch und deaktivieren Sie alle, die unzuverlässig wirken. Dieser Schritt ist optional, da Potato ohnehin nur Funktionen oberhalb Ihrer konfigurierten Präzisionsschwelle behält.
Schritt 9: Aktive Annotation (125-375 Instanzen)
Hier erledigen Sie den Großteil Ihrer Beschriftung. Potato wählt Instanzen anhand der gewichteten Pools aus, die oben in instance_selection festgelegt sind:
low_confidence_weight(0.30): Bewertungen, bei denen die Konfidenz des LLM am niedrigsten istdisagreement_weight(0.25): Bewertungen, bei denen LLM und Labeling-Funktionen nicht übereinstimmendiversity_weight(0.20): Bewertungen, die so gewählt sind, dass sie sich über den Embedding-Raum verteilen, statt sich zu häufenllm_predicted_weight(0.15): Vom LLM beschriftete Bewertungen, die zum Vergleich mit einem Menschen zurückgeholt werdenrandom_weight(0.10): Zufällige Bewertungen zur Kalibrierung
Zwei weitere Gewichte gibt es. Sie bleiben hier auf ihrem Standardwert null und tragen daher nichts bei: edge_case_rule_weight für Instanzen, die zu einer entdeckten Grenzfallregel passen, und cartography_weight für Instanzen, deren Konfidenz zwischen den Runden schwankt. Potato prüft, ob die Gewichte 1.0 ergeben, und protokolliert eine Warnung, wenn nicht. Es verwendet die Werte aber so, wie sie geschrieben sind, also sorgen Sie selbst dafür, dass die Summe stimmt.
Sie beschriften diese in Batches von 25. Nach jedem Batch aktualisiert Potato die Genauigkeitsschätzung des LLM und entscheidet, ob es weitergeht.
Typischer Verlauf:
- Batch 1-3 (75 Instanzen): Die Genauigkeit steigt von 82 % auf 87 %
- Batch 4-6 (150 Instanzen): Die Genauigkeit erreicht 90 %
- Batch 7-10 (250 Instanzen): Die Genauigkeit stagniert bei 91-92 %
Erreicht die Übereinstimmung Ihren Wert für end_human_annotation_agreement, geht Solo Mode zum autonomen Beschriften über. Andernfalls durchläuft es weiter Prüfung und Verfeinerung.
Zeitschätzung: 45-90 Minuten insgesamt, je nachdem, wie viele Batches nötig sind.
Schritt 10: Die Verfeinerungsschleife
Liegt die Genauigkeit nach der aktiven Beschriftung noch unter der Schwelle, führt Potato eine weitere Runde der Verfeinerungsschleife aus:
- Das LLM beschriftet den gesamten Datensatz mit aktualisierten Leitfäden und mehr Few-Shot-Beispielen neu
- Potato berechnet die Genauigkeit gegenüber allen menschlichen Labels neu
- Es ermittelt die neuen Konfusionsmuster
- Es verfeinert die Leitfäden erneut
Diese Phase läuft weitgehend ohne Ihr Zutun. Sie müssen nur die Änderungen an den Leitfäden genehmigen.
Typisches Ergebnis: Die Genauigkeit verbessert sich pro Verfeinerungsrunde um 2-4 %.
Schritt 11: Auflösung von Unstimmigkeiten
Potato legt Ihnen die umstrittensten Instanzen vor: Fälle, in denen LLM, Labeling-Funktionen und Nearest-Neighbor-Analyse jeweils unterschiedliche Antworten liefern. Zu jeder Instanz sehen Sie:
- Den Text der Bewertung
- Die Vorhersage des LLM und ihre Konfidenz
- Die Stimmen der Labeling-Funktionen
- Die 3 nächstgelegenen beschrifteten Beispiele mit ihren Labels
- Die Chain-of-Thought-Begründung des LLM
Das sind die schwierigen Fälle, und Ihre Labels haben hier mehr Gewicht als an jeder anderen Stelle im Prozess.
Zeitschätzung: 20-30 Minuten für 100-150 Instanzen.
Schritt 12: Synthese von Grenzfällen
Potato erzeugt synthetische Bewertungen, die auf die verbleibenden Konfusionsmuster zielen. Hat das LLM zum Beispiel noch Probleme mit „neutralen Bewertungen, die einen erneuten Kauf erwähnen“, erzeugt es Beispiele wie:
"Für den Preis ist das Produkt okay. Vielleicht kaufe ich noch eines, wenn es im Angebot ist."
Sie beschriften diese synthetischen Beispiele, und Potato fügt sie dem Few-Shot-Kontext des LLM hinzu.
Zeitschätzung: 10-15 Minuten für 30 Beispiele.
Schritt 13: Periodische Prüfung
Inzwischen hat das LLM den größten Teil des Datensatzes beschriftet. Potato ordnet alle seine Labels nach Konfidenz und schickt Ihnen die mit der niedrigsten Konfidenz in Batches von 25.
Confidence Escalation Progress:
Batch 1: 25 instances, 23/25 correct (92%)
Batch 2: 25 instances, 24/25 correct (96%)
Batch 3: 25 instances, 25/25 correct (100%)
-> Stopping: last 3 batches stable
Sobald sich die Genauigkeit über drei Batches in Folge nicht mehr bewegt, behandelt Solo Mode die verbleibenden Labels mit hoher Konfidenz als vertrauenswürdig. Beachten Sie, dass es hier um Stabilität geht und nicht um Perfektion. Der Lauf oben stoppt nach 92 %, 96 % und 100 %, weil sich der Wert eingependelt hat, nicht weil der letzte Batch fehlerfrei war.
Zeitschätzung: 15-20 Minuten.
Schritt 14: Prompt-Optimierung
Diese Phase läuft von selbst. Potato probiert 8 Prompt-Varianten aus und behält diejenige mit dem höchsten F1-Score auf Ihren gesammelten menschlichen Labels:
Prompt Optimization Results:
Variant 1 (direct, 5 examples): F1=0.91
Variant 2 (CoT, 5 examples): F1=0.93
Variant 3 (direct, 10 examples): F1=0.92
Variant 4 (CoT, 10 examples): F1=0.94 <-- selected
Variant 5 (direct, 15 examples): F1=0.92
Variant 6 (CoT, 15 examples): F1=0.93
Variant 7 (self-consistency, 5x): F1=0.94
Variant 8 (self-consistency, 10x): F1=0.94
Den besten Prompt verwendet es dann für einen abschließenden Durchgang zur Neubeschriftung.
Schritt 15: Abschließende Validierung
Potato wählt 100 zufällige vom LLM beschriftete Instanzen zur Prüfung aus. Sie beschriften diese, und Potato vergleicht Ihre Labels mit denen des LLM.
Final Validation:
Reviewed: 100 instances
LLM correct: 94/100 (94%)
Threshold: 93%
-> PASSED
Erreicht das LLM Ihre Schwelle, ist das Projekt abgeschlossen. Andernfalls fällt es für eine weitere Runde auf die aktive Annotation zurück. Dieser Rückweg ist der einzige Übergang, der aus der abschließenden Validierung erlaubt ist.
Zeitschätzung: 10-15 Minuten.
Zusammenfassung der Ergebnisse
Am Ende zeigt das Dashboard, woher die Labels stammen. Solo Mode hat keine Kommandozeilenschnittstelle (es läuft im Server und wird über eigene Seiten gesteuert), daher lesen Sie diese Angaben in der laufenden Instanz ab und nicht in einem Terminal:
Solo Mode Complete
==================
Dataset: 10,000 instances
Total human labels: 612
Seed: 50
Active labeling: 275
Disagreement exploration: 137
Edge case synthesis: 30
Confidence escalation: 75
Final validation: 45
LLM labels: 8,200 (accuracy: 94.1%)
LF labels: 1,800 (precision: 95.3%)
Unlabeled: 0
Final label distribution:
Positive: 4,823 (48.2%)
Neutral: 3,011 (30.1%)
Negative: 2,166 (21.7%)
Total human time: ~3.5 hours
Estimated multi-annotator cost (3x): ~$4,500
Solo Mode cost: ~$450 (API fees) + ~$175 (annotator time)
Savings: ~88%
Der Mensch hat 612 von 10.000 Instanzen beschriftet, etwa 6 %. Das LLM und die Labeling-Funktionen haben den Rest mit einer Genauigkeit von über 94 % übernommen.
Ergebnisse exportieren
Solo Mode schreibt in denselben Speicher wie jedes andere Projekt, daher kommen die Labels über den gewöhnlichen Exporter heraus:
python -m potato.export -c config.yaml -f jsonl -o ./export/Jede Zeile enthält das Label und seine Quelle:
{"id": "rev_001", "sentiment": "Positive", "source": "human", "confidence": 1.0}
{"id": "rev_002", "sentiment": "Neutral", "source": "llm", "confidence": 0.91}
{"id": "rev_003", "sentiment": "Negative", "source": "labeling_function", "confidence": 0.97}Für den Parquet-Export:
import pandas as pd
df = pd.read_parquet("output/exports/parquet/annotations.parquet")
print(df["sentiment"].value_counts())annotations.parquet enthält eine Zeile pro Instanz und Annotator, wobei jedes Annotationsschema in eine eigene Spalte aufgelöst wird. Sie wählen das Schema also über seinen Namen aus und nicht über eine generische Spalte value.
Qualitätssicherung: Hybride Verifikation
Für Datensätze in Publikationsqualität lassen Sie einen zweiten Annotator eine Stichprobe prüfen. Die Quelldokumentation zu Solo Mode beschreibt die Verifikationsoptionen ausführlicher.
Solo Mode hat keinen eigenen Verifikationsblock, das hier ist also ein gewöhnlicher zweiter Durchgang: Exportieren Sie die Labels, geben Sie sie als normales Projekt erneut in Potato, wobei ein Prüfer eine Stichprobe von 10 % bearbeitet, und berechnen Sie die Übereinstimmung zwischen Prüfer und Solo-Mode-Labels so, wie Sie es für zwei beliebige Annotatoren tun würden. (icl_labeling hat zwar einen Block verification, der gehört aber zum In-Context-Labeling und nicht zu Solo Mode.)
Fehlerbehebung
LLM-Genauigkeit stagniert unter der Schwelle
- Seed-Anzahl erhöhen: Versuchen Sie 75-100 Seed-Instanzen statt 50
- LLM wechseln: Versuchen Sie
claude-sonnet-4-20250514statt GPT-4o (oder umgekehrt) - Schwelle senken: Wenn 93 % nicht erreichbar sind, überlegen Sie, ob 90 % für Ihren Anwendungsfall genügen
- Daten prüfen: Manche Datensätze sind von Natur aus mehrdeutig. Wenn die Übereinstimmung zwischen Menschen nur bei 90 % läge, erwarten Sie nicht, dass das LLM besser abschneidet
Die aktive Annotation braucht zu viele Batches
- Batch-Größe erhöhen: Ändern Sie
batch_sizevon 25 auf 50 - Pool-Gewichte anpassen: Wenn die meisten eskalierten Instanzen aus dem Pool mit niedriger Konfidenz stammen, senken Sie
low_confidence_weightund erhöhen Siedisagreement_weightoderdiversity_weight
Labeling-Funktionen haben geringe Abdeckung
- Das ist normal bei Aufgaben ohne starke lexikalische Signale (z. B. Sarkasmuserkennung, implizite Stimmung)
- Labeling-Funktionen funktionieren am besten bei expliziten, schlüsselwortbasierten Mustern
- Solo Mode funktioniert auch ohne Labeling-Funktionen, dann deckt das LLM diese Instanzen ab
Weiterführende Lektüre
- Solo-Mode-Dokumentation: vollständige Konfigurationsreferenz
- Active Learning: der zugrunde liegende Auswahlalgorithmus
- KI-Unterstützung: Konfiguration der LLM-Anbieter
- Qualitätskontrolle: weitere Optionen zur Qualitätssicherung
- Parquet-Export: effizienter Datenexport