LINE × n8n × ChatGPT × Google Sheets による FAQ 自動応答システム手順書
目次
■ 構築の目的
淡路島の飲食・宿泊業向けに、LINEからの質問にChatGPTが自動応答する仕組みを構築。FAQはGoogleスプレッドシートで管理。
■ 前提環境
- n8n Self Hosted(fly.io)
- LINE公式アカウント(Messaging API設定済み)
- OpenAI APIキー取得済み
- Google Cloud Console アカウントとSheets API有効化済み
■ ステップ1:n8nのfly.ioデプロイ
- fly.io CLIインストール:
iwr https://fly.io/install.ps1 -useb | iex
- 新アプリ作成:
flyctl launch
- ボリューム追加:
fly volume create n8n_data -r ams
- fly.toml にマウント設定を記述:
123[[mounts]]source = "n8n_data"destination = "/home/node/.n8n" - 環境変数の設定:
flyctl secrets set WEBHOOK_URL=https://n8n-xxxx.fly.dev
flyctl secrets set N8N_OAUTH_UI_ENABLED=true
- BASIC認証を使う場合:
flyctl secrets set N8N_BASIC_AUTH_ACTIVE=true N8N_BASIC_AUTH_USER=admin N8N_BASIC_AUTH_PASSWORD=your_password
■ ステップ2:LINE Developers設定
- LINE公式アカウントとMessaging APIチャネル作成
- Webhook URLにn8nのWebhook Node URLを設定
- Webhookを「有効化」
- チャネルアクセストークンを取得し、n8n HTTPリクエストに使用
■ ステップ3:n8nでワークフロー構築
① Webhook ノード
- HTTP Method: POST
- Path: /webhook/line-webhook
② Codeノード:質問とFAQ整形
1 2 3 4 5 6 7 8 9 10 11 |
const faqs = $input.all().map(item => ({ keyword: item.json.keyword, answer: item.json.answer })); return [{ json: { faqs, userQuestion: $('Webhook').first().json.body.events[0].message.text } }]; |
③ HTTP Requestノード(ChatGPT)
- URL: https://api.openai.com/v1/chat/completions
- Headers:
- Authorization: Bearer sk-xxxxx
- Content-Type: application/json
- Body Parameters:
1234567891011121314{"model": "gpt-4","messages": [{"role": "system","content": "ユーザーの質問に最も近いFAQがあれば、それに対する回答のみを1つ返してください。"},{"role": "user","content": "ユーザーの質問: {{ $json.userQuestion.replace(/\\/g, '\\\\').replace(/\"/g, '\\\"').replace(/\n/g, '\\n').replace(/\r/g, '\\r') }}\n\nFAQ一覧:\n{{ JSON.stringify($json.faqs).replace(/\\/g, '\\\\').replace(/\"/g, '\\\"').replace(/\n/g, '\\n').replace(/\r/g, '\\r') }}"}],"temperature": 0.3}
④ HTTP Requestノード(LINEへの返信)
1 2 3 4 5 6 7 8 9 |
{ "replyToken": "{{ $('Webhook').first().json.body.events[0].replyToken }}", "messages": [ { "type": "text", "text": "{{ $('HTTP Request2').first().json.choices[0].message.content }}" } ] } |
■ トラブルと対処
問題 | 原因 | 解決策 |
---|---|---|
JSON parameter needs to be valid JSON | エスケープ不足 | replace で整形 |
[object Object]が出力される | オブジェクトそのまま展開 | JSON.stringify() で変換 |
replyTokenがundefined | itemの扱いミス | .first() を使って明示 |
Connectボタンが出ない | OAuthリダイレクト未設定 | リダイレクトURI設定と本番公開 |
データが消えた | volume未マウントで再起動 | [[mounts]] とvolume永続化確認 |