Uh oh! We couldn’t find any match.

Please try other search keywords.

Bixby Developer Center

Guides

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 contains a concept value, which can be a primitive or a structure. 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)
...

Primitive Concepts

Primitive concepts store simple data like text or numbers. Well-modeled concepts use the right type for the right job. Primitive concept inheritance requires the type to be maintained.

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 opaque to Bixby. It may be passed to external services or displayed, but is never used internally. 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:

boolean (SeatHasPower) {
description (Does this seat have a power outlet?)
}

decimal (CurrencyValue) {
description (The value part of the currency.)
}

enum (Season) {
description (Names of the seasons)
symbol (Spring)
symbol (Summer)
symbol (Autumn)
symbol (Winter)
}

integer (Quantity) {
description (How many to buy.)
}

name (BusinessName) {
description (The name of a business.)
}

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")
}

text (MapUrl) {
description (Contains an URL to a map of the business)
extends (viv.entity.EntityUrl)
}

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, and each property is itself a concept.

Note

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 {pre-commit-state}
}

The following action model outputs an Order.

action (CreateOrder) {
  type (BeginTransaction)
  collect {
    input (items) {
      type (Item)
      min (Required)
      max (Many)
      default-init {
        intent {
          goal: CreateItem
          value: SearchTerm("")
        }
      }
    }
  }
  output (Order)
}

Here is the corresponding JavaScript:

exports.function = function(items) {
  return items.map(function(item) {
    return {
      items: items,
      totalPrice: calculateTotalPrice(items),
      orderNumber: 23343,
      holdTime: dates.ZonedDateTime.now("UTC").plusSeconds(parseInt(config.get("hold_time"))).getMillisFromEpoch()
    }
  })
}

Properties

Properties define a "has-a" relationship between structure 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; it can't be a primitive type directly. For example, you can't define a latitude property directly as type (decimal) in a structure. Instead, you could refer to it as type (geo.Latitude), an already-defined primitive concept. (Your capsule will need to import viv.geo). Or, you could create latitude as a decimal primitive concept.

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 Business structure with two properties:

structure (Business) {
description (A business with a physical street address.)
property (name) {
type (BusinessName)
min (Required)
}
property (address) {
type (geo.Address)
}
}

The property name must have a single business.BusinessName value. The address property is optional, but if present, it must be a geo.Address.

Property Visibility

There are times when you may 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 {
{
prefixSymbol: ($)
currencyCode: (USD)
}
}
constant {
{
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 is a partial execution graph, in which the user asks for the phone number of Pizza Chicago, that shows how Restaurant extends viv.business.Business:

extension graph

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)
}
}

When you extend a structure concept, you can also choose to override a parent property. You may 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. 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.

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.

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 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.

ProfileStoredUnique Concepts

You may 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 ProfileStoredUnique to enforce that restriction.

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.