給 AI 標註員的碼本:把編碼方案變成可靠的 LLM 標註器
如何編寫一份 LLM 真正能執行的標註碼本,用人工編碼來驗證它的標籤,並讓人始終參與其中,附一份可執行的 Potato 配置。
幾十年來,碼本一直是你交給人看的文件。它告訴一組編碼員每個標籤的含義、哪些情況算數、邊界上的棘手之處在哪裡。如今讀這份碼本的編碼員,往往是一個語言模型;而一份為第三次培訓的研究生寫的碼本,並不能乾淨利落地遷移到一個只會把它通讀一遍、再也不會提出澄清問題的模型上。
碼本是你的標籤與世界之間的契約:對每個碼,它規定什麼含義、什麼算、什麼不算,再加一兩個示例。要用 LLM 做標註員,你要重寫這份契約,讓模型無需來回溝通就能執行;然後在信任它之前,用人工編碼員來核對它的輸出。 這篇文章講的就是這次重寫和這次核對。文末的 Potato 配置展示了執行整個流程的一種方式。
碼本究竟是什麼
在內容分析和質性研究中,碼本是一項研究裡每個碼的共享定義。經典參考是 MacQueen 等人 1998 年的模板:它給每個碼一個名稱、一句簡短定義、一段說明何時適用何時不適用的更完整描述,以及示例文段。把這些都寫下來是為了可靠性——兩名讀同一份碼本的編碼員,面對同一段文本應當得出同樣的標籤,而你可以測量他們是否如此。
碼本有兩種脾性。固定碼本在編碼開始前就已定型,大多數機器學習標籤集和眾包任務都是這樣。活的碼本則在閱讀中生長,屬於紮根理論傳統:你注意到一個反覆出現的想法,給它命名,之後發現兩個碼其實是同一回事便把它們合併。兩者都能驅動 LLM 標註員,但它們失敗的方式不同,這值得記在心裡。
為什麼為人寫的碼本會讓 LLM 出錯
人工編碼員會用判斷力、以及那場一起討論疑難案例的培訓來填補碼本的空白。模型兩者都沒有。它只讀頁面上的字,而你留白的地方,正是它出錯的地方。
- 未定義的邊界。 「當參與者提到錢時編碼為費用顧慮」並沒有說清楚隨口一句「也不便宜」算不算。人會追問;模型只能猜,而且在整個語料裡猜得前後不一。
- 缺失反例。 人工編碼員從「看著像 X 其實不是」中學到的,和從正例中學到的一樣多。碼本很少把這些寫下來,因為培訓者是當場口頭補上的。
- 照字面執行指令。 告訴模型「最多應用三個碼」,它往往不管文本是否需要都湊滿三個。人把這讀成上限;模型把它讀成目標。
- 沒有切分步驟。 人會自然地把訪談切成可編碼的單元。模型需要被明確告知先切分、再對每個單元編碼,否則它會把整段當作一整塊來編碼,丟掉你想要的粒度。
這些都不是迴避 LLM 標註員的理由。它們只是把一份人用的碼本改造成模型能執行的碼本所需的編輯。
編寫一份 LLM 能執行的碼本
一旦知道要補什麼,這次重寫就很機械。對每個碼,把人本會自行推斷的四樣東西寫明白:
- 一句話定義,用平實語言,而不是碼名的同義詞。
- 納入規則:意味著該碼適用的訊號。
- 排除規則:那些擦邊但不算數的情況,每種配一個簡短示例。
- 兩三個真實示例,最好包含一個新手會編碼錯的。
然後把結構和標籤分開處理。讓模型先把文本切成單元,逐個單元對照碼本編碼,當沒有合適的碼時選擇棄權,而不是硬找一個最接近的。一個明確的「以上皆非」選項,對資料品質的幫助勝過再寫一段指令,因為它給了模型一個安放碼本未覆蓋情況的去處,而不是把它們硬塞進一個不該屬於的碼裡。
可靠性問題
你核對 LLM 標註員,不是因為它差,而是因為你事先無從判斷。在若干成熟任務上它確實不錯:Gilardi、Alizadeh 和 Kubli(2023)發現 ChatGPT 在相關性、立場和框架檢測上追平甚至超過眾包工人,編碼員間一致性更高,每條標籤成本不到一美分。但「在那些任務上不錯」並不能說明你的任務,而唯一的辦法就是測量。
這次測量和你對兩名人工編碼員做的完全一樣。讓人標一份樣本,讓模型標同一份樣本,再算一個像 Cohen 或 Krippendorff 那樣對偶然一致做了校正的一致性統計量。一致性高的地方,模型可以承擔語料的大頭;一致性低的地方,你就找到了一個定義沒你以為那麼管用的碼,而修正通常在碼本里,而不是在模型上。
從人工碼本到 LLM 標註員,含打磨迴路
有兩種失敗模式值得專門盯著。當你給模型一個上限卻沒給它保持在上限以下的理由時,它會過度施碼,於是一致性在「是否出現」上看著還行,在「數量」上卻崩掉。而當人去核對模型、而不是重新標註時,自動化偏見便悄然而至:接受一個看似合理的碼比質疑它更快,於是核對者不聲不響地追認了模型的錯誤。這兩點都是要留一份真正盲測、純人工標籤作為標尺的理由。
讓人始終在環內
可行的安排既不是「模型標註一切」,也不是「人標註一切」,而是一個由一致性數字決定的分工。
按一致性分流:讓有把握的編碼通過,把其餘送回
在一份帶標籤的黃金樣本上跑模型,看它在哪裡與人一致,據此分流。模型可靠標對的碼,配一次輕量抽查後放行;它標錯的碼,以及它棄權或看起來沒把握的單元,交給人工編碼員。人解決這些時,分歧會迴流到碼本里,下一輪也因此更好。這就是預標註背後的人在環內思路,只是從單個標籤放大到了整套編碼方案。
在 Potato 裡怎麼做
Potato 在一個工具裡跑通這個迴路:一套以碼本為依託的編碼方案、一個做預標註的 LLM、做核對的人工編碼員,以及對結果的可靠性指標。碼本存放在一個標記為碼本依託的 span 方案裡,正是它把一個普通標籤集變成可編輯、有層級的編碼方案。
annotation_schemes:
- annotation_type: span
name: codes
description: Highlight a passage and apply a code from the codebook
labels: [access barriers, cost concerns, provider trust]在 QDA 模式下碼本預設為 open,編碼員可以在方案定型的過程中新增、重新命名或合併碼。一旦有了穩定的碼本,在擴大規模前把它切到 fixed,共享方案就不會在模型和編碼員腳下繼續移動。
要讓模型預先施碼,開啟 AI 支援並指向你使用的端點:
ai_support:
enabled: true
endpoint_type: anthropic # or openai, gemini, ollama, ...
ai_config:
model: claude-opus-4-8
api_key: ${ANTHROPIC_API_KEY}
temperature: 0.2模型提出碼;標註員確認或糾正。為了讓自動化偏見可測量,不要給你留作測一致性的條目做預填。留一份純人工的盲測切片並以它作對照,正如預標註指南所述。
一輪跑完後,兩個匯出器給你交付物和審計軌跡:
python -m potato.export config.yaml --format codebook -o codebook.csv
python -m potato.export config.yaml --format quotation_report \
--option include_memos=true -o quotations.csvcodebook 匯出每個碼一行,帶其描述和使用次數,於是你能看到模型倚重了哪些碼、哪些從未觸發。quotation_report 每個已編碼文段一行,正是你實際用來核對模型的那份檔案。Potato 會對這些碼報告 Cohen 和 Fleiss 的 kappa,因此模型對人工的比較是一個數字,而不是一種感覺。
繼續閱讀
- 編寫有效的標註指南,同一門手藝裡屬於人的那一面。
- LLM 與視覺預標註,講模型建議的機制和防自動化偏見的護欄。
- 標註者間一致性詳解,講決定分工的可靠性統計量。
- 把質性編碼帶入 Potato,講這套流程所依託的碼本、備忘錄和個案。
以碼本為重的資料集展示了一套規格清晰的方案在實踐中的樣子:GoEmotions 裡細粒度的情緒碼、Social Chemistry 裡的社會規則判斷,以及 Media Frames 裡的框架標籤。