Skip to content

使用者管理

用 user_config 訪問名單、URL 直接登入、RBAC 角色與許可權、按標註者設定的工作量配額和培訓關卡,管理 Potato 裡的標註者。

Potato 對一個人分別決定三件事:能不能註冊、進來之後可以做什麼、以及分給他多少工作。這三件事各是一個配置塊,把它們弄混,通常就是"標註者能登入卻始終拿不到項目"的原因。

訪問模式

開放訪問

Potato 預設允許自助註冊,新標註者可以從登入頁自己建立賬號:

yaml
user_config:
  allow_all_users: true

受限訪問

把 allow_all_users 設為 false,並列出允許註冊的地址。名單之外的人無法建立賬號:

yaml
user_config:
  allow_all_users: false
  users:
    - alice@example.com
    - bob@example.com
    - researcher@university.edu

這兩個鍵都在 user_config 之下。寫在頂層會被靜默忽略,看上去就是一份什麼也不管的訪問名單。

認證

密碼登入

預設方式。標註者用郵箱和密碼註冊,Potato 把密碼存成按使用者加鹽的 PBKDF2 雜湊。

yaml
login:
  type: password

用 URL 參數直接登入

url_direct 直接從 URL 參數裡取使用者名稱,不要求密碼,眾包平臺過來的人就是這麼處理的:

yaml
login:
  type: url_direct
  url_argument: PROLIFIC_PID

標註者隨後訪問 http://your-server:8000/?PROLIFIC_PID=abc123,就以 abc123 的身份登入了。

url_argument 也接受一個列表,這時標註者的輸出目錄名由這些值拼接而成:

yaml
login:
  type: url_direct
  url_argument:
    - PROLIFIC_PID
    - STUDY_ID
    - SESSION_ID

登入類型一共三種:password、url_direct 和 prolific,最後一種是在 URL 直接登入之上再加了 Prolific API 整合。平臺那一側見眾包整合。

關閉密碼或登入表單

Potato 把每位標註者的標籤存在 output_annotation_dir 下以其使用者名稱命名的資料夾裡,所以每位標註者都要用使用者名稱登入。沒有哪個設定能去掉這一步。有兩個設定可以去掉其中的密碼,第二個還會連表單一起去掉。

在配置的頂層寫 require_password: false 後,登入表單只要求填寫使用者名稱。Potato 會當場註冊一個沒見過的名字,而見過的名字會直接回到該標註者的工作中:

yaml
require_password: false

因此,任何人輸入一個已有的使用者名稱,都會接著那位標註者的會話繼續。只有在標註者彼此信任或任務 URL 不公開時,才應關閉密碼。名單在這種模式下依然有效:設定 user_config.allow_all_users: false 時,不在 users 中的名字會被拒絕。要連表單也去掉,就使用 url_direct 登入,並給每位標註者傳送一個帶有其使用者名稱的連結。不需要密碼就能執行的認證後端見免密登入。

角色與許可權

共享管理員金鑰

admin_api_key 是一個通過 X-API-Key 請求頭髮送的共享金鑰,它會繞過所有許可權檢查。不設定時,Potato 會生成一個並寫入 {task_dir}/admin_api_key.txt。

yaml
admin_api_key: "your-shared-key"

基於角色的訪問控制

配上 rbac 塊之後,指定的人正常登入就能進入管理面板,不必持有那個共享金鑰:

yaml
rbac:
  enabled: true
 
  # Custom roles, merged over the built-in ones
  roles:
    lead: [view_admin_dashboard, export_data, annotate]
 
  # Assign roles to specific users
  user_role_assignments:
    carol@example.com: admin
    dave@example.com: lead
 
  # Map an SSO claim to a role
  sso_role_mapping:
    "org:my-github-org": adjudicator

許可權有 view_admin_dashboard、manage_assignment、adjudicate、export_data 和 annotate 五項。內建的 admin 角色擁有全部五項,adjudicator 擁有 adjudicate、export_data 和 annotate,annotator 擁有 annotate。

一個使用者的許可權是他所有角色的並集。完全不寫 rbac 塊時,只有共享金鑰和 adjudication.adjudicator_users 名單能帶來更高許可權,RBAC 出現之前寫的項目就是這樣繼續工作的。

工作量

每名標註者的上限

max_annotations_per_user 給所有人定同一個數:

yaml
max_annotations_per_user: 100

per_annotator_quota 給不同的人定不同的數。它接受 default、by_user 和 by_user_role,其他子鍵在載入時會被拒絕,而不是被忽略:

yaml
per_annotator_quota:
  default: 50
  by_user:
    alice@example.com: 200
  by_user_role:
    expert: 150
    novice: 40

上限的解析順序是先看 by_user,再看 by_user_role,最後看 default。角色標籤來自 user_roles:

yaml
user_roles:
  alice@example.com: expert
  bob@example.com: novice

這裡的標籤只是工作量標籤。只有當它同時在 rbac.roles 裡也是一個角色名時才帶來許可權,所以 expert 和 novice 就只是配額標籤而已。

每個項目的標註者數

num_annotators_per_item 決定每個項目由多少人看到,而這決定了你最後能不能報告一致性:

yaml
num_annotators_per_item: 3
min_annotators_per_instance: 2

max_annotations_per_item 是同一個上限的已棄用別名。兩者設成不同的值會在載入時被拒絕,而不是靜默取其一。

分配策略

yaml
assignment_strategy: random
random_seed: 1234

可選的策略有 random、fixed_order、least_annotated、max_diversity、diversity_clustering、category_based、batch、priority、model_review、llm_confidence、psychometric 和 active_learning。random_seed 預設是 1234,所以需要復現某次執行時把它固定下來。每種策略的作用見任務分配。

甄選標註者

培訓階段在正式任務之前先給標註者一批有已知答案的練習項目,由 passing_criteria 決定誰可以繼續:

yaml
training:
  enabled: true
  data_file: data/training.json
  passing_criteria:
    min_correct: 8
    max_mistakes: 2
    max_mistakes_per_question: 1
  allow_retry: true
  failure_action: block

項目格式和反饋選項見培訓階段。

任務進行中的注意力檢查

培訓在一開始篩人。注意力檢查則在真正開工之後繼續測量:

yaml
attention_checks:
  enabled: true
  items_file: data/attention_checks.json
  frequency: 10
  min_response_time: 3.0
  failure_handling:
    warn_threshold: 2
    warn_message: "Please read items carefully before answering."
    block_threshold: 5
    block_message: "You have been blocked due to too many incorrect responses."

黃金標準和一致性報告見品質控制。

會話

yaml
secret_key: "a-long-random-string"
session_timeout_minutes: 60
persist_sessions: true
session_lifetime_days: 7

secret_key 用來給會話 cookie 簽名,它也可以改由 POTATO_SECRET_KEY 環境變數提供。一個都沒有時,Potato 每次啟動都會生成新金鑰,於是每次重啟所有人都會被登出。

session_timeout_minutes 會清除空閒達到這麼長時間的會話,每次請求都會讓計時重新開始。Potato 2.11 是第一個真正執行這項設定的版本,預設值為 480 分鐘。像這個示例一樣設為 60 時,離開一小時的標註者回來後需要重新登入。

示例:科研團隊配置

yaml
annotation_task_name: "Sentiment Annotation"
task_dir: .
 
user_config:
  allow_all_users: false
  users:
    - researcher1@university.edu
    - researcher2@university.edu
    - student1@university.edu
    - student2@university.edu
 
rbac:
  enabled: true
  user_role_assignments:
    researcher1@university.edu: admin
 
user_roles:
  researcher1@university.edu: expert
  student1@university.edu: novice
 
per_annotator_quota:
  default: 200
  by_user_role:
    expert: 300
    novice: 120
 
num_annotators_per_item: 2
assignment_strategy: least_annotated
 
data_files:
  - data/main.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
    sequential_key_binding: true
 
output_annotation_dir: annotation_output/

示例:眾包配置

yaml
annotation_task_name: "Sentiment Annotation Study"
task_dir: .
 
login:
  type: url_direct
  url_argument: PROLIFIC_PID
 
completion_code: "POTATO2024"
 
user_config:
  allow_all_users: true
 
max_annotations_per_user: 50
num_annotators_per_item: 3
assignment_strategy: random
 
hide_navbar: true
jumping_to_id_disabled: true
 
attention_checks:
  enabled: true
  items_file: data/attention_checks.json
  frequency: 10
  failure_handling:
    warn_threshold: 2
    block_threshold: 5
 
data_files:
  - data/main.json
 
item_properties:
  id_key: id
  text_key: text
 
output_annotation_dir: annotation_output/

延伸閱讀

實現細節見源文件和角色與許可權參考。