證據分類「分析結果報表」— 白話需求(Phase 0 draft)

項目 內容
提出日 2026-05-31
Branch feature/ai-analysis-result-landing(BE + FE 同名)
預計 FR FR-031(新整數號,relates to FR-030 證據自動分類 arc)
範圍 BE(主專案 + DB + 報表計算)+ FE(兩個新報表頁 + 兩處入口連結),跨 2 repo
狀態 Phase 0 白話需求,討論已收斂,待搬 docs/features/ 進 Phase 1
來源 既有獨立 Python 報表專案 ~/Desktop/AirAsia 真實證據/CMMC佐證/_驗證/validate.py / gen_ao_adjudication.py + WEB整合_報告產生規格.md

0. 一句話

把目前「另一個 Python 專案產出的兩份 HTML 分析報表」,搬進系統內變成兩個獨立可瀏覽的報表頁(用前端既有設計樣式重畫),並把每次分類 run 的結果存進資料庫(這階段 Drive / DB 兩邊都存)。


1. 背景與動機(客戶情境)

  • 目前證據分類流程:系統 trigger Claude API → 對 Google Drive 上的證據檔做分析、歸類 → 產出幾個 JSON 結果存在 Drive 上(_report-original.json_state.json_container-log.txt)。
  • 現在要看「這次 AI 分得好不好」,得跑另一個獨立 Python 專案手動產出兩份 HTML 報表 → 流程斷裂、非工程人員看不到。
  • 我們正處於分類器調校期:持續調整 prompt / 換 AI model(sonnet ↔︎ opus),手上有一份 User 自己人工分類好的正解資料,想拿來驗證「AI 與 User 雙方的判斷誰對誰錯」。
  • 因此需要把報表能力整進系統,讓管理員在系統內就能直接瀏覽分析結果報表,邊調邊看。

2. 要做什麼 — 兩份報表

報告①:驗證報表(量化)

對應獨立專案 validate.py

  • 在問什麼:AI 這次分類,跟「User 認定的正解」差多少?
  • 內容
    • 召回率 / 精確率,分兩種顆粒度:AO 層級(要中 [a]/[b] 子項,較嚴)+ 控制項層級(忽略子項,較高)
    • 缺漏四級(User 有、AI 此 AO 沒放,嚴重度遞增):版本/格式差異 → AO 選錯(同控制項) → 分到其他控制項 → AI 完全未分類
    • 多餘四級(AI 放了、User 此 AO 沒有):對稱四級
    • AI 未分類診斷:未放置檔分三類(真正該補 / 格式替代已涵蓋 / User 從未歸檔),A 類附「可否降門檻救回」
    • Docker log 健康:exit_code、處理/分類數、耗時、STDERR、錯誤關鍵字
    • 成本:token 用量 + 估算費用(可開關,沿用既有 flag 概念)

報告②:各 AO 誰對誰錯(質化)

對應獨立專案 gen_ao_adjudication.py

  • 在問什麼:以中立的正解基準(CANON)看,User 跟 AI 同一把尺檢視,誰把證據放錯了?
  • 為什麼需要它:報告① 預設「User 是對的」,但 User 自己也會誤放(實測這批約 30 格誤放)→ 報告① 會高估 AI 的錯。報告② 用固定 CANON 當中立裁判,才看得出 AI 的真實對齊度
  • 內容
    • 🔴 User 標錯的格子(應修正的人工誤放)
    • 🟠 AI 多放 / 過度的格子
    • ⚫ 超出框架範圍(如 L1 收到 L2 證據,應標 N/A)
    • 逐 AO 逐檔的 User / AI 判定明細
  • 判定原則:控制項精確比對(放在 CANON 列出的控制項=對,放別的=錯,即使同家族也算);CANON 採寬列原則(合理的都列、只排除明確錯的)。

兩者關係

並存、互補,不是二選一切換:① 給「對照 User 的數字成績」,② 給「AI 對中立正解的真實對齊度」。


3. 報表的資料來源(已追 code 驗證 ✅)

獨立專案是 offline 跑,靠外部 Excel + Source_Evidences/ 資料夾。搬進系統後,這些外部依賴大多不需要,對應如下:

報表概念 獨立專案(offline)來源 系統內來源
AI 放置 _report-original.json matches≥門檻 run 的 _report-original.json(AI 第一次分析的原始輸出,immutable)
User 正解 / ground truth Source_Evidences/ 外部人工資料夾 run 的 _state.json placements(User 在既有審閱頁修正後的當前狀態)
CANON(報告② 基準) 腳本內寫死 63 檔 固定 seed 一份(per-framework,這階段先固定,不做動態維護)
catalog(控制項/AO 定義) Excel 系統既有 cmmc_l1_aos.json(已是 NIST 編碼)
FAR↔︎NIST crosswalk INDEX_TO_NIST / SPECIAL_IX 不需要 — 系統內 AI 與 ground truth 都已是 NIST ao_id

報告① 走「即時」,不做確認按鈕

  • _state.json 本來就會隨 User 在審閱頁編輯而持續異動;報表頁是 on-demand 計算,每次打開就拿當下最新的 _state 重算 → 永遠反映即時分類狀態。
  • 因此不加「確認為正解」按鈕、不存 approved 快照 / approved_at / approved_by 欄位。
  • 唯一邊界:User 完全還沒動過的 run,_state 還等於 AI 原始 → 即時算會是召回/精確 100%、缺漏多餘 0(無意義)。此時報表頁自動偵測(讀 last_edited_at == null)→ 顯示一行純資訊提示:「此 run 尚未經人工審閱,目前分類等同 AI 原始輸出,召回/精確僅供參考」。不擋、不需動作。
  • 沒人工審閱時要看準度,看報告②:CANON 是固定 seed、不依賴任何人確認 → 報告② 隨時可跑,剛跑完就能評「這次 prompt/model 調得好不好」,正好服務調校期需求。

4. 進系統的形態

兩個獨立報表頁(唯讀)

  • 前端既有設計系統(Vue 3 + PrimeVue)重畫,不沿用獨立專案那套 inline-CSS HTML。
  • BE 算出結構化 JSON、FE 渲染(規格 Option B;HTML 匯出未列入這階段)。
  • 完全獨立、純讀取:讀該 run 的 _report-original.json + _state.json + 固定 CANON + catalog → 算 → 顯示。不寫回、不觸發任何既有流程。

強制約束:不動既有畫面 ⚠️

  • 既有的審閱頁 / 歸檔流程 / 比較畫面一律不改。報表是額外的瀏覽能力,不是改造既有功能。

兩處入口連結

  1. 分析結果頁(run 詳情頁) /project/projects/<project_uid>/ap/<ap_uid>/classify-evidence/run/<run_folder_id>
  2. 專案總覽 → 自動分類證據 Dialog → 歷史執行資料後面 入口頁 /project/projects/<project_uid>/ap/<ap_uid>,在「自動分類證據」Dialog 內、歷史執行資料清單後面掛上每筆 run 的兩個報表連結。

5. 範圍

這次做 ✅

  • 報告①(含完整版 + 未審閱降級版)+ 報告②(固定 CANON 基準)兩頁
  • 兩份報表的 BE 結構化 JSON 計算邏輯(移植兩支 Python 演算法)
  • 每次分類 run 結果存進 DB(這階段 Drive / DB 兩邊都存)
  • CANON 與 catalog 走固定 seed(一份 cmmc-l1)
  • 兩處入口連結

這次不做(未來再說)❌

  • 動態 CANON:上線後「記錄每次 User 調整完的分類當 CANON」← 明確延後
  • CANON 規則表 + 稽核員維護 UIcanon_rules 證據類型→控制項規則表)← 延後
  • 管理員「核可為正解」流程 / ground_truth 核可表(因為報告① 走即時,不需要)
  • 報表 HTML / PDF 匯出
  • 多框架(這階段只 cmmc-l1)
  • 完全停用 Drive、只用 DB(這階段兩邊都存,之後才考慮收斂)

6. 待討論 / 待設計階段敲定的問題

  1. 報表頁「即時讀」的後端接法(不影響需求,留 Phase 2 design):
    • 方案 a:報表頁直接讀 Drive 當前 _state.json(零碰既有 put_state
    • 方案 b:在既有 put_state 補一行同步 DB state 欄位,報表讀 DB(較貼合「移到 DB」目標,但動到既有後端 method —— 不改畫面)
  2. 「未審閱降級提示」那行要不要顯示(純 UX,可最後決定)。
  3. CANON 固定 seed 放哪:repo JSON 資源檔(如 cmmc_l1_canon.json,零 migration、可直接編輯)vs DB 表。傾向 JSON 資源檔。
  4. 報表②「User 側」在 User 尚未審閱時 == AI(兩欄相同)→ 顯示上是否需特別標示(避免誤讀成「User 也放這」)。

附錄 A. 技術可行性分析(初步,正式版進 Phase 2 design.md)

報告 可行性 關鍵點
報告① ✅ 高度可行 輸入(AI=_report-original.json、User=_state.json、catalog=cmmc_l1_aos.json)系統內全有;系統內已是 NIST → 免 crosswalk;演算法(doc_key 去重 / 四級 / 未分類三類診斷 / Docker log)只吃 JSON,零阻礙
報告② ✅ 演算法可行 唯一前提是 CANON 要存在;這階段用固定 seed(移植現有 63 檔版本)即可,不需規則表/維護 UI

已追 code 驗證的流程串接

POST classify-evidence → container write_outputs 寫 _report-original.json(AI原始) + _state.json(初始=AI)
   → BE _finalize_drive_output 建 run folder、上傳兩 JSON
   → [既有審閱頁] User 編輯 → put_state 改 source=manual、覆寫 _state.json  ← User 正解落地點
   → [新報表頁] 唯讀讀 _report-original + _state(當前) + 固定CANON + catalog → 算 → 顯示

附錄 B. 資料儲存初步構想(DB,正式 schema 進 Phase 2)

原則:欄位會一直調整 → 大 payload 走 JSONB;只把要查/排序/顯示的少數欄位升成正式 column。報表不另存、on-demand 算(改演算法不用洗舊資料)。

主表 evidence_classification_runs(鏡像整個 Drive run folder)

欄位 型別 說明
id BIGSERIAL PK
run_folder_id VARCHAR Drive run folder id(自然鍵,現在 URL 用的就是這個)
run_folder_name VARCHAR
tenant_id / project_id / ap_id / org_unit_id INT 查詢 / RLS / 列表索引欄
framework_id / model VARCHAR
confidence_threshold NUMERIC
status VARCHAR queued/running/completed/failed
archive_files BOOLEAN analyze-only vs 已歸檔
input_file_count / classified_count INT 列表顯示
estimated_cost_usd NUMERIC 跨批比成本(亦留 metadata json 內)
triggered_at / completed_at / archived_at / last_edited_at TIMESTAMPTZ last_edited_at 供報告① 判降級
triggered_by_user_id / archived_by_user_id / last_edited_by_user_id INT
report_original JSONB _report-original.json 全文(AI 原始,immutable)
state JSONB _state.json 全文(當前狀態,與 Drive 同步)
container_log TEXT _container-log.txt(報告① 的 Docker log 診斷段用)
審計欄位 created_user / created_dt / updated_user / updated_dt(依專案規範含 *_name)
  • 不需要 approved_at / approved_by(報告① 走即時,已砍)。
  • 報表快取表(..._report_cache)這階段先不做,需要時再加。

兩份基準(固定 seed,這階段)

基準 範圍 存法 未來
CANON(報告② 用) per-framework 固定 seed JSON(file_name → [control_id] + 理由,移植現有 63 檔) 規則表 + 維護 UI
catalog(控制項/AO 定義) per-framework 沿用既有 cmmc_l1_aos.json

報告① 的 ground truth 不另建表 —— 它就是 run 的 state JSONB(即時),不是獨立資料集。


參考

  • 獨立報表專案:~/Desktop/AirAsia 真實證據/CMMC佐證/_驗證/
    • 報告① 演算法:validate.py
    • 報告② 演算法 + CANON:gen_ao_adjudication.py
    • 整合權威規格:WEB整合_報告產生規格.md
  • 系統既有:
    • 證據分類 arc 收尾:docs/features/FR-030.3-2605-evidence-classify-xlsx-pptx/handoff/2026-05-30-evidence-classify-arc-SUMMARY.md
    • 輸出 JSON schema:docs/api/evidence-classification/state-json-schema.md
    • API 端點:docs/api/evidence-classification/api-spec.md
    • BE service:app/evidence_classification/service/evidence_classification_service.py
    • container 寫出:scripts/evidence/classify/docker/container_entrypoint.py write_outputs