CareerWise 的目標設定與監控:從設計到實作
30 Jul 2026
CareerWise 是一個以 LLM 為核心的職涯諮詢網站,提供履歷健檢、職涯建議與預約諮詢。使用者可以詢問轉職、面試、薪資談判等問題,系統透過知識庫搭配 Groq 的 LLM 來提供 grounded 的建議。在上一篇中,我們從概念面拆解了目標設定與監控模式。這一篇則記錄如何把這些概念真正落實到 CareerWise 中。
現狀:純被動回應
目前 CareerWise 的 Summer 是純被動回應系統:
使用者 → 發問 → Summer → 回答 → 結束
具體問題有六個:
- 無目標概念 — 使用者問什麼就答什麼,不知道「這次想達成什麼」
- 無達成確認 — 對話結束時不知道問題是否被解決
- 無跨對話連續性 — 三天後 Summer 完全忘了之前聊過什麼
- 球員兼裁判 — review agent 跟 Summer 用同一模型,難以發現自身盲點
- 無長期規劃結構 — 「五年內成為 CTO」這類目標只能得到一次性建議
- 無目標可視化 — 使用者的目標分散在對話歷史中,無法一覽
整體架構
新架構在既有的對話流程中嵌入目標相關的環節:
initChat()
├─ 載入最近 2 個 chat
├─ 檢查前一個 chat 是否有未完成 goal → 顯示 proactive prompt
└─ 檢查當前 chat 是否有 goal → 無則顯示 goal input
POST /api/chat
├─ classifyIntent()
├─ classifyTier()
│ ├─ simple → SSE streaming
│ ├─ medium → career chain
│ ├─ planned → plan review
│ ├─ planning → goal decomposition chain (新增)
│ └─ complex → 平行化
└─ 注入 goal context → system prompt
回答後
├─ 顯示 achievement prompt(若存在 goal)
├─ 使用者按 👍 → goal.achieved = true
└─ 使用者按「還要問」→ 繼續
決策項目
共六項設計決策,從基礎的模型配置到上層的 UI 呈現。
Review 模型獨立
問題:reflect.ts 的 reviewAgent() 和 rewriteAgent() 都用 llama-3.1-8b-instant。同一模型同時負責生成和審查,難以發現自身盲點與幻覺。
| 選項 | 內容 | 選擇 |
|---|---|---|
| A) 維持同一模型 | review + rewrite 都用 llama-3.1-8b-instant | |
| B) 不同 prompt 同模型 | review 用更嚴格的 system prompt | |
| C) 不同模型做 review | review 換成 mixtral-8x7b-32768 | ✅ |
選擇 C。B 只能改善語氣差異,無法解決模型本身的盲點。C 讓 review 與 generate 使用不同架構的模型(Mixtral MoE vs Llama dense),兩者的知識邊界與幻覺模式不同,能更有效發現問題。
const REVIEW_MODEL = "mixtral-8x7b-32768" // 不同模型
const REWRITE_MODEL = "llama-3.1-8b-instant" // 維持原模型
Session Goal 設定與儲存
問題:使用者每次對話都從零開始,Summer 不知道「這次想達成什麼」。
| 選項 | 內容 | 選擇 |
|---|---|---|
| A) 只存對話歷史 | 依賴 LLM 從歷史推斷目標 | |
| B) 獨立 goals 集合 | users/{uid}/goals/ 獨立於 chat |
|
| C) 擴充 chat document | users/{uid}/chats/{chatId} 加入 goal 欄位 |
✅ |
選擇 C。goal 與對話生命週期一致:chat 建立時可設 goal,chat 結束時 goal 自然 archive,不需要獨立管理。
// users/{uid}/chats/{chatId} — 新增欄位
{
goal?: {
text: string,
achieved: boolean,
achievedAt?: Timestamp,
createdAt: Timestamp,
smartGoal?: {
specific: string,
measurable: string,
achievable: string,
relevant: string,
timeBound: string
}
},
followUpFrom?: {
chatId: string,
achieved: boolean
}
}
注入後的 system prompt 會包含目標資訊:
你是 Summer — 一位擁有豐富經驗的前端工程師與職涯顧問。
...
使用者的個人檔案:現職:TSMC Principal Engineer,年資:15 年
使用者的偏好:喜歡簡潔回答
使用者的目標:幫我評估該不該轉職
跨 Session 主動追蹤
問題:使用者今天問了「該不該離職」,三天後 Summer 完全忘了。
| 選項 | 內容 | 選擇 |
|---|---|---|
| A) 不追蹤 | 每次從零開始 | |
| B) 被動顯示歷史 | 頁面側邊欄顯示過往目標 | |
| C) 主動問候 | 偵測未完成目標時主動關心 | ✅ |
選擇 C。initChat() 時,檢查前一個 chat 是否有未完成的 goal。若存在,顯示 proactive prompt:「上次聊到…後來有進展嗎?」使用者可回應「有進展」或「還沒」。
SMART 目標框架
問題:使用者常說模糊的目標(「我想變強」),Summer 直接回應,沒有幫助使用者把目標具體化。
| 選項 | 內容 | 選擇 |
|---|---|---|
| A) 不處理 | 直接回答 | |
| B) 被動提供 SMART 模板 | 使用者自行點開 | |
| C) 主動偵測 + 引導 | Summer 主動引導 SMARTify | ✅ |
選擇 C。偵測到模糊目標時,Summer 以結構化提問引導:
使用者:「我想學前端」
→ Summer:「我來幫你把這個目標具體化:
- Specific:你想學到什麼程度?(找工作 / 轉職 / 純興趣)
- Measurable:怎樣算學會?(完成專案 / 拿到 offer)
- Time-bound:希望多久達成?」
長期目標分解(Goal Decomposition Chain)
問題:使用者說「五年內成為 CTO」—— Summer 只能給一次性建議,無法分解為可執行的子目標。
| 選項 | 內容 | 選擇 |
|---|---|---|
| A) 單次回答 | 一次 LLM 呼叫 | |
| B) 提示鏈 3-step | 背景分析 → KB 比對 → 報告 | |
| C) 提示鏈 4-step | SMARTify → 分解 → 排序 → 報告 | ✅ |
選擇 C。在 classifyTier() 中新增 "planning" tier,觸發 4-step chain:
Step 1: SMARTify Goal — 模糊目標具體化
Step 2: Decompose Sub-goals — 拆成 4-8 個子目標(含依賴關係)
Step 3: Priority & Timeline — 安排 3-5 個階段與時程
Step 4: Generate Report — 產出自然語言 roadmap
classifyTier 擴充邏輯:
const PLANNING_KEYWORDS = [
"規劃", "長期", "五年", "十年", "路線", "藍圖",
"目標", "願景", "生涯規劃", "職涯規劃"
]
export function classifyTier(message: string): "simple" | "medium" | "planned" | "planning" | "complex" {
const hasPlanningKeywords = PLANNING_KEYWORDS.some(kw => message.includes(kw))
const isLong = message.length > 30
if (hasPlanningKeywords && isLong) return "planning"
// ... 其餘 tier 邏輯維持不變
}
目標進度儀表板
問題:目標分解完後,使用者沒有地方可以持續追蹤進度。
| 選項 | 內容 | 選擇 |
|---|---|---|
| A) 不顯示 | 只存在後端 | |
| B) 整合進 /memories | memories 頁面加入 goals 區塊 | |
| C) 獨立頁面 + memories 區塊 | 新增 /goals 頁面 |
✅ |
選擇 C。/goals 有完整的目標管理(目標卡片 + 進度條 + 子目標列表),/memories 只放摘要與連結。目標建立後,Summer 在回應中引導使用者前往 /goals 查看完整儀表板,讓使用者知道目標已經被記錄且可以隨時追蹤。
使用者旅程
情境 A:短期目標
Day 1 — Alice 第一次打開 CareerWise:
┌─────────────────────────────────────────────────────┐
│ 🎯 這次想討論什麼? │
│ [我想確定該不該轉職] [開始對話] [跳過] │
└─────────────────────────────────────────────────────┘
Alice:「該不該從金融業轉職到前端工程師?」
→ Summer 回答(system prompt 已注入目標,回答針對轉職評估)
┌─────────────────────────────────────────────────────┐
│ 這個回答有幫助到你嗎? [有 👍] [還要問] │
└─────────────────────────────────────────────────────┘
Alice 按「還要問」→ 繼續對話,直到按「有 👍」完成目標。
情境 B:跨 Session 追蹤
Day 3 — Alice 再次打開 CareerWise:
┌─────────────────────────────────────────────────────┐
│ 上次我們聊到「該不該轉職」,後來有進展嗎? │
│ [有進展] [還沒] │
└─────────────────────────────────────────────────────┘
Alice 按「有進展」:
→ Summer:「太好了!學 HTML/CSS 是很好的開始。今天想聊什麼?」
→ 前一個目標標記為已完成
情境 C:長期目標分解
Bob:「我想五年內成為 CTO」
→ classifyTier → "planning"
→ Summer 先 SMARTify,引導 Bob 把目標具體化
→ Bob 回答後 → 4-step decomposition chain
→ 產出 roadmap 報告(願景目標 → 階段里程碑 → 具體行動 → 時間線)
→ 儲存到 Firestore → /goals 可查看進度

對 UI/UX 的影響
這項設計對 CareerWise 使用者來說,最直接的感受是 Summer 從被動回答變成主動關心。
改變了什麼
對話開始時,使用者看到的不再是空白輸入框,而是一個目標設定卡片:「🎯 這次想討論什麼?」。使用者可以設定這次想達成的目標,或點「跳過」保持原本的自由模式。
每次 Summer 回答後,如果存在目標,下方會出現「這個回答有幫助到你嗎?」的提示。使用者按 👍 表示目標達成,按「還要問」則繼續對話。這個反饋讓 Summer 知道問題是否被解決。
如果使用者沒按 👍 就關閉對話,下次回來時會看到:「上次聊到⋯後來有進展嗎?」。這種跨 session 的關心讓 Summer 感覺有記憶,不只是每次從零開始的陌生人。
目標建立後,Summer 會在回應結尾引導使用者前往 /goals 儀表板查看完整的目標路線圖,讓使用者知道目標已經被記錄且可以隨時追蹤進度。
對長期規劃的支援
當使用者提到「我想五年內成為 CTO」這類模糊目標時,Summer 不再直接給一次性建議,而是先引導使用者把目標具體化(SMART 提問),然後產出結構化的 roadmap。使用者可以在 /goals 頁面看到自己的目標卡片與進度條,隨時追蹤。
使用者的控制權
所有目標相關的 UI 都是 opt-in:goal input 可以跳過、achievement prompt 可以忽略、proactive follow-up 只發生在有未完成目標時。使用者不會被強迫設定目標,但當需要時,Summer 會引導而非直接回答。
已知 UX 風險與解法
| 風險 | 問題 | 解法 |
|---|---|---|
| Achievement prompt 疲乏 | 每次回答後都出現,長期目標(20+ 輪)從關心變干擾 | 連續按 3 次「還要問」後自動隱藏;或偵測密集對話時延後顯示 |
| Goal input 疲乏 | 每次新對話都顯示,連續跳過的使用者覺得多餘 | 跳過次數累計 3 次後自動隱藏,使用者可在 /memories 設定重新開啟 |
| SMART 引導打斷節奏 | 使用者說「我想學前端」,Summer 不回答先問三題 | 引導結尾加一句「先隨便聊聊也行,之後隨時可以設定目標」,讓自由探索不被堵死 |
總結
這次設計將 CareerWise 從純被動回應升級為具備目標設定與監控能力的主動教練系統。對照原本的六個問題:
| 原本問題 | 對應解法 |
|---|---|
| 無目標概念 | Session Goal |
| 無達成確認 | Achievement Prompt |
| 無跨對話連續性 | 跨 Session 追蹤 |
| 球員兼裁判 | Review 模型獨立 |
| 無長期規劃結構 | Goal Decomposition Chain |
| 無目標可視化 | 目標儀表板 |
讓 Summer 不只是回答問題,而是陪使用者一起設定目標、追蹤進度、達成結果。