利用 Agentic Design Pattern 重構 CareerWise — 從單一流程到路由、提示鏈與反思模式

CareerWise 是一個提供履歷健檢、職涯建議與預約諮詢的網站。最初它的 AI 對話功能很單純:不管使用者說什麼,全部丟進同一條生產線處理。這種作法雖然很快就上線了,卻也帶來了三個問題——對簡單的提問浪費 token、對複雜的需求深度不足、以及預約諮詢這種能直接給表單的需求卻還要經過 LLM 流程。

這篇文章記錄 CareerWise 如何逐步導入三種 Agentic Design Pattern - 路由(Routing,含意圖分類與混合路由)、提示鏈(Prompt Chaining)與反思模式(Reflection),將單一的 LLM 呼叫流程,重構成一個具備智慧分流、多步驟分析與品質把關的代理系統。

CareerWise 提供履歷健檢、職涯建議與預約諮詢的網站

階段一:意圖路由(Intent Routing)

原始系統架構

在導入任何設計模式之前,CareerWise 的 AI 對話就是一支單純的 route.ts

POST /api/chat
  └─ 使用者問題
       │
       ├─ 關鍵字搜尋,有出現在知識庫條目中就算匹配
       │
       ├─ 把知識庫內容用字串取代的方式直接嵌入 system prompt,讓 LLM 在生成回覆時「看到」這些參考資料
       │
       ├─ LLM 收到 system prompt + 使用者問題後,一次推理完畢才回傳完整回答
       │
       └─ 回傳 JSON { reply: "..." } 給前端(非串流,HTTP response 只在 LLM 完全生成完畢後才回傳一次)

整個流程是線性的:使用者送出 → API 開始處理 → LLM 花 2-5 秒生成 → 回傳完整 JSON → 前端一次顯示全部文字。

這樣的設計有幾個問題:

Routing

原先這樣的設計會讓所有提問(嗨、改履歷、預約)都走同一條路:知識庫搜尋 → 完整 system prompt → LLM。不需要知識庫的簡單問題,卻還要經過完整的 system prompt,造成了資源浪費,例如:打招呼浪費 1,400 tokens、預約浪費 1,400 tokens,且無法針對不同問題深度處理。

使用者輸入 → 知識庫搜尋 → 同一組 system prompt → LLM → 回覆

改善的方式是加入一個 router,先判斷使用者意圖,再分流到對應的 handler。這樣可以針對不同意圖使用不同的 system prompt、max_tokens 與知識庫搜尋策略。用意圖分流把「嗨 / 預約 / 職涯 / 履歷」分開處理,輕的輕、重的重,不浪費 token。

我們加入了一個 router,先判斷使用者意圖,再分流到對應的 handler:

使用者輸入
    │
    ▼
┌──────────────┐
│  意圖分類器    │ ← 用 LLM 分類,只回傳一個詞
└──────┬───────┘
       │
       ├── greeting   → 不搜知識庫,簡短歡迎,引導提問
       ├── career     → 知識庫搜尋 + 職涯建議專用 prompt
       ├── resume     → 知識庫搜尋 + 履歷分析專用 prompt
       └── booking    → 不呼叫 LLM,直接回傳預約表單連結

分類 prompt 非常簡潔,每次呼叫約 150 ~ 200 tokens:

你是一個分類器。根據使用者訊息只能回應一個詞:greeting / career / resume / booking

- greeting: 打招呼、問候、自我介紹
- career: 職涯問題、轉職建議、學習路線、薪資談判(不含履歷)
- resume: 履歷檢查、履歷修改、履歷建議
- booking: 預約、諮詢、想進一步討論

各 handler 的行為差異如下:

意圖 知識庫搜尋 max_tokens 說明
greeting ❌ 無 80 不搜知識庫,簡短歡迎,引導提問
career ✅ 有 512 知識庫搜尋 + 職涯建議專用 prompt
resume ✅ 有 512 知識庫搜尋 + 履歷分析專用 prompt
booking ❌ 無 0 不呼叫 LLM,直接回傳預約表單連結

單是這個改動,打招呼省下了 80% 以上的 token,預約諮詢更是直接歸零。但只有四種意圖的 LLM 分類還不夠穩定,而且每次路由都要等 LLM 回傳,於是進入了第二階段。

階段二:混合路由(Hybrid Router)

前面的改善會經由 LLM 進行意圖分類,這純 LLM 路由雖然比原本的單一流程好,但仍有兩個痛點:一是每次分類約 200ms 的延遲,二是當 LLM 遇到 rate limit 時,整個路由層直接癱瘓。

CareerWise 參考了 Agentic Design Pattern 中的 Routing 模式,將單一 LLM 判斷改為三層遞迴過濾、三層層層把關。需注意,這仍然是 Routing 模式的一種實作演進,而非全新的設計模式——LLM-based、Rules-based、Embedding-based 並列為路由的四種實作方式,CareerWise 將三者組合為三層架構,以兼顧速度、彈性與容錯:

使用者輸入
    │
    ▼
┌──────────────┐
│  Layer 1     │ ← 規則路由,正則比對
│  Rules       │    零成本、零延遲
└──────┬───────┘
       │ 無匹配
       ▼
┌──────────────┐
│  Layer 2     │ ← 嵌入路由,embedding 比對
│  Embedding   │    ~50ms,語意理解強
└──────┬───────┘
       │ 信心 < 0.7
       ▼
┌──────────────┐
│  Layer 3     │ ← LLM 路由,LLM 判斷
│  LLM         │    模糊案件才呼叫
└──────┬───────┘
       │
       ▼
     Handler

Layer 1:規則路由

用正則表達式比對高確定性的關鍵字。零 token 成本、延遲可忽略:

規則 意圖
/預約|諮詢|約時間/ booking
/嗨|你好|早安|晚安|哈囉/ greeting
其餘 交給 Layer 2

規則層只處理最明確的 case。履歷相關問題不放這裡,因為「幫我看 CV」和「我的 resume 有什麼問題」寫法太多樣,交給嵌入層更準確。

Layer 2:嵌入路由 (Embedding Based Routing)

預先為每個意圖定義 3–5 個範例句,並在系統初始化時先算好它們的向量。當使用者提問時,計算輸入與所有範例的 embedding 餘弦相似度,並取最高分:

greeting: ["你好", "嗨", "早安", "哈囉", "嗨 Summer"]
career:   ["我想轉職", "面試怎麼準備", "怎麼談薪水", "該不該離職", "學習路線規劃"]
resume:   ["幫我看履歷", "履歷怎麼改", "CV 要怎麼寫", "幫我檢查履歷", "我的 resume"]
booking:  ["我想預約", "可以約諮詢嗎", "想進一步討論", "預約一對一"]

這層的優勢在於不需要 LLM 進行沉重的文字生成推理,僅需將輸入向量化後進行純數學計算,大約 50ms 即可完成,且成本極低。此外,它比單純的關鍵字比對更具語意彈性——例如使用者輸入「我想聊聊」,雖然字面上完全沒有「預約」二字,但在語意向量空間中,它會被精準地分類到 booking 意圖。

Layer 3:LLM 路由

當前兩層都無法確定時才呼叫 LLM。這在一般對話中占比不到 20%,比之前每次都要 LLM 分類節省約 80% 的 LLM 路由成本。而且當 LLM 掛掉時,Layer 1 + 2 仍然可以正常運作。

實際流程

「嗨 Summer」
  → Layer 1:規則 /^嗨/ → greeting ✅(零 token,1ms)

「幫我檢查履歷」
  → Layer 1:無匹配
  → Layer 2:嵌入比對 → resume 0.89 ✅(~50ms,零 token)

「我想問關於職涯發展的問題」
  → Layer 1:無匹配
  → Layer 2:嵌入比對 career 0.65 < 0.7(信心度不足)
  → Layer 3:LLM 判斷 → career ✅(~150 - 200 tokens)

層層把關的綜合延遲與成本,遠低於每次提問都直接盲目呼叫單層 LLM。

Layer 方法 延遲 Token 成本 估計命中率 說明
Layer 1 規則 ~1ms 30% 純 Regex 字串匹配
Layer 2 嵌入 ~50ms 零(Hugging Face API) 50% 向量相似度純數學計算
Layer 3 LLM ~200ms ~150 - 200 20% 僅用於處理模糊極端案件

而且有了 graceful degradation——應對災難的情境模擬:當 LLM 遭遇 Outage 或 Rate Limit 時,Layer 1 + 2 仍然可以正常運作,只有模糊問題才會受到影響。Layer 2 是呼叫線上的 Hugging Face API,當 LLM 和 HF API 同時掛掉時,系統的最後防線是直接退回到最不依賴網路的 Layer 1 規則路由。

情境:LLM 掛掉(rate limit / outage) │ Layer 1 ── 規則路由 ── ✅ 正常運作(純 Regex,不依賴任何外部 API) │ Layer 2 ── 嵌入路由 ── ✅ 正常運作(Hugging Face API 呼叫) │
Layer 3 ── LLM 路由 ── ❌ 服務掛了 │ ▼ Handler(無法使用 LLM)

階段三:提示鏈(Prompt Chaining)

履歷健檢與職涯諮詢是較為複雜的功能。原本的做法是單一步驟:使用者貼上履歷 → AI 一次給出建議。這就像請一個人同時做「閱讀理解 + 知識庫搜尋 + 文案撰寫」三份工作,AI 容易在某個環節產生幻覺,而且建議的結構也很不固定。

要怎麼解決呢?分解為三步驟提示鏈。提示鏈的概念是把一個任務拆成多個步驟,每個步驟專注一件事,步驟之間用 JSON 強制交接。這阻斷了錯誤的放大效應——第一步驟的輸出是結構化的 JSON,第二步驟的模型必須在這個結構上工作,無法隨意發散。

單一步骤:
  使用者問 → AI 一次回答 → 容易幻覺、結構鬆散

提示鏈:
  Step 1 (結構化提取) → JSON → Step 2 (知識庫搜尋) → JSON → Step 3 (產出報告)

Step 1 — 結構化提取

不做任何主觀分析,只把履歷原始文字轉成固定的 JSON 格式。這個步驟確保 AI 真的有讀懂履歷結構:

{
  "summary": "一句話總結背景與目標",
  "experience": [
    { "company": "公司名稱", "title": "職稱", "period": "期間", "highlights": ["成就1", "成就2"] }
  ],
  "education": [
    { "school": "學校名稱", "degree": "學位", "major": "主修" }
  ],
  "skills": ["技能1", "技能2"],
  "portfolio": "網址或 null",
  "github": "網址或 null",
  "blog": "網址或 null"
}

Step 2 — 知識庫搜尋

接著,Step 2 會拿 Step 1 的 JSON 去比對知識庫,找出優點與可改善之處,並輸出結構化的分析結果:

{
  "strengths": ["量化成果明確", "技術符合市場需求"],
  "improvements": [
    { "field": "experience.0.highlights", "suggestion": "缺少 STAR 原則描述" }
  ],
  "knowledge_matches": ["引用知識庫中關於履歷撰寫的建議"]
}

Step 3 — 產出報告

根據 Step 2 的 JSON 產出自然語言報告。這個步驟不再進行額外的邏輯推理,只專注於文案渲染,幻覺風險最低。報告結構固定為:優點 → 可改善的地方 → 具體建議 → 下一步行動。

挑戰

目前 career 走的是 SSE streaming——送出後 200ms 就看到第一個字。chain 是 3 次串行 LLM 呼叫,無法 streaming,要等全部跑完(約 3-5 秒的首字延遲(TTFT))才一次顯示。所以實作 chain 後,所有 career 問題都會失去串流體驗,因此做了以下取捨:

career handler 內部微路由
  ├─ 簡單問題 (短問句、單一主題) ──→ 🚀 直走單一 Prompt 流程 + 支援回應速度快、體驗佳 SSE streaming
  ├─ 中等問題 (需結合背景深度分析) → ⛓️ 走三階段提示鏈 (犧牲前段串流,換取更好的品質)
  └─ 複雜問題 (多面向、含決策詞) ─→ 🔀 走 Parallelization 平行化處理 (後續改善計畫)

並不是所有職涯提問都需要使用沉重的提示鏈。使用者如果只是問一句「前端推薦學 Vue 還是 React?」,直接走單一層 Prompt 檢索並串流輸出,體感速度最快;只有當使用者貼入長篇大論、涉及「背景與痛點交叉分析」的中等複雜問題時,系統才會切換到提示鏈軌道。這種分級防禦的思維,讓 CareerWise 在「回應速度快、體驗佳」與「高價值諮詢的嚴謹度」之間,找到了最佳的平衡點。

職涯諮詢提示鏈

類似的思路也可以套用在職涯諮詢上。與履歷檢查相同,步驟之間以 JSON 強制交接,確保結構一致性:

Step 1 — 背景分析(輸出 JSON)
  { "current_role": "前端工程師", "years": 5, "pain_points": ["薪資成長停滯", "不確定該轉管理職還是繼續鑽研技術"] }

Step 2 — 知識庫比對(輸出 JSON)
  {
    "analysis_tags": ["轉職策略", "薪資談判"],
    "gaps": ["缺乏跨團隊協調經驗的論述"],
    "strategic_advice": ["建議先在現職爭取架構主導權,累積筹碼再談判"]
  }

Step 3 — 個人化建議(產出自然語言報告)
  結合背景 JSON + 知識庫比對結果,產出個人化建議

提示鏈的代價是 token 成本變為三倍,回應時間也變長。但對於履歷檢查與職涯諮詢這種高價值場景,品質的提升遠大於成本的增加。

階段四:反思模式(Reflection)

即使是三步驟提示鏈,最後的輸出仍有可能有幻覺。我們需要一道最後的品質防線 - 反思審查器。

反思模式分為兩種實作方式:

  1. Self-Reflection(自我反思):同一個 AI 在產出後以「審查員」角色檢查自己的輸出,優點是實作簡單,但缺點是 AI 可能難以跳出自己的思維盲點。
  2. Producer-Critic 模型:產出者(Producer)與審查者(Critic)分屬不同的角色,使用各自的 system prompt。審查者以全新的視角檢查產出,不被先前的生成邏輯影響,結果更客觀可靠。

CareerWise 採用第二種 Producer-Critic 模型,審查者使用獨立的審查 prompt,與產出者的 system prompt 完全分開。

舉例來說,履歷報告或職涯建議產出後,Critic AI 以「審查員」角色檢查一次輸出。檢查標準有四項:

  1. 是否有事實錯誤或幻覺
  2. 是否給出具體可行的建議,而非空泛的鼓勵
  3. 語氣是否恰當(直接但不失溫暖)
  4. 是否根據使用者的具體情況來回答
Step 1 → JSON → Step 2 → JSON → Step 3 → JSON → 反思 → 輸出
                                           │
                                           └─ 有問題就修正,沒問題才放行

反思模式每次約 100 tokens,只對履歷與職涯等複雜度高的問題觸發。打招呼和預約則直接跳過。

總結

回顧整個重構歷程,架構的演進可以用一張圖總結:

 Before(原始系統)                        After(重構後)
                                                                                
 ┌──────────────┐                    ┌──────────────┐
 │  使用者輸入    │                    │  使用者輸入    │
 └──────┬───────┘                    └──────┬───────┘
        │                                    │
        ▼                                    ▼
 ┌──────────────────┐              ┌──────────────────┐
 │  知識庫關鍵字搜尋   │              │  Layer 1 規則路由 │ ← 1ms,零 token
 └──────┬──────----─┘              └─----────┬─-──────┘
        │                                    │ 無匹配
        ▼                                    ▼
 ┌──────────────────┐              ┌──────────────────┐
 │  system prompt   │              │  Layer 2 嵌入路由  │ ← 50ms,零 token
 │  (萬用同一組)      │              └─────---─┬─────-──┘
 └──────┬─────----──┘                        │ 信心 < 0.7
        │                                    ▼
        ▼                          ┌──────────────────┐
 ┌──────────────────┐              │  Layer 3 LLM 路由 │ ← ~200ms,~150 - 200 tokens
 │  LLM 一次生成     │              └────────┬──────────┘
 │  (max 1024 tok)  │                       │
 └──────┬─────----──┘                       ▼
        │                           ┌──────────────────┐
        ▼                           │    Handler 分流   │
 ┌──────────────┐                   ├──────────────────┤
 │  JSON 回傳    │                   │ greeting  ✂️ 80t  │
 └──────────────┘                   │ career    📚 512t │
                                    │ resume    📚 512t │
 ── 一條路走到底 ──                   │ booking   🔗 0t   │
 不分意圖、浪費 token                  └──────────────────┘
 ❌ 無 streaming(等 LLM 全部跑完)            │
 易幻覺                                       ▼
                                      ┌──────────────────┐
                                      │  簡單職涯問題 ────│ 🚀 SSE streaming
                                      │  (單一 Prompt)   │    200ms 首字
                                      └──────────────────┘
                                            ▼
                                    ┌──────────────────┐
                                    │  提示鏈(履歷用)   │
                                    │  Step 1 → JSON    │
                                    │  Step 2 → JSON    │
                                    │  Step 3 → 報告    │
                                    └────────┬─────────┘
                                             ▼
                                    ┌──────────────────┐
                                    │  反思(Producer-  │
                                    │  Critic 審查)    │
                                    └────────┬─────────┘
                                             ▼
                                    ┌──────────────┐
                                    │  最終輸出     │
                                    └──────────────┘

 ── 三層路由 + 提示鏈 + 反思 ──
 意圖分流、JSON 交接、品質把關

最後總結各階段的實作優先級,按效益與難度排序:

優先級 項目 預期效益 實作難度
1 混合路由(三層) 降低 LLM 呼叫次數,省 token,graceful degradation
2 提示鏈(履歷檢查) 提升分析品質,減少幻覺
3 反思模式 降低高風險回應的幻覺

從單一流程到多層路由、提示鏈與反思模式,每一步的改進都是在 token 成本、回應品質與延遲之間做取捨。這也正是 Agentic Design Pattern 的核心精神——不是盲目地「讓 AI 做更多事」,而是有策略地引導 AI 在正確的地方做正確的事,在資源與效果之間找到最佳的平衡點。


參考資料


CareerWise


Agentic Design Pattern Routing Prompt Chaining CareerWise Intent Routing Embedding Based Routing Reflection AI Agentic AI LLM Design Pattern Architecture