AI 支援
接入 OpenAI、Anthropic、Gemini、Ollama、vLLM 或 HuggingFace,讓標註者按需獲得提示、關鍵詞高亮和標籤理由。
開啟 AI 支援後,標註者工作時會有一個大語言模型寫提示、高亮關鍵詞、解釋每個標籤為什麼可能適用。它不會替你填表單。決定權仍在標註者手裡,每個助手都藏在一個需要他們按下的按鈕後面。
安裝
各家提供商的 SDK 都是可選依賴。基礎安裝不需要其中任何一個,只有當配置選中某個 endpoint_type 時才會匯入對應的 SDK:
pip install "potato-annotation[ai]"這覆蓋了常用的那幾個。如果配置選了一個 SDK 缺失的端點,伺服器會告訴你該裝哪個包,而不是在匯入時就失敗。
支援的提供商
雲端: openai、anthropic、gemini、huggingface
本地: ollama、vllm
視覺: ollama_vision、openai_vision、anthropic_vision、yolo
視覺端點以及影像和影片助手請見視覺 AI 支援。
配置
ai_support:
enabled: true
endpoint_type: "openai"
ai_config:
model: "gpt-4o-mini"
api_key: "${OPENAI_API_KEY}"
temperature: 0.7
max_tokens: 800
include:
all: true關於這個塊有兩點值得直說,因為執行時哪一點都不會被發現:
模型設定放在 ai_config 裡面,比想當然的位置深一層。ai_support.model 和 ai_support.base_url 會被忽略,不過 potato validate --strict 會把它們指出來。
include.all 預設是關閉的。沒有它,頁面上任何地方都不會出現助手按鈕,AI 面板渲染成空的,校驗乾淨通過,也沒有任何警告。
配置選項
| 選項 | 類型 | 描述 |
|---|---|---|
enabled | boolean | 開啟 AI 支援 |
endpoint_type | string | 使用哪個提供商 |
ai_config_file | string | 存放端點細節的外部配置檔案路徑 |
ai_config.model | string | 模型名稱,預設為該提供商自己的預設模型 |
ai_config.api_key | string | 雲服務商必填 |
ai_config.base_url | string | 用某個相容 OpenAI 的伺服器替代廠商自家的,例如 vLLM、SGLang、LM Studio 或 LiteLLM。設定它之後 api_key 變為可選 |
ai_config.temperature | float | 回覆的隨機程度,0.0 到 2.0,預設 0.7 |
ai_config.max_tokens | integer | 回覆的最大長度,預設 800 |
ai_config.include.all | boolean | 在所有方案上啟用助手,預設 false |
ai_config.include.special_include | object | 按頁面、按方案分別控制 |
cache_config.disk_cache.enabled | boolean | 把回覆快取到磁碟,預設 false |
cache_config.disk_cache.path | string | 快取檔案路徑,開啟快取時必填 |
cache_config.prefetch.warm_up_page_count | integer | 啟動時預先生成的實例數 |
cache_config.prefetch.on_next | integer | 向前翻頁時預取的實例數 |
cache_config.prefetch.on_prev | integer | 向後翻頁時預取的實例數 |
openai 和 openai_vision 接受三種提供 API 金鑰的方式,校驗三種都認:api_key 的值、環境中的 OPENAI_API_KEY,或指向一臺不需要金鑰的自託管伺服器的 base_url。anthropic、huggingface 和 gemini 只讀第一種,所以對這三個來說金鑰確實是必需的。
沒有理由就讓 max_tokens 保持預設值。理由助手和關鍵詞助手會在一次回覆裡為所有標籤作答,所以幾百個 token 會把回覆從物件中間截斷,助手渲染成空的,而且不報錯。
幾個助手
標註者在每個方案上會拿到三個按鈕,外加第四種隨提示一起出現的行為。
提示給出關於如何思考這條資料的指引,可以附帶一個建議標籤。
關鍵詞標出與每個標籤相關的詞和短語,畫成文本上的方框覆蓋層,而不是背景高亮。
理由解釋每個可選標籤為什麼可能適用,對所有標籤給出平衡的推理。在培訓標註者或判斷確實困難時,這個最值得開啟。
標籤建議不是單獨的按鈕。當提示帶有建議標籤時,那個標籤會帶上琥珀色邊框和一個閃游標記。
各端點能做什麼
| 端點 | 文本 | 視覺 | 方框 | 關鍵詞 | 理由 |
|---|---|---|---|---|---|
openai、anthropic、ollama | 是 | 否 | 否 | 是 | 是 |
openai_vision、anthropic_vision、ollama_vision | 是 | 是 | 否 | 僅文本條目 | 是 |
yolo | 否 | 是 | 是 | 否 | 否 |
「僅文本條目」是按條目判定的,而不是按端點判定。視覺模型仍然是語言模型,所以在文本條目上它提供全部三個助手,而在影像條目上關鍵詞按鈕會被過濾掉,因為沒有詞可標。
圖文都有的條目
帶截圖的客服工單,或配著評論的產品照片,應該圖文一起送到模型。Potato 從 item_properties.text_key 取文本,圖片則取下面第一個能解析出結果的來源:
ai_support.image_keyitem_properties.image_keyinstance_display中type: image的欄位,或第一個取值看起來像圖片的展示欄位
所以已經通過 instance_display 聲明瞭照片的配置,不需要再寫一遍:
instance_display:
fields:
- {key: body, type: text, label: Ticket}
- {key: screenshot, type: image, label: Screenshot}只把圖片發過去,提示就會信心十足地描述這條資料裡錯誤的那一半。給模型一張通用配圖,再讓它處理「匯出按鈕一直轉圈」,它會回說自己沒有拿到上下文。
這個欄位接受 http(s) URL、data URI,或 media_directory 下的檔名。本地檔案會從磁碟讀出並以 base64 傳送。既不是 URL、Potato 也找不到對應檔案的值會被記進日誌,然後不帶圖片去問模型,所以一條只針對文本推理的提示,就是去查那行日誌的理由。
按方案啟用助手
include.all 在所有地方開啟所有助手。另一種做法是 special_include,它把頁面索引對映到標註 id,再對映到該方案應帶的助手列表:
ai_support:
enabled: true
endpoint_type: "openai"
ai_config:
model: "gpt-4o-mini"
api_key: "${OPENAI_API_KEY}"
include:
all: false
special_include:
"0":
"0": ["hint", "keyword"]
"1":
"1": ["hint"]
"2":
"0": ["hint", "keyword"]
"1": ["hint", "keyword"]內層的鍵是標註 id,也就是該方案在 annotation_schemes 中從零開始數的位置。
當表單按網格排布時,這一點比看上去更要緊。助手那一行是按方案渲染的,所以三個方案各三個助手就是九個按鈕,每個單元格一行。單元格寬度低於約 260px 時,這一行會摺疊成單行圖示,標籤保留為按鈕的無障礙名稱並放在它的 title 上。如果要把 layout.grid 和 AI 支援一起用,請按方案指定想要的助手,而不是在所有地方全部開啟。
快取與預取
一次大語言模型呼叫會給頁面載入添上好幾秒,而等待的標註者就不再按那個按鈕了。快取還能讓你不必為別人重新訪問過的條目付兩次錢:
ai_support:
enabled: true
endpoint_type: "openai"
ai_config:
model: "gpt-4o-mini"
api_key: "${OPENAI_API_KEY}"
include:
all: true
cache_config:
disk_cache:
enabled: true
path: "annotation_output/ai_cache.json"
prefetch:
warm_up_page_count: 20
on_next: 10
on_prev: 3預熱在啟動時為前 N 條實例預先生成回覆。預取則在標註者瀏覽時於游標前方生成,on_next 比 on_prev 大,反映的是大部分移動都是向前的。磁碟快取在重啟後依然保留。
外部 AI 配置檔案
端點細節往往正是不能提交進倉庫的那部分:API 金鑰、內部伺服器 URL、那臺機器上裝的是哪個模型。ai_config_file 把它們移進自己的檔案:
# config.yaml, committed, no secrets
ai_support:
enabled: true
ai_config_file: ai-config.yaml
ai_config:
temperature: 0.7
max_tokens: 800
include:
all: true# ai-config.yaml, gitignored
endpoint_type: ollama
model: qwen3:0.6b
base_url: http://localhost:11434外部檔案負責設定 endpoint_type,它的其他值會合並進 ai_config 並優先於內聯的值。合併是扁平的:外部檔案在自己的頂層直接放 model、base_url 和 api_key。把它們包在該檔案裡的 ai_config: 塊中會產生 ai_config.ai_config,沒有任何程式碼讀它,啟動隨後會因缺少 API 金鑰而失敗,報錯指向的還是錯的鍵。
如果設定了 ai_config_file 但檔案不存在,AI 支援會給出警告並自行關閉,伺服器照常啟動。potato validate --strict 把那條警告當成錯誤,所以一項以 AI 輔助為研究物件的研究,在 AI 關著的情況下過不了自己的檢查。請在配置旁邊附一份 ai-config.yaml.example 供人複製。ai-config.yaml 和 ai-config*.yaml 這兩個模式已被 gitignore。
自定義提示詞
提示詞以 JSON 檔案的形式放在 potato/ai/prompt/ 裡,每種標註類型一個:
| 標註類型 | 提示詞檔案 |
|---|---|
| Radio | radio.json |
| Likert | likert.json |
| Multiselect | multiselect.json |
| Span | span.json |
| Slider | slider.json |
| Select | select.json |
| Number | number.json |
| Free text | textbox.json |
每個檔案為每個助手儲存一個模板,包含 name、prompt、output_format 和一個圖示:
{
"hint": {
"name": "Hint",
"prompt": "TASK: Generate annotation guidance...\n- Text to annotate: \"${text}\"\n- Annotation task: ${description}\n- Available labels: ${labels}",
"output_format": "default_hint",
"img": "/static/ai_assistant_img/blub.svg"
}
}可用的變數是 ${text}、${description}、${labels}、${min_label}、${max_label}、${size}、${min_value} 和 ${max_value}。
output_format 指明渲染器期待的回覆結構。default_hint 返回 {hint, suggestive_choice},default_keyword 返回 {label_keywords: [{label, keywords}]},default_rationale 返回 {rationales: [{label, reasoning}]}。
各提供商的配置
OpenAI
ai_support:
enabled: true
endpoint_type: "openai"
ai_config:
model: "gpt-4o-mini"
api_key: "${OPENAI_API_KEY}"
temperature: 0.7
max_tokens: 800
include:
all: trueAnthropic
ai_support:
enabled: true
endpoint_type: "anthropic"
ai_config:
model: "claude-sonnet-4-20250514"
api_key: "${ANTHROPIC_API_KEY}"
temperature: 0.7
max_tokens: 800
include:
all: trueGoogle Gemini
ai_support:
enabled: true
endpoint_type: "gemini"
ai_config:
model: "gemini-2.0-flash-exp"
api_key: "${GOOGLE_API_KEY}"
max_tokens: 800
include:
all: trueOllama
ai_support:
enabled: true
endpoint_type: "ollama"
ai_config:
model: "llama3.2"
base_url: "http://localhost:11434"
max_tokens: 800
include:
all: truevLLM
ai_support:
enabled: true
endpoint_type: "vllm"
ai_config:
model: "meta-llama/Llama-3.2-3B-Instruct"
base_url: "http://localhost:8000"
max_tokens: 800
include:
all: trueHuggingFace
ai_support:
enabled: true
endpoint_type: "huggingface"
ai_config:
model: "meta-llama/Llama-3.2-3B-Instruct"
api_key: "${HF_API_KEY}"
max_tokens: 800
include:
all: trueOpenRouter 不在 ai_support.endpoint_type 接受的十個取值之內,在這裡寫它,配置載入不起來。它能用在聊天側欄:chat_support.endpoint_type: openrouter,注意這個拼寫沒有下劃線。
給影像單獨配一個端點
文本模型和視覺模型可以並排執行,讓每種內容類型都用上更合適的那個:
ai_support:
enabled: true
endpoint_type: "ollama"
visual_endpoint_type: "ollama_vision"
ai_config:
model: "llama3.2"
include:
all: true
visual_ai_config:
model: "qwen2.5-vl:7b"完整示例
annotation_task_name: "Sentiment Analysis with AI Support"
task_dir: "."
data_files:
- "data/reviews.json"
item_properties:
id_key: id
text_key: text
annotation_schemes:
- annotation_type: radio
name: sentiment
description: "What is the sentiment of this text?"
labels: ["positive", "negative", "neutral"]
- annotation_type: multiselect
name: topics
description: "What topics are discussed?"
labels: ["product", "service", "price", "quality"]
ai_support:
enabled: true
endpoint_type: "openai"
ai_config:
model: "gpt-4o-mini"
api_key: "${OPENAI_API_KEY}"
temperature: 0.7
max_tokens: 800
include:
all: true
cache_config:
disk_cache:
enabled: true
path: "annotation_output/ai_cache.json"
prefetch:
warm_up_page_count: 20
on_next: 10
on_prev: 3
output_annotation_dir: "output/"
export_annotation_format: jsonl
user_config:
allow_all_users: true環境變數
把金鑰留在配置之外:
export OPENAI_API_KEY="sk-..."
export ANTHROPIC_API_KEY="sk-ant-..."
export GOOGLE_API_KEY="..."用 ${VARIABLE_NAME} 引用它們,主配置和外部 AI 配置檔案裡都能用。
故障排查
提示框是空的,但伺服器確實回覆了
模型回覆了,請求返回 200,而提示框什麼都不顯示。有四件事會產生同樣的症狀,按這個順序檢查:
include.all缺失。 頁面上根本沒有助手按鈕,而且沒有任何警告。max_tokens太低。 理由助手和關鍵詞助手會一次性為所有標籤作答,所以回覆從物件中間被截斷。日誌裡會寫模型觸到了max_tokens。- 伺服器忽略了 schema。 檢查回復是 JSON 而不是散文。沒有約束解碼的伺服器會按提示詞暗示的任何結構作答。
- 鍵放錯了地方。 所有跟模型有關的東西都屬於
ai_config。validate --strict會指出它不認識的任何鍵。
一個按鈕都沒有,而啟動日誌看著正常
在日誌裡找 "AI endpoint ready"。如果它說端點啟動失敗,原因就在那一行上方的警告裡。
Ollama 或 vLLM 連線失敗
確認伺服器正在執行、模型已經拉取,Ollama 用 ollama list 檢視,並檢查配置的 base_url 可以訪問。
最佳實踐
- 當成輔助來用 - 決定由標註者做出,一項預設接受建議的研究測的是模型
- 在生產環境啟用快取 - 它能降低延遲和重複開銷
- 使用預熱 - 預先生成開頭那幾條實例,第一位標註者就不用等
- 留意賬單 - 雲服務商按請求收費,每個方案都配一個助手會在整個語料上成倍放大
- 考慮本地端點 - 大批次工作,或語料不能離開本機時,用 Ollama 或 vLLM
- 把金鑰放在環境變數裡 - 絕不要提交它們
延伸閱讀
- 視覺 AI 支援 - 面向影像和影片的視覺端點
- 選項高亮 - 弱化可能性較低的標籤
- 多樣性排序 - 基於嵌入的條目排序
- ICL 標註 - 在自有標註上做上下文學習
- 主動學習 - 模型驅動的實例優先順序排序
有關實現細節,請參閱源文件。