FDE 面試準備指南(四十一):RKK 實戰——分散式 AI 系統的故障排查:結構化診斷框架與五種常見失效模式

「AI 系統出問題了」不是問題描述,是症狀描述。
在沒有找到根因之前,任何修復都是猜測。
結構化的故障排查不是把所有可能都試一遍,
而是用最少的資訊快速縮小到一個節點。


面試情境

面試官:「你們的 AI 客服系統,今天早上 9 點開始,客戶回報:系統變慢了,有時候會給出奇怪的答案。你不在現場,只能遠端處理。請一步一步說明你的排查思路,以及你平時會怎麼設計可觀測性來讓這類問題更快被找到。」


一、AI 系統故障排查的特殊性

傳統系統 vs AI 系統的故障特性對比:

  維度              傳統系統                   AI 系統
  ──────────────────────────────────────────────────────────────
  確定性            相同輸入 = 相同輸出          LLM 輸出有隨機性,問題可能間歇出現
  錯誤信號          明確 Error Code(500/404)   品質問題沒有 Error Code,只有「感覺不對」
  根因數量          通常在代碼或配置             分佈在:模型、Retrieval、Tool、基礎設施
  「正確」定義       有明確的正確答案             需要評估,不是二元對錯
  ──────────────────────────────────────────────────────────────

最重要的 AI 特有洞察:

  ┌──────────────────────────────────────────────────────────────┐
  │  Retrieval 失敗 → 「奇怪的答案」                               │
  │                                                              │
  │  Vector Search 返回 0 個結果                                 │
  │      ↓                                                       │
  │  LLM Context 是空的                                           │
  │      ↓                                                       │
  │  LLM 沒有 Context,靠「自己的知識」猜測                        │
  │      ↓                                                       │
  │  症狀:「答非所問」「答案不基於我們的資料」                    │
  │  Error Log:沒有任何錯誤  ← 這就是難以發現的原因              │
  │                                                              │
  │  只有 Trace 才能發現:                                        │
  │  vector_search Span → result_count=0(返回 0 結果)           │
  └──────────────────────────────────────────────────────────────┘

三個常見的排查誤區:

  誤區 1:「LLM 模型一定有問題」
           → 不一定。延遲問題通常是基礎設施;品質問題可能是 Retrieval 失敗

  誤區 2:「昨天還好,一定是昨晚的部署造成的」
           → 不一定。流量模式改變(如特定類型查詢增多)也能觸發潛在問題

  誤區 3:「重啟一下試試」
           → 可能暫時緩解(Cold Start 問題除外),但根因沒找到必定再發

二、三個可觀測性成熟度階段

╔══════════════════════════════════════════════════════════════╗
║  Phase 1:基礎可觀測性(POC / 初期上線)                       ║
║  「能知道系統壞了」                                            ║
╚══════════════════════════════════════════════════════════════╝

  元件:
  ├── 結構化日誌(JSON 格式,帶 timestamp、level、service 欄位)
  ├── 基本 Metrics(Error Rate、P50 Latency、Uptime)
  └── 簡單 Alert(Error Rate > 5% → 發 Email)

  能解決的問題:
  ├── 「系統是不是掛了?」(Uptime 告警)
  └── 「有沒有大量錯誤?」(Error Rate 告警)

  無法解決的問題:
  ├── 「哪個 Step 慢?」(沒有 Trace)
  └── 「品質退化了嗎?」(沒有 Eval 指標)

╔══════════════════════════════════════════════════════════════╗
║  Phase 2:生產級可觀測性(正式上線後)                          ║
║  「能知道系統為什麼慢,慢在哪裡」                               ║
╚══════════════════════════════════════════════════════════════╝

  新增元件(在 Phase 1 基礎上):
  ├── Distributed Tracing(OTel + Cloud Trace)
  │   每個 LLM 呼叫、Tool 呼叫、Vector Search 都有獨立 Span
  ├── 完整 Metrics 儀表板
  │   P50/P95/P99 延遲、Token 消耗趨勢、快取命中率、Error Rate by type
  ├── 告警精細化
  │   P95 > 5s 持續 5 分鐘 → PagerDuty
  │   Error Rate > 1% 持續 2 分鐘 → Slack
  └── 日誌結構化增強(加入 trace_id,可與 Trace 關聯)

  能解決的問題:
  ├── 「哪個 Span 是延遲瓶頸?」(瀑布圖)
  ├── 「哪個 Tool 最常失敗?」(tool.success=false 的 Span 統計)
  └── 「Token 在哪裡被消耗?」(input_tokens Span Attribute)

╔══════════════════════════════════════════════════════════════╗
║  Phase 3:SLO 驅動的可觀測性(企業級)                          ║
║  「能預測系統什麼時候會壞,並主動防止」                          ║
╚══════════════════════════════════════════════════════════════╝

  新增元件(在 Phase 2 基礎上):
  ├── SLO 定義與 Error Budget 追蹤
  │   SLO:P95 < 5s,99% 的 30 天窗口內
  │   Error Budget:允許 1% = 432 分鐘/月 的違規
  ├── Shadow Eval Pipeline(線上品質監控)
  │   3% 流量自動評估 Faithfulness + Safety
  │   7 日移動平均低於閾值 → 告警
  ├── 容量預測(Capacity Planning)
  │   基於流量趨勢預測何時需要升級
  └── Anomaly Detection
      異常流量模式(如特定查詢類型突然增多)主動告警

  能解決的問題:
  ├── 「Error Budget 還剩多少?」(決定是否可以部署新功能)
  ├── 「品質是否在緩慢退化?」(Shadow Eval 趨勢)
  └── 「容量什麼時候會到瓶頸?」(Capacity Planning)

三、五步驟結構化診斷框架

步驟 1:釐清症狀(Clarify Symptoms)|目標時間:2 分鐘

  必問六個問題(把模糊描述轉化為可測量指標):

  問題              目標                         示例回答
  ──────────────────────────────────────────────────────────────
  「多慢?」         P50/P95/P99 的具體數字        「P95 從 3s 升到 12s」
  「多奇怪?」       品質問題的具體類型             「答非所問、沒有引用我們的資料」
  「什麼時候開始?」 精確時間點,對應部署記錄       「09:00,昨晚 20:00 有部署」
  「影響範圍?」     全部用戶 or 特定場景           「所有查詢都有問題」
  「頻率?」         100% or 間歇性                「每次都這樣」
  「最近有變化?」   部署、資料更新、流量異常       「昨晚更新了 RAG 索引」
  ──────────────────────────────────────────────────────────────
  目標:把「系統很慢,答案很奇怪」轉化為:
  「從 09:00 開始,P95 延遲從 3s 升到 12s,
   所有用戶都有,答案品質差(答非所問),
   昨晚 20:00 更新了 RAG 索引。」

步驟 2:確認可觀測性資料(Check Observability Data)|目標時間:3 分鐘

  按順序看(不要跳步):

  ①  Metrics Dashboard(1 分鐘)
      確認問題確實存在(不只是用戶主觀感受)
      找到問題開始的精確時間點
      看哪個 Metrics 異常:P95 Latency?Error Rate?Throughput?

  ②  Trace 瀑布圖(2 分鐘,看 3-5 條問題請求)
      找哪個 Span 佔了最多時間
      看 vector_search 的 result_count(返回幾個結果?)
      看 LLM Span 的 input_tokens 和 finish_reason

  ③  Logs(有針對性,不是 grep 全部)
      在問題開始的時間點,有沒有新的 Error Type?
      有沒有 Warning 訊息(如 vector_search result_count=0)?

步驟 3:建立假說(Form Hypotheses)|目標時間:1 分鐘

  基於步驟 2 的發現,提出 2-3 個最可能的假說
  優先選能快速驗證的假說(不是最可能的,而是最容易驗證的)

步驟 4:測試假說(Test Hypotheses)|目標時間:5-15 分鐘

  快速測試(< 1 分鐘):直接呼叫疑似問題的服務,測一個標準查詢
  比較測試:今天的 Trace vs 昨天的 Trace,找差異
  隔離測試:繞過疑似元件(用 Mock 替代),看症狀是否消失

步驟 5:根因確認與修復(Fix and Verify)

  在 Staging 環境驗證修復方案(不要直接在 Production 試)
  修復後,確認 Metrics 回到正常水位(數字說話,不是「感覺好了」)
  寫 Post-Mortem:根因、時間線、影響範圍、預防措施

四、症狀分類矩陣

症狀 → 最可能根因 → 第一步看什麼:

  ┌──────────────┬─────────────────────────────┬────────────────────────┐
  │  症狀         │  最可能根因(按概率排序)      │  第一步看的資料         │
  ├──────────────┼─────────────────────────────┼────────────────────────┤
  │  P95 延遲     │  1. Vector DB Cold Start    │  Trace 瀑布圖           │
  │  突然升高     │  2. 外部 API 變慢(特定時段) │  vector_search Span 時長│
  │              │  3. Context Window 膨脹      │  LLM input_tokens 趨勢 │
  │              │  4. Cold Start(Scale-Out)  │                        │
  ├──────────────┼─────────────────────────────┼────────────────────────┤
  │  Error Rate  │  1. 外部 API 故障/Rate Limit  │  Error Log error_type  │
  │  升高         │  2. LLM API 配額耗盡          │  HTTP Status 分佈圖    │
  │              │  3. Token 超限(輸入太長)    │  LLM input_tokens 峰值 │
  │              │  4. DB 連接數耗盡             │                        │
  ├──────────────┼─────────────────────────────┼────────────────────────┤
  │  品質退化     │  1. Retrieval 失敗(result=0)│  Shadow Eval 分數趨勢  │
  │  答案奇怪     │  2. Embedding Model 版本不一  │  vector_search         │
  │              │  3. LLM 模型版本靜默更新      │  result_count 分佈     │
  │              │  4. Knowledge Base 資料過期   │                        │
  ├──────────────┼─────────────────────────────┼────────────────────────┤
  │  間歇性錯誤  │  1. 外部依賴特定時段不穩定    │  錯誤的時間分佈         │
  │              │  2. Memory Leak → OOM 重啟   │  是否有規律?(每小時?)│
  │              │  3. Race Condition           │  服務重啟記錄           │
  ├──────────────┼─────────────────────────────┼────────────────────────┤
  │  對話記憶     │  Session State 配置問題      │  Session 儲存           │
  │  消失         │  Scale-Down / Scale-Out      │  讀寫成功率             │
  │              │  Redis 連接中斷              │  服務重啟時間點          │
  └──────────────┴─────────────────────────────┴────────────────────────┘

五、診斷決策樹

AI 系統故障的診斷決策樹:

  收到故障報告
       │
       ▼
  【釐清:是延遲問題、品質問題、還是兩者?】
       │
       ├──→ 只有延遲問題(答案正常,但很慢)
       │         │
       │         ▼
       │    【打開 Trace 瀑布圖,找最長 Span】
       │         │
       │         ├──→ vector_search 最長
       │         │         │
       │         │         ├──→ 持續高延遲 → Vector DB 效能問題(索引大小、配置)
       │         │         └──→ 間歇性尖峰 → Cold Start → 設定 min-instances
       │         │
       │         ├──→ llm.generate 最長
       │         │         │
       │         │         ├──→ input_tokens 異常多 → Context 膨脹或對話 History 太長
       │         │         └──→ input_tokens 正常 → LLM API 本身變慢(查 Status Page)
       │         │
       │         └──→ tool.call 最長
       │                   │
       │                   └──→ 外部 API 問題(查 API Status Page 或直接呼叫測試)
       │
       └──→ 品質問題(答案奇怪、答非所問)
                 │
                 ▼
            【看 Trace 的 vector_search result_count】
                 │
                 ├──→ result_count = 0(搜尋無結果)
                 │         │
                 │         ├──→ 最近有部署 Embedding Model 更新?
                 │         │         └──→ 是 → Embedding Model 版本不一致 → 降回舊版
                 │         │
                 │         └──→ 沒有更新 → 索引損壞或資料不足 → 檢查 Vector DB 健康狀態
                 │
                 └──→ result_count > 0(有找到文件,但答案還是奇怪)
                           │
                           ├──→ 找到的文件相關嗎?(抽樣幾條 Trace 看 retrieved_docs)
                           │         └──→ 不相關 → Retrieval 精確度問題 → 檢查 Embedding 品質
                           │
                           └──→ 文件相關,但 LLM 沒有正確使用
                                     │
                                     ├──→ LLM 模型版本有沒有靜默更新?
                                     └──→ Prompt 版本有沒有變動?

六、五種 AI 系統常見失效模式

失效模式 1:Vector DB Cold Start(冷啟動延遲)

  ┌──────────────────────────────────────────────────────────────┐
  │  症狀:每隔一段閒置後的第一個請求極慢(10-50x 正常延遲)       │
  │  之後第二個、第三個請求恢復正常                                │
  └──────────────────────────────────────────────────────────────┘
  
  特徵信號(Trace 中可見):
  vector_search Span 有規律的尖峰(不是持續高延遲):
  
  時間軸:
  08:00  req_1: vector_search = 8,500ms  ← 冷啟動後第一個請求
  08:00  req_2: vector_search = 180ms    ← 正常(已載入)
  08:00  req_3: vector_search = 175ms    ← 正常
  ...(閒置 30 分鐘)
  08:30  req_4: vector_search = 9,200ms  ← 再次冷啟動
  08:30  req_5: vector_search = 182ms    ← 正常

  根因:Vector DB 實例閒置後進入低功耗狀態,第一個查詢觸發索引重新載入記憶體
  
  修復策略:
  ├── 短期(30 秒):設定 min-instances = 1
  └── 長期:Warmup 排程(每 10 分鐘一個空查詢保持活躍)

─────────────────────────────────────────────────────────────────

失效模式 2:Context Window 累積膨脹

  ┌──────────────────────────────────────────────────────────────┐
  │  症狀:新對話的請求正常,長對話的請求逐漸變慢                  │
  │  重啟 Session 後問題消失                                      │
  └──────────────────────────────────────────────────────────────┘
  
  特徵信號(Trace + Metrics):

  llm.generate Span 的 input_tokens 隨對話輪次增長:
  第 1 輪:input_tokens = 1,200
  第 5 輪:input_tokens = 4,800  (4 倍)
  第 10 輪:input_tokens = 9,500  (8 倍)
  第 15 輪:input_tokens = 14,300(12 倍)→ 接近模型上限

  LLM 延遲 ∝ input_tokens → 第 15 輪比第 1 輪慢 5 倍

  根因:Conversation History 沒有截斷策略,每輪都把所有歷史加入 Context
  
  修復策略:
  ├── 設定 Token Budget(History 超過 30% Budget → 截斷最舊輪次)
  └── 超過 10 輪的 History → 先壓縮成摘要,再繼續對話

─────────────────────────────────────────────────────────────────

失效模式 3:外部 API 間歇性超時(Circuit Breaker 缺席)

  ┌──────────────────────────────────────────────────────────────┐
  │  症狀:Error Rate 升高,但不是 100%;特定時段更嚴重            │
  │  某些查詢等很久才出錯(timeout 後才失敗)                      │
  └──────────────────────────────────────────────────────────────┘
  
  特徵信號:
  tool.call Span:success=false,latency 集中在 timeout 附近(如 5,000ms)
  錯誤有時間規律:09:00-10:00、月底最後一週更嚴重(月結日)

  根因:外部 API(SAP、Oracle)在月結、備份等特定時段負載高,頻繁超時
  
  完整修復策略:

  層次              做法
  ──────────────────────────────────────────────────────────────
  Timeout           每個 Tool 呼叫設定明確 timeout(不用系統預設)
                    SAP=5s, Oracle=3s, 外部API=8s
  ──────────────────────────────────────────────────────────────
  Retry             指數退避重試:1s → 2s → 4s(最多 3 次)
                    不要立刻重試(可能讓 API 更過載)
  ──────────────────────────────────────────────────────────────
  Circuit Breaker   連續失敗 5 次 → 斷路 30 秒
                    30 秒後:放行 10% 探測請求
                    探測成功 → 逐漸恢復;探測失敗 → 繼續斷路
  ──────────────────────────────────────────────────────────────
  Fallback          Circuit 開路時:返回快取的上次結果
                    或告知用戶「xxx 系統暫時不可用,請稍後再試」
  ──────────────────────────────────────────────────────────────

─────────────────────────────────────────────────────────────────

失效模式 4:Embedding Model 版本不一致

  ┌──────────────────────────────────────────────────────────────┐
  │  症狀:Retrieval 品質下降,但 Vector DB 查詢延遲正常           │
  │  Shadow Eval 的 Context Recall 指標突然下降                   │
  │  沒有任何 Error(最難發現的失效模式之一)                       │
  └──────────────────────────────────────────────────────────────┘
  
  根因示意圖:

  建立索引時:   文件 → Embedding Model v1 → 向量 A
  查詢時:       Query → Embedding Model v2 → 向量 B
                                              ↑ 不同向量空間!
  
  餘弦相似度計算(A ⋅ B)= 接近 0(沒有語義關係)
  → vector_search 找不到相似向量 → result_count = 0 或很少
  → LLM 沒有 Context → 靠自己猜

  觸發場景:
  └── 部署時更新了 Query 使用的 Embedding Model 版本,
      但 Vector Index 是用舊版 Model 建立的,忘記同步更新

  修復策略:
  ├── 短期(30 秒):把 Query Embedding 改回舊版(改環境變數)
  └── 長期:建立版本綁定機制
            EMBEDDING_MODEL_VERSION=v1
            INDEX_BUILT_WITH=v1  // 兩個必須一致,CI 檢查

─────────────────────────────────────────────────────────────────

失效模式 5:LLM 模型版本靜默更新

  ┌──────────────────────────────────────────────────────────────┐
  │  症狀:品質緩慢退化,沒有明顯 Error,持續幾天才被注意到        │
  │  Shadow Eval Faithfulness 7 日移動平均緩慢下降               │
  └──────────────────────────────────────────────────────────────┘
  
  特徵信號:
  Faithfulness:0.87 → 0.85 → 0.82 → 0.79(2 週緩慢下滑)
  用戶 Thumbs Down:3% → 4% → 5% → 7%(同步上升)
  但 Error Rate = 0,P95 Latency 正常(沒有任何技術錯誤)
  
  根因:使用了 model alias(如 gemini-pro)而非具體版本號
        服務商靜默更新了模型行為,新版本對現有 Prompt 效果不同
  
  預防策略:
  ├── 使用具體版本號(gemini-2.0-flash-001)而非 alias
  ├── Shadow Eval 7 日移動平均低於 0.83 → 自動告警
  └── 新模型版本升級流程:Staging → Eval Pipeline → Canary 10% → 全量

七、SLO 與 Error Budget 設計

為什麼 SLO 比「我們要系統穩定」更有用:

  「要系統穩定」:沒有量化 → 無法判斷是否可以部署新功能
  SLO + Error Budget:量化 → 工程師和業務可以做出有依據的決策

SLO 定義(AI 系統示例):

  維度              SLO 定義                          測量方式
  ──────────────────────────────────────────────────────────────
  延遲 SLO          P95 < 5s,99% of rolling 30-day   Cloud Trace 分位數
  ──────────────────────────────────────────────────────────────
  可用性 SLO        Availability > 99.5%               Error Rate < 0.5%
  ──────────────────────────────────────────────────────────────
  品質 SLO          Shadow Faithfulness > 0.85(7日MA) Eval Pipeline
  ──────────────────────────────────────────────────────────────

Error Budget 計算:

  延遲 SLO(P95 < 5s,99% of 30 days)的 Error Budget:
  = 30 天 × 24 小時 × 60 分鐘 × 1% 允許違規
  = 432 分鐘/月

  解讀:
  ├── 本月已用 200 分鐘 Error Budget(P95 > 5s 的時間累計)
  └── 剩餘 232 分鐘

Error Budget 驅動的工程決策:

  Error Budget 剩餘        決策
  ──────────────────────────────────────────────────────────────
  > 50%(> 216 分鐘)      可以正常部署新功能(Risk OK)
  25-50%(108-216 分鐘)   謹慎部署(做好 Rollback 準備)
  < 25%(< 108 分鐘)      暫停非緊急部署,專注穩定性
  耗盡(0 分鐘)           凍結所有非緊急部署,全力修復
  ──────────────────────────────────────────────────────────────

  這讓「能不能部署」從爭論變成數據決定:
  Error Budget 耗盡 → 不是 PM 的需求和工程的穩定性之間的爭論,
  而是一個客觀的數字決定優先順序。

Alert 設計(避免 Alert Fatigue):

  原則:不同嚴重度的 Alert 用不同的通知方式

  嚴重度    觸發條件                     通知方式        行動
  ──────────────────────────────────────────────────────────────
  P1        Error Rate > 10% 持續 2 分鐘  PagerDuty 電話  立刻處理
  P2        P95 > 8s 持續 5 分鐘          PagerDuty 訊息  30 分鐘內
  P3        Shadow Faithfulness < 0.83    Slack Channel  工作時間處理
  P4        Error Budget < 25%            週報           Sprint 計劃
  ──────────────────────────────────────────────────────────────
  
  避免 Alert Fatigue 的設計:
  ├── 每個 Alert 必須有明確的 Runbook(收到告警知道第一步做什麼)
  ├── P3/P4 不在非工作時間通知(避免夜間驚擾)
  └── 每季 Alert Review:找出從未觸發的 Alert(可能閾值設錯了)

八、為什麼選 X 不選 Y:可觀測性技術選型

決策 1:OpenTelemetry(OTel)vs 廠商專有 SDK

  ┌──────────────────┬──────────────────────┬──────────────────────┐
  │                  │  OTel(✅ 選擇)       │  廠商專有 SDK         │
  ├──────────────────┼──────────────────────┼──────────────────────┤
  │  廠商鎖定         │  低(標準協議)        │  高(換後端要改代碼) │
  ├──────────────────┼──────────────────────┼──────────────────────┤
  │  後端選擇         │  Cloud Trace、Jaeger、│  只能用指定後端       │
  │                  │  Datadog 等任意選擇   │                      │
  ├──────────────────┼──────────────────────┼──────────────────────┤
  │  社群生態         │  豐富(自動 Instrument)│  依廠商支援          │
  ├──────────────────┼──────────────────────┼──────────────────────┤
  │  AI/ADK 整合      │  ✅(ADK 有 OTel 整合)│  可能支援,看廠商     │
  └──────────────────┴──────────────────────┴──────────────────────┘
  結論:OTel 是業界標準,AI 系統應該優先採用,避免廠商鎖定。

決策 2:Distributed Tracing vs 純 Log 分析

  純 Log 的問題(在 Multi-Agent 系統中):

  Log 1: [09:00:00.001] Agent received query
  Log 2: [09:00:00.050] LLM call started
  Log 3: [09:00:00.002] Sub-Agent A started     ← 時間序列混亂
  Log 4: [09:00:12.300] LLM call completed
  Log 5: [09:00:00.003] Sub-Agent B started
  
  從 Log 重建「哪個 Sub-Agent 佔了多少時間」需要手動 JOIN → 很難
  
  Trace 的優勢:
  ├── 瀑布圖直觀顯示每個 Span 的時間
  ├── 自動計算每個 Span 佔總延遲的比例
  └── 支援跨服務的請求追蹤(Multi-Agent 必要)
  
  結論:有 Multi-Agent 的系統必須有 Distributed Tracing;Log 作為補充。

決策 3:Shadow Eval(線上品質評估)vs 純用戶信號

  純用戶信號的問題:
  ├── 用戶可能不按 Thumbs Down(即使對結果不滿意)
  ├── 用戶回饋有延遲(不是即時品質指標)
  └── 法律場景:「AI 給了錯誤的法律建議」用戶可能不知道是錯的

  Shadow Eval 的優勢:
  ├── 主動評估(不依賴用戶行為)
  ├── 即時(每個請求可選擇性評估)
  └── 可以偵測「看起來合理但實際上錯的」答案(用戶信號偵測不到)
  
  最佳組合:Shadow Eval(客觀、即時)+ 用戶信號(真實感受、補充)

決策 4:P95 vs P50 vs P99 作為主要延遲 SLO 指標

  P50(中位數):50% 的請求這麼快
  └── 問題:如果 50% 請求 < 2s,50% 請求 > 20s,P50=2s 但體驗很差

  P99(99th 百分位):99% 的請求這麼快
  └── 問題:受極端異常值影響大,可能被 1% 的特殊請求拉高,
            讓日常優化難以看出效果

  P95(95th 百分位):最佳平衡點
  └── 代表 95% 用戶的體驗,排除了最極端的 5% 異常請求
      足夠代表大多數用戶,又不被少數異常值主導
  → AI 系統 SLO 推薦 P95 作為主要指標

九、實際診斷流程示例

症狀:「今天早上 9 點開始,系統變慢了,有時候給出奇怪的答案」

步驟 1:釐清症狀(2 分鐘)
  「多慢?」→ P95 從 3s 升到 12s,有時 30s timeout
  「奇怪答案是哪種?」→ 答非所問,好像沒有查到資料就在猜
  「什麼時候開始?」→ 09:00,昨晚 20:00 有更新 RAG 索引
  「影響全部用戶?」→ 是的,所有查詢都有

步驟 2:查可觀測性資料(3 分鐘)
  Metrics:P95 延遲確實從 09:00 開始升高 ✓
  Trace(打開一條慢請求的瀑布圖):
    ├── vector_search Span:9,800ms(正常:200ms)✗
    ├── vector_search result_count:0(!)
    └── llm.generate Span:280ms(正常)✓
  關鍵發現:Vector DB 搜尋返回 0 結果 → LLM 在沒有 Context 下猜測

步驟 3:建立假說(1 分鐘)
  假說 A:昨晚索引重建失敗,索引損壞
  假說 B:Embedding Model 版本不一致(假說 B 更可能,因為有部署)

步驟 4:測試假說(5 分鐘)
  測試:查昨晚 20:00 的部署記錄
  發現:同時更新了 Embedding Model v1 → v2 和 Vector Index 重建
        但 Agent Query Embedding 也被更新到 v2,
        而 Index 是用 v2 重建的... 等等
  
  進一步確認:Vector Index 的重建失敗了(磁碟空間不足),
              Index 還是舊的(v1),但 Query 已經在用 v2
              → Embedding Model 版本不一致 ✓

步驟 5:修復(立即 + 長期)
  立刻(30 秒):把 Query Embedding 改回 v1(改環境變數,重啟 Agent)
  確認:P95 延遲在 5 分鐘內回到 3s;品質指標恢復
  
  長期:
  ├── 擴大 Vector DB 磁碟空間(根本原因)
  ├── 建立 Embedding Model 版本和 Index 版本綁定檢查
  └── 部署 Vector Index 時,先驗證 result_count > 0 才切換流量

十、系統效應

維度              有結構化診斷 + Phase 3 可觀測性    基礎可觀測性(Phase 1)
──────────────────────────────────────────────────────────────────
找到根因時間       3-15 分鐘(Trace 直接指向問題)    1-4 小時(Log 慢慢找)
──────────────────────────────────────────────────────────────────
品質問題發現       主動(Shadow Eval 發現)            被動(用戶抱怨後才知道)
──────────────────────────────────────────────────────────────────
修復有效性         根因確認後修復,不再復發            猜測修復,可能再發
──────────────────────────────────────────────────────────────────
Error Budget       量化決策(Budget 剩餘指導部署)     主觀決策(「我感覺可以上」)
管理
──────────────────────────────────────────────────────────────────
Embed. Model       版本綁定機制,CI 檢查               靠人記得
版本問題           → 不會再發                         → 月月都在犯同樣的錯
──────────────────────────────────────────────────────────────────
可觀測性建設成本   Phase 2:1-2 週工程工時             Phase 1:~3 天
                   Phase 3:3-4 週工程工時              每次 Debug 節省 2-4 小時
──────────────────────────────────────────────────────────────────

十一、面試答題要點

「聽到『慢了』和『奇怪的答案』,我的第一反應是:這是兩個獨立問題,還是同一個根因?我不會同時追兩個方向。AI 系統有一個特殊的診斷模式:品質問題的根因往往是 Retrieval 失敗(vector_search result_count=0),而不是 LLM 本身的問題——LLM 在沒有 Context 的情況下靠自己猜,症狀是「答非所問」,但 Error Log 完全沒有錯誤,只有 Trace 才能發現。

診斷流程:五步驟——釐清症狀(2 分鐘,把模糊描述轉化為具體數字)→ 查可觀測性資料(3 分鐘,先 Metrics 確認問題存在,再 Trace 瀑布圖定位到哪個 Span)→ 建立假說 → 測試假說 → 確認根因後修復並用指標驗證。

可觀測性設計:我會按三個階段推進。Phase 1(上線前必備):結構化日誌 + 基本告警。Phase 2(正式上線後):OTel Distributed Tracing,每個 LLM 呼叫、Tool 呼叫、Vector Search 都有獨立 Span,帶 result_count、input_tokens、finish_reason 等 Attribute。Phase 3(企業級):SLO + Error Budget,讓部署決策量化,Shadow Eval 主動監控品質退化。

為什麼選 OTel 不選廠商專有 SDK:OTel 是業界標準,換 Trace 後端不需要改代碼。為什麼選 P95 不選 P50 或 P99:P95 在代表大多數用戶和排除極端異常值之間最平衡,是 AI 系統 SLO 的最佳指標。」


系列導覽:
(四十)AI 系統的 PII 保護:資料脫敏與合規稽核
(四十二)顧問技能:從客戶對話挖掘真實需求到 POC 範圍定義

Yen

Yen

Yen