Webhook

Để giúp bạn linh hoạt hơn nữa trong việc tạo Hành động, bạn có thể uỷ quyền logic cho các dịch vụ web HTTPS (phương thức thực hiện). Hành động của bạn có thể kích hoạt các webhook gửi yêu cầu đến một điểm cuối HTTPS. Sau đây là một số ví dụ về những việc bạn có thể làm trong quá trình thực hiện:

  • Tạo lời nhắc linh hoạt dựa trên thông tin do người dùng cung cấp.
  • Đặt hàng trong hệ thống bên ngoài và xác nhận thành công.
  • Xác thực các vị trí có dữ liệu phụ trợ.
Hình 1. Ý định và cảnh gọi có thể kích hoạt webhook.

Trình kích hoạt và trình xử lý webhook

Hành động của bạn có thể kích hoạt một webhook trong ý định gọi hoặc cảnh, từ đó gửi yêu cầu đến điểm cuối của phương thức thực hiện. Phương thức thực hiện của bạn chứa trình xử lý webhook xử lý tải trọng JSON trong yêu cầu. Bạn có thể kích hoạt webhook trong các trường hợp sau:

  • Sau khi khớp ý định gọi
  • Trong khi một cảnh quay chuẩn bị vào sân khấu
  • Sau khi một điều kiện được đánh giá là true trong giai đoạn điều kiện của một cảnh
  • Trong giai đoạn lấp đầy vị trí của cảnh
  • Sau khi quá trình so khớp ý định xảy ra trong giai đoạn đầu vào của một cảnh

Khi bạn kích hoạt một webhook trong Hành động, Trợ lý Google sẽ gửi một yêu cầu có tải trọng JSON đến phương thức thực hiện của bạn. Yêu cầu này chứa tên của trình xử lý cần sử dụng để xử lý sự kiện. Điểm cuối của phương thức thực hiện có thể chuyển sự kiện đến trình xử lý thích hợp để thực hiện logic và trả về một phản hồi tương ứng có tải trọng JSON.

Gói dữ liệu

Các đoạn mã sau đây cho thấy các yêu cầu mẫu mà Hành động của bạn gửi tới phương thức thực hiện và phản hồi mà phương thức thực hiện của bạn gửi lại. Hãy xem tài liệu tham khảo để biết thêm thông tin.

Yêu cầu mẫu

{
  "handler": {
    "name": "handler_name"
  },
  "intent": {
    "name": "actions.intent.MAIN",
    "params": {},
    "query": ""
  },
  "scene": {
    "name": "SceneName",
    "slotFillingStatus": "UNSPECIFIED",
    "slots": {}
  },
  "session": {
    "id": "example_session_id",
    "params": {},
    "typeOverrides": []
  },
  "user": {
    "locale": "en-US",
    "params": {
      "verificationStatus": "VERIFIED"
    }
  },
  "home": {
    "params": {}
  },
  "device": {
    "capabilities": [
      "SPEECH",
      "RICH_RESPONSE",
      "LONG_FORM_AUDIO"
    ]
  }
}

Ví dụ về phản hồi

{
  "session": {
    "id": "example_session_id",
    "params": {}
  },
  "prompt": {
    "override": false,
    "firstSimple": {
      "speech": "Hello World.",
      "text": ""
    }
  },
  "scene": {
    "name": "SceneName",
    "slots": {},
    "next": {
      "name": "actions.scene.END_CONVERSATION"
    }
  }
}

Tương tác trong thời gian chạy

Các phần sau đây mô tả các tác vụ phổ biến mà bạn có thể thực hiện trong trình xử lý webhook.

Gửi lời nhắc

Bạn có thể tạo lời nhắc bằng văn bản đơn giản, văn bản đa dạng thức, thẻ và thậm chí cả lời nhắc HTML hoàn chỉnh được hỗ trợ bởi ứng dụng web có Canvas tương tác. Tài liệu về lời nhắc có đầy đủ thông tin về cách tạo lời nhắc khi xử lý một sự kiện webhook. Các đoạn mã sau đây cho thấy lời nhắc về thẻ:

Node.js

app.handle('rich_response', conv => {
  conv.add('This is a card rich response.');
  conv.add(new Card({
    title: 'Card Title',
    subtitle: 'Card Subtitle',
    text: 'Card Content',
    image: new Image({
      url: 'https://developers.google.com/assistant/assistant_96.png',
      alt: 'Google Assistant logo'
    })
  }));
});

Định dạng JSON của phản hồi

{
  "session": {
    "id": "example_session_id",
    "params": {}
  },
  "prompt": {
    "override": false,
    "content": {
      "card": {
        "title": "Card Title",
        "subtitle": "Card Subtitle",
        "text": "Card Content",
        "image": {
          "alt": "Google Assistant logo",
          "height": 0,
          "url": "https://developers.google.com/assistant/assistant_96.png",
          "width": 0
        }
      }
    },
    "firstSimple": {
      "speech": "This is a card rich response.",
      "text": ""
    }
  }
}

Đọc tham số ý định

Khi thời gian chạy của Trợ lý khớp với một ý định, Trợ lý sẽ trích xuất mọi tham số đã xác định. Thuộc tính gốc là giá trị mà người dùng cung cấp dưới dạng dữ liệu đầu vào và thuộc tính đã được giải quyết là giá trị mà NLU đã giải quyết dữ liệu đầu vào dựa trên thông số kỹ thuật của loại.

Node.js

conv.intent.params['param_name'].original
conv.intent.params['param_name'].resolved

Yêu cầu tệp JSON

{
  "handler": {
    "name": "handler_name"
  },
  "intent": {
    "name": "intent_name",
    "params": {
      "slot_name": {
        "original": "1",
        "resolved": 1
      }
    },
    "query": ""
  },
  "scene": {
    "name": "SceneName",
    "slotFillingStatus": "UNSPECIFIED",
    "slots": {},
    "next": {
      "name": "actions.scene.END_CONVERSATION"
    }
  },
  "session": {
    "id": "session_id",
    "params": {},
    "typeOverrides": []
  },
  "user": {
    "locale": "en-US",
    "params": {
      "verificationStatus": "VERIFIED"
    }
  },
  "home": {
    "params": {}
  },
  "device": {
    "capabilities": [
      "SPEECH",
      "RICH_RESPONSE",
      "LONG_FORM_AUDIO"
    ]
  }
}

Đọc ngôn ngữ của người dùng

Giá trị này tương ứng với chế độ cài đặt ngôn ngữ của người dùng cho Trợ lý Google.

Node.js

conv.user.locale

JSON

{
  "handler": {
    "name": "handler_name"
  },
  "intent": {
    "name": "actions.intent.MAIN",
    "params": {},
    "query": ""
  },
  "scene": {
    "name": "SceneName",
    "slotFillingStatus": "UNSPECIFIED",
    "slots": {}
  },
  "session": {
    "id": "session_id",
    "params": {},
    "typeOverrides": []
  },
  "user": {
    "locale": "en-US",
    "params": {
      "verificationStatus": "VERIFIED"
    }
  },
  "home": {
    "params": {}
  },
  "device": {
    "capabilities": [
      "SPEECH",
      "RICH_RESPONSE",
      "LONG_FORM_AUDIO"
    ]
  }
}

Bộ nhớ đọc và ghi

Xem tài liệu về bộ nhớ để biết thông tin đầy đủ về cách sử dụng các tính năng bộ nhớ khác nhau.

Node.js

//read
conv.session.params.key
conv.user.params.key
conv.home.params.key

// write
conv.session.params.key = value
conv.user.params.key = value
conv.home.params.key = value 

Yêu cầu tệp JSON

{
  "handler": {
    "name": "handler_name"
  },
  "intent": {
    "name": "actions.intent.MAIN",
    "params": {},
    "query": ""
  },
  "scene": {
    "name": "SceneName",
    "slotFillingStatus": "UNSPECIFIED",
    "slots": {}
  },
  "session": {
    "id": "session_id",
    "params": {
      "key": "value"
    },
    "typeOverrides": [],
    "languageCode": ""
  },
  "user": {
    "locale": "en-US",
    "params": {
      "verificationStatus": "VERIFIED",
      "key": "value"
    }
  },
  "home": {
    "params": {
      "key": "value"
    }
  },
  "device": {
    "capabilities": [
      "SPEECH",
      "RICH_RESPONSE",
      "LONG_FORM_AUDIO"
    ]
  }
}

Định dạng JSON của phản hồi

{
  "session": {
    "id": "session_id",
    "params": {
      "key": "value"
    }
  },
  "prompt": {
    "override": false,
    "firstSimple": {
      "speech": "Hello world.",
      "text": ""
    }
  },
  "user": {
    "locale": "en-US",
    "params": {
      "verificationStatus": "VERIFIED",
      "key": "value"
    }
  },
  "home": {
    "params": {
      "key": "value"
    }
  }
}

Kiểm tra các chức năng của thiết bị

Bạn có thể kiểm tra các khả năng của thiết bị để mang lại nhiều trải nghiệm hoặc luồng cuộc trò chuyện.

Node.js

const supportsRichResponse = conv.device.capabilities.includes("RICH_RESPONSE");
const supportsLongFormAudio = conv.device.capabilities.includes("LONG_FORM_AUDIO");
const supportsSpeech = conv.device.capabilities.includes("SPEECH");
const supportsInteractiveCanvas = conv.device.capabilities.includes("INTERACTIVE_CANVAS");

Yêu cầu tệp JSON

{
  "handler": {
    "name": "handler_name"
  },
  "intent": {
    "name": "actions.intent.MAIN",
    "params": {},
    "query": ""
  },
  "scene": {
    "name": "SceneName",
    "slotFillingStatus": "UNSPECIFIED",
    "slots": {}
  },
  "session": {
    "id": "session_id",
    "params": {},
    "typeOverrides": [],
    "languageCode": ""
  },
  "user": {
    "locale": "en-US",
    "params": {
      "verificationStatus": "VERIFIED"
    }
  },
  "home": {
    "params": {}
  },
  "device": {
    "capabilities": [
      "SPEECH",
      "RICH_RESPONSE",
      "LONG_FORM_AUDIO",
      "INTERACTIVE_CANVAS"
    ]
  }
}

Để biết danh sách đầy đủ các tính năng nền tảng, hãy xem tài liệu tham khảo Capability.

Ghi đè loại thời gian chạy

Các loại thời gian chạy cho phép bạn sửa đổi thông số kỹ thuật của loại trong thời gian chạy. Bạn có thể sử dụng tính năng này để tải dữ liệu từ các nguồn khác nhằm điền các giá trị hợp lệ của một loại. Ví dụ: bạn có thể sử dụng cơ chế ghi đè loại thời gian chạy để thêm các tuỳ chọn động vào câu hỏi khảo sát hoặc để thêm một mục hằng ngày vào trình đơn.

Để sử dụng các loại thời gian chạy, bạn cần kích hoạt một webhook từ Hành động gọi một trình xử lý trong phương thức thực hiện của bạn. Tại đó, bạn có thể điền tham số session.typeOverrides vào phản hồi cho Hành động của mình. Các chế độ có sẵn bao gồm TYPE_MERGE để giữ lại các mục nhập loại hiện có hoặc TYPE_REPLACE để thay thế các mục hiện có bằng cơ chế ghi đè.

Node.js

conv.session.typeOverrides = [{
    name: type_name,
    mode: 'TYPE_REPLACE',
    synonym: {
      entries: [
        {
          name: 'ITEM_1',
          synonyms: ['Item 1', 'First item']
        },
        {
          name: 'ITEM_2',
          synonyms: ['Item 2', 'Second item']
       },
       {
          name: 'ITEM_3',
          synonyms: ['Item 3', 'Third item']
        },
        {
          name: 'ITEM_4',
          synonyms: ['Item 4', 'Fourth item']
        },
    ]
  }
}];

Định dạng JSON của phản hồi

{
  "session": {
    "id": "session_id",
    "params": {},
    "typeOverrides": [
      {
        "name": "type_name",
        "synonym": {
          "entries": [
            {
              "name": "ITEM_1",
              "synonyms": [
                "Item 1",
                "First item"
              ]
            },
            {
              "name": "ITEM_2",
              "synonyms": [
                "Item 2",
                "Second item"
              ]
            },
            {
              "name": "ITEM_3",
              "synonyms": [
                "Item 3",
                "Third item"
              ]
            },
            {
              "name": "ITEM_4",
              "synonyms": [
                "Item 4",
                "Fourth item"
              ]
            }
          ]
        },
        "typeOverrideMode": "TYPE_REPLACE"
      }
    ]
  },
  "prompt": {
    "override": false,
    "firstSimple": {
      "speech": "This is an example prompt.",
      "text": "This is an example prompt."
    }
  }
}

Cung cấp xu hướng lời nói

Tính năng xu hướng lời nói cho phép bạn chỉ định các gợi ý cho NLU để cải thiện khả năng so khớp ý định. Bạn có thể chỉ định tối đa 1.000 mục nhập.

Node.js

conv.expected.speech = ['value_1', 'value_2']
conv.expected.language = 'locale_string'

Định dạng JSON của phản hồi

{
  "session": {
    "id": "session_id",
    "params": {}
  },
  "prompt": {
    "override": false,
    "firstSimple": {
      "speech": "This is an example prompt.",
      "text": "This is an example prompt."
    }
  },
  "expected": {
    "speech": "['value_1', 'value_2']",
    "language": "locale_string"
  }
}

Cảnh chuyển tiếp

Ngoài việc xác định chuyển đổi tĩnh trong dự án Actions, bạn có thể khiến chuyển đổi cảnh xảy ra trong thời gian chạy.

Node.js

app.handle('transition_to_hidden_scene', conv => {
  // Dynamic transition
  conv.scene.next.name = "HiddenScene";
});

Định dạng JSON của phản hồi

{
  "session": {
    "id": "session_id",
    "params": {}
  },
  "prompt": {
    "override": false,
    "firstSimple": {
      "speech": "This is an example prompt.",
      "text": ""
    }
  },
  "scene": {
    "name": "SceneName",
    "slots": {},
    "next": {
      "name": "HiddenScene"
    }
  }
}

Đọc khung cảnh

Trong quá trình lấp đầy vùng, bạn có thể sử dụng phương thức thực hiện để xác thực vùng hoặc kiểm tra trạng thái lấp đầy vùng (SlotFillingStatus).

Node.js

conv.scene.slotFillingStatus  // FINAL means all slots are filled
conv.scene.slots  // Object that contains all the slots
conv.scene.slots['slot_name'].<property_name> // Accessing a specific slot's properties

Ví dụ: giả sử bạn muốn trích xuất múi giờ từ một câu trả lời. Trong ví dụ này, tên vùng là datetime1. Để có được múi giờ, bạn cần sử dụng:

conv.scene.slots['datetime1'].value.time_zone.id

Yêu cầu tệp JSON

{
  "handler": {
    "name": "handler_name"
  },
  "intent": {
    "name": "",
    "params": {
      "slot_name": {
        "original": "1",
        "resolved": 1
      }
    },
    "query": ""
  },
  "scene": {
    "name": "SceneName",
    "slotFillingStatus": "FINAL",
    "slots": {
      "slot_name": {
        "mode": "REQUIRED",
        "status": "SLOT_UNSPECIFIED",
        "updated": true,
        "value": 1
      }
    },
    "next": {
      "name": "actions.scene.END_CONVERSATION"
    }
  },
  "session": {
    "id": "session_id",
    "params": {
      "slot_name": 1
    },
    "typeOverrides": []
  },
  "user": {
    "locale": "en-US",
    "params": {
      "verificationStatus": "VERIFIED"
    }
  },
  "home": {
    "params": {}
  },
  "device": {
    "capabilities": [
      "SPEECH",
      "RICH_RESPONSE",
      "LONG_FORM_AUDIO"
    ]
  }
}

Vô hiệu hoá thời điểm cảnh

Bạn có thể vô hiệu hoá các vùng quảng cáo và yêu cầu người dùng cung cấp một giá trị mới.

Node.js

conv.scene.slots['slot_name'].status = 'INVALID'

Định dạng JSON của phản hồi

{
  "session": {
    "id": "session_id",
    "params": {
      "slot_name": 1
    }
  },
  "prompt": {
    "override": false,
    "firstSimple": {
      "speech": "This is an example prompt.",
      "text": ""
    }
  },
  "scene": {
    "name": "SceneName",
    "slots": {
      "slot_name": {
        "mode": "REQUIRED",
        "status": "INVALID",
        "updated": true,
        "value": 1
      }
    },
    "next": {
      "name": "actions.scene.END_CONVERSATION"
    }
  }
}

Tùy chọn phát triển

Trình tạo hành động cung cấp một trình chỉnh sửa cùng dòng có tên là trình chỉnh sửa Hàm đám mây, cho phép bạn tạo và triển khai Chức năng đám mây cho Firebase ngay trong bảng điều khiển. Bạn cũng có thể tạo và triển khai phương thức thực hiện cho lựa chọn lưu trữ mà mình chọn, đồng thời đăng ký điểm cuối của phương thức thực hiện HTTPS làm trình xử lý webhook.

Trình chỉnh sửa cùng dòng

Cách phát triển bằng trình chỉnh sửa Cloud Functions:

  1. Mở dự án Hành động rồi chuyển đến thẻ Phát triển > Webhook > Thay đổi phương thức thực hiện. Cửa sổ Phương thức thực hiện sẽ xuất hiện.
  2. Chọn Inline Cloud Functions (Hàm đám mây nội tuyến) rồi nhấp vào Confirm (Xác nhận).

Điểm cuối HTTPS bên ngoài

Phần này mô tả cách thiết lập Cloud Functions cho Firebase làm dịch vụ thực hiện cho Hành động trò chuyện. Tuy nhiên, bạn có thể triển khai phương thức thực hiện cho dịch vụ lưu trữ mà bạn chọn.

Thiết lập môi trường

Để thiết lập môi trường, hãy làm theo các bước sau:

  1. Tải Node.js xuống và cài đặt.
  2. Thiết lập và khởi chạy Firebase CLI. Nếu lệnh sau không thực hiện được với lỗi EACCES, bạn có thể cần phải thay đổi quyền npm.

    npm install -g firebase-tools
    
  3. Xác thực công cụ Firebase bằng Tài khoản Google:

    firebase login
    
  4. Khởi động thư mục dự án mà bạn đã lưu dự án Actions của mình. Bạn sẽ được yêu cầu chọn những tính năng Firebase CLI mà bạn muốn thiết lập cho dự án Actions của mình. Chọn Functions và các tính năng khác mà bạn có thể muốn sử dụng, chẳng hạn như Firestore, sau đó nhấn Enter để xác nhận và tiếp tục:

    $ cd <ACTIONS_PROJECT_DIRECTORY>
    $ firebase init
    
  5. Liên kết công cụ Firebase với dự án Actions của bạn bằng cách chọn công cụ này bằng các phím mũi tên để di chuyển trong danh sách dự án:

  6. Sau khi chọn dự án, công cụ Firebase sẽ bắt đầu thiết lập hàm và hỏi bạn muốn sử dụng ngôn ngữ nào. Chọn bằng các phím mũi tên và nhấn Enter để tiếp tục.

    === Functions Setup
    A functions directory will be created in your project with a Node.js
    package pre-configured. Functions can be deployed with firebase deploy.
    
    ? What language would you like to use to write Cloud Functions? (Use arrow keys)
    > JavaScript
    TypeScript
    
  7. Chọn xem bạn có muốn sử dụng ESLint để phát hiện lỗi có thể xảy ra và thực thi kiểu bằng cách nhập Y hoặc N:

    ? Do you want to use ESLint to catch probable bugs and enforce style? (Y/n)
  8. Lấy phần phụ thuộc của dự án bằng cách nhập Y vào lời nhắc:

    ? Do you want to install dependencies with npm now? (Y/n)

    Sau khi thiết lập xong, bạn sẽ thấy một kết quả tương tự như sau:

    ✔  Firebase initialization complete!
    
  9. Cài đặt phần phụ thuộc @assistant/conversation:

    $ cd <ACTIONS_PROJECT_DIRECTORY>/functions
    $ npm install @assistant/conversation --save
    
  10. Lấy các phần phụ thuộc của phương thức thực hiện và triển khai hàm thực hiện:

    $ npm install
    $ firebase deploy --only functions
    

    Quá trình triển khai sẽ mất vài phút. Sau khi hoàn tất, bạn sẽ thấy kết quả tương tự như sau. Bạn cần có URL chức năng để nhập vào Dialogflow.

    ✔  Deploy complete!
    Project Console: https://console.firebase.google.com/project/<PROJECT_ID>/overview Function URL (<FUNCTION_NAME>): https://us-central1-<PROJECT_ID>.cloudfunctions.net/<FUNCTION_NAME>
  11. Sao chép URL của phương thức thực hiện để dùng trong phần tiếp theo.

Đăng ký trình xử lý webhook

Cách đăng ký điểm cuối Cloud Function làm trình xử lý webhook:

  1. Trong bảng điều khiển Actions, hãy nhấp vào Phát triển > Webhook.
  2. Nhấp vào Thay đổi phương thức thực hiện. Cửa sổ Phương thức thực hiện sẽ xuất hiện.
  3. Chọn Webhook rồi nhấp vào Xác nhận.
  4. Dán URL dịch vụ web vào trường Webhook.
  5. Nhấp vào Lưu.