Skip to content

佈局自定義

在 Potato 中用 HTML 模板和 CSS 構建自定義標註佈局,涵蓋並排對比、多列 scheme 和項目級樣式。

v2.1.0 新增

Potato 提供兩種自定義標註介面佈局的方式:

  1. 自動生成佈局:Potato 生成一個 HTML 佈局檔案,你可以編輯它
  2. 自定義佈局檔案:建立你自己的 HTML 模板,完全掌控樣式

快速開始

使用自動生成的佈局

  1. 執行一次伺服器,Potato 會寫出 layouts/task_layout.html
  2. 編輯生成的檔案來自定義樣式
  3. 你的修改在伺服器重啟後依然保留(除非你修改了配置中的 annotation_schemes)

編輯 annotation_schemes 會重新生成該檔案,因為表單標記必須與它收集的 scheme 相匹配。如果某個佈局你想保留,請在改動 scheme 之前把它另存為自己的檔名。

使用自定義佈局檔案

  1. 建立你的佈局檔案(例如 layouts/custom_task_layout.html)
  2. 在配置中引用它:
yaml
task_layout: layouts/custom_task_layout.html

該路徑相對於配置檔案所在目錄解析,因此與配置放在一起的佈局檔案會隨項目一同遷移。

項目級基礎 CSS

佈局檔案只負責標註頁面的樣式。若要為項目提供的每一個頁面設定樣式,包括知情同意頁和說明頁,請用 base_css 指向一個樣式表:

yaml
base_css: styles/custom.css

Potato 在伺服器啟動時讀取該檔案,並把它作為 <style id="potato-project-base-css"> 塊注入每個頁面的 <head> 中,位置在所有內建樣式之後,因此你的規則優先生效。修改後需要重啟伺服器;檔案缺失只會記錄一條警告,不會讓伺服器停止。

佈局檔案結構

自定義佈局檔案必須包含:

html
<style>
    /* Your custom CSS */
</style>
 
<div class="annotation_schema">
    <!-- Your annotation forms -->
    <form id="schema_name" class="annotation-form radio" data-annotation-id="0">
        <fieldset schema="schema_name">
            <legend>Question text</legend>
            <!-- Input elements -->
        </fieldset>
    </form>
</div>

必需的表單屬性

Potato 通過以下四個屬性把標記與你的配置對應起來,其中任何一個不匹配,標註就到不了輸出檔案:

屬性描述
id必須與配置中 annotation_schemes 的 name 一致
class包含 annotation-form 和類型(如 radio、multiselect)
data-annotation-id順序索引(0, 1, 2...)
schemafieldset 和 input 上的屬性,與 scheme 名稱一致

必需的輸入屬性

html
<input class="schema_name annotation-input"
       type="radio"
       name="schema_name"
       value="label_value"
       schema="schema_name"
       label_name="label_value"
       onclick="onlyOne(this);registerAnnotation(this);">

示例佈局

Potato 附帶三個完整的示例佈局。下面的命令要在克隆下來的 Potato 倉庫根目錄下執行,因為這些配置及其資料檔案都是該 checkout 的一部分。若要用你自己的配置執行自己的佈局,請改用 potato start <your-config>.yaml -p 8000。

1. 內容稽核儀表板

位置:examples/custom-layouts/content-moderation/

包含帶內容後設資料的警告橫幅頭部、違規類別的雙列網格、按顏色編碼的嚴重程度級別,以及一條稽核工作流。

bash
python potato/flask_server.py start examples/custom-layouts/content-moderation/config.yaml -p 8000

2. 客服對話品質評估

位置:examples/custom-layouts/dialogue-qa/

包含帶後設資料徽章的案例頭部、分組的評估區塊、圓形 Likert 量表評分、品質問題清單,以及按顏色編碼的解決狀態指示。

bash
python potato/flask_server.py start examples/custom-layouts/dialogue-qa/config.yaml -p 8000

3. 醫學影像審閱

位置:examples/custom-layouts/medical-review/

包含醫療風格的 UI 樣式、位置與嚴重程度的雙列布局、分組的檢查結果區塊、結構化報告,以及帶說明的建議卡片。

bash
python potato/flask_server.py start examples/custom-layouts/medical-review/config.yaml -p 8000

CSS 技巧

網格佈局

建立多列布局:

css
.annotation-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 16px;
}
 
.full-width {
    grid-column: 1 / -1;
}
 
@media (max-width: 768px) {
    .annotation-grid {
        grid-template-columns: 1fr;
    }
}

按顏色編碼的選項

用表示嚴重程度的顏色來設定單選按鈕的樣式:

css
.severity-option input[type="radio"] {
    position: absolute;
    opacity: 0;
}
 
.severity-label {
    display: block;
    padding: 10px;
    border-radius: 6px;
    border: 2px solid transparent;
    cursor: pointer;
    transition: all 0.2s;
}
 
/* Green for "None" */
.severity-none .severity-label {
    background: #dcfce7;
    color: #166534;
}
.severity-none input:checked + .severity-label {
    background: #22c55e;
    color: white;
}
 
/* Red for "Severe" */
.severity-severe .severity-label {
    background: #fee2e2;
    color: #991b1b;
}
.severity-severe input:checked + .severity-label {
    background: #ef4444;
    color: white;
}

隱藏原生 input 而對它的 label 設定樣式,可以讓整個彩色區塊都能點選,當選項集是網格而不是豎排列表時這一點尤其重要。

區塊樣式

建立視覺分組:

css
.annotation-section {
    background: #f8fafc;
    border: 1px solid #e2e8f0;
    border-radius: 8px;
    padding: 16px;
    margin-bottom: 16px;
}
 
.section-title {
    font-size: 13px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    margin-bottom: 12px;
    padding-bottom: 8px;
    border-bottom: 2px solid #3b82f6;
}

圓形 Likert 評分

圓點一眼就能讀作一個量表,而且比一摞單選行佔用更少的垂直空間,這能讓多問題表單保持在一屏之內:

css
.likert-circle {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    border: 2px solid #e2e8f0;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
}
 
.likert-option input:checked + .likert-circle {
    background: #8b5cf6;
    color: white;
    border-color: #7c3aed;
}

與實例顯示結合

自定義佈局可以和 instance_display 配置一起使用。實例內容(影像、文本、對話)在標註表單上方單獨渲染,因此佈局檔案控制的是問題,instance_display 控制的是被標註的材料。

yaml
instance_display:
  fields:
    - key: image_url
      type: image
      display_options:
        zoomable: true
 
task_layout: layouts/custom_task_layout.html
 
annotation_schemes:
  - annotation_type: radio
    name: category
    description: "Which category does this image belong to?"
    labels: [A, B, C]

最佳實踐

  1. 讓 scheme 名稱對上:表單 id 必須與 annotation_schemes 中的 name 完全一致
  2. 順序的標註 ID:data-annotation-id 使用 0, 1, 2...
  3. 帶上必需的處理函式:單選用 onclick="onlyOne(this);registerAnnotation(this);",核取方塊用 onclick="registerAnnotation(this);"
  4. 測試響應式:用媒體查詢支援移動端
  5. 保持可訪問性:使用規範的 label,並保留鍵盤導航

故障排除

標註沒有儲存

檢查:

  • 表單 id 是否與標註 scheme 的 name 一致
  • input 是否帶有 schema 和 label_name 屬性
  • 點選處理函式(registerAnnotation)是否存在

樣式沒有生效

  • 確認 CSS 優先順序足夠高,能覆蓋預設樣式
  • 檢查 <style> 塊是否位於佈局檔案內部
  • 用瀏覽器開發者工具檢視實際生效的樣式

佈局沒有載入

  • 確認 task_layout 中的路徑是相對於配置檔案的
  • 檢查 HTML 語法錯誤
  • 檢視伺服器日誌中的錯誤資訊

延伸閱讀

有關實現細節,請參閱原始碼文件。