בקשות להחזר (Dialogflow)

אפשרויות נוספות ב-Dialogflow

צריך ללחוץ על המשך כדי לייבא את דוגמת הבקשות ל-Dialogflow. לאחר מכן, מבצעים את הפעולות הבאות כדי לפרוס את הדוגמה ולבדוק אותה:

  1. צריך להזין שם נציג וליצור נציג חדש ב-Dialogflow לדוגמה.
  2. כשמסיימים לייבא את הנציג, לוחצים על מעבר לנציג.
  3. מתפריט הניווט הראשי, עוברים אל מילוי הזמנה.
  4. מפעילים את עורך מוטבע ולוחצים על פריסה. העורך מכיל את הקוד לדוגמה.
  5. בתפריט הניווט הראשי, נכנסים אל Integrations (שילובים) ולוחצים על Google Assistant.
  6. בחלון החלון הקופץ, מפעילים את האפשרות שינויים בתצוגה מקדימה אוטומטית ולוחצים על בדיקה כדי לפתוח את סימולטור הפעולות.
  7. בסימולטור, מזינים Talk to my test app כדי לבדוק את הטעימה!
המשך

תוכלו להיעזר בתכונות הבאות כדי לטפל במקרים שבהם המשתמשים לא מספקים קלט לפעולות (שגיאות ללא קלט):

  • הפניות כברירת מחדל של המערכת – בקשות אלה מפנות את המשתמש באופן אוטומטי בעזרת תגובות גנריות לכל המקרים.
  • החזרים דינמיים – הצהרה שאתם רוצים לטפל בתגובה לאימיילים שלכם, וקבלת כוונה (Actions SDK) או אירוע (Dialogflow) בכל פעם שאין קלט, כדי שתוכלו לטפל בהם בכל מקרה לגופו.

תגובות כברירת מחדל של המערכת

כברירת מחדל, כשעונים ל-Assistant, המערכת משתמשת בהפניות שמוגדרות כברירת מחדל כדי לבקש מהמשתמשים לחזור על הקלט או להקליד אותו מחדש.

Dialogflow

בעזרת Dialogflow אנחנו אוכפים מקסימום שלושה סוגים של קלט ללא התאמה וללא קלט. אחרי 3 ניסיונות איסוף שיחה, הנציג שלכם ב-Dialogflow יסיים את השיחה עם תגובת ברירת מחדל. קלט ללא התאמה ב-Dialogflow מתואר כשאחת מכוונות ה-Intent החלופיות מופעלת.

תגובות דינמיות

אפשר לקבל אירוע Intent או אירוע Dialogflow בכל פעם שפעולה מסוימת לא מצליחה לקבל קלט. כך תוכלו להחזיר תשובה שונה בהתאם ללוגיקה מסוימת, ולשחזר את המשתמש בהתאם.

Dialogflow

יש שני סוגים של אובייקטים מסוג Intent ללא קלט:

  • Intent רגיל – השיטה הזו לא מחילה הקשרים כלשהם, ולכן היא תופעל כשאין כוונה אחרת שקשורה להקשר. האפשרות הזו שימושית בתגובה לתגובות כלליות שבהן אתם רוצים להשתמש ברוב המקרים.

  • כוונת המשך – כוונות ההמשך נאכפות באמצעות ההקשרים של Dialogflow, כדי להבטיח שהתגובות יופעלו רק לאחר פניות מסוימות בשיחה. האפשרות הזו שימושית לתשובות מותאמות אישית שרציתם ליישם במצבים ספציפיים.

כדי לטפל באירועים ללא קלט:

  1. בחלונית הניווט הימנית, לוחצים על אובייקטים מסוג Intent.
  2. יוצרים כוונת מעקב רגילה או כוונת מעקב.
    • לאובייקטים מסוג Intent רגילים: לוחצים על הסמל + ליד הפריט בתפריט Intent ונותנים שם ל-Intent, למשל 'Reprompt'.

    • לכוונות המשך: מעבירים את העכבר מעל הכוונה שרוצים להתאים אישית את ההודעה ללא קלט ולוחצים על הוספת כוונת מעקב > בהתאמה אישית. אובייקט Intent חדש נוצר מתחת ל-Intent המקורי.

  3. לוחצים על ה-Intent החדש שנוצר כדי לפתוח את עורך Intent.
  4. לוחצים על הקטע אירועים ומזינים "actions_intent_NO_INPUT" בשדה Add event (הוספת אירוע).
  5. בקטע Actions מזינים את שם הפעולה או משתמשים בשם שניתן כברירת מחדל. בדוגמה הזו נשתמש ב-"no.input".

  6. לוחצים על שמירה.
  7. בחלונית הניווט הימנית, לוחצים על שילובים.
  8. בוחרים באפשרות Google Assistant ולוחצים על בדיקה כדי לוודא שהשינויים יבואו לידי ביטוי בפרויקט הפעולות.

בכל פעם שאין קלט לכוונה הזו, אפשר להשתמש במילוי הבקשה כדי להחזיר תשובה מתאימה או ליצור תשובה ב-Dialogflow. לדוגמה, בהמשך מופיע קוד מילוי הזמנה שמשתמש בספריית הלקוח כדי לטפל ב-Intent רגיל ללא קלט שנקרא "Reprompt".

Node.js

const {dialogflow} = require('actions-on-google');
const functions = require('firebase-functions');

const app = dialogflow({debug: true});

app.intent('Reprompt', (conv) => {
  const repromptCount = parseInt(conv.arguments.get('REPROMPT_COUNT'));
  if (repromptCount === 0) {
  conv.ask(`What was that?`);
  } else if (repromptCount === 1) {
  conv.ask(`Sorry I didn't catch that. Could you repeat yourself?`);
  } else if (conv.arguments.get('IS_FINAL_REPROMPT')) {
  conv.close(`Okay let's try this again later.`);
  }
});

exports.dialogflowFirebaseFulfillment = functions.https.onRequest(app);

Java

package com.example;

import com.google.actions.api.ActionRequest;
import com.google.actions.api.ActionResponse;
import com.google.actions.api.DialogflowApp;
import com.google.actions.api.ForIntent;
import com.google.actions.api.response.ResponseBuilder;

public class MyActionsApp extends DialogflowApp {

  @ForIntent("Reprompt")
  public ActionResponse reprompt(ActionRequest request) {
    ResponseBuilder responseBuilder = getResponseBuilder(request);
    int repromptCount = request.getRepromptCount();
    String response;
    if (repromptCount == 0) {
      response = "What was that?";
    } else if (repromptCount == 1) {
      response = "Sorry, I didn't catch that. Could you repeat yourself?";
    } else {
      responseBuilder.endConversation();
      response = "Okay let's try this again later.";
    }
    return responseBuilder.add(response).build();
  }
}

בקשת JSON

שימו לב: קובץ ה-JSON שמוצג בהמשך מתאר בקשת webhook.

{
  "responseId": "f26a9188-4998-42eb-ac16-d0e6e273b137-712767ed",
  "queryResult": {
    "queryText": "actions_intent_NO_INPUT",
    "parameters": {},
    "allRequiredParamsPresent": true,
    "fulfillmentText": "Webhook failed for intent: Reprompt",
    "fulfillmentMessages": [
      {
        "text": {
          "text": [
            "Webhook failed for intent: Reprompt"
          ]
        }
      }
    ],
    "outputContexts": [
      {
        "name": "projects/df-reprompts-kohler/agent/sessions/ABwppHFi9Dpwy6KiEtS0UIPDNVfa7mlkrPIEZRlikFkjuN_4SGPixgX8OCatpXu38ln7VG43-nk-7veZWhds3nLljA/contexts/actions_capability_media_response_audio"
      },
      {
        "name": "projects/df-reprompts-kohler/agent/sessions/ABwppHFi9Dpwy6KiEtS0UIPDNVfa7mlkrPIEZRlikFkjuN_4SGPixgX8OCatpXu38ln7VG43-nk-7veZWhds3nLljA/contexts/actions_capability_account_linking"
      },
      {
        "name": "projects/df-reprompts-kohler/agent/sessions/ABwppHFi9Dpwy6KiEtS0UIPDNVfa7mlkrPIEZRlikFkjuN_4SGPixgX8OCatpXu38ln7VG43-nk-7veZWhds3nLljA/contexts/actions_capability_audio_output"
      },
      {
        "name": "projects/df-reprompts-kohler/agent/sessions/ABwppHFi9Dpwy6KiEtS0UIPDNVfa7mlkrPIEZRlikFkjuN_4SGPixgX8OCatpXu38ln7VG43-nk-7veZWhds3nLljA/contexts/google_assistant_input_type_voice"
      },
      {
        "name": "projects/df-reprompts-kohler/agent/sessions/ABwppHFi9Dpwy6KiEtS0UIPDNVfa7mlkrPIEZRlikFkjuN_4SGPixgX8OCatpXu38ln7VG43-nk-7veZWhds3nLljA/contexts/actions_intent_no_input",
        "parameters": {
          "REPROMPT_COUNT": 2,
          "IS_FINAL_REPROMPT": true
        }
      }
    ],
    "intent": {
      "name": "projects/df-reprompts-kohler/agent/intents/75dfd97d-6368-4436-9533-70f05ae76c96",
      "displayName": "Reprompt"
    },
    "intentDetectionConfidence": 1,
    "languageCode": "en"
  },
  "originalDetectIntentRequest": {
    "source": "google",
    "version": "2",
    "payload": {
      "user": {
        "locale": "en-US",
        "userVerificationStatus": "VERIFIED"
      },
      "conversation": {
        "conversationId": "ABwppHFi9Dpwy6KiEtS0UIPDNVfa7mlkrPIEZRlikFkjuN_4SGPixgX8OCatpXu38ln7VG43-nk-7veZWhds3nLljA",
        "type": "ACTIVE",
        "conversationToken": "[]"
      },
      "inputs": [
        {
          "intent": "actions.intent.NO_INPUT",
          "rawInputs": [
            {
              "inputType": "VOICE"
            }
          ],
          "arguments": [
            {
              "name": "REPROMPT_COUNT",
              "intValue": "2"
            },
            {
              "name": "IS_FINAL_REPROMPT",
              "boolValue": true
            }
          ]
        }
      ],
      "surface": {
        "capabilities": [
          {
            "name": "actions.capability.MEDIA_RESPONSE_AUDIO"
          },
          {
            "name": "actions.capability.ACCOUNT_LINKING"
          },
          {
            "name": "actions.capability.AUDIO_OUTPUT"
          }
        ]
      },
      "availableSurfaces": [
        {
          "capabilities": [
            {
              "name": "actions.capability.AUDIO_OUTPUT"
            },
            {
              "name": "actions.capability.SCREEN_OUTPUT"
            },
            {
              "name": "actions.capability.WEB_BROWSER"
            }
          ]
        }
      ]
    }
  },
  "session": "projects/df-reprompts-kohler/agent/sessions/ABwppHFi9Dpwy6KiEtS0UIPDNVfa7mlkrPIEZRlikFkjuN_4SGPixgX8OCatpXu38ln7VG43-nk-7veZWhds3nLljA"
}

קובץ JSON בתשובות

שימו לב: קובץ ה-JSON שמוצג בהמשך מתאר תגובה של תגובה לפעולה מאתר אחר (webhook).

{
  "payload": {
    "google": {
      "expectUserResponse": false,
      "richResponse": {
        "items": [
          {
            "simpleResponse": {
              "textToSpeech": "Okay let's try this again later."
            }
          }
        ]
      }
    }
  }
}

Actions SDK

כדי לטפל באובייקטים מסוג Intent ללא קלט:

  1. באובייקט conversations בתוך חבילת הפעולות, צריך להצהיר שאתם רוצים לקבל את ה-Intent actions.intent.NO_INPUT בכל פעם שמשתמש לא מספק קלט.
    
    {
      "actions": [
        {
          "description": "Default Welcome Intent",
          "name": "MAIN",
          "fulfillment": {
            "conversationName": "conversation_1"
          },
          "intent": {
            "name": "actions.intent.MAIN"
          }
        }
      ],
      "conversations": {
        "conversation_1": {
          "name": "conversation_1",
          "url": "YOUR_FULFILLMENT_URL",
          "inDialogIntents": [
            {
              "name": "actions.intent.NO_INPUT"
            }
          ]
        }
      }
    }
    
  2. אם Assistant לא תקבל קלט מהמשתמש, תוצג לכם הכוונה ללא קלט בבקשה הבאה למילוי הבקשה. לאחר מכן תוכלו לעבד את הכוונה ולהחזיר תגובה מתאימה. לדוגמה:

    Node.js

    const {actionssdk} = require('actions-on-google');
    const functions = require('firebase-functions');
    
    const app = actionssdk({debug: true});
    
    app.intent('actions.intent.MAIN', (conv) => {
      conv.ask(`Hi! Try this sample on a speaker device, ` +
        `and stay silent when the mic is open. If trying ` +
        `on the Actions console simulator, click the no-input ` +
        `button next to the text input field.`);
    });
    
    app.intent('actions.intent.TEXT', (conv, input) => {
      conv.ask(`You said ${input}`);
      conv.ask(`Try this sample on a speaker device, ` +
        `and stay silent when the mic is open. If trying ` +
        `on the Actions console simulator, click the no-input ` +
        `button next to the text input field.`);
    });
    
    app.intent('actions.intent.NO_INPUT', (conv) => {
      const repromptCount = parseInt(conv.arguments.get('REPROMPT_COUNT'));
      if (repromptCount === 0) {
        conv.ask(`What was that?`);
      } else if (repromptCount === 1) {
        conv.ask(`Sorry I didn't catch that. Could you repeat yourself?`);
      } else if (conv.arguments.get('IS_FINAL_REPROMPT')) {
        conv.close(`Okay let's try this again later.`);
      }
    });
    
    exports.dialogflowFirebaseFulfillment = functions.https.onRequest(app);

    Java

    package com.example;
    
    import com.google.actions.api.ActionRequest;
    import com.google.actions.api.ActionResponse;
    import com.google.actions.api.ActionsSdkApp;
    import com.google.actions.api.ConstantsKt;
    import com.google.actions.api.ForIntent;
    import com.google.actions.api.response.ResponseBuilder;
    import com.google.actions.api.response.helperintent.Confirmation;
    import com.google.actions.api.response.helperintent.DateTimePrompt;
    import com.google.actions.api.response.helperintent.Permission;
    import com.google.actions.api.response.helperintent.Place;
    import com.google.api.services.actions_fulfillment.v2.model.DateTime;
    import com.google.api.services.actions_fulfillment.v2.model.Location;
    
    public class MyActionsApp extends ActionsSdkApp {
    
      @ForIntent("actions.intent.MAIN")
      public ActionResponse welcome(ActionRequest request) {
        ResponseBuilder responseBuilder = getResponseBuilder(request);
        responseBuilder.add("Hi! Try this sample on a speaker device, and stay silent when the mic is open. If trying on the Actions console simulator, click the no-input button next to the text input field.");
        return responseBuilder.build();
      }
    
      @ForIntent("actions.intent.TEXT")
      public ActionResponse fallback(ActionRequest request) {
        ResponseBuilder responseBuilder = getResponseBuilder(request);
        responseBuilder.add("You said " + request.getRawInput().getQuery());
        responseBuilder.add("Try this sample on a speaker device, and stay silent when the mic is open. If trying on the Actions console simulator, click the no-input button next to the text input field.");
        return responseBuilder.build();
      }
    
      @ForIntent("actions.intent.NO_INPUT")
      public ActionResponse reprompt(ActionRequest request) {
        ResponseBuilder responseBuilder = getResponseBuilder(request);
        int repromptCount = request.getRepromptCount();
        String response;
        if (repromptCount == 0) {
          response = "What was that?";
        } else if (repromptCount == 1) {
          response = "Sorry, I didn't catch that. Could you repeat yourself?";
        } else {
          responseBuilder.endConversation();
          response = "Okay let's try this again later.";
        }
        return responseBuilder.add(response).build();
      }
    
    }

    בקשת JSON

    שימו לב: קובץ ה-JSON שמוצג בהמשך מתאר בקשת webhook.

    {
      "user": {
        "locale": "en-US",
        "userVerificationStatus": "VERIFIED"
      },
      "conversation": {
        "conversationId": "ABwppHEVDuKUPjdZ4Ud-F2yBXN5ssRg2funUp59hSHQheAi-B5Y3EzehAKFtVwMkduqMRWscUp77ScrDjYnYxISqAM-qOXuXEuCw",
        "type": "ACTIVE",
        "conversationToken": "{\"data\":{}}"
      },
      "inputs": [
        {
          "intent": "actions.intent.NO_INPUT",
          "rawInputs": [
            {
              "inputType": "VOICE"
            }
          ],
          "arguments": [
            {
              "name": "REPROMPT_COUNT",
              "intValue": "2"
            },
            {
              "name": "IS_FINAL_REPROMPT",
              "boolValue": true
            }
          ]
        }
      ],
      "surface": {
        "capabilities": [
          {
            "name": "actions.capability.AUDIO_OUTPUT"
          },
          {
            "name": "actions.capability.ACCOUNT_LINKING"
          },
          {
            "name": "actions.capability.MEDIA_RESPONSE_AUDIO"
          }
        ]
      },
      "availableSurfaces": [
        {
          "capabilities": [
            {
              "name": "actions.capability.SCREEN_OUTPUT"
            },
            {
              "name": "actions.capability.WEB_BROWSER"
            },
            {
              "name": "actions.capability.AUDIO_OUTPUT"
            }
          ]
        }
      ]
    }

    קובץ JSON בתשובות

    שימו לב: קובץ ה-JSON שמוצג בהמשך מתאר תגובה של תגובה לפעולה מאתר אחר (webhook).

    {
      "expectUserResponse": false,
      "finalResponse": {
        "richResponse": {
          "items": [
            {
              "simpleResponse": {
                "textToSpeech": "Okay let's try this again later."
              }
            }
          ]
        }
      }
    }