כדי לתת לכם יותר גמישות ביצירת פעולות, אפשר להאציל לוגיקה לשירותי אינטרנט מסוג HTTPS (מילוי הזמנות). הפעולות שלך יכולות להפעיל webhooks לשלוח בקשות לנקודת קצה (endpoint) מסוג HTTPS. דוגמאות לפעולות שאפשר לבצע כולל:
- נוצרת הנחיה דינמית שמבוססת על מידע שהמשתמש סיפק.
- ביצוע הזמנה במערכת חיצונית ואישור בהצלחה.
- אימות משבצות עם נתונים בקצה העורפי.
טריגרים ורכיבי handler של תגובה לפעולה מאתר אחר (webhook)
הפעולות יכולות להפעיל תגובה לפעולה מאתר אחר (webhook) בסצנות או במטרות של הפעלה, שולחת בקשה לנקודת הקצה של האספקה. מילוי ההזמנות מכיל webhook רכיבי handler שמעבדים את המטען הייעודי (payload) של JSON בבקשה. אפשר להפעיל webhooks במצבים הבאים:
- אחרי התאמת Intent בהפעלה
- במהלך סצנה בכניסה לבמה
- אחרי שתנאי מוגדר כ-True בשלב התנאי של סצנה
- במהלך שלב מילוי המשבצות בסצנה
- אחרי שמתרחשת התאמת Intent בשלב הקלט של סצנה
כשמפעילים תגובה לפעולה מאתר אחר (webhook) בפעולות, Google Assistant שולחת בקשה עם מטען ייעודי (payload) של JSON למילוי הזמנות, שמכיל את שם ה-handler שישמש לעיבוד האירוע. נקודת הקצה למילוי הזמנות לנתב את האירוע ל-handler המתאים כדי לבצע לוגיקה ולהחזיר תגובה תואמת עם מטען ייעודי (payload) של JSON.
מטענים ייעודיים (payloads)
קטעי הקוד הבאים מציגים דוגמאות לבקשות שהפעולות שלך שולחות אל ותשובה שאתם שולחים חזרה למילוי ההזמנות. לצפייה אפשר לקרוא מידע נוסף במאמרי עזרה מידע.
בקשה לדוגמה
{
"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"
]
}
}
דוגמה לתגובה
{
"session": {
"id": "example_session_id",
"params": {}
},
"prompt": {
"override": false,
"firstSimple": {
"speech": "Hello World.",
"text": ""
}
},
"scene": {
"name": "SceneName",
"slots": {},
"next": {
"name": "actions.scene.END_CONVERSATION"
}
}
}
אינטראקציות בזמן ריצה
בחלקים הבאים מתוארות משימות נפוצות שניתן לבצע גורמים מטפלים בתגובה לפעולה מאתר אחר (webhook).
שליחת הנחיות
אפשר ליצור הנחיות עם טקסט פשוט, טקסט עשיר, קלפים ואפילו טקסט מלא הנחיות HTML שמגובות על ידי אפליקציית אינטרנט באמצעות לוח הציור האינטראקטיבי. במסמכי התיעוד של ההוראות יש כל המידע על יצירת הנחיה במהלך טיפול באירוע webhook. בקטעי הקוד הבאים מוצגת בקשה לכרטיס:
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
{
"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": ""
}
}
}
קריאת הפרמטרים של Intent
כשזמן הריצה של Assistant תואם ל-Intent, הוא מחלץ כל הגדרה מוגדרת . הנכס המקורי היה מה שהמשתמש סיפק כקלט, המאפיין הזה הוא הפריט שה-NLU פתר את הקלט, על סמך הסוג למפרט.
Node.js
conv.intent.params['param_name'].original
conv.intent.params['param_name'].resolved
בקשת 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"
]
}
}
קריאת הלוקאל של המשתמש
הערך הזה תואם להגדרת הלוקאל של המשתמש ב-Google Assistant.
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"
]
}
}
קריאה וכתיבה של אחסון
במסמכי התיעוד בנושא אחסון יש הסבר מלא להשתמש בתכונות אחסון שונות.
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
בקשת 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
{
"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"
}
}
}
בדיקת יכולות המכשיר
אפשר לבדוק את היכולות של המכשיר כדי לספק חוויות שונות או לזוז.
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");
בקשת 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"
]
}
}
לרשימה מלאה של היכולות בפלטפורמות השונות: Capability
הפניה.
שינויים בסוגי זמן הריצה
סוגים של סביבת זמן ריצה מאפשרים לשנות את מפרטי הסוגים בזמן הריצה. אפשר להשתמש כדי לטעון נתונים ממקורות אחרים ולאכלס ערכים חוקיים של סוג מסוים. עבור לדוגמה, אפשר להשתמש בשינויים מסוג סביבת זמן ריצה כדי להוסיף לסקר אפשרויות דינמיות. או להוסיף פריט יומי לתפריט.
כדי להשתמש בסוגים של זמן ריצה, צריך להפעיל תגובה לפעולה מאתר אחר (webhook) שקוראת לפעולה
של ה-handler. משם אפשר לאכלס
הפרמטר session.typeOverrides
בתגובה לפעולה. נמצא/ת
המצבים כוללים את TYPE_MERGE
כדי לשמור ערכי סוגים קיימים, או TYPE_REPLACE
כדי להחליף ערכים קיימים עם השינויים מברירת המחדל.
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
{
"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."
}
}
}
הטייה של דיבור
הטיית דיבור מאפשרת לציין רמזים ל-NLU כדי לשפר את ההתאמה לכוונת הרכישה. שלך יכול לציין עד 1,000 רשומות.
Node.js
conv.expected.speech = ['value_1', 'value_2']
conv.expected.language = 'locale_string'
תגובת JSON
{
"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"
}
}
סצנות מעבר
נוסף להגדרת מעברים סטטיים בפרויקט Actions, תוכלו לגרום למעברים בין סצנות בזמן ריצה.
Node.js
app.handle('transition_to_hidden_scene', conv => {
// Dynamic transition
conv.scene.next.name = "HiddenScene";
});
תגובת JSON
{
"session": {
"id": "session_id",
"params": {}
},
"prompt": {
"override": false,
"firstSimple": {
"speech": "This is an example prompt.",
"text": ""
}
},
"scene": {
"name": "SceneName",
"slots": {},
"next": {
"name": "HiddenScene"
}
}
}
קריאת משבצות לסצנות
במהלך מילוי המשבצות, אפשר להשתמש במילוי האוטומטי כדי לאמת את המשבצת הזו או לבדוק את
סטטוס מילוי המשבצות (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
לדוגמה, נניח שרוצים לחלץ את אזור הזמן מתשובה. לחשבון
בדוגמה הזו, השם של משבצת הזמן הוא datetime1
. כדי לקבל את אזור הזמן, עליך
להשתמש ב:
conv.scene.slots['datetime1'].value.time_zone.id
בקשת 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"
]
}
}
ביטול התוקף של משבצות לסצנות
אפשר לבטל את התוקף של משבצות השידור ולתת למשתמש ערך חדש.
Node.js
conv.scene.slots['slot_name'].status = 'INVALID'
תגובת JSON
{
"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"
}
}
}
אפשרויות פיתוח
הכלי Actions Builder כולל כלי עריכה מוטבע שנקרא עורך Cloud Functions, שמאפשר ליצור ולפרוס פונקציה של Cloud Functions ל-Firebase ישירות במסוף. אפשר גם ליצור ולפרוס מילוי הזמנות באירוח לבחירתכם ורושמים את נקודת הקצה למילוי הזמנות ב-HTTPS כ-handler של ה-webhook.
עורך מוטבע
כדי לפתח באמצעות העורך של Cloud Functions:
- יוצרים את הקובץ
sdk/webhooks/ActionsOnGoogleFulfillment.yaml
, ולהגדיר את ה-handlers של הפעולה ושל הפונקציה בענן המוטבעת שבה נעשה שימוש למילוי הזמנות.handlers: - name: questionOnEnterFunc - name: fruitSlotValidationFunc inlineCloudFunction: executeFunction: ActionsOnGoogleFulfillment
- יוצרים את התיקייה
sdk/webhooks/ActionsOnGoogleFulfillment
, ולהוסיף קובץindex.js
שמטמיע את רכיבי ה-handler שהוגדר קודם לכן וקובץpackage.json
שמגדיר NPM הדרישות לקוד.// 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" } }
נקודת קצה חיצונית מסוג HTTPS
בקטע הזה נסביר איך מגדירים את Cloud Functions for Firebase בתור שירות מילוי הזמנה לפעולה בממשק שיחה. אבל אפשר לפרוס או שירות אירוח לבחירתך.
הגדרת סביבה
כשמשתמשים בפונקציות של Cloud, מומלץ להשתמש במבנה הבא של הפרויקט, Firebase כשירות מילוי הזמנה:
ProjectFolder - Root folder for the project sdk - Actions project configuration files functions - Cloud functions for Firebase files
כדי להגדיר את הסביבה, מבצעים את השלבים הבאים:
- מורידים ומתקינים את Node.js.
מגדירים ומפעילים את ה-CLI של Firebase. אם הפקודה הבאה נכשלת עם שגיאת
EACCES
, יכול להיות שיהיה צורך לשנות את ההרשאות של NPM.npm install -g firebase-tools
מאמתים את כלי firebase באמצעות חשבון Google:
firebase login
מתחילים את ספריית הפרויקט שבה שמרתם את פרויקט הפעולות. תתבקשו לבחור לאילו תכונות של Firebase CLI רוצים להגדיר לפרויקט הפעולות שלכם. בחירה של
Functions
ותכונות אחרות שאולי יעניינו אותך למשל Firestore, ואז מקישים על Enter כדי לאשר ולהמשיך:$ cd <ACTIONS_PROJECT_DIRECTORY> $ firebase init
משייכים את כלי Firebase לפרויקט Actions (פעולות) על ידי בחירה בו באמצעות מקשי החיצים כדי לנווט ברשימת הפרויקטים:
אחרי שבוחרים את הפרויקט, הכלי של Firebase מפעיל את הפונקציות ושואלת באיזו שפה להשתמש. בחירה באמצעות מקשי החיצים ומקישים על Enter כדי להמשיך.
=== 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
בוחרים אם להשתמש ב-ESLint כדי לזהות באגים אפשריים ולאכוף את הסגנון באמצעות הקלדת Y או N:
? Do you want to use ESLint to catch probable bugs and enforce style? (Y/n)
כדי לקבל את יחסי התלות של הפרויקט, מקלידים Y בהנחיה:
? Do you want to install dependencies with npm now? (Y/n)
לאחר השלמת ההגדרה, יתקבל פלט שדומה לזה:
✔ Firebase initialization complete!
מתקינים את התלות @assistant/conversation:
$ cd <ACTIONS_PROJECT_DIRECTORY>/functions $ npm install @assistant/conversation --save
מקבלים את יחסי התלות של מילוי ההזמנות ופורסים את פונקציית מילוי ההזמנות:
$ npm install $ firebase deploy --only functions
הפריסה נמשכת כמה דקות. בסיום התהליך, הפלט יהיה דומה הבאות. כדי להזין ב-Dialogflow, צריך את כתובת ה-URL של הפונקציה.
✔ 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>מעתיקים את כתובת ה-URL של מילוי ההזמנות שרוצים להשתמש בה בקטע הבא.
רישום webhook handler
- יוצרים את הקובץ
sdk/webhooks/ActionsOnGoogleFulfillment.yaml
ומגדירים של הגורמים המטפלים בפעולה של הפעולה ובכתובת ה-URL של בקשות ה-webhook.httpsEndpoint: baseUrl: https://my.web.hook/ActionsOnGoogleFulfillment endpointApiVersion: 2 handlers: - name: questionOnEnterFunc - name: fruitSlotValidationFunc