ต่อ Chatbot เข้ากับ LINE OA
คู่มือทีละขั้นตอนแบบละเอียด — คำสั่งครบทั้ง macOS และ Windows พร้อมเส้นทาง n8n Cloud ที่ไม่ต้องใช้ tunnel เลย
บทนี้ต่อยอดจาก คอร์สหลัก (แชทบนหน้าเว็บ) ↗ เปลี่ยนจากหน้าแชทมาเป็น LINE Official Account ซึ่งเป็นช่องทางที่คนไทยใช้จริงมากที่สุด พนักงานไม่ต้องจำ URL ไม่ต้องล็อกอิน แค่แอดเพื่อนแล้วพิมพ์ถามได้เลย
ฝั่งนำเข้าไฟล์ความรู้ (Excel, PDF, Word, TXT, MD, HTML) ยังเหมือนเดิมทุกอย่าง เปลี่ยนเฉพาะฝั่งรับ-ส่งข้อความ
Line_Webhook → Parse_Line_Event ─┬─ Show_Typing (กิ่งขนาน)
└─ Find_Answer → IF_Use_AI ─┬─ AI_Answer ────┐
└─ Direct_Reply ─┴→ Send_Line_Reply| เส้นทาง A: localhost | เส้นทาง B: n8n Cloud | |
|---|---|---|
| ค่าใช้จ่าย | ฟรี | มีค่าบริการรายเดือน |
| ต้องใช้ tunnel | ต้องใช้ | ไม่ต้อง มี URL สาธารณะให้เลย |
| URL เปลี่ยนบ่อย | เปลี่ยนทุกครั้งที่รีสตาร์ท tunnel | คงที่ตลอด |
| ต้องเปิดเครื่องค้างไว้ | ต้อง ปิดเครื่องบอทตาย | ไม่ต้อง ทำงาน 24 ชม. |
| อ่านไฟล์ .docx | ได้ (ตั้ง env var เอง) | ไม่ได้ ต้องแปลงเป็น PDF ก่อน |
| เหมาะกับ | เรียนรู้ ทดลอง พัฒนา | ใช้งานจริงในองค์กร |
สำหรับการอบรม แนะนำให้ผู้เรียนทำเส้นทาง A ก่อนเพื่อเข้าใจกลไก แล้วค่อยสาธิตเส้นทาง B ให้ดูว่าตอนขึ้นใช้จริงต่างกันอย่างไร
ไฟล์ความรู้ 6 สกุลเป็นชุดเดียวกับ คอร์สหลัก ↗ — ข้อมูลสมมติของ “บริษัท ตัวอย่าง จำกัด” เอาไปทดลองอัปโหลดผ่าน Production URL ของ workflow ตัว LINE ได้เลย
📚 ไฟล์ทั้งหมด — workflow + ไฟล์ความรู้ตัวอย่าง 6 สกุล
- 🔧n8n_Thai_QA_Chatbot_LineOA.json
Workflow ครบ 23 โหนด — ฝั่งนำเข้าความรู้เหมือนคอร์สหลักทุกอย่าง บวกโหนดใหม่ 4 ตัวสำหรับรับ-ส่งข้อความผ่าน LINE
- 📊QA_Chatbot_Knowledge_TH.xlsx
ตาราง Q&A 45 รายการ 7 หมวด (ทั่วไป · HR · IT · สวัสดิการ · เงินเดือน · จัดซื้อ · สถานที่)
- 📝ระเบียบการลาพนักงาน.docx
ลาพักร้อน ลาป่วย ลาคลอด ลากิจ — ใช้ทดสอบโค้ดแกะ .docx (เส้นทาง A เท่านั้น)
- 📕คู่มือสวัสดิการ.pdf
ประกันสุขภาพกลุ่ม กองทุนสำรองเลี้ยงชีพ เบิกค่าเดินทาง — PDF ที่มีตัวข้อความจริง ไม่ใช่ภาพสแกน
- 📄นโยบายความปลอดภัยไอที.txt
รหัสผ่าน 2FA อีเมลฟิชชิง สำรองข้อมูล — ไฟล์ข้อความธรรมดา
- 📘คู่มือใช้งานระบบภายใน.md
ระบบ HR ออนไลน์ Helpdesk จองห้องประชุม จัดซื้อ — ไฟล์ Markdown
- 🌐ประกาศบริษัท.html
ประกาศเรื่องแนวปฏิบัติการทำงานแบบไฮบริด — ไฟล์ HTML ใช้ทดสอบการถอดแท็กออก
💡 ไฟล์ .docx .pdf .xlsx เป็นไฟล์ไบนารี กดดาวน์โหลดแล้วเปิดด้วยโปรแกรมของตัวเองได้เลย ส่วนไฟล์ข้อความกด ดูเนื้อหา อ่านบนเว็บได้ก่อนโหลด
เรียนไปแล้ว 0 จาก 9 บท
เตรียม LINE OA
1.1 สร้าง Channel
- เข้า LINE Developers Console แล้วล็อกอินด้วยบัญชี LINE
- สร้าง Provider ใหม่ (ชื่อองค์กรหรือชื่อทีม) ถ้ายังไม่มี
- ในโปรไวเดอร์นั้น กด Create a new channel → เลือก Messaging API
- กรอกข้อมูล: ชื่อ OA, คำอธิบาย, หมวดหมู่, อีเมล แล้วยอมรับเงื่อนไข
1.2 เอา Channel access token
- เปิด Channel ที่เพิ่งสร้าง → แท็บ Messaging API
- เลื่อนลงล่างสุดหาหัวข้อ Channel access token (long-lived)
- กด Issue แล้วคัดลอกเก็บไว้ — token นี้ยาวมากและจะแสดงเต็มครั้งเดียว
ในแท็บเดียวกันจะมี Channel secret อยู่ด้วย เก็บไว้ก่อน จะได้ใช้ตอนทำระบบจริงในบท 9
1.3 ปิดการตอบกลับอัตโนมัติ
ข้อนี้ลืมกันบ่อยที่สุด และทำให้บอทของเราถูกตอบทับจนงงว่าทำไมไม่ทำงาน
- เข้า LINE Official Account Manager (คนละเว็บกับ Developers Console)
- เลือก OA ของคุณ → ตั้งค่า → การตอบกลับ
- ตั้งค่าดังนี้
- โหมดตอบกลับ: Chat หรือเปิด Webhook
- การตอบกลับอัตโนมัติ: ปิด
- ข้อความทักทายเมื่อเพิ่มเพื่อน: ปิด (workflow ของเราทักทายเองแล้ว)
เส้นทาง A: รันบนเครื่อง
2.1 ติดตั้ง n8n
# ต้องมี Node.js ก่อน ถ้ายังไม่มี brew install node npm install -g n8n
# ต้องมี Node.js ก่อน ถ้ายังไม่มี winget install OpenJS.NodeJS.LTS npm install -g n8n
2.2 เปิดสิทธิ์โมดูล zlib (จำเป็นเฉพาะถ้าจะอ่านไฟล์ .docx)
NODE_FUNCTION_ALLOW_BUILTIN=zlib n8n start
$env:NODE_FUNCTION_ALLOW_BUILTIN="zlib" n8n start
set NODE_FUNCTION_ALLOW_BUILTIN=zlib n8n start
ตั้งแบบถาวรไม่ต้องพิมพ์ทุกครั้ง
echo 'export NODE_FUNCTION_ALLOW_BUILTIN=zlib' >> ~/.zshrc source ~/.zshrc
[Environment]::SetEnvironmentVariable("NODE_FUNCTION_ALLOW_BUILTIN", "zlib", "User")ตรวจว่าได้ผล สร้าง Code node วางโค้ดนี้แล้วกด Test step ต้องได้ "function"
return [{ json: { ok: typeof require('zlib').inflateRawSync } }];ถ้ายังไม่ได้ทั้งที่ตั้งค่าแล้ว ให้ลองปิด Task Runner ซึ่งรันโค้ดในโปรเซสแยกและอาจไม่รับตัวแปรนี้ต่อ
N8N_RUNNERS_ENABLED=false NODE_FUNCTION_ALLOW_BUILTIN=zlib n8n start
2.3 แก้ปัญหาพอร์ตชนกัน
ตัวแปร environment อ่านตอนโปรเซสเริ่มเท่านั้น ทุกครั้งที่เปลี่ยนค่าต้องปิด n8n ก่อน ถ้าเจอข้อความ port 5678 is already in use
kill -9 $(lsof -ti :5678)
Get-NetTCPConnection -LocalPort 5678 | Select-Object -ExpandProperty OwningProcess | ForEach-Object { Stop-Process -Id $_ -Force }2.4 เปิด tunnel
LINE ต้องยิง webhook เข้ามาหาเครื่องเราได้จากอินเทอร์เน็ต และต้องเป็น https ซึ่ง http://localhost:5678 ทำไม่ได้
ใช้ Cloudflare Tunnel แทน ฟรีและไม่ต้องสมัครบัญชี
ติดตั้ง
brew install cloudflared
winget install --id Cloudflare.cloudflared
เปิด tunnel (ใช้ terminal หน้าต่างใหม่ ปล่อย n8n รันค้างในหน้าต่างเดิม)
cloudflared tunnel --url http://localhost:5678
รอสักครู่จะได้กล่องข้อความแบบนี้
+-------------------------------------------------------------+ | Your quick Tunnel has been created! Visit it at: | | https://colour-context-expectations-gaps.trycloudflare.com | +-------------------------------------------------------------+
2.5 บอก n8n ว่า URL จริงคืออะไร
สาเหตุคือ n8n ยังคิดว่าตัวเองอยู่ที่ localhost จึงฝัง URL localhost ลงในหน้าฟอร์มที่ส่งออกไป พอเบราว์เซอร์เปิดหน้าจากโดเมน trycloudflare แล้วยิงกลับไปหา localhost ก็โดนบล็อก
ปิด n8n แล้วสั่งใหม่พร้อมตัวแปรสองตัวนี้
kill -9 $(lsof -ti :5678) export WEBHOOK_URL=https://ใส่-tunnel-url-ของคุณ.trycloudflare.com export N8N_EDITOR_BASE_URL=https://ใส่-tunnel-url-ของคุณ.trycloudflare.com NODE_FUNCTION_ALLOW_BUILTIN=zlib n8n start
$env:WEBHOOK_URL="https://ใส่-tunnel-url-ของคุณ.trycloudflare.com" $env:N8N_EDITOR_BASE_URL="https://ใส่-tunnel-url-ของคุณ.trycloudflare.com" $env:NODE_FUNCTION_ALLOW_BUILTIN="zlib" n8n start
ตัวแปรสองตัวนี้จำเป็นเสมอเมื่อรัน n8n หลัง tunnel หรือ reverse proxy ไม่ใช่แค่กรณี LINE เพราะทุกฟีเจอร์ที่ n8n ต้องสร้าง URL ให้ตัวเอง — หน้าฟอร์ม หน้าแชท URL ของ webhook — จะยังบอกเป็น localhost อยู่จนกว่าจะตั้งค่านี้
เส้นทาง B: n8n Cloud
เส้นทางนี้สั้นกว่ามาก เพราะไม่ต้องยุ่งกับ tunnel และตัวแปร environment เลย
3.1 สมัครและเข้าใช้งาน
- สมัครที่ n8n.io แล้วเลือกแพ็กเกจ (มีช่วงทดลองใช้ฟรี)
- จะได้ URL ประจำตัวหน้าตาแบบ https://ชื่อของคุณ.app.n8n.cloud
- URL นี้เป็นสาธารณะและใช้ https อยู่แล้ว จึงข้ามหัวข้อ 2.4 และ 2.5 ไปได้เลย
3.2 Import workflow
เมนู Workflows → Import from File → เลือกไฟล์ n8n_Thai_QA_Chatbot_LineOA.json
3.3 ข้อจำกัดที่ต้องรู้: อ่านไฟล์ .docx ไม่ได้
n8n Cloud ไม่เปิดให้ผู้ใช้ตั้ง environment variable เอง (เอกสารการตั้งค่า NODE_FUNCTION_ALLOW_BUILTIN อยู่ในหมวด self-host เท่านั้น) โหนด Docx_To_Text ที่ต้องใช้โมดูล zlib จึงทำงานไม่ได้
ทางแก้มีสองทาง
- แปลงไฟล์ Word เป็น PDF ก่อนอัปโหลด ง่ายที่สุด และ Word/Pages มีเมนู Save as PDF อยู่แล้ว เนื้อหาที่ได้แทบไม่ต่างกัน
- ถ้าจำเป็นต้องรับ .docx จริง ๆ ให้ย้ายไป self-host บน VPS ซึ่งตั้ง environment variable ได้
ส่วนสกุลอื่นทั้ง Excel, PDF, TXT, Markdown, HTML ทำงานได้ปกติทุกอย่างบน Cloud
3.4 ข้อดีที่เห็นชัดตอนใช้จริง
- URL คงที่ ตั้งค่าใน LINE ครั้งเดียวจบ ไม่ต้องกลับมาแก้ทุกวัน
- ทำงาน 24 ชั่วโมง ปิดโน้ตบุ๊กได้ บอทยังตอบ
- ไม่ต้องเปิด terminal ค้างสองหน้าต่าง
ตั้งค่าใน n8n
4.1 สร้าง credential สำหรับ LINE
ออกแบบให้ใช้ credential แทนการฝังโทเคนใน workflow เพราะไฟล์ JSON ต้องแจกให้ผู้เรียน ถ้าฝังไว้ในไฟล์ โทเคนจะรั่วทันทีที่แชร์
- เมนู Credentials → Add credential → ค้นหา Header Auth
- กรอก
- Name (ชื่อ header): Authorization
- Value: Bearer <วาง channel access token ตรงนี้>
- ตั้งชื่อ credential ว่า LINE Channel Access Token แล้วบันทึก
จากนั้นเปิดโหนด Show_Typing และ Send_Line_Reply แล้วเลือก credential นี้ให้ทั้งสองโหนด
4.2 ใส่ OpenAI API key
เปิดโหนด OpenAI_Model → Create new credential → วาง API key → เลือกโมเดล gpt-4o-mini
4.3 Publish และ Activate
n8n เวอร์ชัน 2.0 แยก Save กับ Publish ออกจากกัน ต่างจาก 1.x ที่กด Save แล้วขึ้นใช้งานทันที
- กด Save
- กด Publish (ปุ่มมุมขวาบน)
- เปิดสวิตช์ Active
4.4 นำเข้าไฟล์ความรู้
เปิดโหนด Upload_Knowledge → คัดลอก Production URL จากในโหนด (อย่าพิมพ์เอง เพราะถ้า path ซ้ำกับ workflow อื่น n8n อาจเปลี่ยน path ให้อัตโนมัติ)
เปิด URL นั้นในเบราว์เซอร์ อัปโหลดไฟล์ทีละไฟล์ ครั้งแรกเลือกโหมด "ล้างของเดิมแล้วนำเข้าใหม่" ครั้งต่อไปเลือก "เพิ่มต่อจากของเดิม"
4.5 ตั้ง Webhook URL ใน LINE
เปิดโหนด Line_Webhook → คัดลอก Production URL
| เส้นทาง | รูปแบบ URL |
|---|---|
| A (localhost) | https://xxxxx.trycloudflare.com/webhook/line-qa-bot |
| B (n8n Cloud) | https://ชื่อของคุณ.app.n8n.cloud/webhook/line-qa-bot |
จากนั้นไปที่ LINE Developers Console → Messaging API → Webhook URL → วาง → Update → กด Verify ควรขึ้น Success
อย่าลืมเปิดสวิตช์ Use webhook ให้เป็น Enabled
ทดสอบระบบ
5.1 เช็กลิสต์ก่อนทดสอบ
- ☐Credential Header Auth เลือกให้ทั้ง Show_Typing และ Send_Line_Reply แล้ว
- ☐OpenAI API key ใส่แล้ว
- ☐workflow Publish และ Active แล้ว
- ☐อัปโหลดไฟล์ความรู้เข้า workflow ตัวนี้แล้ว
- ☐Webhook URL ใน LINE Verify ผ่าน และเปิด Use webhook
- ☐ปิดการตอบกลับอัตโนมัติใน OA Manager แล้ว
- ☐(เส้นทาง A) หน้าต่าง cloudflared ยังเปิดอยู่
5.2 กรณีทดสอบ
สแกน QR จากแท็บ Messaging API เพื่อแอด OA เป็นเพื่อน แล้วทดสอบตามนี้
| ทดสอบ | ผลที่ควรได้ |
|---|---|
| แอดเพื่อนครั้งแรก | ข้อความทักทายพร้อมตัวอย่างคำถาม |
| พิมพ์ /stats | จำนวน Q&A และจำนวนท่อนเอกสาร (ไม่เรียก AI) |
| พิมพ์ /sources | รายชื่อไฟล์ที่นำเข้าแล้ว |
| ถาม "ลาคลอดได้กี่วัน" | ตอบ 98 วัน (จาก docx หรือ pdf) |
| ถาม "รหัสผ่านต้องยาวกี่ตัว" | ตอบ 12 ตัวอักษร (จาก txt) |
| ถามต่อว่า "แล้วต้องเปลี่ยนบ่อยแค่ไหน" | ตอบ 90 วัน โดยเข้าใจว่ายังพูดเรื่องรหัสผ่าน |
| ส่งสติกเกอร์ | บอกว่ารองรับเฉพาะข้อความ |
| ถาม "ราคาทองวันนี้" | บอกว่าไม่มีข้อมูลเรื่องนี้ |
กรณีที่ 6 คือจุดที่ผู้เรียนมักตื่นเต้นที่สุด เพราะเห็นชัดว่าบอทจำบริบทได้
5.3 ตัวอย่างการสนทนาจริง

- “เปิดกี่โมง” — ตรงกับคำถาม “บริษัทเปิดทำการกี่โมง” ในไฟล์ Excel แค่ระดับคำสำคัญ ไม่ใช่คำต่อคำ แต่บอทก็หาเจอและตอบได้ตรง
- “มีสสัสดิการอะไรบ้าง” (พิมพ์ตกหล่นด้วย) — ไม่มีแถวไหนในไฟล์ Excel ถามคำถามนี้ตรง ๆ บอทจึงรวมคำตอบจากหลายแถวในหมวด HR และสวัสดิการเข้าด้วยกันเอง นี่คือขั้นตอน AI สังเคราะห์คำตอบ (RAG) ที่อธิบายไว้ในบทที่ 6 ไม่ใช่การหาแถวที่ตรงที่สุดแถวเดียว
- “ลากิจได้กี่วัน ได้เงินไหม” — ส่วน “3 วันทำการ” มาจากไฟล์ Excel ตรง ๆ แต่ส่วน “ไม่ได้รับค่าจ้าง” เป็นสิ่งที่ AI อนุมานเอง เพราะไฟล์ความรู้ตัวอย่างชุดนี้ (ทั้ง Excel และ .docx) ไม่มีข้อความไหนระบุเรื่องนี้ตรง ๆ — เอกสารบอกแค่ว่าลาป่วย ลาคลอด และลาทหารได้รับค่าจ้าง แต่ไม่ได้พูดถึงลากิจเลย นี่คือตัวอย่างจริงว่า AI สังเคราะห์คำตอบได้ไกลกว่าที่ข้อมูลมีจริง — ถ้าจะเอาไปตอบเรื่องที่มีผลทางกฎหมายหรือการเงิน ควรเขียนคำตอบนั้นให้ชัดเจนในไฟล์ความรู้เอง อย่าปล่อยให้ AI อนุมานเอง
5.4 ถ้าไม่มีอะไรเกิดขึ้น
เปิดเมนู Executions ใน n8n แล้วดูว่ามี execution เข้ามาไหม
- ไม่มีเลย → ปัญหาอยู่ฝั่ง LINE หรือ tunnel (webhook URL ผิด, ไม่ได้เปิด Use webhook, cloudflared ปิดไปแล้ว, workflow ยังไม่ Publish)
- มีแต่ error → ปัญหาอยู่ใน workflow ดูว่าโหนดไหนแดง
เข้าใจโค้ดสำคัญ
6.1 แกะ event ของ LINE
LINE ส่ง webhook มาเป็น array ของ event ไม่ใช่ event เดียว และมีหลายประเภทที่ไม่ต้องตอบ
const body = $json.body ?? $json ?? {};
const events = Array.isArray(body.events) ? body.events : [];
const out = [];
for (const ev of events) {
const replyToken = ev.replyToken || '';
const userId = ev.source?.userId || ev.source?.groupId || ev.source?.roomId || 'unknown';
if (ev.type === 'follow') { // เพิ่มเพื่อน → ทักทาย
out.push({ json: { replyToken, userId, question: '', messageType: 'none' } });
continue;
}
if (ev.type !== 'message') continue; // ข้าม unfollow, join, postback
if (!replyToken) continue;
const msg = ev.message || {};
const question = msg.type === 'text' ? String(msg.text || '').trim() : '';
out.push({ json: { replyToken, userId, question, messageType: msg.type } });
}
return out;สามเรื่องที่โค้ดนี้จัดการให้
- LINE ส่ง array ว่างมาตอน Verify ถ้าโค้ดไม่เช็ก Array.isArray จะพังทันทีตอนกดปุ่ม Verify ในคอนโซล
- LINE รวมหลาย event มาใน request เดียวได้ ถ้าสองคนพิมพ์พร้อมกัน โค้ดต้องคืนหลาย item และแต่ละ item ต้องพก replyToken ของตัวเอง
- event ที่ไม่ต้องตอบมีเยอะ unfollow, join, leave, postback ถ้าไม่กรองออกจะพยายามตอบแล้ว error
6.2 กฎของ replyToken ที่ต้องรู้
- ใช้ได้ครั้งเดียว ส่งซ้ำจะได้ 400
- หมดอายุประมาณ 1 นาที ถ้า AI คิดนานเกินไปจะส่งไม่ทัน
- ตอบได้สูงสุด 5 ข้อความต่อหนึ่ง token
ถ้าต้องการส่งข้อความหลังจากนั้น ต้องใช้ Push API แทน ซึ่งนับโควตาข้อความ ต่างจาก Reply API ที่ไม่นับ นี่คือเหตุผลที่ระบบนี้ตอบด้วย reply เสมอ
6.3 กับดัก: HTTP Request ลบข้อมูลเดิมทิ้ง
ตอนแรกวาง Show_Typing คั่นระหว่าง Parse_Line_Event กับ Find_Answer ผลคือบอทตอบข้อความทักทายทุกครั้งไม่ว่าจะถามอะไร
สาเหตุคือ โหนด HTTP Request แทนที่ json ของ item ด้วย response ที่ API ตอบกลับมา พอ LINE ตอบ {} ว่าง ๆ กลับมา ข้อมูล question replyToken userId ที่แกะไว้ก็หายหมด Find_Answer เลยเห็นคำถามเป็นค่าว่าง
วิธีแก้คือให้ Show_Typing เป็น กิ่งขนาน แยกออกจากเส้นทางหลัก
Parse_Line_Event ─┬─ Show_Typing (จบในตัว)
└─ Find_Answer → ...n8n จะรันกิ่งที่อยู่ลำดับแรกก่อน จุดสามจุดจึงยังขึ้นก่อนที่ AI จะเริ่มคิดเหมือนเดิม
6.4 ความจำแยกรายบุคคล
Chat_Memory ใช้ userId ของ LINE เป็นคีย์ แต่ละคนจึงมีบทสนทนาของตัวเอง ไม่ปนกัน ต่างจากเวอร์ชันหน้าเว็บที่ใช้ sessionId ของเบราว์เซอร์
const sessionId = $json.userId ?? $json.sessionId ?? 'default';
userId ของ LINE เป็นค่าคงที่ต่อหนึ่งผู้ใช้ต่อหนึ่ง OA จึงจำข้ามวันได้ด้วย ไม่ใช่แค่ในเซสชันเดียว
ปัญหาที่เจอบ่อย
| อาการ | สาเหตุ | วิธีแก้ |
|---|---|---|
| port 5678 is already in use | n8n ตัวเดิมยังรันอยู่ | kill -9 $(lsof -ti :5678) |
| สั่ง --tunnel แล้วไม่มี URL ขึ้น | n8n 2.0 ถอดออกแล้ว | ใช้ cloudflared |
| ฟอร์มหมุนค้าง + CORS error ในคอนโซล | ไม่ได้ตั้ง WEBHOOK_URL | ตั้งตามหัวข้อ 2.5 แล้วรีสตาร์ท |
| Problem loading form | ยังไม่ได้ Publish | กด Publish |
| Verify ใน LINE ไม่ผ่าน | URL ผิด หรือ workflow ไม่ Active | ใช้ Production URL จากในโหนด |
| Verify ผ่านแต่บอทเงียบ | ยังไม่เปิด Use webhook | เปิดสวิตช์ใน Messaging API |
| บอทตอบข้อความสำเร็จรูปของ LINE | ยังไม่ปิดการตอบกลับอัตโนมัติ | ปิดใน OA Manager |
| Send_Line_Reply ขึ้น 401 | โทเคนผิด หรือลืมคำว่า Bearer | แก้ที่ credential |
| Send_Line_Reply ขึ้น 400 | replyToken หมดอายุหรือถูกใช้ไปแล้ว | ดูว่า AI ใช้เวลานานเกิน 1 นาทีไหม |
| ถามอะไรก็ตอบข้อความทักทาย | Show_Typing คั่นเส้นทางหลัก | แยกเป็นกิ่งขนาน (บท 6.3) |
| บอทบอกว่ายังไม่มีข้อมูล | ยังไม่ได้อัปโหลดไฟล์เข้า workflow ตัวนี้ | อัปโหลดผ่าน Production URL |
| อ่าน .docx ไม่ได้ | ไม่ได้ตั้ง zlib หรืออยู่บน Cloud | ตั้ง env var หรือแปลงเป็น PDF |
| ข้อความขึ้นสัญลักษณ์ขึ้นบรรทัดใหม่ในตารางของ n8n | เป็นแค่วิธีแสดงผลของ n8n | ไม่ต้องแก้ ใน LINE ขึ้นบรรทัดใหม่ถูกต้อง |
ต้นทุนต่อคำถาม
วัดจากระบบจริง คำถามแรกของแต่ละคนใช้ 467 input tokens เมื่อคุยต่อเนื่องจะไต่ขึ้นไปนิ่งที่ประมาณ 750 โทเคนตั้งแต่รอบที่ 6
ใช้ค่าเฉลี่ย 600 โทเคนเป็นตัวเลขวางแผน
| ปริมาณ | ค่าใช้จ่ายโดยประมาณ |
|---|---|
| 1 คำถาม | 0.0042 บาท |
| 1,000 คำถาม | ~5 บาท |
| 10,000 คำถาม | ~50 บาท |
คำสั่งพิเศษ (/stats, /sources) และกรณีที่ค้นไม่เจอไม่เรียก AI จึงไม่เสียเงิน ส่วน LINE Messaging API ใช้ Reply API ซึ่งไม่นับโควตาข้อความ ตราบใดที่ไม่ได้ส่ง Push
ก่อนขึ้นจริง
9.1 ตรวจลายเซ็นของ LINE
เปิดโมดูล crypto เพิ่ม
NODE_FUNCTION_ALLOW_BUILTIN=zlib,crypto n8n start
แล้วเพิ่ม Code node ต่อจาก Line_Webhook
const crypto = require('crypto');
const sig = $json.headers['x-line-signature'];
const expected = crypto
.createHmac('SHA256', $env.LINE_CHANNEL_SECRET)
.update(JSON.stringify($json.body))
.digest('base64');
if (sig !== expected) throw new Error('ลายเซ็นไม่ถูกต้อง');
return $input.all();เก็บ Channel secret ไว้ใน environment variable ไม่ใช่ในโค้ด
9.2 ย้ายออกจาก tunnel
Quick tunnel ของ Cloudflare เหมาะกับการทดสอบเท่านั้น URL เปลี่ยนทุกครั้งที่รีสตาร์ท ทางเลือกสำหรับใช้จริงเรียงตามความง่าย
- n8n Cloud — ไม่ต้องดูแลอะไรเลย แลกกับข้อจำกัดเรื่อง .docx
- VPS + Cloudflare Tunnel แบบ named tunnel — ผูกโดเมนตัวเอง URL คงที่ ตั้ง env var ได้ครบ
- VPS + reverse proxy (nginx/Caddy) + SSL — คุมได้ทุกอย่าง แต่ต้องดูแลเอง
9.3 เรื่องที่ควรคิดต่อ
- ข้อมูลส่วนบุคคล คำถามของพนักงานจะถูกส่งไป OpenAI ควรแจ้งให้ทราบและกำหนดว่าห้ามพิมพ์ข้อมูลอ่อนไหวลงแชท
- ฐานความรู้ใน static data เหมาะกับข้อมูลไม่เยอะและผู้ดูแลคนเดียว ถ้าจะโตกว่านี้ควรย้ายไป Google Sheets หรือฐานข้อมูลจริง
- log คำถามที่ตอบไม่ได้ ใช้ /misses ดูเป็นประจำแล้วเติมเข้าไฟล์ Excel จะทำให้บอทฉลาดขึ้นเรื่อย ๆ โดยไม่ต้องแตะโค้ด
- ง่ายเปลี่ยนข้อความทักทายตอนแอดเพื่อนให้เป็นชื่อหน่วยงานของตัวเอง
- ง่ายทดสอบครบทั้ง 8 กรณีในบทที่ 5.2 แล้วบันทึกผลว่าข้อไหนไม่ผ่านและเพราะอะไร
- กลางเพิ่มการจัดการ event ประเภท postback เพื่อรองรับ Rich Menu
- กลางทำให้บอทตอบเป็น Flex Message แทนข้อความธรรมดาเมื่อคำตอบมีหลายหัวข้อ
- กลางเพิ่มโหนดแจ้งเตือนเข้ากลุ่ม LINE ของผู้ดูแลทุกครั้งที่บอทตอบไม่ได้
- ยากเพิ่มการตรวจลายเซ็นตามบทที่ 9.1 แล้วทดสอบด้วยการยิง request ปลอมด้วย curl ว่าถูกปฏิเสธจริง
- ยากทำให้บอทรองรับการถามในกลุ่ม LINE โดยตอบเฉพาะเมื่อถูก mention เท่านั้น
การต่อ LINE OA ไม่ได้ยากที่ตัวโค้ด แต่ยากที่ การตั้งค่ารอบนอก ทั้งเรื่อง tunnel, URL ของ n8n, การ Publish, สวิตช์ใน LINE สองหน้าเว็บ และการปิดการตอบกลับอัตโนมัติ ทุกจุดที่ลืมจะให้อาการ "บอทเงียบ" เหมือนกันหมด ซึ่งเป็นอาการที่หาสาเหตุยากที่สุด
เช็กลิสต์ในบทที่ 5.1 กับตารางในบทที่ 7 จึงเป็นสองส่วนที่ควรพิมพ์แจกผู้เรียนไว้ข้างตัว
ส่วนที่เหลือ — การค้นหาภาษาไทย การตัดท่อนเอกสาร การให้ AI เรียบเรียง — ยกมาจากคอร์สหลักได้ทั้งหมดโดยไม่ต้องแก้อะไรเลย นั่นคือข้อดีของการแยกฝั่งรับข้อความออกจากฝั่งประมวลผลตั้งแต่แรก อยากเปลี่ยนไปใช้ Facebook Messenger, Discord หรือ Telegram ก็เปลี่ยนแค่สามโหนดหัวท้าย
ตรวจกับเอกสารทางการเมื่อ กันยายน 2569 — ราคา ฟีเจอร์ และเงื่อนไขบริการภายนอก เปลี่ยนแปลงได้ตลอด ก่อนนำไปสอนควรเปิดเช็กซ้ำจากลิงก์ด้านล่าง
- n8n · v2.0 Breaking changes — ยืนยันว่า --tunnel ถูกถอดออกจริง
- LINE · Verify webhook signature — อัลกอริทึมตรวจลายเซ็นที่ใช้ในบทที่ 9.1
- LINE · Messaging API reference — อายุและข้อจำกัดของ replyToken
- LINE · Messaging API pricing — ยืนยันว่า Reply API ไม่นับโควตาข้อความ
- LINE Developers Console — สร้าง Channel และเอา token
- LINE Official Account Manager — ปิดการตอบกลับอัตโนมัติ
คอร์สหลักที่บทนี้ต่อยอดมา ต้องทำให้จบก่อนค่อยมาต่อ LINE
ยังไม่เคยใช้ n8n มาก่อน เริ่มที่บทเรียนนี้ก่อน
อยากเสนอโครงการนี้ให้หน่วยงาน ดูตัวอย่างข้อเสนอฉบับเต็ม
คำถามพนักงานจะถูกส่งไป OpenAI ควรรู้ว่าข้อมูลไปไหนบ้าง