AI 用量(AI Usage)¶
功能群:系統管理|選單位置「系統管理 › AI 用量」
事實基準:2026-09-30 從 FE
src/views/ai-call-log/(AiUsagePage.vue、AiUsageSummary.vue、AiCallLogList.vue)+ BEapi/ai_call_log/、app/ai_call_log/、infra/ai_call_log/、common/code/ai_call_log_error_code.py+ migrationscripts/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.jsondump 內,欄位以 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. 邊界情況與已知坑¶
- 看不到原文是設計:要追某次對話內容,只能靠請求編號對後端 log,或租戶先開完整保留。
- 金鑰來源兩頁用同一組值:兩頁三個選項定義相同;
key_source為 NULL(解不到金鑰)的呼叫只在「全部」出現。 - 儀表板一次生成兩筆:
ai-dashboard.select與ai-dashboard.layout各一筆,彙總表把它們收在同一列可展開。