n8n 雙 LLM 路由實作:用 Switch + AI Classifier 把任務派發到 OpenAI 或 Claude
n8n 雙 LLM 路由實作教學:用 Switch + AI Classifier 動態派發任務到 OpenAI 或 Claude,含節點配置、JSON schema 約束、錯誤回退與低信心 fallback,完整實戰範例可直接套到你的 production workflow。
n8n 雙 LLM 路由實作:Switch + AI Classifier 把任務派發到對的模型
n8n 雙 LLM 路由實作是用 Switch 節點搭配 AI Classifier 把不同類型的任務動態派發給 OpenAI 或 Claude,透過分類器先判斷任務、再選最合適的模型,解決同一條 workflow 卻硬塞同一個 LLM 造成品質與成本失衡的問題。
本文是《n8n 雙 LLM 工作流:OpenAI 跟 Claude 什麼時候用哪個?》的實作深度版。如果還沒看過 pillar 文,先回去看 n8n 雙 LLM 工作流方法論 了解整體選型表跟使用情境。本篇直接進 n8n 節點層,把每一條設定攤開來看。
路由實作的核心三件事
跟 LLM 接 API 比起來,「路由」其實是個簡單問題。但如果搞錯抽象層,就會把工作流寫得比應用程式還複雜。先把這三件事釐清:
- 入口統一:所有上游請求進同一個 webhook,不要每個 task type 開不同 endpoint
- 分類層獨立:分類器跟業務邏輯分開,分類錯了不會把資料搞壞
- 模型抽象成 node:OpenAI、Claude 都包成 sub-workflow,主 workflow 只看分支
這三條做好,後續加新模型(Gemini、Mistral、自架 Llama)只是多接一條分支,不用重寫。
範例 workflow 全貌
下面是一個面向客服 / 員工助理的雙 LLM workflow 全貌:
Webhook (POST /api/assist)
↓
Set (整理 prompt 跟 metadata)
↓
OpenAI Chat (gpt-4o-mini, 分類器, Structured Output)
↓
Switch (intent)
├─ "factual_lookup" → Sub-workflow: RAG-Claude
├─ "creative_writing" → Sub-workflow: Claude-Writer
├─ "structured_form" → Sub-workflow: OpenAI-Structured
├─ "small_talk" → Sub-workflow: OpenAI-Mini
└─ default → Sub-workflow: Human-Handoff
↓
Merge (各分支匯流)
↓
Code (套上模板、加上 model 標記)
↓
Respond to Webhook
主 workflow 只負責「分類 + 路由 + 回應」,所有重活塞到 sub-workflow。日後改 Claude prompt 不會動到主流程。
Step 1:分類器節點配置
這一步是雙 LLM 路由的腦。寫好分類器,後面分支才有意義。
Model:gpt-4o-mini(也可換 Claude Haiku)。為什麼不用 Claude?因為 OpenAI 的 Structured Outputs 在 enum 強約束上是業界最穩,分類任務拿這個跑幾乎不會錯誤格式。
System prompt(請替換成你業務的分類規則):
你是任務分類器。讀完使用者訊息後,回傳 intent 與 confidence。
intent 只能是以下之一:
- factual_lookup:查公司文件、SOP、政策
- creative_writing:寫文案、貼文、宣傳稿
- structured_form:填表單、CRM 紀錄、發票
- small_talk:閒聊、問候、無實質需求
confidence 是 0~1 的浮點數。低於 0.7 表示分類不確定。
只回傳 JSON,不要任何前後文。
Response Format(在 OpenAI node 的 JSON Schema 設定):
{
"type": "json_schema",
"json_schema": {
"name": "intent_classification",
"strict": true,
"schema": {
"type": "object",
"properties": {
"intent": {
"type": "string",
"enum": ["factual_lookup", "creative_writing", "structured_form", "small_talk"]
},
"confidence": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"reasoning": { "type": "string" }
},
"required": ["intent", "confidence", "reasoning"],
"additionalProperties": false
}
}
}
strict: true 是關鍵,沒設就可能多吐欄位。additionalProperties: false 也要設,避免 model 自己加新欄位讓下游 Switch 對不上。schema 用法詳見 OpenAI Structured Outputs 文件。
輸入 prompt(n8n expression):
={{ $json.user_message }}
只丟使用者訊息,不要把整段對話歷史塞進來,分類器看一句就夠了,多餘 context 反而干擾。
Step 2:Switch 節點分支
n8n 的 Switch node 用 Mode: Expression,比較欄位填 ={{ $json.message.content.intent }}(路徑依 OpenAI node 結構調整,新版可能是 $json.choices[0].message.parsed.intent)。
每個分支對應一個 sub-workflow trigger,呼叫 Execute Workflow node:
| 分支值 | 接的 sub-workflow | Sub-workflow 內主要 LLM |
|---|---|---|
factual_lookup | wf-rag-claude | Qdrant 檢索 → Claude Sonnet |
creative_writing | wf-claude-writer | Claude Opus |
structured_form | wf-openai-form | GPT-4o + Structured Outputs |
small_talk | wf-openai-mini | gpt-4o-mini |
| 其他 | wf-human-handoff | 純模板回覆 |
重點規則:每條分支都要回傳同一個欄位結構(例如 { reply, model, tokens_in, tokens_out, latency_ms }),這樣 Merge 之後 Code node 才能統一處理。禁止某條分支多吐欄位、某條分支少欄位,會在後續報表跟監控階段瘋狂踩雷。
Step 3:低信心 fallback
confidence < 0.7 的請求不要進主分支,路徑改走 wf-human-handoff 或加一個 review queue:
Switch → IF (confidence >= 0.7)
├─ true → Switch by intent
└─ false → Human Handoff (寫進 D1/Sheets 等待人工審核)
這個機制非常重要。沒做這層,當分類器在邊界模糊時(例如「我想知道公司休假規定,順便幫我寫一封請假信」同時觸發 factual + creative),系統會挑信心稍高的那條,可能就走錯。讓人類介入幾秒比讓客戶看到亂回應好太多。
Step 4:sub-workflow 內的單模型呼叫
以 wf-rag-claude 為例:
Execute Workflow Trigger
↓
Qdrant Search (top_k=5)
↓
Set (組 augmented prompt)
↓
Anthropic Chat (claude-sonnet-4-5-20250929)
↓
Code (整理 reply / metadata)
↓
Respond to Workflow
Anthropic node 設定要點:
- Model:鎖定具體 snapshot,例如
claude-sonnet-4-5-20250929,避免 latest alias 行為突變 - Max tokens:依任務設定,客服回覆建議 800~1500
- System prompt:另外存在共用 Set node,避免散落
- Temperature:問答型 0.3、寫作型 0.7
wf-openai-form 的 sub-workflow 一樣模式,只是把 Anthropic node 換成 OpenAI Chat node + Structured Outputs schema 約束輸出格式。
Step 5:失敗時自動切換另一家
production 場景一定要做 fallback。改 Switch 為 IF + 雙 chat node 串接:
Set
↓
OpenAI Chat (主)
↓
IF ($json.success === true)
├─ true → Format → Respond
└─ false → Anthropic Chat (備) → Format → Respond
n8n 的 chat node 失敗(429、5xx、timeout)時,$json.success 會是 false 或拋出 error。這時可以用:
- Continue On Fail = true:節點失敗不中斷 workflow,把錯誤往後送
- Error Output 連到 fallback chat node:n8n 1.40 之後支援節點 Error Output 分支
- Wait + Retry:fallback 之前先等 1~2 秒,避免短暫故障被誤判
n8n 內建的 retry 設定可以對 5xx 自動重試 3 次;超出後才走 fallback 才合理。錯誤處理通用模式可參考 N8N 工作流錯誤處理 6 種模式。
Step 6:日誌與成本追蹤
每次 LLM 呼叫後,把這份資料打進 D1 / Sheets / PostHog:
// Code node
const { reply, model, tokens_in, tokens_out, latency_ms } = $input.first().json;
const cost = calcCost(model, tokens_in, tokens_out);
return [{
json: {
request_id: $('Webhook').first().json.headers['x-request-id'],
intent: $('Classifier').first().json.message.content.intent,
confidence: $('Classifier').first().json.message.content.confidence,
chosen_model: model,
tokens_in,
tokens_out,
cost_usd: cost,
latency_ms,
timestamp: new Date().toISOString()
}
}];
兩週後拉這份日誌做樞紐分析:
- 哪個 intent 最常出現?對應模型成本是否合理?
- 信心分數 < 0.7 的比例有多少?是不是該重訓 prompt?
- 哪些 case 走錯分支了?(檢查 reply 跟 intent 是否相符)
沒打日誌的雙 LLM workflow 是憑感覺,不是工程。
常見坑與解法
坑 1:Structured Outputs 偶爾回 null
OpenAI 在邊界 case 或被 prompt 引導時可能回 { intent: null }。對策:
- schema 設
required: ["intent", "confidence"] - prompt 加一句「絕不可回傳 null,沒辦法判斷時回 ‘small_talk’ + confidence: 0.5」
- 加 IF 檢查 null,null 直接走 default 分支
坑 2:Claude 回應中夾雜 markdown 格式但下游期待純文字
Claude 喜歡用 ** 強調。如果你下游是 LINE / WhatsApp 客服,把 markdown 直接送出去會變亂碼。在 Code node 加:
const cleaned = reply
.replace(/\*\*(.*?)\*\*/g, '$1') // 移除粗體
.replace(/^#+\s/gm, '') // 移除標題符號
.replace(/`([^`]+)`/g, '$1'); // 移除行內 code
坑 3:Sub-workflow 太多 webhook 卡住主 workflow
n8n self-hosted 沒設 worker 模式時,並行請求會在 Execute Workflow 排隊。production 一定要:
- 啟用 queue mode(Redis-based)
- 至少 2 個 worker 處理 LLM sub-workflow
- 主 workflow 用 webhook trigger,sub-workflow 用 Execute Workflow Trigger,不要互相 webhook
坑 4:分類器跟主 LLM 用同一把 API key 引起 rate limit
意圖分類在 high traffic 時會吃掉很多 RPM 配額,跟主 LLM 撞車。建議:
- 分類器用一把 OpenAI key(pay-as-you-go 或 lower tier)
- 主 LLM 各自用獨立 key 並升級到 tier 4/5
- 兩家 API key 各做 budget alert
模板結構建議
把這條 workflow 模板化,下次新案子直接套:
templates/
├─ dual-llm-router.json # 主 workflow
├─ sub-rag-claude.json # RAG + Claude
├─ sub-openai-structured.json # GPT-4o + Structured Outputs
├─ sub-claude-writer.json # Claude 長文寫作
├─ sub-openai-mini.json # mini small talk
└─ sub-human-handoff.json # 人工接手樣板
n8n 的 export workflow 是 JSON,可以放 git 做版本控制,未來每次新增分支只要 fork 既有 sub-workflow。模板選擇邏輯可參考 N8N 模板挑選原則。
上線檢查表(實作版)
回到 pillar 文那張上線檢查表的實作落地:
- ✅ 兩家 API key 都進 n8n Credentials,分別命名
openai-prod、anthropic-prod - ✅ 主 workflow 與 sub-workflow 都加 Error Trigger,集中送告警
- ✅ 分類器設
strict: true+additionalProperties: false - ✅ 低信心 fallback 路徑可用(confidence < 0.7)
- ✅ 每條 sub-workflow 都回統一的 reply schema
- ✅ 日誌節點打到 D1 / Sheets,含 model / tokens / cost
- ✅ 模型版本鎖到具體 snapshot
- ✅ 雙家 API budget alert 都開
- ✅ Queue mode + 至少 2 個 worker(self-hosted)
- ✅ 端對端 smoke test 跑過 5 種 intent,確認分支都通
每一條都打 ✅ 才算 production ready。
接下來
把雙 LLM 路由架起來只是開始。真正讓這條 workflow 越用越穩的,是兩件事:
- 每月跑一次成本分析,依任務分布調整路由比例
- 每季重評估模型選型,OpenAI 跟 Anthropic 都很常推新版
需要更多模板?逛逛 N8Nmarket 商城,1700+ 工作流模板可以直接改裝你的雙 LLM 路由。