Skip to content
Tutorials6 min read

Solo Mode:一個標註者如何標註 10,000 個樣本

Potato Solo Mode 分步教程:先自己標註一個種子集,其餘交給 LLM 標註,再用準確率檢查決定何時停手。

Potato Team

你有 10,000 條產品評論需要進行情感標註(正面、中性、負面)。僱用三名標註者標註所有資料需要數週時間和數千美元的費用。使用 Solo Mode,一位領域專家只需標註 500-1,000 個實例即可達到相當的品質,LLM 處理其餘部分——而人類稽核 LLM 不確定的每一個決定。

本教程將引導你完成整個流程。


你需要準備什麼

  • Potato 2.3.0+ 並安裝 Solo Mode 擴充套件:pip install potato-annotation[solo]
  • 一個 OpenAI 或 Anthropic API 金鑰(用於 LLM 元件)
  • JSONL 格式的資料集
  • 一位知識豐富的標註者(可以是你自己)

第 1 步:準備資料

建立 data/reviews.jsonl,每行一條評論:

json
{"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"}

在本教程中,假設此檔案包含 10,000 條評論。


第 2 步:建立配置

建立 config.yaml

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
 
  llm:
    endpoint_type: openai
    model: "gpt-4o"
    api_key: ${OPENAI_API_KEY}
    temperature: 0.1
    max_tokens: 64
 
  # Quality targets
  seed_count: 50
  accuracy_threshold: 0.93
  confidence_threshold: 0.85
 
  # Phase-specific settings
  phases:
    seed:
      count: 50
      selection: diversity
      embedding_model: "all-MiniLM-L6-v2"
 
    calibration:
      batch_size: 200
      holdout_fraction: 0.2
 
    labeling_functions:
      enabled: true
      max_functions: 15
      min_precision: 0.92
      min_coverage: 0.01
 
    active_labeling:
      batch_size: 25
      strategy: hybrid
      max_batches: 15
 
    refinement_loop:
      max_iterations: 3
      improvement_threshold: 0.02
 
    disagreement_exploration:
      max_instances: 150
      show_llm_reasoning: true
      show_nearest_neighbors: 3
 
    edge_case_synthesis:
      enabled: true
      count: 30
 
    confidence_escalation:
      escalation_budget: 150
      batch_size: 25
      stop_when_stable: true
 
    prompt_optimization:
      enabled: true
      candidates: 8
      metric: f1_macro
 
    final_validation:
      sample_size: 100
      min_accuracy: 0.93
 
  # Instance prioritization
  prioritization:
    pools:
      - name: uncertain
        weight: 0.30
      - name: disagreement
        weight: 0.25
      - name: boundary
        weight: 0.20
      - name: novel
        weight: 0.10
      - name: error_pattern
        weight: 0.10
      - name: random
        weight: 0.05
 
# --- 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"
 
parquet_export:
  enabled: true
  output_dir: "output/parquet/"

第 3 步:啟動伺服器

bash
potato start config.yaml -p 8000

開啟 http://localhost:8000 並登入。Solo Mode 面板將顯示你處於 階段 1:種子標註


第 4 步:階段 1 -- 種子標註(50 個實例)

Potato 使用基於嵌入的聚類選擇了 50 條多樣化的評論。這些不是隨機選擇的;它們被選擇以最大化資料分佈的覆蓋範圍。

逐一標註。這是最重要的階段——種子標籤的品質決定了 LLM 學習的效果。請認真對待並保持一致。

預計時間: 每個實例 20-30 秒,共 15-25 分鐘。

當你完成第 50 個實例時,Potato 自動進入階段 2。


第 5 步:階段 2 -- 初始 LLM 校準

此階段自動執行。Potato 將你的 50 個種子標籤作為少樣本示例傳送給 LLM,讓其標註 200 個實例的批次。然後將 LLM 的預測與 10 個留出的種子標籤進行比較,以估算基線準確率。

你將在面板中看到進度指示器。這通常需要 1-2 分鐘,具體取決於 LLM 提供商。

典型結果: LLM 在第一次校準中達到 75-85% 的準確率。這是預期的——LLM 尚未學會你特定的標註風格。


第 6 步:階段 3 -- 混淆分析

Potato 顯示一個混淆矩陣,展示 LLM 與你的標籤不一致的地方。典型輸出:

text
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%)

這告訴你 LLM 的主要弱點:它傾向於將中性評論升級為正面。這很常見——LLM 通常對正面情感有偏差。

你的操作: 審查混淆對。點選每個配對檢視 LLM 標註錯誤的具體實例。這有助於你理解 LLM 的失敗模式。


第 7 步:階段 4 -- 指南最佳化

基於混淆分析,Potato 為 LLM 生成最佳化的指南。你會看到並排檢視:

  • 當前指南: 用於 LLM 的初始提示
  • 建議編輯: LLM 根據錯誤模式提出的具體修改

例如,Potato 可能建議新增:

"將產品描述為'還行'、'湊合'或'一般'且沒有強烈情感的評論應標為 Neutral,即使提到可能再次購買。"

逐一審查建議的編輯。批准、修改或拒絕每一條。你也可以新增自己的說明。

預計時間: 5-10 分鐘。


第 8 步:階段 5 -- 標註函式生成

Potato 從種子標籤的模式中生成程式化標註函式。這些是處理簡單案例的快速、確定性規則:

text
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)

標註函式以 92%+ 的精確率覆蓋了資料集的 18%。這些實例被自動標註,將人類和 LLM 的精力留給更難的案例。

你的操作: 審查生成的函式。停用任何看起來不可靠的函式。這是可選的——Potato 只保留超過你配置的精確率閾值的函式。


第 9 步:階段 6 -- 主動標註(125-375 個實例)

這是主要的人工標註階段。Potato 使用六池優先順序系統選擇實例:

  • 不確定(30%):LLM 置信度低於 85% 的評論
  • 分歧(25%):LLM 和標註函式給出不同標籤的評論
  • 邊界(20%):在嵌入空間中靠近決策邊界的評論
  • 新穎(10%):與你已標註內容完全不同的評論
  • 錯誤模式(10%):匹配已知混淆模式的評論(如偏正面的中性評論)
  • 隨機(5%):用於校準的隨機評論

你以 25 個為一批進行標註。每批之後,Potato 更新 LLM 的準確率估計並決定是否繼續。

典型軌跡:

  • 第 1-3 批(75 個實例):準確率從 82% 升至 87%
  • 第 4-6 批(150 個實例):準確率達到 90%
  • 第 7-10 批(250 個實例):準確率在 91-92% 趨於平穩

如果準確率達到 93%(你設定的閾值),Solo Mode 將跳至階段 10。否則,繼續進入階段 7。

預計時間: 總計 45-90 分鐘,取決於需要多少批次。


第 10 步:階段 7 -- 自動化最佳化迴圈

如果主動標註後準確率仍低於閾值,Potato 執行新一輪最佳化迴圈:

  1. LLM 使用更新的指南和更多少樣本示例重新標註完整資料集
  2. 根據所有人工標籤重新計算準確率
  3. 識別新的混淆模式
  4. 再次最佳化指南

此階段大部分是自動的。你只需批准指南變更。

典型結果: 每輪最佳化準確率提高 2-4%。


第 11 步:階段 8 -- 分歧探索

Potato 呈現最有爭議的實例:LLM、標註函式和最近鄰分析都給出不同答案的案例。對於每個實例,你會看到:

  • 評論文本
  • LLM 預測和置信度
  • 標註函式投票
  • 3 個最近的已標註示例及其標籤
  • LLM 的思維鏈推理

這些是真正困難的案例。你在這裡的標籤在整個過程中具有最高的邊際價值。

預計時間: 100-150 個實例需 20-30 分鐘。


第 12 步:階段 9 -- 邊緣案例合成

Potato 生成針對剩餘混淆模式的合成評論。例如,如果 LLM 仍然在"提到再次購買的中性評論"上有困難,它會生成如下示例:

"這個產品在這個價位還行。如果打折的話我可能會再買一個。"

你標註這些合成示例,它們被新增到 LLM 的少樣本上下文中。

預計時間: 30 個示例需 10-15 分鐘。


第 13 步:階段 10 -- 級聯置信度升級

LLM 現在已經標註了大部分資料集。Potato 按置信度排序所有 LLM 標註的實例,並將最低置信度的實例以 25 個為一批發送給你。

text
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

一旦你看到連續三批 LLM 全部正確,Solo Mode 即判定剩餘的高置信度標籤是可信的。

預計時間: 15-20 分鐘。


第 14 步:階段 11 -- 提示最佳化

此階段自動執行。Potato 嘗試 8 種提示變體,並選擇在你積累的人工標籤上 F1 分數最高的那個:

text
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

最佳提示用於最終的重新標註。


第 15 步:階段 12 -- 最終驗證

Potato 隨機選擇 100 個 LLM 標註的實例供你稽核。你進行標註,Potato 將其與 LLM 的標籤進行比較。

text
Final Validation:
  Reviewed: 100 instances
  LLM correct: 94/100 (94%)
  Threshold: 93%
  -> PASSED

如果 LLM 的準確率達到閾值,資料集即告完成。如果沒有,Solo Mode 迴圈回階段 6 進行新一輪主動標註。

預計時間: 10-15 分鐘。


結果彙總

完成所有 12 個階段後,檢視最終統計:

bash
python -m potato.solo status --config config.yaml
text
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%

人類標註了 10,000 個實例中的 612 個(6.1%)。LLM 和標註函式以 94%+ 的準確率處理了其餘部分。


匯出結果

匯出最終的標註資料集:

bash
python -m potato.solo export --config config.yaml --output final_labels.jsonl

每行包含標籤及其來源:

json
{"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}

Parquet 匯出:

python
import pandas as pd
df = pd.read_parquet("output/parquet/annotations.parquet")
print(df["value"].value_counts())

品質保證:混合驗證

對於出版級品質的資料集,新增第二個標註者審查樣本:

yaml
solo_mode:
  verification:
    enabled: true
    sample_fraction: 0.10
    annotator: "reviewer_1"

這將 1,000 個隨機實例分配給第二個標註者。然後你可以計算 Solo Mode 標籤與稽核者標籤之間的標註者間一致性。


故障排除

LLM 準確率在閾值以下停滯

  • 增加種子數量: 嘗試 75-100 個種子實例而不是 50 個
  • 更換 LLM: 嘗試 claude-sonnet-4-20250514 代替 GPT-4o(或反之)
  • 降低閾值: 如果 93% 無法達到,考慮 90% 對你的用例是否可接受
  • 檢查資料: 某些資料集本身就是模糊的。如果人類間一致性只有 90%,不要期望 LLM 做得更好

階段 6 需要太多批次

  • 增加批次大小:batch_size 從 25 改為 50
  • 調整池權重: 如果大多數升級的實例來自"不確定"池,降低其權重並增加"分歧"和"錯誤模式"的權重

標註函式覆蓋率低

  • 這對於沒有強詞彙訊號的任務是正常的(如諷刺檢測、隱含情感)
  • 標註函式對顯式的、基於關鍵詞的模式效果最好
  • Solo Mode 在沒有標註函式的情況下仍然有效——LLM 會補上

延伸閱讀