餵知識:FAQ 資料庫與轉真人機制
第 4 課接好 AI 之後,你的 LINE 機器人確實會「說話」了。但一般店家上線一兩天就會發現一個問題:顧客問「你們有提供發票嗎」,AI 回一串關於電子發票制度的通則文字;問「現在有優惠嗎」,AI 掰了一個根本不存在的折扣活動。AI 不是壞,是它真的不知道你的店——你沒餵它知識,它只好從訓練資料裡隨便猜。
更嚴重的狀況:顧客要退貨、有緊急問題急著找真人,機器人還是喋喋不休回一堆廢話。這才是會讓人崩潰的體驗。這堂課就解決這兩件事:讓機器人只說它知道的事,以及在該閉嘴的時候閉嘴、轉給真人。
這堂學什麼
- 設計一張 Google Sheets FAQ 資料庫,規劃 keywords、question、answer 等欄位,讓 n8n 能精準比對
- 建立三層決策流程:先查 FAQ 直接回覆→查不到才問 AI→AI 也不確定就轉真人
- 防亂答的 System Prompt 架構:AI 只能根據 FAQ 回答,答不出來必須輸出固定標籤
- 轉真人機制:關鍵字觸發 → 回覆顧客安撫訊息 → LINE Notify 通知店主 → 寫入待處理清單
- 更新知識庫只要改 Sheets,流程本身永遠不用動
觀念一:三層知識決策樹
在開始動手之前,先把整個邏輯畫清楚。這套架構的核心精神是「能省就省,能確定就確定」:

第一層:偵測「轉真人」關鍵字。顧客主動說「我要找真人」「客服」「投訴」,不用經過 AI,直接觸發通知機制。這是最高優先,任何問題都不能蓋過它。
第二層:查 FAQ 關鍵字,直接回答。如果顧客的訊息裡含有 FAQ 表格的 keywords 欄內的字,就直接拉出對應的 answer 回覆。這一層完全不需要呼叫 AI,省時省錢,而且答案 100% 是你自己寫的,不會出錯。
第三層:交給 AI,但要帶著 FAQ 當知識庫。前兩層都沒命中,才請 AI 出場——但把整張 FAQ 表格當作 context 帶進去,加上嚴格的 System Prompt 限制,讓 AI 只能根據這些資料回答,答不出來就輸出一個固定標籤,n8n 偵測到這個標籤再觸發轉真人。
這個架構有一個很重要的好處:每一層的職責都很清楚,出問題時你馬上知道要去查哪個環節。
觀念二:把知識放在 Sheets,不是放在 Prompt
很多人第一直覺是把 FAQ 直接貼進 AI 的 System Prompt。問題在於 Prompt 存在 n8n 節點裡,每次要更新都要打開 n8n 去改節點、測試、再存回去——非技術的小編或店長根本辦不到,一切都卡在會操作 n8n 的人身上。

把知識存在 Google Sheets 之後,更新流程變成:打開試算表 → 改一行 → Enter。n8n 每次收到訊息才去撈表格,所以永遠拿到最新的資料,完全不需要重啟流程。小編、店長自己就能維護,工程師不用每次被叫去改機器人。這才是長期可以活下去的架構。
手把手實戰
以下假設你已完成第 3、4 課的 webhook 接收和 AI 回覆基本流程。我們在這個基礎上加層。
建立 Google Sheets FAQ 資料庫
先在 Google Drive 新增一個試算表,取名例如「LINE OA FAQ」。第一行設定欄位標題,照下圖的規格設計:

六個欄位說明:
| 欄位 | 必填 | 用途 |
|---|---|---|
| keywords | 必填 | 逗號分隔的同義詞,n8n 用這欄比對 |
| question | 必填 | 標準問法,讓 AI 理解語境 |
| answer | 必填 | 回給顧客的完整答案 |
| category | 選填 | 分類,之後做快速選單按鈕可用 |
| active | 選填 | TRUE/FALSE,FALSE 就暫停這筆不用刪 |
| updated_at | 選填 | 日期,方便審查過期資訊 |
填幾筆範例資料讓流程有東西可測試。keywords 欄的同義詞要盡量齊全,例如「營業時間」這個主題,keywords 可以填:
營業時間,幾點開,幾點關,開門,打烊,幾點到幾點,上班時間
一個字都別省。中文的問法非常多元,keywords 越完整,第二層直查命中率越高,呼叫 AI 的次數就越少。
填好之後,把這張試算表的分享設定調成「知道連結的人可以檢視」——n8n 接 Google Sheets 用的是 OAuth,不需要公開,但要確認你連 n8n 的 Google 帳號有這張表的讀取權限。
n8n:在 Webhook 節點後加轉真人偵測
打開第 4 課的 n8n 流程。在 Webhook 節點之後、AI 節點之前,加入一個 IF 節點做關鍵字偵測。
IF 節點的設定:
- 要比對的值:Webhook 收到的訊息文字,路徑通常是
{{ $json.events[0].message.text }} - 條件:選 String → Contains
- 比對值:先填一個最主要的關鍵字,例如
真人
但一個 IF 只能填一個值,要同時偵測多個關鍵字怎麼辦?有兩種方法:
方法 A:多個 IF 節點串聯(簡單但笨)。把「真人」「客服」「投訴」各做一個 IF,True 分支都接到同一個「轉真人處理」節點。
方法 B:用 Code 節點做一次比對(推薦)。在 Webhook 後加一個 Code 節點:
// Code 節點 (Node.js)
const msg = $input.first().json.events[0].message.text || '';
const handoffKeywords = ['真人', '客服', '投訴', '不滿意', '退款', '退貨', '申訴'];
const needsHandoff = handoffKeywords.some(kw => msg.includes(kw));
return [{ json: { ...$input.first().json, needsHandoff } }];
接著用一個 IF 節點判斷 needsHandoff 是否為 true。True 就走轉真人分支,False 繼續往下走 FAQ 查詢。方法 B 只要在這個陣列新增字串就能加關鍵字,維護比方法 A 方便。
n8n:Google Sheets 查詢節點
轉真人偵測之後、AI 呼叫之前,加入一個 Google Sheets 節點:
- Operation:選 Get Many Rows
- Spreadsheet:選你剛建好的「LINE OA FAQ」
- Sheet:選放資料的那頁
- Filters:加一個條件
active=TRUE(只撈啟用中的 FAQ) - Return All:勾選
這樣每次顧客傳訊,n8n 就會把所有 active = TRUE 的 FAQ 全部撈回來,存成一個陣列。
接著在 Sheets 節點之後加一個 Code 節點,做關鍵字比對:
// Code 節點:FAQ 關鍵字比對
const msg = $input.first().json.events[0].message.text || '';
const faqs = $('Google Sheets').all().map(item => item.json);
let matchedFaq = null;
for (const faq of faqs) {
const keywords = (faq.keywords || '').split(',').map(k => k.trim());
if (keywords.some(kw => kw && msg.includes(kw))) {
matchedFaq = faq;
break;
}
}
return [{
json: {
...$input.first().json,
matchedFaq,
faqHit: matchedFaq !== null,
faqContext: faqs.map(f => `Q: ${f.question}\nA: ${f.answer}`).join('\n\n')
}
}];
這段程式做兩件事:
- 把訊息文字拿去跟每一筆 FAQ 的 keywords 比對,找到第一筆命中的就存進
matchedFaq - 把所有 FAQ 整理成純文字格式存進
faqContext,等一下要塞給 AI 當知識庫
接著加 IF 節點判斷 faqHit 是否為 true:
- True 分支:直接用 LINE Reply API 回覆
matchedFaq.answer的內容,這條路不碰 AI - False 分支:走 AI 分支
True 分支的 HTTP Request 節點設定(第 3、4 課已做過,這裡只補重點):
{
"replyToken": "{{ $json.events[0].replyToken }}",
"messages": [
{
"type": "text",
"text": "{{ $json.matchedFaq.answer }}"
}
]
}
記得打開 Body 裡的 Expression 模式,才能用 {{ }} 帶入變數。
AI 節點:注入 FAQ 知識庫 + 防亂答 Prompt
FAQ 沒命中的訊息,走到 AI 節點。這一步的關鍵是怎麼寫 System Prompt。先看整體結構:

System Prompt 完整範本如下,直接複製再依你的店改:
# 角色定義
你是「{填入你的店名}」的 LINE 官方帳號客服助理,負責回答顧客的問題。
你的所有回答,只能根據下方「知識庫」的內容作答,不得自行猜測或補充知識庫以外的資訊。
# 知識庫
{{ $json.faqContext }}
# 回答規則
1. 若顧客的問題在知識庫中有對應資訊:請根據知識庫內容回答,語氣親切自然,
回覆長度不超過 100 字,適時加上換行讓訊息易讀。
2. 若顧客的問題在知識庫中完全找不到對應資訊,或資訊不足以確定回答:
不可猜測、不可編造、不可說「應該是...」之類的模糊回覆。
請直接輸出以下完整文字,不得更改任何字:
HUMAN_NEEDED
3. 回覆請使用繁體中文台灣用語。禁止使用「您」,改用「你」。
# 絕對禁止
- 提及其他品牌或做比較
- 承諾知識庫未列出的折扣、服務或保證
- 說「我不知道」「無法確定」——這些情況一律輸出 HUMAN_NEEDED
- 回覆與店家服務完全無關的話題(請顧客聯絡真人客服)
幾個關鍵設計說明:
{{ $json.faqContext }} 是動態帶入的。這是前一步 Code 節點輸出的 faqContext 變數,把所有 FAQ 整理成純文字注入 prompt,所以只要 Sheets 更新,AI 下次就知道新的內容。
HUMAN_NEEDED 用全大寫,是為了讓後續的 IF 節點可以精準比對,不會被 AI 改字或混入其他回覆。如果你的 AI 模型回覆時習慣換行,可以改成 [HUMAN_NEEDED] 並在 IF 節點改用 Contains 而不是 Equals。
明確的分支指令比「請判斷」更可靠。Prompt 要寫清楚「符合條件 A 就做 X,符合條件 B 就輸出 Y」,不要留給 AI 自己決定。AI 的「自由裁量」是混亂答案的根源。
偵測 HUMAN_NEEDED,觸發轉真人機制
AI 節點之後加一個 IF 節點:判斷 AI 的回覆內容是否包含 HUMAN_NEEDED。
True 分支(需要轉真人):執行下圖這整套動作序列:

動作 1:先回覆顧客安撫訊息
用 HTTP Request 呼叫 LINE Reply API:
{
"replyToken": "{{ $json.events[0].replyToken }}",
"messages": [
{
"type": "text",
"text": "收到你的問題囉!我已通知客服人員,將在 5–10 分鐘內為你服務,請稍候 🙏"
}
]
}
這步要放最前面。顧客等真人時需要知道「有人知道了」,否則他會以為訊息沒送到、開始狂傳。
動作 2:用 Messaging API 推播通知店主
早期很多教學會用 LINE Notify 來做這種通知,但 LINE Notify 已於 2025 年 3 月 31 日正式終止服務,notify-api.line.me 完全無法再使用。官方指定的替代方案就是用你這個 OA 的 Messaging API 主動推播(push message)——好處是不用再多申請一個服務,同一把 Channel Access Token 就能用。
做法是把通知「推播」給店主本人:請店主先用自己的 LINE 加入這個 OA 好友,隨便傳一句話,從 n8n 執行歷史的 webhook 裡撈到店主的 userId(以 U 開頭的字串),記下來。之後就用這個 userId 當推播對象。若要推到店家的內部群組,也可以把 OA 拉進群組、改推 groupId。
HTTP Request 節點設定:
- Method:POST
- URL:
https://api.line.me/v2/bot/message/push - Authentication:Header Auth,名稱
Authorization,值Bearer {{你的 Channel Access Token}} - Body:JSON,內容如下(把
to換成店主的 userId):
{
"to": "U店主的userId",
"messages": [
{
"type": "text",
"text": "{{ '需要真人接手!\\n顧客:' + $json.events[0].source.userId + '\\n原始訊息:' + $json.events[0].message.text + '\\n時間:' + new Date().toLocaleString('zh-TW', {timeZone:'Asia/Taipei'}) }}"
}
]
}
注意 push message 和前面回覆顧客用的 reply message 會各算一則訊息,計入你的每月免費額度,這點下一課會細講。
動作 3:寫入 Google Sheets 待處理表
另開一個分頁「待處理」,欄位:userId / 訊息 / 觸發原因 / 時間 / 狀態(預設 FALSE)。用 Google Sheets 節點的 Append Row 把這次事件寫進去。你就有一個完整的待辦清單,處理完了自己去勾 TRUE。
False 分支(AI 有答案):直接用 HTTP Request 呼叫 LINE Reply API 把 AI 回覆送出去。這邊和第 4 課的做法一樣,不再重複。
測試整條流程
流程接好之後,用你自己的手機打開 LINE 加入這個 OA,分別傳這幾種訊息測試:
- 命中 FAQ 關鍵字的問題:例如你在 Sheets 有填「營業時間」,傳「你們幾點開門」,應該秒回 Sheets 裡的答案,不經過 AI。
- 沒命中 FAQ 但合理的問題:例如「你們有哪些品項」,AI 應該根據 FAQ 內容回覆,不亂掰。
- 完全超出範圍的問題:例如問你們 OA 一些奇怪的事,AI 應該不回覆你那些問題、不瞎扯,而是收到 HUMAN_NEEDED → 通知你。
- 直接傳「真人」:應該直接觸發轉真人,不走 FAQ 或 AI 流程。
- 傳「客服」:同上。
每一個都測過一遍,確認 n8n 執行歷史裡每個節點都走到預期的分支,沒有意外跳到錯的路。LINE Reply API 呼叫成功會回 {} 空 JSON,失敗的話注意看錯誤訊息。
常見坑
坑 1:AI 不肯輸出 HUMAN_NEEDED,老是給「抱歉我無法回答」
這是 prompt 寫法問題。「請直接輸出 HUMAN_NEEDED」對某些模型沒用,它會把 HUMAN_NEEDED 包在其他文字裡,例如「這個問題我需要轉 HUMAN_NEEDED 給...」。解法有兩個:第一,在 prompt 裡再強調一次「不得在 HUMAN_NEEDED 前後加任何文字」;第二,把 IF 節點的比對條件從 Equals 改成 Contains——只要回覆裡有這段文字就觸發。第二個方法更實用,因為即使 AI 換行或加了空格,Contains 也照樣抓得到。
坑 2:Google Sheets 撈資料的速度讓顧客等太久
n8n 每次呼叫 Google Sheets API 大約需要 12 秒,加上 AI 呼叫又 25 秒,整個流程跑完可能 5~8 秒,顧客感覺像卡住。兩個改善方向:第一,把「先查 FAQ 關鍵字直接回」的邏輯做好——大部分常見問題都直查命中,不走 AI 那條,整體速度就快很多;第二,如果你的 FAQ 資料量超過 200 行,可以考慮改用 n8n 的「Schedule Trigger」每 10 分鐘把 Sheets 撈回來存到 n8n 的 Static Data,正式回覆時從 Static Data 讀而不是每次重撈。
坑 3:轉真人之後 AI 還是繼續插嘴回覆
這是因為沒有做「暫停 AI 的狀態記錄」。你通知了店主,但下一條訊息進來,n8n 還是走正常流程讓 AI 回。解法:在 Google Sheets 待處理表加一個「handoff_active」欄,轉真人時寫入 userId + TRUE。在流程最前面加一個 Sheets 查詢,看這個 userId 有沒有 handoff_active = TRUE 的紀錄,有的話直接回「正在連繫客服人員,請稍候」,跳過後面所有節點。店主處理完之後去把那筆改成 FALSE,AI 才會重新接手。
坑 4:$('Google Sheets').all() 報錯「Cannot read properties of undefined」
這是 n8n 節點名稱對不上。$('Google Sheets') 的括號裡必須填你在 n8n 介面上看到的節點「顯示名稱」,如果你把那個節點改名成「查詢 FAQ 表」,就要改成 $('查詢 FAQ 表').all()。報這個錯就去確認 Code 節點裡引用的名稱和畫布上的節點名稱是否完全一致,包括大小寫和空格。
坑 5:keywords 比對到不相關的詞
例如你的 keywords 填了「有」這個字,結果任何帶「有」的問題都命中這筆 FAQ。關鍵字太短或太通用就會這樣。解法:keywords 一律填兩個字以上的詞組;如果真的需要單字,在 Code 節點的比對邏輯裡加長度限制——例如 kw.length >= 2 && msg.includes(kw);或者把比對邏輯從 includes 改成用正則加字邊界。
作業
- 實際填好你自己店家的 FAQ 表格,至少 10 筆,涵蓋最常被問的問題類別(例如:營業時間、訂位方式、退換貨政策、停車、付款方式)。
- 把五種測試情境都跑過一遍,截圖下來對照:是否每種都走到正確的分支?
- 選做:在 Google Sheets 待處理表加「處理人」欄,有多個客服時可以在這欄填入誰負責這張單。
- 思考作業:你的店有哪些問題屬於「一定要真人接手」的類型?把這些加進 handoffKeywords 陣列裡。
下一課預告
機器人現在已經懂事多了:懂你的知識、知道自己不懂的要轉給真人、不會亂說話。但還差最後一關——真正上線給陌生顧客用,會遇到你在測試時想不到的狀況:流程偶爾出錯要怎麼監控?LINE 的 200 則免費額度(2026 輕用量方案)用完了怎麼辦?哪些節點會產生費用、如何精算成本?有顧客故意傳奇怪東西攻擊機器人怎麼辦?
第 6 課「上線實戰:測試、成本控管與常見坑」把這些實戰問題全部講清楚,讓你的 LINE 客服機器人從「可以動」變成「可以放心用」。