返回首頁Dialogflow

Dialogflow Fulfillment 與 API 整合完整教學

15 min 分鐘閱讀
#Dialogflow#Fulfillment#Webhook#API#Cloud Functions

Dialogflow Fulfillment 與 API 整合完整教學

Dialogflow Fulfillment 與 API 整合完整教學

靜態回覆只能做簡單的 FAQ 機器人。要讓機器人真正有用,必須連接後端系統:查訂單、查庫存、處理預約。

Dialogflow 透過 Fulfillment(Webhook)讓你的機器人能呼叫外部 API,實現動態回覆。這篇文章從零開始,教你開發 Webhook、部署到 Cloud Functions、整合第三方 API。

如果你還不熟悉 Dialogflow 基礎,建議先閱讀 Dialogflow 完整指南Intent 與 Context 教學


Fulfillment 基礎概念

什麼時候需要 Fulfillment

不需要 Fulfillment 的場景

  • 回答固定問題(營業時間、地址)
  • 純粹的閒聊對話
  • 提供靜態資訊

需要 Fulfillment 的場景

  • 查詢即時資訊(訂單狀態、庫存數量)
  • 執行動作(建立訂單、預約)
  • 根據條件動態回覆
  • 連接外部系統(CRM、ERP)

Webhook 運作原理

使用者 → Dialogflow → Webhook → 你的後端 → Webhook → Dialogflow → 使用者
  │          │          │          │          │          │          │
「查訂單」   意圖理解   呼叫API    查資料庫    回傳結果   組合回覆   「您的訂單...」

流程說明

  1. Dialogflow 偵測到需要 Fulfillment 的 Intent
  2. 發送 HTTP POST 請求到你設定的 Webhook URL
  3. 你的 Webhook 處理請求,呼叫資料庫或 API
  4. 回傳結構化的 JSON 給 Dialogflow
  5. Dialogflow 把內容發送給使用者

ES vs CX Fulfillment 差異

差異ESCX
Request 格式v2 API 格式v3 API 格式
Response 格式fulfillmentText / messagesfulfillmentResponse
Context 處理outputContextssessionInfo.parameters
觸發方式Intent 級別啟用Page/Route 級別啟用
官方 SDKdialogflow-fulfillment無官方 SDK

本文主要以 ES 為例,CX 的 Webhook 開發請參考 Dialogflow CX 教學

插圖:Fulfillment 架構圖

場景描述: 一張架構圖展示 Fulfillment 的資料流。左側是使用者和 Dialogflow,中間是 Webhook 服務(Cloud Functions),右側是後端系統(資料庫、第三方 API)。箭頭標示 Request 和 Response 的方向和內容。

視覺重點:

  • 主要內容清晰呈現

必須出現的元素:

  • 依據描述中的關鍵元素

需要顯示的中文字:

顏色調性: 專業、清晰

避免元素: 抽象圖形、齒輪、發光特效

Slug: dialogflow-fulfillment-architecture


建立 Webhook 服務

使用 Cloud Functions(推薦)

Google Cloud Functions 是最簡單的 Webhook 部署方式,免管伺服器、自動擴展。

Step 1:建立 Cloud Function

  1. 前往 Google Cloud Console
  2. 選擇你的專案(與 Dialogflow Agent 相同)
  3. 搜尋「Cloud Functions」並進入
  4. 點擊「Create Function」

基本設定

  • Function name:dialogflow-webhook
  • Region:asia-east1(台灣)
  • Trigger type:HTTPS
  • Authentication:Allow unauthenticated invocations

Step 2:撰寫程式碼

選擇 Runtime:Node.js 20

package.json

{
  "name": "dialogflow-webhook",
  "version": "1.0.0",
  "dependencies": {
    "dialogflow-fulfillment": "^0.6.1"
  }
}

index.js

const { WebhookClient } = require('dialogflow-fulfillment');

exports.dialogflowWebhook = (request, response) => {
  const agent = new WebhookClient({ request, response });

  console.log('Intent: ' + agent.intent);
  console.log('Parameters: ' + JSON.stringify(agent.parameters));

  function welcome(agent) {
    agent.add('歡迎使用我們的服務!請問有什麼可以幫您?');
  }

  function fallback(agent) {
    agent.add('抱歉,我不太理解您的意思。');
  }

  function checkOrder(agent) {
    const orderId = agent.parameters.order_id;
    // 這裡呼叫你的訂單系統
    agent.add(`訂單 ${orderId} 的狀態是:處理中,預計明天出貨。`);
  }

  const intentMap = new Map();
  intentMap.set('Default Welcome Intent', welcome);
  intentMap.set('Default Fallback Intent', fallback);
  intentMap.set('check_order', checkOrder);

  agent.handleRequest(intentMap);
};

Step 3:部署

  1. 點擊「Deploy」
  2. 等待部署完成(約 1-2 分鐘)
  3. 複製觸發 URL

Step 4:在 Dialogflow 設定

  1. 進入 Dialogflow Console
  2. 點擊左側「Fulfillment」
  3. 啟用「Webhook」
  4. 貼上 Cloud Functions 的 URL
  5. 點擊「Save」

Step 5:啟用 Intent 的 Fulfillment

  1. 進入需要 Fulfillment 的 Intent
  2. 滾動到最下方
  3. 展開「Fulfillment」區塊
  4. 勾選「Enable webhook call for this intent」
  5. 儲存

使用 Node.js + Express

如果你想在自己的伺服器部署:

const express = require('express');
const { WebhookClient } = require('dialogflow-fulfillment');

const app = express();
app.use(express.json());

app.post('/webhook', (req, res) => {
  const agent = new WebhookClient({ request: req, response: res });

  function handleIntent(agent) {
    agent.add('這是自訂伺服器的回覆');
  }

  const intentMap = new Map();
  intentMap.set('my_intent', handleIntent);

  agent.handleRequest(intentMap);
});

app.listen(3000, () => {
  console.log('Webhook server running on port 3000');
});

注意:自建伺服器需要:

  • HTTPS(可用 ngrok 測試)
  • 公開可存取的 URL
  • 處理擴展性問題

使用 Python Flask

from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/webhook', methods=['POST'])
def webhook():
    req = request.get_json()

    intent_name = req['queryResult']['intent']['displayName']
    parameters = req['queryResult']['parameters']

    if intent_name == 'check_order':
        order_id = parameters.get('order_id')
        response_text = f'訂單 {order_id} 的狀態是:處理中'
    else:
        response_text = '收到您的訊息'

    return jsonify({
        'fulfillmentText': response_text
    })

if __name__ == '__main__':
    app.run(port=5000)

部署與 HTTPS 設定

本地測試用 ngrok

# 安裝 ngrok
npm install -g ngrok

# 啟動本地伺服器
node server.js

# 另一個終端機
ngrok http 3000

# 複製 ngrok 給的 HTTPS URL,貼到 Dialogflow

正式部署選項

  • Google Cloud Functions(推薦)
  • Google Cloud Run
  • AWS Lambda
  • Heroku
  • 自建伺服器 + SSL 憑證

Dialogflow API 呼叫

除了被動接收 Webhook,你也可以主動呼叫 Dialogflow API。

DetectIntent API

DetectIntent API 讓你從自己的應用程式發送訊息給 Dialogflow。

使用場景

  • 自建聊天介面
  • 整合到現有 App
  • 批次測試對話

服務帳戶與驗證設定

Step 1:建立服務帳戶

  1. 前往 Google Cloud Console > IAM & Admin > Service Accounts
  2. 點擊「Create Service Account」
  3. 輸入名稱(如:dialogflow-client)
  4. 授予角色:「Dialogflow API Client」
  5. 建立金鑰(JSON 格式)
  6. 下載並安全保存金鑰檔案

Step 2:設定環境變數

export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account-key.json"

範例程式碼

Node.js

const dialogflow = require('@google-cloud/dialogflow');
const uuid = require('uuid');

async function detectIntent(projectId, text) {
  const sessionId = uuid.v4();
  const sessionClient = new dialogflow.SessionsClient();
  const sessionPath = sessionClient.projectAgentSessionPath(projectId, sessionId);

  const request = {
    session: sessionPath,
    queryInput: {
      text: {
        text: text,
        languageCode: 'zh-TW',
      },
    },
  };

  const [response] = await sessionClient.detectIntent(request);
  const result = response.queryResult;

  console.log('Intent:', result.intent.displayName);
  console.log('Response:', result.fulfillmentText);

  return result;
}

// 使用範例
detectIntent('your-project-id', '我要訂位');

Python

from google.cloud import dialogflow_v2 as dialogflow
import uuid

def detect_intent(project_id, text):
    session_client = dialogflow.SessionsClient()
    session_id = str(uuid.uuid4())
    session = session_client.session_path(project_id, session_id)

    text_input = dialogflow.TextInput(text=text, language_code='zh-TW')
    query_input = dialogflow.QueryInput(text=text_input)

    response = session_client.detect_intent(
        request={'session': session, 'query_input': query_input}
    )

    result = response.query_result
    print(f'Intent: {result.intent.display_name}')
    print(f'Response: {result.fulfillment_text}')

    return result

# 使用範例
detect_intent('your-project-id', '我要訂位')

插圖:DetectIntent API 流程圖

場景描述: 一張流程圖展示 DetectIntent API 的呼叫過程。從左到右:你的應用程式 → API Request(含 projectId、sessionId、text)→ Dialogflow → API Response(含 intent、fulfillmentText)→ 你的應用程式。

視覺重點:

  • 主要內容清晰呈現

必須出現的元素:

  • 依據描述中的關鍵元素

需要顯示的中文字:

顏色調性: 專業、清晰

避免元素: 抽象圖形、齒輪、發光特效

Slug: dialogflow-detect-intent-api-flow


GitHub 範例專案

官方範例庫介紹

Google 提供官方範例程式碼:

Dialogflow ES

Dialogflow CX

社群推薦專案

專案語言功能
dialogflow-fulfillment-nodejsNode.js官方 Fulfillment 函式庫
flask-dialogflow-webhookPythonFlask Webhook 模板
dialogflow-angularTypeScriptAngular 整合範例

快速部署模板

一鍵部署到 Cloud Functions

# 克隆範例專案
git clone https://github.com/your-repo/dialogflow-webhook-template.git
cd dialogflow-webhook-template

# 部署
gcloud functions deploy dialogflow-webhook \
  --runtime nodejs20 \
  --trigger-http \
  --allow-unauthenticated \
  --region asia-east1

進階整合

連接資料庫(Firestore / MySQL)

Firestore 範例

const { Firestore } = require('@google-cloud/firestore');
const firestore = new Firestore();

async function checkOrder(agent) {
  const orderId = agent.parameters.order_id;

  const doc = await firestore.collection('orders').doc(orderId).get();

  if (!doc.exists) {
    agent.add('找不到這筆訂單,請確認訂單編號是否正確。');
    return;
  }

  const order = doc.data();
  agent.add(`訂單 ${orderId} 的狀態是:${order.status},預計 ${order.delivery_date} 送達。`);
}

MySQL 範例

const mysql = require('mysql2/promise');

async function checkInventory(agent) {
  const productName = agent.parameters.product;

  const connection = await mysql.createConnection({
    host: process.env.DB_HOST,
    user: process.env.DB_USER,
    password: process.env.DB_PASSWORD,
    database: process.env.DB_NAME,
  });

  const [rows] = await connection.execute(
    'SELECT stock FROM products WHERE name = ?',
    [productName]
  );

  if (rows.length > 0) {
    agent.add(`${productName} 目前庫存 ${rows[0].stock} 件。`);
  } else {
    agent.add('找不到這個商品。');
  }

  await connection.end();
}

呼叫第三方 API

天氣 API 範例

const axios = require('axios');

async function getWeather(agent) {
  const city = agent.parameters['geo-city'];

  try {
    const response = await axios.get(
      `https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${process.env.WEATHER_API_KEY}&units=metric&lang=zh_tw`
    );

    const weather = response.data;
    agent.add(`${city} 目前天氣:${weather.weather[0].description},氣溫 ${weather.main.temp}°C。`);
  } catch (error) {
    agent.add('抱歉,無法取得天氣資訊,請稍後再試。');
  }
}

非同步處理與長時間任務

Dialogflow Webhook 有 5 秒的 timeout 限制。如果任務需要更久:

方法 1:快速回覆 + 後續通知

async function processLongTask(agent) {
  const taskId = generateTaskId();

  // 立即回覆
  agent.add(`收到您的請求,處理中...我們會在完成後通知您(任務編號:${taskId})`);

  // 非同步處理(不等待)
  processTaskInBackground(taskId);
}

async function processTaskInBackground(taskId) {
  // 執行長時間任務
  const result = await someHeavyOperation();

  // 完成後發送通知(透過 LINE Push、Email 等)
  await sendNotification(taskId, result);
}

方法 2:使用 Cloud Tasks

把任務放入佇列,另一個服務處理:

const { CloudTasksClient } = require('@google-cloud/tasks');

async function queueTask(agent) {
  const client = new CloudTasksClient();

  const task = {
    httpRequest: {
      httpMethod: 'POST',
      url: 'https://your-worker-service.com/process',
      body: Buffer.from(JSON.stringify({ data: agent.parameters })).toString('base64'),
    },
  };

  await client.createTask({ parent: queuePath, task });

  agent.add('您的請求已加入處理佇列,稍後會通知您結果。');
}

錯誤處理與重試機制

async function robustApiCall(agent) {
  const maxRetries = 3;
  let lastError;

  for (let i = 0; i < maxRetries; i++) {
    try {
      const result = await callExternalApi();
      agent.add(`查詢結果:${result}`);
      return;
    } catch (error) {
      lastError = error;
      console.error(`Attempt ${i + 1} failed:`, error.message);

      if (i < maxRetries - 1) {
        await sleep(1000 * (i + 1)); // 指數退避
      }
    }
  }

  // 所有重試都失敗
  console.error('All retries failed:', lastError);
  agent.add('系統暫時忙碌,請稍後再試。如急需協助,請撥打客服專線。');
}

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

插圖:進階整合架構圖

場景描述: 一張複雜的架構圖展示進階整合。中央是 Cloud Functions,連接到:左邊的 Dialogflow、右上的資料庫(Firestore、MySQL)、右中的第三方 API(天氣、金流)、右下的訊息服務(LINE Push、Email)。每個連接標示資料流向。

視覺重點:

  • 主要內容清晰呈現

必須出現的元素:

  • 依據描述中的關鍵元素

需要顯示的中文字:

顏色調性: 專業、清晰

避免元素: 抽象圖形、齒輪、發光特效

Slug: dialogflow-advanced-integration-architecture


整合做不出來?後端整合是技術門檻最高的部分,牽涉到資安、效能、錯誤處理。預約技術諮詢,讓有經驗的人幫你解決整合難題。


部署與維運

監控與日誌

Cloud Functions 日誌

  1. 前往 Google Cloud Console > Cloud Functions
  2. 選擇你的 Function
  3. 點擊「Logs」分頁

設定告警

  1. 前往 Cloud Monitoring
  2. 建立告警政策
  3. 設定條件:錯誤率 > 5%、延遲 > 2 秒
  4. 設定通知管道(Email、Slack)

效能優化

1. 減少冷啟動

// 在 Function 外初始化連線,避免每次都重新連
const firestore = new Firestore();

exports.webhook = async (req, res) => {
  // 使用已建立的連線
  const doc = await firestore.collection('orders').doc('123').get();
  // ...
};

2. 使用快取

const NodeCache = require('node-cache');
const cache = new NodeCache({ stdTTL: 300 }); // 5 分鐘快取

async function getData(key) {
  let data = cache.get(key);

  if (!data) {
    data = await fetchFromDatabase(key);
    cache.set(key, data);
  }

  return data;
}

3. 設定 minimum instances

避免冷啟動延遲:

gcloud functions deploy webhook \
  --min-instances 1 \
  --max-instances 10

安全性考量

1. 驗證請求來源

確認請求真的來自 Dialogflow:

// 檢查 User-Agent
if (!req.headers['user-agent'].includes('Google-Dialogflow')) {
  return res.status(403).send('Forbidden');
}

2. 環境變數管理

敏感資訊不要寫在程式碼中:

// ❌ 不好
const apiKey = 'sk-xxxxx';

// ✓ 好
const apiKey = process.env.API_KEY;

3. 限制存取範圍

服務帳戶只給需要的權限,不要用 Owner 權限。

如果需要整合到行動 App,請參考 Dialogflow 行動開發整合教學。LINE Bot 整合請參考 Dialogflow LINE Bot 串接教學


下一步

掌握 Fulfillment 開發後,你可以:

  1. 優化對話設計Dialogflow Intent 與 Context 完整教學
  2. 學習 CX 版本Dialogflow CX 教學:從入門到進階
  3. 整合 LINE BotDialogflow LINE Bot 串接教學
  4. 行動 App 整合Dialogflow 行動開發整合教學

後端整合需要協助?

好的後端架構能讓系統穩定、安全、易於擴展。不好的架構會在流量增加時出問題,或成為資安漏洞。

如果你需要:

  • 設計可擴展的 Webhook 架構
  • 整合複雜的企業系統
  • 處理高流量場景
  • 確保資安合規

預約架構諮詢,讓有經驗的工程師幫你設計穩健的後端架構。

諮詢完全免費,我們會在 24 小時內回覆。


需要專業的雲端建議?

無論您正在評估雲平台、優化現有架構,或尋找節費方案,我們都能提供協助

預約免費諮詢

相關文章