Bixby Developer Center

Guides
References

Modeling Concepts

A concept describes any "thing." It could represent a concrete object, such as coffee, flowers, or an airport. A concept can also be abstract, such as a day, flight, or order. Well-modeled concepts are essential to Bixby because the planner uses concept models as inputs and goals when executing plans. Concepts are comparable to data types and data structures in a programming language.

Primitive concepts represent simple types, like text or numbers. Structure concepts are more complex, representing records with named properties. Each property is itself a concept. A property is usually a primitive concept, but could be a structure concept itself.

Concepts can also model inheritance relationships. For example, a restaurant inherits the properties of a business, as shown in the following snippet from a structure:

structure (restaurant.Restaurant) {
description (A business who prepares and serves food to customers)
extends (business.Business)
...

As you start to build out your concepts, make sure that you have read Bixby's Design Guidelines so that your models follow a consistent user experience.

Primitive Concepts

Primitive concepts store simple data like text or numbers. There are seven data types for primitive concepts:

  • boolean: A binary variable with two possible values, true and false.
  • decimal: A floating-point number, positive or negative. This type allows a decimal part.
  • enum: An enumeration of a fixed set of possible values (symbols). Use this when it makes sense to list all the possible values in advance. (Also see structure enums.)
    Note

    If there is no vocab file, the enums will not be recognized by natural language.

  • integer: A whole number, positive or negative, with no decimals.
  • name: A Unicode string that is available to Bixby. Use this when the string might be part of natural language input, dialog, or vocabulary. Examples include business names, menu items, and movie titles.
  • qualified: A name that matches a regular expression. This is a good choice when you want to validate a string, and want it to be visible to Bixby, but can't enumerate every possible value in advance. The regex also makes it easier for Bixby to recognize valid values.
  • text: A Unicode string that is not available for use with vocabulary, although it can be displayed or passed to external services. This is good for URLs, blocks of XML or JSON, and large blocks of text such as movie or restaurant reviews.

Here are a few examples:

qualified (PhoneNumber) {
description (A string representing a phone number.)
regex-pattern ("\\+?1? ?-? ?((\\(\\d\\d\\d\\))|\\d\\d\\d)? ?-? ?\\d\\d\\d ?-? ?\\d\\d\\d\\d")
}
boolean (Confirmation) {
extends (core.Confirmation)
}

View on GitHub

decimal (PlanetSize) {
description (A planet's diameter in miles)
}

View on GitHub

enum (Type) {
description (Type of a shoe.)
symbol (Athletic)
symbol (Boot)
symbol (Casual)
symbol (Dance)
symbol (Formal)
symbol (Sandals)
}

View on GitHub

integer (RollConcept) {
description (The result of a dice roll.)
}

View on GitHub

name (PersonName) {
description ("The person's name. Ex: Jackie Chan")
}

View on GitHub

text (Answer) {
description (The user's answer)
}

View on GitHub

Well-modeled concepts use the right type for the right job. When primitive concepts are extended, the concepts must all be the same primitive type. In the boolean example above, core.Confirmation is a boolean primitive, because that is required for Confirmation to inherit from it.

Structure Concepts

A structure concept is a record-like type, similar to a struct or a key/value object in other programming languages. Structure concepts contain any number of properties. Each property of a structure must be a concept, not a primitive data type; see Properties, below.

In order for Bixby to use structures, you need an appropriate action model and corresponding function that outputs these structures.

For example, consider the following Order structure:

structure (Order) {
property (items) {
type (Item)
min (Optional)
max (Many)
}
property (orderNumber) {
type (OrderNumber)
min (Required)
}
property (totalPrice) {
type (Price)
min (Required)
}
property (holdTime) {
type (HoldTime)
min (Required)
}
features {
transaction
}
}

View on GitHub

The following action model outputs an Order.

action (CreateOrder) {
type (BeginTransaction)
collect {
input (initialItems) {
type (InitialItems)
min (Required)
max (One)
default-init {
intent: goal: CreateItems
}
}
}
output (Order)
}

View on GitHub

Here is the corresponding JavaScript:

var dates = require('dates')
var config = require('config')
//CreateOrder
exports.function = function(initialItems) {
return {
items: initialItems.items,
totalPrice: calculateTotalPrice(initialItems.items),
orderNumber: 23343,
holdTime: dates.ZonedDateTime.now("UTC").plusSeconds(parseInt(config.get("hold_time"))).getMillisFromEpoch()
}
}

function calculateTotalPrice(items) {
var totalPrice = 0
for (var i=0; i<items.length; i++) {
totalPrice += items[i].shirt.price.value * items[i].quantity
}
return {
value: totalPrice,
currencyType: {
prefixSymbol: '$',
currencyCode: 'USD'
}
}
}

View on GitHub

Properties

Properties define a "has-a" relationship between concepts. For example, a business has an address; address could be defined as a primitive concept of type name, and the Business structure concept could include address as a property.

Properties must be semantically meaningful, so they can be useful as input to other concepts or actions. Because of this, every property must be a concept. For example, you can't define a Magnitude property directly as type (decimal) in a structure. Instead, define a Magnitude primitive concept using the decimal data type:

decimal (Magnitude) {
description (The magnitude of an earthquake)
features {
recognized-range {
min-value(0)
max-value(12)
}
}
}

View on GitHub

Then use type (Magnitude) for your property in the structure:

structure (Earthquake) {
description (An earthquake)

property (title) {
type (Title)
min (Optional) max (One)
}
property (dateTime) {
type (EarthquakeDateTime)
min (Optional) max (One)
}
property (location) {
type (EarthquakeLocation)
min (Optional) max (One)
}
property (magnitude) {
type (Magnitude)
min (Optional) max (One)
}
}

View on GitHub

Note

There are some cases where it'd be easier to instead import a library capsule and call it . For example, if you need a Latitude property, you can import the viv.geo library capsule, which includes not only a predefined Latitude concept but higher-level geographical concepts and actions.

Cardinality

By default, each property is optional and single in cardinality, meaning it can optionally have a single value. Optionality is set with the min keyword; cardinality is set with max.

You can state the default values explicitly with min (Optional) and max (One). To allow any number of values for a property, specify max (Many). To require at least one value, specify min (Required). If a property allows more than one value, all of the values must be of the property's declared type.

Here's an example Hotel structure with several properties:

structure (Hotel) {
property (name) {
type (HotelName)
min (Required) max (One)
}
property (rating) {
type (HotelRating)
min (Required) max (One)
}
property (lowRate) {
type (HotelLowRate)
min (Required) max (One)
}
property (location) {
type (geo.GeoPoint)
min (Optional) max (One)
}
property (reviewCount) {
type (HotelReviewCount)
min (Optional) max (One)
}
property (images) {
type (core.BaseImage)
min (Optional) max (Many)
}
property (amenities) {
type (HotelAmenity)
min (Optional) max (Many)
}
}

View on GitHub

The property rating must have a single HotelRating value. The reviewCount property is optional, but if present, it must be a HotelReviewCount and have a max of one. However, the images and amenities properties are also optional but can have multiple values.

A property will normally only store unique values: if your capsule adds a value to a max (Many) node that is equivalent to a value already in that node, the values will be automatically merged. If a departments property had the values ["Hardware", "Toys", "Home Goods"], you could add the value "Kitchen" to it, but if you added the value "Toys", it would automatically be merged with the existing value "Toys" and the values in the departments property would remain unique. Read about Merging and Equivalence for more about this, as well as how this behavior can be overridden.

Property Visibility

There are times when you might want the properties within concepts to be visible or invisible to the Planner.

For example, let's say you're defining the GeoPoint structure. This contains latitude and longitude properties, which you probably wouldn't expose independently of the rest of the structure. But it might make sense to declare the timeZone property with visibility(Public). That helps if some execution plan includes an action with a time.TimeZoneId input and the system already has a GeoPoint input.

structure (GeoPoint) {
description (A geographic point.)
property (latitude) {
type (Latitude)
min (Required)
}
property (longitude) {
type (Longitude)
min (Required)
}

property (timeZone) {
type (time.TimeZoneId)
visibility (Public)
min (Optional) max (One)
}
}

Here's an example of an execution graph for the utterance, "get the timezone in Seoul, South Korea," in which NamedPoint contains a property point of type GeoPoint:

timezone graph

Likewise, for a stock lookup feature, certain commonly used properties such as the stock exchange (stockExchange) and stock symbol (StockSymbol) should be available throughout the entire plan:

structure (ExchangeListing) {
description (Listings on various exchanges)
property (stockExchange) {
type (Exchange)
min (Required) max (One)
visibility (Public)
}
property (companyName) {
type (CompanyName)
min (Required) max (One)
visibility (Public)
}
property (stockSymbol) {
type (StockSymbol)
min (Required) max (One)
visibility (Public)
}
property (ipoYear) {
type (IpoYear)
}
property (companyUrl) {
type (entity.EntityUrl)
}
}

Here is an execution graph that illustrates this usage:

timezone graph

If a property has Default visibility, subsequent actions won't see it separately from its parent structure. But the Planner can still see the final goal, and so can a route or a sort value. For example, Weather is a structure with a DayHighTemperature property with Default visibility. If a user asks "What was the high temperature today?" that becomes the plan's final goal, and gains direct access to the DayHighTemperature property.

temperature graph

You could prevent this by setting visibility (Private), prohibiting the use of the property anywhere in a plan. Private properties should be properties that a user would never want to use; properties that are only used internally.

Structure Enums

A Structure Enum is the structure counterpart to the the enum data type used in primitive concepts. Both primitive and structure enums have a value chosen from a pre-defined list of constants, but a structure enum's constants set all the properties in the structure at once. It composes properties into a single enumeration list.

Here is an example of the syntax for a structure enum:

structure-enum (CurrencyType) {
property (currencyCode) {
type (CurrencyCode)
}
property (prefixSymbol) {
type (PrefixSymbol)
}
constant: CurrencyType {
prefixSymbol: ($)
currencyCode: (USD)
}
constant: CurrencyType {
prefixSymbol: ()
currencyCode: (EUR)
}
// ... additional currency types ...
}

This structure enum contains two properties, prefixSymbol and currencyCode, and the enumeration sets them together:

  • prefixSymbol: $, currencyCode: USD
  • prefixSymbol: €, currencyCode: EUR

As you can see, this CurrencyType structure-enum is important in any capsule where different currency is required and the appropriate currency needs to be used.

Relationships Between Concepts

Before creating new concepts, see if you can reuse or extend any existing concepts. This is very powerful. Besides saving time, you will benefit from existing training.

You have already seen how to reuse existing concepts as properties of a new concept. That's useful, but you can also define relationships between concepts.

Extension

You can extend a parent concept with a new child concept. If the parent concept is a structure with properties, the child concept inherits those properties as well. Then you can define new properties specific to the child concept. This is like inheritance in many programming languages and represents an "is-a" relationship; it describes a parent-child or subset relationship. You can extend both primitive concepts and structure concepts. You can also extend multiple concepts at the same time.

For example, a restaurant is a business. Like any business, it has a phone number, but it can also have a menu. All restaurants are businesses, but not all businesses are restaurants. Restaurants have characteristics that not all other businesses have. Because of this, you can treat any restaurant as a business. But you can't treat all businesses as restaurants.

Here are some other examples:

// A DeliveryRestaurant is both a Restaurant and a
// Vendor (that has a catalog you can buy from, e.g. a Menu)
structure (DeliveryRestaurant) {
extends (viv.restaurant.Restaurant)
extends (viv.order.Vendor)
}
// A Country is a special type of AdministrativeDivision
structure (CountryDivision) {
extends (AdministrativeDivision)
property (countryCode2) {
type (ISOCountryCode2)
min (Optional)
max (One)
}
property (countryCode3) {
type (ISOCountryCode3)
min (Optional)
max (One)
}
}
structure (ThisPlanet) {
role-of (Planet)
//extends will allow projections as goals description
extends (Planet)
}

View on GitHub

When you extend a structure concept, you can also choose to override a parent property. You can use this to bind a particular value. This example for Restaurant inherits BusinessCategory from business.Business, but its value will always be "Restaurant."

structure (Restaurant) {
description (A business who prepares and serves food to customers)
extends (business.Business)
property (name) {
override type (RestaurantName)
}
property (category) {
override bind (Restaurant)
}
property (restaurantStyle) {
type (RestaurantStyle)
max (Many)
}
// ... more properties ...
}

You can also override the type of a property to a more specific type. In the last example, the name property of a Restaurant is specified as RestaurantName. This is more specific than the BusinessName used by the parent concept. This only works if RestaurantName extends BusinessName.

When overriding a property you can also change the minimum cardinality, but only from Optional to Required.

Role Assignment

You can give a concept the role-of another concept to change its behavior based solely on context. Such a contextualization of a concept cannot add new properties. If you need to add new properties to the role-of concept, you should extend the original concept instead. The context is the only difference between it and its parent.

For example, the same airport can act as both a departure airport and an arrival airport. Suppose you have a FindFlight action that takes a DepartureAirport and an ArrivalAirport. If these types were extensions, any actions upstream in the plan would have to know about the downstream type expected and have to instantiate the subtype. However, with a role assignment, an air.Airport that is instantiated upstream in the plan, can be converted into a specific role when needed. This might be useful for a travel app, where we might use any airport for either arrival or departure in the context of different itineraries.

structure (DepartureAirport) {
role-of (Airport)
}

Here's how a corresponding execution graph for flight booking looks:

roles graph

Notice that both DepartureAirport and ArrivalAirport first start as Airport, after which they are given new roles.

Note

You can add new symbols to an enum with extends, but not with role-of. An enum can extend multiple concepts or have multiple roles only if all the target enum concepts have identical symbol sets.

Concept Features

When you flag a concept with concept features, you are flagging it so that the Bixby platform can treat it in a special way. This special treatment ranges from marking a concept as something stored with a user profile to not storing a value at all. Concept features offer ways to manage user preferences, privacy, or security.

  • profile-stored: Associate the concept value with the user profile. Store and retrieve as needed.

  • transient: Do not store the concept value. Do not preserve it across execution context.

  • transaction: Treat a concept as a "transaction draft", which you can use for inputs to transaction and commit actions.

  • activity: Represents "transaction records", which are the result of completing commit-type actions. They can also be used as inputs to activity actions.

  • recognized-range: Used with decimal and integer concepts to set a range of acceptable values with a lower bound (min-value) and an upper bound (max-value).

The transaction and activity features are transactional features, so after you mark a concept with a transactional feature, you must also define the corresponding state in corresponding support files (*.transaction.bxb for transaction and *.activity.bxb for activity). You can read more in Transactional Workflows.

Profile-Stored Concepts

Sometimes you know that the user will want to reuse a concept value. It might be the user's name, billing address, or airline seat preferences. Mark these concepts with the features key profile-stored, and users will have the option to save their values for reuse.

structure (FlightPreferences) {
description (Used to store user flight preferences.)
features {
profile-stored { max (Many) }
}
property (seat) {
type (AirplaneSeatType)
}
property (carrier) {
type (CarrierCode)
}
}

Storing these values is optional, and Bixby prompts the user for approval.

You might want to store certain concept values as singletons, where there can only be one value at a time for the concept. For example, when booking a flight, a single passenger's name must appear on each ticket. Mark such concepts with profile-stored with a max cardinality of One, to ensure that the profile is unique and the restriction is enforced.

Transient Concepts

Mark a concept Transient to ensure that Bixby will never store or reuse the concept values. Transient concepts will not be re-used from the historical context of a conversation. For example the system concepts time.Tense and geo.CurrentLocation are transient.