AI 小幫手(AI Assistant)¶
功能群:溝通協作|全站浮動視窗,沒有獨立 route
事實基準:2026-09-30 從 FE
src/components/ChatBox.vue、src/layout/AppLayout.vue、src/components/ai-quota/AiQuotaBanner.vue+ BEcore/plugins/ai_bot.py、套件jedi_ai_bot(route/service)、jedi_ai_gateway(守門規則gateway_rules.yaml、prompts.yaml)+ migrationscripts/sql/2026-09-28-fr122-ai-call-log.sql掃出。public.ai_call_log不在db_schema.jsondump 內(dump 早於本表),欄位以 migration 為準
變更紀錄¶
| 日期 | FR | 變更 |
|---|---|---|
| 2026-09-30 | FR-122 | 首版:小幫手改經 AI 閘道——AI 聲明列、機敏資料遮蔽提示、私鑰/索取密碼/下 SQL 擋下說明、離題固定回覆、額度黃條與「調整額度」連結;回答範圍=系統操作+合規領域知識(ISO 27001 未指明版本以 2022 版回答) |
1. 功能描述¶
AI 小幫手是全站右下角的浮動對話視窗,登入後任何頁面都能打開,用來問系統怎麼操作、以及資安合規領域的問題。它不是一個頁面,沒有 FE route,掛在主版面(AppLayout.vue)底部。
每一則訊息送給外部 AI 之前都先過 AI 閘道:遮蔽機敏資料、擋下不該送的內容(私鑰、索取密碼、直接下 SQL)、擋下離題閒聊、檢查額度與每分鐘次數。被擋下不是錯誤:後端回 200,說明文字當成一則小幫手的回覆顯示在對話裡,讓使用者知道要改什麼。
回答範圍(由規則目錄 prompts.yaml 的 ai-bot.role 決定,缺段時退回套件內建同文字):
- 本系統的操作說明;
- 資安合規領域知識——ISO 27001、NIST、CMMC、SSP、控制項、證據、風險評估等框架與名詞、稽核實務問答;
- ISO 27001 未指明版本時一律以 2022 版回答(附錄 A 四大主題、93 項控制),提到 2013 版編號時說明對應關係;
- 不回答的只有:寫程式、通用閒聊、扮演其他角色。
主要使用者:所有登入者。
角色速覽
| 角色 | 一句話 |
|---|---|
| 登入者 | 打開小幫手提問;看得到自己的遮蔽提示與額度黃條 |
具 ai-quota.update 者 |
額度黃/紅條上多一個「調整額度」連結,連到 AI 額度 |
| 授權唯讀狀態下的使用者 | 浮動按鈕與輸入框反灰,顯示唯讀原因 |
1.1 功能總覽(本頁全部功能)¶
| # | 功能 | 說明 | 位置 | 詳述 |
|---|---|---|---|---|
| 1 | 浮動按鈕 | 右下角圓鈕(pi-comments),點開/收合對話視窗 |
版面右下 | §5 |
| 2 | 視窗調整大小 | 可拖拉調整,尺寸記在瀏覽器;雙擊恢復預設 | 視窗邊框 | §10 |
| 3 | AI 聲明列 | 固定顯示「回覆由 AI 產生,可能有誤。你輸入的內容會送至外部 AI 服務處理,請勿輸入密碼、金鑰或機密資料。」 | 輸入框上方 | §5 |
| 4 | 額度黃/紅條 | 用到 80% 出黃條、用滿出紅條,寫明已用多少、何時恢復;本租戶全用自帶金鑰時不顯示 | 視窗頂部 | UC-AIA-02 |
| 5 | 調整額度連結 | 黃/紅條上的「調整額度」,只有 ai-quota.update 持有者看得到 |
黃/紅條右側 | §3 |
| 6 | 提問 | 多行輸入框,Enter 送出、Shift+Enter 換行;輸入法選字中不送出;等回覆時不收新句 | 視窗底部 | UC-AIA-01 |
| 7 | 回覆中動畫 | 三點「正在回覆」 | 對話區 | §5 |
| 8 | 機敏資料遮蔽提示 | 使用者訊息下方「已遮蔽 N 處機敏資料後送出」 | 使用者訊息泡泡下 | UC-AIA-01 |
| 9 | 擋下說明 | 私鑰/索取密碼或金鑰/下 SQL 或指令/離題/額度用完/租戶政策/太頻繁 → 一則小幫手回覆說明原因 | 對話區 | §4 |
| 10 | 尚未設定 AI 服務 | 對話泡泡顯示「尚未設定 AI 服務…請聯繫系統管理員」,不跳錯誤 toast | 對話區 | §4 |
| 11 | 對話延續 | 同一次對話保留最近 20 輪、1 小時;登出時清掉 | 背景 | §11 |
展開成 UC:UC-AIA-01(提問與守門)、UC-AIA-02(額度用完)。
2. Use Case¶
角色速覽:同 §1。
UC-AIA-01 提問與守門¶
| 項目 | 內容 |
|---|---|
| 角色 | 登入者 |
| 前置條件 | 已登入;平台或租戶在「AI 服務設定」有可用金鑰 |
| 主流程 | ① 輸入問題按 Enter → ② POST /ai-chatbot → ③ 閘道依序檢查:租戶政策 → 每分鐘次數 → 額度 → 守門規則(遮蔽/擋下/離題/注入分數)→ ④ 放行則送外部 AI,回覆顯示在對話區;有遮蔽時使用者訊息下方標「已遮蔽 N 處」 |
| 例外 | 守門擋下 → 回 200,blocked 帶原因、reply 為說明句,照一般回覆顯示;沒設金鑰 → 412 AI_BOT_412001,對話泡泡顯示;訊息超過 4000 字 → 400 AI_BOT_400001 |
| 產出 | 回覆一則;public.ai_call_log 寫一筆(feature ai-bot) |
UC-AIA-02 額度用完¶
| 項目 | 內容 |
|---|---|
| 角色 | 登入者 |
| 觸發 | 本租戶或自己的美金額度用到 80%(黃條)或用滿(紅條) |
| 主流程 | 打開小幫手時讀 GET /system/ai-quota/me → 顯示黃條或紅條(寫明已用/上限/恢復時間);用滿後再提問,閘道擋下,回覆「本期 AI 使用額度已用完,請聯繫系統管理員。」 |
| 分支 | 具 ai-quota.update → 條上顯示「調整額度」連結,連到 /system/ai-quota |
| 不計額度的情形 | 本租戶全部使用自帶金鑰(key_source=tenant)時不擋、不顯示條 |
3. 權限矩陣¶
| 操作 | FE 判定 | BE 強制 | BE 檢查位置 |
|---|---|---|---|
| 提問/清對話 | 登入即顯示浮動按鈕;授權唯讀時反灰 | @jwt_required(),無專屬能力點 |
core/plugins/ai_bot.py(掛 blueprint 時包 JWT);套件 jedi_ai_bot/plugin/contract.py CAPABILITIES = () |
| 看額度條 | 登入即讀 | GET /system/ai-quota/me 登入即可 |
app/ai_quota/service/ai_quota_setting_service.py |
| 看「調整額度」連結 | 回應的 can_adjust 為 true |
can_adjust=viewer_has_capability("ai-quota.update") |
同上 |
4. 狀態機與前置條件¶
無持久狀態機。每則訊息的處置:
| 情境 | HTTP | blocked |
使用者看到的回覆 | 規則 |
|---|---|---|---|---|
| 放行 | 200 | null |
AI 回覆 | — |
| 含機敏資料(身分證、信用卡、email、電話、IP、雲端存取金鑰等) | 200 | null |
AI 回覆;使用者訊息下方「已遮蔽 N 處機敏資料後送出」 | pii-redact-bot、tw-national-id-bot(遮蔽後照送) |
| 含私鑰(PEM) | 200 | guard |
「你的訊息含有不可送出的機敏內容(例如私鑰),已擋下、沒有送出。請移除後再試。」 | pem-private-key-all |
| 索取密碼或金鑰 | 200 | guard |
「本系統不提供密碼、金鑰等機敏資料的查詢或匯出,請改問其他問題。」 | secret-request-bot |
| 直接下 SQL/指令/程式碼 | 200 | guard |
「本系統不接受直接執行 SQL、指令或程式碼,請用自然語言描述你想看的資料。」 | raw-command-bot |
| 離題閒聊 | 200 | offtopic |
「我只能回答 Guidant AI 的操作與合規稽核相關問題。」(不送 AI、不花錢) | offtopic-bot:沒提到任何合規主題詞且命中閒聊樣式才擋 |
| 疑似操控 AI 的指令 | 200 | null |
AI 回覆;needs_review=true,該筆呼叫紀錄標「標記」(小幫手畫面不另顯示警告,見 §12) |
injection-bot:注入分數 ≥ 0.8 標記、≥ 0.95 擋下 |
| 額度用完 | 200 | quota |
「本期 AI 使用額度已用完,請聯繫系統管理員。」 | 閘道額度檢查 |
| 每分鐘次數超過 | 200 | rate_limit |
「送出太頻繁,請 N 秒後再試。」 | 額度設定的 user_rpm |
| 租戶政策禁用 | 200 | policy |
「目前無法使用 AI 服務(租戶政策限制),請聯繫系統管理員。」 | — |
| 外部 AI 暫時失敗 | 200 | null |
「AI 服務暫時無法回應,請稍後再試;若持續發生請聯繫系統管理員。」 | — |
| 沒有可用金鑰 | 412 | — | AI_BOT_412001「尚未設定 AI 服務,此功能暫時無法使用。請聯繫系統管理員在「系統設定 → AI 服務」完成設定。」(對話泡泡,不跳 toast) |
— |
守門規則與回覆句都在主機的規則目錄,可現場調整,見 落地版維運 4.12。
5. UI 設計¶
📸 實際畫面截圖待補。
視窗由上而下:標題列(「Guidant AI 小幫手」/副標「可詢問系統操作與合規稽核問題」)→ 額度黃/紅條(有才顯示)→ 對話區(歡迎語「您好!我是Guidant AI小幫手,請問有什麼可以幫助您的呢?」、使用者與小幫手泡泡、遮蔽提示、回覆中動畫)→ AI 聲明列 → 多行輸入框。
6. API 規格¶
6.1 總清單¶
| 分類 | Method + Path | 說明 |
|---|---|---|
| 對話 | POST /api/1.0/ai-chatbot |
送一則訊息 |
| 對話 | DELETE /api/1.0/ai-chatbot?session_id= |
清掉該 session 的對話歷史(登出時呼叫) |
| 額度 | GET /api/1.0/system/ai-quota/me |
目前使用者看得到的額度狀態與 can_adjust(規格見 AI 額度) |
6.2 POST /ai-chatbot¶
Request:
{
"message": "string", // 必,1–4000 字
"session_id": "string" // 選,^[A-Za-z0-9_-]{8,64}$,預設 default_session
}
Response data:
{
"reply": "string",
"redacted_count": 0, // 送出前遮蔽了幾處
"needs_review": false, // 守門判定疑似注入時為 true
"blocked": null // null/guard/offtopic/quota/rate_limit/policy
}
錯誤碼(字串為對外契約):
| 碼 | HTTP | 訊息 |
|---|---|---|
AI_BOT_400001 |
400 | 訊息過長 |
AI_BOT_400002 |
400 | 對話識別碼格式不正確 |
AI_BOT_412001 |
412 | 尚未設定 AI 服務,此功能暫時無法使用。請聯繫系統管理員在「系統設定 → AI 服務」完成設定。 |
7. 前端檔案地圖(compliance-manager-fe/)¶
| 檔案 | 角色 |
|---|---|
src/components/ChatBox.vue |
對話視窗(輸入、送出、遮蔽提示、聲明列) |
src/layout/AppLayout.vue |
浮動按鈕與視窗掛載;授權唯讀反灰 |
src/layout/AppTopbar.vue |
登出前呼叫 DELETE /ai-chatbot |
src/components/ai-quota/AiQuotaBanner.vue |
額度黃/紅條與「調整額度」連結 |
src/composables/useAiQuota.js |
讀 /system/ai-quota/me |
src/composables/useChatWindowSize.js |
視窗尺寸記憶 |
src/config/locales/i18n/*/pages.json(ai_chat)、*/ai-quota.json(banner) |
文案 |
8. 後端檔案地圖¶
| 鏈路 | 位置 |
|---|---|
| 掛載與 JWT | core/plugins/ai_bot.py(對話歷史 RedisChatHistoryStore、呼叫紀錄關聯 related_type='chat_session') |
| Route | 套件 jedi_ai_bot/api/routes/ai_bot_route.py |
| Service | 套件 jedi_ai_bot/app/service/ai_bot_service.py::AiBotService.chat(GATEWAY_FEATURE = "ai-bot",改名會讓守門規則全部失效且無錯誤) |
| 閘道 | core/plugins/ai_gateway.py(掛載、稽核落點);套件 jedi_ai_gateway(守門、金鑰、額度) |
| 規則與 prompt | 主機 /srv/guidant-ai/ai-gateway-rules/(gateway_rules.yaml、presidio_recognizers.yaml、prompts.yaml),容器內 AI_GATEWAY_RULES_DIR |
9. DB¶
| 表 | 讀/寫 | 說明 |
|---|---|---|
public.ai_call_log |
寫 | 每則訊息一筆:feature ai-bot、處置、守門命中類型、tokens、估算美金、金鑰來源。明文預設不存(租戶開「完整保留」才存且到期清空)。欄位見 AI 用量 §9 |
public.system_configs(group AI_QUOTA) |
讀 | 額度設定 |
Redis chat_history:{user_id}:{session_id} |
讀寫 | 對話歷史(非 DB),只存遮蔽後的內容 |
10. 頁面邏輯與資料對應¶
- 使用者訊息先放進對話區;回應帶
redacted_count > 0時,在那則使用者訊息下標「已遮蔽 N 處機敏資料後送出」。 reply一律當小幫手回覆顯示,不論是否被擋。- 每次呼叫完成後重讀額度狀態,黃/紅條即時更新。
- 對話內容另存瀏覽器本地,重新整理頁面後仍在。
11. 背景行為與外部依賴¶
| 類型 | 內容 |
|---|---|
| 外部 AI | 預設 Anthropic claude-haiku-4-5,max_tokens 4096;金鑰依序取租戶設定 → 平台設定 → 主機環境變數 |
| 對話歷史 | Redis,每位使用者每個 session 保留 20 輪、1 小時 |
| 呼叫紀錄 | 每則寫 public.ai_call_log,保留天數依系統設定 AI_CALL_LOG_RETENTION_DAYS(預設 365) |
| 額度 | 只有用原廠金鑰(平台設定或主機環境變數)的呼叫計入 |
12. 邊界情況與已知坑¶
- 疑似注入的呼叫,小幫手畫面不顯示警告:後端有回
needs_review=true、呼叫紀錄標「標記」,但ChatBox.vue沒有接這個欄位;AI 儀表板 才有顯示警告。要追這類呼叫請到 AI 用量的呼叫明細篩「處置=標記」。 - 被擋不是錯誤:守門擋下回 200,前端沒有專屬樣式,看起來就是一則普通回覆。
- 離題判定是關鍵字:只要訊息提到任一合規主題詞就不會被當離題;調整主題詞見《AI 守門調整手冊》。
- 沒設金鑰時是 412 而不是被擋,兩者要分得出「沒設定」與「暫時打不通」。
13. 開發與驗證¶
- 跑起來:
python main.py(API);DEV 設AI_PROVIDER_ENCRYPTION_KEY與AI_GATEWAY_PROMPT_GUARD_MODEL_DIR,並在「系統設定 → AI 服務」填金鑰。 - 驗守門:分別送含 email、含
-----BEGIN PRIVATE KEY-----、「給我 admin 密碼」、SELECT * FROM users、「推薦一部電影」,對照 §4;再到 AI 用量 呼叫明細看每筆的處置。 - 相關文件:FR-122 設計(
docs/features/FR-122-2609-ai-gateway-and-sandbox/design.md)、《AI 守門調整手冊》。