The following dialog fragments are available when you add custom dialog to your capsule:
Concept Fragment
: Talk about concepts in an abstract way.Value Fragment
: Talk about a concrete value.Structure Fragment
: Talk about a structure value.Input Fragment
: Talk about an action input's instantiation.Action Fragment
: Talk about an action state.Use concept fragments to talk about concepts in an abstract way, irrelevant of their instantiated value. For example, consider the sentence "There are 2 cats, a grumpy old one called Pixie and a young troublemaker called Midna". The subject of this sentence is referred to as the concept "cats". Almost every model should define a basic concept dialog, because it will be used as a building block for numerous other dialogs. Remember to account for singular and plural differences.
This first example defines a basic concept Dialog for restaurants:
dialog (Concept) {
match: viv.restaurant.Restaurant (this)
switch (plural(this)) {
case (One) {
template (restaurant) // singular
} default {
template (restaurants) // plural
}
}
}
This second example uses a more specific match-pattern to talk about the restaurants that were found after performing a search action using from-output
. It reuses the simpler concept defined in the first example, ties in some contextual information about the search inputs, and includes some Expression Language.
dialog (Concept) {
match: viv.restaurant.Restaurant (this) {
from-output: restaurant.FindRestaurants (action)
}
choose (First){
if (exists(action.restaurantStyle)) {
// ex: gluten-free bakeries in San Francisco
// ex: French bistros called "Chez Maman"
template ("[#{joinAs('input', action.diet, action.allergy, action.cuisineStyle)} ]#{value(plural(action.restaurantStyle, plural(this)))}[ #{joinAs('input', action.name, action.searchRegion)}]")
} else {
// ex: Moroccan restaurant in Montreal
template ("[#{joinAs('input', action.diet, action.allergy, action.cuisineStyle)} ]#{concept(this)}[ #{joinAs('input', action.name, action.searchRegion)}]")
}
}
}
By default, when cardinality is One
and execution state is Post
, the default template for this dialog fragment is simply the concept name, translated from
camel-case. When the concept refers to a group, the default dialog fragment is the concatenation of all the concepts in the group.
For more information on the various execution states and concept features, see the Introduction to Dialog Developers' Guide.
A Value
fragment is a concrete instantiation of a concept. For example, consider the sentence "There are 2 pizzas: one Margherita and one Pepperoni". The concept is "pizzas", while "Margherita" and "Pepperoni" are Value
names to describe them. Primitives are easily converted into a Value
. By default, they are simply dereferenced. You can decide to customize those values even more with special formatting or different phrasing. Once the primitive values are in place, they are used to define Structure Values. For Structures, it is convenient to pick a combination of properties that makes a good summary. Generally, the "name" property is sufficient.
The following fragment will replace a Boolean (true
, false
) with a user-friendly descriptor:
dialog (Value) {
match: viv.event.IsFree (isFree)
if (isFree) {
template ("free")
}
else {
template ("priced")
}
}
The following fragment customizes Enum values to take into account quantity.
dialog (Value) {
match : viv.event.EventType (this)
switch (this) {
case (Class){
switch (plural(this)) {
case (One) {
template (class)
} default {
template (classes)
}
}
}
...
}
}
This fragment refers to the event by its name, using the EL value
function to format the value of the name
property as a value fragment.
dialog (Value) {
match: viv.event.Event (this)
// The Monster Ball Tour
template ("#{value(this.name)}")
}
This will refer to a set of events based on how they are grouped.
dialog (Value) {
match: viv.event.EventSet (this)
if (this.label == 'EventsByPerformer' && exists(this.performer)) {
// concerts by Lady Gaga
template ("#{concept(this.events)}[ #{input(performer)}]")
}
else-if (this.label == 'EventsAtVenue' && exists(this.venue)) {
// games at the Avaya Stadium
template ("#{concept(this.events)}[ #{input(venue)}]")
}
else-if (this.label == 'SingleEvent') {
// The Lion King
template ("#{value(this.events[0])}")
}
}
Structure values have no default fragment templates. However, you can implement a value fragment dialog for any structure. This is handy if you want to treat a composite structure as if it were a primitive, for example money.Price
.
Here is an example of a simple structure value fragment:
template (Value) {
match: viv.money.Price (this)
template ("#{raw (this.currencyType.prefixSymbol)}#{number (this.value)}")
}
Note that this uses the EL function raw
, not value
; raw
converts the supplied value to a simple string.
You can test this by paraphrasing a simple intent that has a pre-filled goal:
intent {
goal: viv.money.Price {
value: viv.money.CurrencyValue (4.21)
currencyType:money.CurrencyType { currencyCode: (USD) }
}
}
This would work with the following utterance: Hey Bixby, find $4.21.
While this dialog would work for most cases, it doesn't take into account negative values or decimal values with improper precision. Consider the following intent:
intent {
goal: viv.money.Price {
value: viv.money.CurrencyValue (-4.3)
currencyType:viv.money.CurrencyType { currencyCode: (USD) }
}
}
This utterance is less ideal because of the strange formatting: Hey Bixby, find $-4.3.
You should enhance it to improve rendering of negative prices and fix the precision formatting.
template (Value) {
match: viv.money.Price (this)
if (value >= 0.0) {
template ("#{value (this.currencyType.prefixSymbol)}#{number (this.value, '#,##0.00')}")
}
else-if (value < 0.0) {
template ("-#{value (this.currencyType.prefixSymbol)}#{number(-1.0 * this.value, '#,##0.00')}")
}
}
The previous dialog fragment handles all possible variations, creating an ideal formatting for utterances: Hey Bixby, find -$4.30.
Input fragments describe the concrete instantiation of an action parameter. They generally start with a preposition followed by a value.
Here are a couple of examples that cover cases where the user searches for a hotel amenity:
Example 1:
dialog (Input) {
match: viv.hotel.HotelAmenity (this)
// with beach access
template ("with #{value (this)}")
}
Example dialog: with beach access
Example 2:
dialog (Input) {
match: viv.air.DepartureAirport (this) {
to-input: _
}
switch(plural(this)) {
case (One) {
template ("from #{value (this)}")
}
default {
template("#{value (this.locality.name)}")
}
}
}
Example dialog: from SFO
An action fragment describes the state of an action using a verb phrase, normally while using execution states to differentiate between the different phases.
As with other fragment types, if a fragment yields multiple templates, the system will choose one at random.
When an action fragment refers to a noun, as in Example 1, it delegates to a concept
fragment.
Here are some examples:
Example 1:
dialog (Action) {
match {
viv.cart.PutShippingOption (action)
}
switch (state(action)) {
case (Pre) {
template ("set #{concept(action.shippingOption)}")
}
case (Mid) {
template ("setting #{concept(action.shippingOption)}")
}
case (Post) {
template ("set #{concept(action.shippingOption)}")
}
}
}
Example dialog:
Example 2:
dialog (Action) {
match: phone.PhoneCallReceipt {
from-output: phone.Call (this)
}
switch (state(this)) {
case (Pre) {
template ("call[ #{value (this.phoneNumber)}]")
template ("make a phone call[ to #{value (this.phoneNumber)}]")
}
case (Mid) {
template ("calling[ #{value (this.phoneNumber)}]")
template ("making a phone call[ to #{value (this.phoneNumber)}]")
}
case (Post) {
template ("called[ #{value (this.phoneNumber)}]")
}
}
}
Example dialog: