跳轉到

AI 用量(AI Usage)

功能群:系統管理|選單位置「系統管理 › AI 用量」

事實基準:2026-09-30 從 FE src/views/ai-call-log/(AiUsagePage.vue、AiUsageSummary.vue、AiCallLogList.vue)+ BE api/ai_call_log/、app/ai_call_log/、infra/ai_call_log/、common/code/ai_call_log_error_code.py + migration scripts/sql/2026-09-28-fr122-ai-call-log.sql、2026-09-29-fr122-ai-call-log-page.sql、2026-09-29-fr122-ai-usage-menu-rename.sql 掃出。public.ai_call_log 不在 db_schema.json dump 內,欄位以 migration 為準

變更紀錄

日期 FR 變更
2026-10-04 FR-122 用量彙總「金鑰來源範圍」預設由「原廠金鑰」改為「全部」;彙總表六欄可排序(預設花費由高到低)、數字欄表頭靠右;金鑰來源改為全部/原廠金鑰/本租戶金鑰三選一;呼叫明細加同一個篩選,下鑽時帶入彙總的選擇(CM-2477)
2026-09-30 FR-122 首版:AI 用量頁——「用量彙總」與「呼叫明細」兩個分頁、明細詳情(不顯示任何原文)、兩種 xlsx 匯出;能力點 ai-call-log.read

1. 功能描述

AI 用量頁記錄每一次送給外部 AI 的呼叫:誰、哪個功能、守門怎麼處置、花了多少 token 與美金、成功與否、用的是誰的金鑰。三支 AI 功能(AI 小幫手、AI 儀表板、證據自動分類)都經 AI 閘道,閘道每呼叫一次就寫一筆 public.ai_call_log。

頁面只顯示後設資料,不顯示任何送出或回覆的原文——原文預設根本不存;租戶開「完整保留」才存,且到期由每日排程清空,這一頁也不提供查看。

主要使用者:租戶管理員(看本租戶)、平台管理員(看全部租戶、可按租戶分組)。

角色速覽

角色 一句話
具 ai-call-log.read 者 看得到本選單;只看得到自己租戶的紀錄(RLS)
平台管理員 另可在用量彙總按租戶分組、指定租戶篩選
其他登入者 無此選單;直打 API 回 403 GRC_403022

1.1 功能總覽(本頁全部功能)

# 功能 說明 位置 詳述
1 分頁切換 「用量彙總」/「呼叫明細」,網址 ?tab=summary\|detail 記住目前分頁 頁首 TabView §5
2 期間 本日/本週/本月(預設)/自訂 用量彙總 UC-AIU-01
3 分組 使用者(預設)/功能/模型/日期;平台管理員多「租戶」 用量彙總 UC-AIU-01
4 金鑰來源範圍 全部(預設)/原廠金鑰/本租戶金鑰 用量彙總 §10
5 租戶下拉 僅平台管理員,可清除 用量彙總 §3
6 三張統計卡 花費(美金)/呼叫次數/被擋下(額度、次數、守門) 用量彙總 §10
7 彙總表 分組維度、呼叫次數、輸入 token、輸出 token、花費(美金)、占比、「明細 →」;各欄可點表頭排序(預設花費由高到低),不分頁;AI 儀表板列可展開成「挑資料來源」「設計圖表」,排序時子列跟著父列 用量彙總 §10
8 下鑽明細 點「明細 →」切到呼叫明細並帶入該列條件與金鑰來源範圍,兩頁筆數一致 用量彙總 UC-AIU-01
9 匯出彙總 xlsx 用量彙總 §6
10 明細篩選 功能(多選)、處置(多選)、狀態、金鑰來源(全部/原廠金鑰/本租戶金鑰,預設全部)、起訖時間、重設 呼叫明細 UC-AIU-02
11 明細列表 見 §10 欄位表;每頁 25/50/100 筆 呼叫明細 §10
12 詳情 點列開 Dialog:基本資料、守門命中表、錯誤訊息;無任何原文欄位 呼叫明細 UC-AIU-02
13 匯出明細 xlsx,套用目前篩選,上限 50,000 筆(取最新) 呼叫明細 §6

展開成 UC:UC-AIU-01(看用量彙總並下鑽)、UC-AIU-02(查一筆被擋下的呼叫)。

2. Use Case

UC-AIU-01 看用量彙總並下鑽

項目 內容
角色 具 ai-call-log.read 者
主流程 ① 進頁預設「用量彙總」、本月、按使用者分組、金鑰來源全部 → ② 看三張卡與彙總表 → ③ 點某列「明細 →」→ 切到呼叫明細,帶入該使用者/模型/功能/日期
分支 平台管理員可改按租戶分組;租戶分組與系統呼叫(無使用者)的列沒有下鑽

UC-AIU-02 查一筆被擋下的呼叫

項目 內容
角色 具 ai-call-log.read 者
主流程 ① 呼叫明細篩「狀態=被阻擋」或「處置=阻擋」→ ② 點該列 → ③ 詳情的「守門命中」表看命中哪條規則(類型、分數、處數、階段、處置、規則編號)
用途 使用者回報「小幫手不回我」時,對照是哪條守門規則擋的,再決定要不要照《AI 守門調整手冊》放寬

3. 權限矩陣

操作 FE 判定 BE 強制 BE 檢查位置
看選單與頁面 route_capabilities 綁 ai-call-log.read — ui_routes seed
列表/詳情/彙總/兩種匯出 同上 require_capability("ai-call-log.read"),否則 403 GRC_403022 api/ai_call_log/routes/ai_call_log_route.py
看到的範圍 — ai_call_log RLS:租戶隔離、超級管理員放行 migration 2026-09-28-fr122-ai-call-log.sql
指定租戶篩選/按租戶分組 僅平台管理員顯示 非平台管理員帶租戶條件回 403 AI_CALL_LOG_403001 app/ai_call_log/service/

能力點預設授予:ai-call-log.read 授予目前持有 security-policy.read 的角色。

4. 狀態機與前置條件

本頁唯讀,無狀態機。紀錄保留天數依租戶設定 AI_CALL_LOG_RETENTION_DAYS(預設 365 天,0=永久),過期整筆刪除;明文保留另由 CALL_LOG_RETENTION 控制,預設不存。

5. UI 設計

📸 實際畫面截圖待補。

TabView 兩分頁。「用量彙總」上方一列控制項(期間/分組/金鑰來源範圍/租戶),下接三張統計卡與彙總表,右上匯出。「呼叫明細」上方篩選列,下接分頁表格,右上匯出;點列開 48rem 寬 Dialog,頂端提示「不會顯示任何送出或回覆的原文」。

6. API 規格

6.1 總清單(皆需 ai-call-log.read)

Method + Path 說明
POST /api/1.0/system/ai-call-logs 明細分頁列表
GET /api/1.0/system/ai-call-logs/<uid> 單筆詳情
POST /api/1.0/system/ai-call-logs/export 明細匯出 xlsx(上限 50,000 筆)
POST /api/1.0/system/ai-call-logs/usage 用量彙總
POST /api/1.0/system/ai-call-logs/usage/export 彙總匯出 xlsx

6.2 明細篩選(filters)

feature[]、guard_action[]、status、needs_review、user_id、model、key_scope(all 預設/vendor=只留 key_source 為 root、env/tenant=只留 tenant)、date_from、date_to;分頁 pager。明細匯出吃同一組條件。

6.3 錯誤碼

碼 HTTP 訊息
AI_CALL_LOG_404001 404 AI 呼叫紀錄不存在
AI_CALL_LOG_403001 403 只有平台管理員可指定租戶篩選
GRC_403022 403 使用者不具備此操作所需的權限(能力點)

7. 前端檔案地圖(compliance-manager-fe/)

檔案 角色
src/views/ai-call-log/AiUsagePage.vue 頁框與分頁切換
src/views/ai-call-log/AiUsageSummary.vue 用量彙總
src/views/ai-call-log/AiCallLogList.vue 呼叫明細、篩選、詳情 Dialog
src/config/router/index.js route ai-call-log(/system/ai-call-log)
src/config/locales/i18n/*/ai-call-log.json 文案

8. 後端檔案地圖

鏈路 位置
Route api/ai_call_log/routes/ai_call_log_route.py;序列化 api/ai_call_log/serializers/ai_call_log.py(明文四欄刻意不宣告)
App service app/ai_call_log/service/ai_call_log_app_service.py;匯出 ai_call_log_export.py
Repo infra/ai_call_log/repository/ai_call_log_repo_impl.py
寫入端 core/plugins/ai_gateway.py(閘道稽核落點,獨立於業務交易寫入)

9. DB

9.1 資料表

表 讀/寫 說明
public.ai_call_log 讀 本頁唯一資料來源(寫入端是 AI 閘道)
public.users 讀 使用者暱稱/帳號 enrich

9.2 public.ai_call_log 主要欄位

欄位 說明
feature ai-bot(AI 助理)/ai-dashboard.select(儀表板挑資料來源)/ai-dashboard.layout(儀表板設計圖表)/classification(證據自動分類)
executor api/worker
provider、model 供應商與模型
key_source tenant(本租戶自帶)/root(原廠:平台設定)/env(原廠:主機環境變數);沒解析到金鑰為 NULL
guard_action 最終處置,取最重:allow/redact/flag/block
guard_findings JSONB,每項 entity/score/count/stage/action/rule_id;不存命中原文
needs_review 有「標記」命中時為 true
input_hash、input_length 使用者輸入段的 sha256 與字數
input_tokens、output_tokens、cache_read_tokens、cache_write_tokens token 數
estimated_usd NUMERIC(12,6),估算美金,NULL=無估算
latency_ms、status(success/failed/blocked)、error 結果
related_type、related_uid、request_id、source_ip 關聯與追蹤
input_raw、input_sent、output_raw、output_final、raw_expires_at 明文,預設 NULL;本頁不讀

10. 頁面邏輯與資料對應

呼叫明細列表欄位:

欄 來源
時間 created_at
使用者 user_nickname/user_login_name;無使用者顯示「系統」
功能 feature
供應商/模型 provider/model
處置 guard_action:放行(綠)/遮蔽後送出(藍)/標記(黃)/阻擋(紅)
輸入 tokens/輸出 tokens input_tokens/output_tokens
估算費用(美金) estimated_usd,$ 加 6 位小數
耗時(ms) latency_ms
狀態 status:成功/失敗/被阻擋
金鑰來源 key_source

列表沒有「需人工審閱」欄;needs_review 只在後端可篩。

詳情 Dialog:時間、使用者、功能、供應商/模型、輸入字數、請求編號、守門命中表(類型/分數/處數/階段/處置/規則)、錯誤訊息(有才顯示)。

用量彙總:金鑰來源範圍預設「全部」,與呼叫明細的筆數一致;切「原廠金鑰」=只算 key_source 為 root 或 env,平台算原廠花費用,額度也只計這兩種;「本租戶金鑰」=只算 tenant。租戶自填金鑰的呼叫在「原廠金鑰」下不出現,只用自填金鑰的使用者會整列消失;「被擋下」卡計 status='blocked'。金額 ≥1 或 =0 顯示 2 位小數、<1 顯示 4 位。

明細匯出欄:時間、使用者暱稱、使用者帳號、功能、執行位置、供應商、模型、處置、守門命中類型、輸入字數、輸入/輸出 tokens、快取讀取/寫入 tokens、估算費用、耗時、狀態、金鑰來源、關聯類型、關聯編號、請求編號、紀錄編號。

11. 背景行為與外部依賴

類型 內容
寫入 AI 閘道每次呼叫(含被擋下)寫一筆;稽核寫入不掛業務交易,業務回滾不會吃掉紀錄
清理 每日排程清空到期明文、刪除超過保留天數的整筆紀錄

12. 邊界情況與已知坑

  1. 看不到原文是設計:要追某次對話內容,只能靠請求編號對後端 log,或租戶先開完整保留。
  2. 金鑰來源兩頁用同一組值:兩頁三個選項定義相同;key_source 為 NULL(解不到金鑰)的呼叫只在「全部」出現。
  3. 儀表板一次生成兩筆:ai-dashboard.select 與 ai-dashboard.layout 各一筆,彙總表把它們收在同一列可展開。

13. 開發與驗證

  • 導航路徑:系統管理 › AI 用量(/system/ai-call-log)
  • 前置資料:用 AI 小幫手 送幾則訊息(含會被擋的),再來看明細與彙總。
  • 相關文件:AI 額度、FR-122 設計(docs/features/FR-122-2609-ai-gateway-and-sandbox/design.md)。