Webhook

Để linh hoạt hơn nữa trong việc tạo Hành động, bạn có thể uỷ quyền logic đến 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 webhook đưa ra yêu cầu đến một điểm cuối HTTPS. Một số ví dụ về những việc bạn có thể làm trong phương thức thực hiện bao gồm:

  • Tạo một câu lệnh linh hoạt dựa trên thông tin do người dùng cung cấp.
  • Đặt hàng trong một hệ thống bên ngoài và xác nhận thành công.
  • Xác thực vị trí có dữ liệu phụ trợ.
Hình 1. Cảnh và ý định gọi 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 cảnh hoặc ý định của lệnh gọi 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 webhook các trình xử lý 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 so khớp ý định gọi
  • Khi một cảnh đang diễn ra
  • 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 việc 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 mục Hành động, Trợ lý Google sẽ gửi một yêu cầu có tải trọng JSON vào phương thức thực hiện của bạn, trong đó chứa tên của trình xử lý để sử dụng nhằm xử lý sự kiện. Điểm cuối thực hiện có thể định tuyến sự kiện đến bộ xử lý thích hợp để thực hiện logic và trả về một phản hồi có tải trọng JSON tương ứng.

Tải trọng

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 đến 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. Xem tài liệu tham khảo để biết thêm của bạn.

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"
    }
  }
}

Số lần tương tác trong thời gian chạy

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

Gửi câu lệnh

Bạn có thể tạo câu lệnh bằng văn bản đơn giản, văn bản đa dạng thức, thẻ và thậm chí là toàn bộ văn bản Lời nhắc HTML được một ứng dụng web hỗ trợ bằng Canvas tương tác. Tài liệu về lời nhắc đã hoàn chỉnh thông tin về cách tạo lời nhắc khi xử lý sự kiện webhook. Các đoạn mã sau đây hiển thị một lời nhắc 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'
    })
  }));
});

JSON 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 các tham số ý định

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

Node.js

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

Yêu cầu 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ữ mà người dùng chọn 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

Hãy xem tài liệu về bộ nhớ để nắm được đầy đủ thông tin về cách sử dụng nhiều tính năng lưu trữ.

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 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"
    ]
  }
}

JSON 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 chức năng của thiết bị

Bạn có thể kiểm tra khả năng của một thiết bị để mang lại nhiều trải nghiệm hoặc luồng 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 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"
    ]
  }
}

Để xem danh sách đầy đủ các tính năng của nền tảng, hãy xem Capability tham chiếu.

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

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ể dùng để tải dữ liệu từ các nguồn khác nhằm điền giá trị hợp lệ của một loại. Cho ví dụ: bạn có thể sử dụng chế độ ghi đè loại thời gian chạy để thêm các lựa chọn động vào một bản khảo sát hoặc thêm mục hàng ngày vào thực đơn.

Để sử dụng các loại thời gian chạy, hãy kích hoạt một webhook từ Hành động của mình nhằm gọi một webhook trong phương thức thực hiện của bạn. Từ đó, bạn có thể điền sẵn session.typeOverrides để phản hồi Hành động của bạn. Có sẵn các chế độ 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 nhập hiện tại bằng các mục 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']
        },
    ]
  }
}];

JSON 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 giọng nói

Xu hướng giọng nói cho phép bạn chỉ định gợi ý cho NLU để cải thiện việc so khớp ý định. Bạn có thể chỉ định tối đa 1000 mục nhập.

Node.js

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

JSON 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 các hiệu ứng 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";
});

JSON 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 khi 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 trong ví dụ này, tên ô là datetime1. Để có được múi giờ, bạn sẽ sử dụng:

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

Yêu cầu 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á vùng cảnh

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

Node.js

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

JSON 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 trình chỉnh sửa nội tuyến được gọi 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 Google Play. Bạn cũng có thể xây dựng và triển khai phương thức thực hiện cho máy chủ lưu trữ mà bạn chọn và đăng ký điểm cuối 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. Tạo tệp sdk/webhooks/ActionsOnGoogleFulfillment.yaml, và xác định trình xử lý cho Hành động của bạn cũng như chức năng đám mây tại chỗ được dùng để thực hiện đơn hàng.
    handlers:
    - name: questionOnEnterFunc
    - name: fruitSlotValidationFunc
    inlineCloudFunction:
      executeFunction: ActionsOnGoogleFulfillment
        
  2. Tạo thư mục sdk/webhooks/ActionsOnGoogleFulfillment, và thêm một tệp index.js triển khai trình xử lý được xác định trước đó và tệp package.json định nghĩa npm cho mã của bạn.
    // index.js
    const {conversation} = require('@assistant/conversation');
    const functions = require('firebase-functions');
    
    const app = conversation();
    
    app.handle('questionOnEnterFunc', conv => {
      conv.add('questionOnEnterFunc triggered on webhook');
    });
    
    app.handle('fruitSlotValidationFunc', conv => {
      conv.add('fruitSlotValidationFunc triggered on webhook');
    });
    
    exports.ActionsOnGoogleFulfillment = functions.https.onRequest(app);
        
    // package.json
    {
      "name": "ActionsOnGoogleFulfillment",
      "version": "0.1.0",
      "description": "Actions on Google fulfillment",
      "main": "index.js",
      "dependencies": {
        "@assistant/conversation": "^3.0.0",
        "firebase-admin": "^5.4.3",
        "firebase-functions": "^0.7.1"
      }
    }
        

Đ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 dưới dạng một dịch vụ thực hiện hành động cho Hành động trò chuyện. Tuy nhiên, bạn có thể triển khai khả năng đáp ứng dịch vụ lưu trữ mà bạn chọn.

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

Bạn nên sử dụng cấu trúc dự án sau đây khi sử dụng các hàm của Cloud Firebase làm dịch vụ thực hiện:

ProjectFolder        - Root folder for the project
  sdk                - Actions project configuration files
  functions          - Cloud functions for Firebase files

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

  1. Tải và cài đặt Node.js.
  2. Thiết lập và khởi chạy Giao diện dòng lệnh (CLI) của Firebase. Nếu lệnh sau không thành công 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. Bắt đầu 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 các tính năng Giao diện dòng lệnh (CLI) của Firebase mà bạn muốn thiết lập dự án Actions của bạn. Chọn Functions và các tính năng khác mà bạn có thể muốn sử dụng sử dụng, chẳng hạn như Firestore, rồi 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 bằng cách chọn dự án đó bằng cách sử dụ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ẽ khởi động các Hàm thiết lập và hỏi bạn muốn 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 các 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 các 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 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. Nhận 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 mất vài phút. Sau khi hoàn tất, bạn sẽ thấy kết quả tương tự thành phần sau. Bạn cần có URL hàm để nhập 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 thực hiện đơn hàng để sử dụng trong phần tiếp theo.

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

  1. Tạo tệp sdk/webhooks/ActionsOnGoogleFulfillment.yaml rồi định nghĩa trình xử lý cho Hành động của bạn và URL cho các yêu cầu webhook.
    httpsEndpoint:
      baseUrl: https://my.web.hook/ActionsOnGoogleFulfillment
      endpointApiVersion: 2
    handlers:
    - name: questionOnEnterFunc
    - name: fruitSlotValidationFunc