歷經了前 9 天的摸索與實作,我們從最底層的 Docker 容器環境、FastAPI 微服務、Dify 搭配 Google Gemini 大腦、ngrok 公網隧道,一路推進到了 LINE Messaging API 的事件監聽。
今天 Day 10,是整個實作系列的完結篇與總驗收!我們將把散落在各處的所有拼圖正式串聯起來,打造一條完整的端到端閉環(End-to-End Pipeline):
只要在手機 LINE 聊天室隨口說出一句想吃的需求,AI 大腦便會自動解析、微服務即時運算篩選,最後透過 LINE Reply API 將排版精美的推薦店家即時送回手機!
在正式把線路全部接在一起前,我們先回顧整條完整的資料鏈路流向:
[使用者手機 LINE 聊天室]
│ 1. 使用者輸入口語需求(例如:「板橋有什麼 300 元內的安靜甜點店?」)
▼
[LINE Platform]
│ 2. 觸發 Webhook (HTTPS POST)
▼
[ngrok 隧道] ➜ 轉發至本地連接埠 5678
│
▼
[n8n 工作流 (Webhook 節點)]
│ 3. 擷取 replyToken 與使用者文字
▼
[Dify API + Gemini 3.5 Flash-Lite]
│ 4. 自然語言意圖辨識,提取 JSON(預算、地區、類別)
▼
[FastAPI 微服務 (POST /api/v1/recommend/)]
│ 5. 執行商業邏輯與條件篩選,回傳推薦餐廳清單
▼
[n8n 訊息組裝 (Set / Code 節點)]
│ 6. 格式化為友善對話文字或 LINE Flex Message
▼
[LINE Messaging API (POST /v2/bot/message/reply)]
│ 7. 使用 replyToken 免費回覆訊息
▼
[使用者手機 LINE 聊天室即時收到推薦小卡!]
請打開瀏覽器進入 n8n 介面(http://localhost:5678),打開昨天的 LINE Bot Core Workflow,依序完成以下節點的對齊與拼接:
節點 1:Webhook (LINE Receiver)
HTTP Method:POST
Path:line-webhook
Response Mode:On Received,Response Body 填寫 {"status": "ok"}
💡 關鍵觀念:LINE 伺服器要求 Webhook 必須在短時間內收到 200 回應,否則會判定逾時。將 Response Mode 設為 On Received 能讓 n8n 第一時間回傳 200 給 LINE,後續運算再非同步繼續執行。
節點 2:Code (Extract Event)
過濾並提取出關鍵欄位:
const event = $input.first().json.body.events[0];
if (!event || event.type !== 'message' || event.message.type !== 'text') {
return [];
}
return {
reply_token: event.replyToken,
user_id: event.source.userId,
user_message: event.message.text
};
節點 3:HTTP Request (Call Dify AI Intent)
將使用者的自然語言送入 Dify 的 Gemini 大腦進行參數解析:
Method:POST
URL:http://host.docker.internal/v1/chat-messages
Authentication:Header Auth
Name:Authorization
Value:Bearer <你的_DIFY_API_KEY>
Headers:Content-Type: application/json
JSON Body:
{
"inputs": {},
"query": "={{ $json.user_message }}",
"response_mode": "blocking",
"user": "={{ $json.user_id }}"
}
節點 4:Code (Parse AI JSON)
將 Dify 回傳的字串格式化為乾淨的 JSON 物件,同時保留 reply_token 以供後續回覆使用:
let rawAnswer = $input.first().json.answer;
rawAnswer = rawAnswer.replace(/```json/g, '').replace(/```/g, '').trim();
let parsedData = {};
try {
parsedData = JSON.parse(rawAnswer);
} catch (e) {
parsedData = {
cuisine: "全部",
budget_max: 500,
location: "板橋區",
notes: ""
};
}
// 取得前一個節點保存的 reply_token
const replyToken = $('Extract Event').first().json.reply_token;
return {
reply_token: replyToken,
cuisine: parsedData.cuisine || "全部",
budget_max: parsedData.budget_max || 500,
location: parsedData.location || "板橋區",
notes: parsedData.notes || ""
};
節點 5:HTTP Request (Call FastAPI Backend)
呼叫本機運行的 FastAPI 推薦微服務:
Method:POST
URL:http://host.docker.internal:8000/api/v1/recommend/
Headers:Content-Type: application/json
JSON Body:
{
"user_id": "line_user",
"cuisine": "={{ $json.cuisine }}",
"budget_max": {{ $json.budget_max }},
"location": "={{ $json.location }}",
"notes": "={{ $json.notes }}"
}
節點 6:Code / Set (Format Reply Message)
根據推薦結果組裝回傳給使用者的文字排版:
const responseData = $input.first().json;
const replyToken = $('Parse AI JSON').first().json.reply_token;
let replyText = "";
if (!responseData.recommendations || responseData.recommendations.length === 0) {
replyText = "抱歉,目前在該區域與預算條件下找不到合適的店家,建議放寬預算或更換料理分類再試試看哦!";
} else {
const shop = responseData.recommendations[0];
replyText = `🎉 收到!已為您找到最推薦的店家:\n\n` +
`【店名】:${shop.name}\n` +
`【類型】:${shop.cuisine}\n` +
`【均消】:約 ${shop.price_avg} 元\n` +
`【地點】:${shop.location}\n` +
`【評分】:⭐️ ${shop.rating}\n` +
`【招牌必點】:${shop.signature_dish}\n\n` +
`💡 小編推薦筆記:${shop.reason || '無'}`;
}
return {
reply_token: replyToken,
reply_text: replyText
};
節點 7:HTTP Request (LINE Reply API)
最後一步,呼叫 LINE 官方的 Reply API 回傳訊息至聊天室:
Method:POST
URL:https://api.line.me/v2/bot/message/reply
Authentication:Header Auth
Name:Authorization
Value:Bearer <你的_LINE_CHANNEL_ACCESS_TOKEN>
Headers:Content-Type: application/json
JSON Body:
{
"replyToken": "={{ $json.reply_token }}",
"messages": [
{
"type": "text",
"text": "={{ $json.reply_text }}"
}
]
}
1.確保 FastAPI 伺服器仍在執行(uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload)。
2.確保 ngrok 隧道保持在線上狀態(ngrok http 5678)。
3.在 n8n 畫布右上角,將 Active 開關切換為 開啟(Active / Published)。
4.到 LINE Developers 後台,將 Webhook URL 確認為正式路徑:
[https://xxxx.ngrok-free.app/webhook/line-webhook](https://xxxx.ngrok-free.app/webhook/line-webhook)
打開手機 LINE,進入美食小幫手的聊天室,傳送口語訊息進行測試:
使用者輸入:
「我人在板橋,預算大概抓 300,下午想找間安靜的甜點店吃蛋糕,有推薦的嗎?」
數秒之內,聊天室即時彈出回覆:
美食探險小幫手:
收到!已為您找到最推薦的店家:
【店名】:恬淡日常法式甜點
【類型】:甜點/下午茶
【均消】:約 280 元
【地點】:板橋區
【評分】:⭐️ 4.7
【招牌必點】:草莓戚風蛋糕、伯爵生乳捲
💡 小編推薦筆記:巷弄隱密甜點店,氣氛溫馨悠閒,適合放鬆聊天。