Dialogs in the Alexa Conversations Description Language (ACDL)

In the Alexa Conversations Description Language (ACDL), a dialog is a set of sample conversations that bring together events and actions to represent the different conversational experiences your skill can support. You put your dialogs in ACDL files.

The purpose of dialogs is to guide the process of training a dialog management model. When you build the model, Alexa Conversations significantly expands the dialog samples into a large sample set by simulating the interaction between a user and your Alexa skill based on your sample dialogs. Alexa Conversations machine learning then uses the expanded dialog sample set to train a dialog management model.

Overview

A dialog represents a conversation between the user and a skill. The dialog helps the user accomplish a task or goal. You write dialogs to represent the desired conversational flow between the user and the skill. To do so, you declare the actions that should be performed as a reaction to received events.

Each dialog contains a set of samples. Each sample is a variation in the conversational flow to accomplish the task or goal of the user. Here, "goal" or "task" represent what the user is trying to accomplish through the interaction with the skill. For example, the goal might be to get the weather report, book a flight, or make a restaurant reservation.

Keep in mind that the Alexa Conversations simulator expands the provided dialog samples to thousands of variations. The order of the actions observed at runtime might not match the order the ACDL files capture.

Alexa Conversations uses data-flow dependency rules and other heuristics to determine the order of the predicted actions. You can be certain that Alexa Conversations always observes the data-flow dependencies in your ACDL files. For example, in the following dialog samples, Alexa Conversations always predicts the response() action after the getWeather() action because there is a data-flow dependency between the two. The weatherForecast expression represents the result of the latter flows as input argument to the former.

sample {
  ..

  weatherForecast = getWeather(req.cityName)

  response(forecastReport, Notify {actionName = getWeather, success = true}, payload = WeatherPayload {forecast = weatherForecast})
}    

Dialogs

The following is the syntax and an example of a dialog declaration.

Dialog declaration syntax

A dialog declaration consists of the keyword dialog, a required type, an unqualified name for the dialog, and a dialog expression block, which consists of sample declarations.

dialogDeclaration
   : DIALOG typeReference IDENTIFIER dialogBody
   ;

dialogBody
   : LBRACE sampleDeclaration+ RBRACE

You must specify a type for the dialog. Currently, you can only declare dialogs to be of type Nothing.

Dialog requirements

Dialogs have the following requirements:

  • All dialogs must have at least one sample.
  • All samples in a dialog must be compatible with the declared type of the dialog. For compatibility rules, see Type compatibility rules.

Dialog declaration example

The following example shows how to declare a dialog named Weather of type Nothing.

dialog Nothing Weather {
   ...
}

Samples

A dialog can contain one or more sample variations of the desired flow. The samples should describe a conversational flow that helps users accomplish the same task or goal. Typically, the task or goal corresponds to an API call.

Sample declaration syntax

A sample declaration consists of the keyword sample followed by an expression block. The type of the sample is the type of the expression block. All samples in a dialog must have the same type.

sampleDeclaration
   : SAMPLE blockExpression
   ;

Sample requirements

  • Every sample must have at least one expression.
  • All samples must start with an expect() action with an Invoke request act.
  • Every sample in the same dialog must be compatible with the declared type of the dialog.
  • All samples must end with a response() action.

Sample declaration example

The following is an example of a sample.

    sample {
        weatherEvent = expect(Invoke, getWeatherEvent)
        ensure(
           RequestArguments {arguments = [getWeather.arguments.cityName], response = request_city_prompt},
           RequestArguments {arguments = [getWeather.arguments.date], response = request_date_prompt}
        )
        weatherResult = getWeather(weatherEvent.cityName, weatherEvent.date)
        response(weather_prompt, Notify {actionName = getWeather, success = true}, payload = WeatherResultPayload {weatherResult = weatherResult})
    }

The type of the sample is Nothing because the type of response(), which is the final expression in the block, is Nothing.

Example

The following dialog example has two samples. The first sample represents a conversational flow in which the user might provide both the city name and the date when requesting the weather forecast. An action retrieves the weather forecast, which Alexa Conversations uses to generate a response.

The second sample represents a conversational flow in which the user might only provide the date. If the user only provides the date, Alexa requests the city name before calling the action to retrieve the weather forecast. Alexa Conversations then uses the forecast to generate the response.

namespace com.weatherbot.dialogs

import org.weatherbot.artifacts.* // Imports everything under this namespace, including the events and actions
import prompts.* // Imports the responses that the response action uses.
import com.amazon.alexa.schema.Nothing

dialog Nothing Weather {
  sample {
    // An event that uses the getWeatherEvent samples that specify both cityName and date.
    weatherRequest = expect(Invoke, getWeatherEvent)

    // Ensure that the user provided the required arguments, "cityName" and "date".
    ensure(
      RequestArguments {arguments = [getWeather.arguments.cityName], response = request_city_prompt},
      RequestArguments {arguments = [getWeather.arguments.date], response = request_date_prompt}
     )

    // An external action that might be implemented in an AWS Lambda.
    weatherResult = getWeather(weatherRequest.cityName, weatherRequest.date)

    // A response to the user with weather information, which is the result from the external action call.
    response(weather_prompt, Notify {actionName = getWeather, success = true}, payload = WeatherResultPayload {weatherResult = weatherResult})
  }

  sample {
    // An event that uses the getWeatherEvent samples that specify only the date.
    weatherRequest = expect(Invoke, getWeatherEvent)

    // Ensure that the user provided the required argument "date".
    ensure(RequestArguments {arguments = [getWeather.arguments.date], response = request_date_prompt})

    // A response that asks the user for the city.
    response(request_city_cityName, Request {arguments = [getWeather.arguments.cityName]})

    // A user's response to the above request using the samples of informCityEvent.
    cityNameResponse = expect(Inform, informCityNameEvent)

    // An external action that might be implemented in an AWS Lambda.
    weatherResult = getWeather(cityNameResponse.cityName, weatherRequest.date)

    // A response to the user with weather information, which is the result from the external action call.
    response(weather_prompt, Notify {actionName = getWeather, success = true}, payload = WeatherResultPayload {weatherResult = weatherResult})
  }
}