CUI Component, a requirement analysis

Sean Wu
5 min readNov 3, 2021

Even through it is common knowledge that component-based approach can significantly drive down the cost of software development, there is not component-based conversational user interface (CUI) framework yet. As a first step, let’s identify the requirement for such framework.

Component driven development

Component-Driven Development (CDD) is a development methodology that advocates building things using prefabricated components. In software development, a component performs some claimed task, and can be combined into bigger components and solve bigger problems. Software component has the following three characteristics:

  1. Blackbox functionality: The component should provide the advertised functionality without external help. The user of the component should not need to understand the underlying mechanics. For example, a date picker handles complexities such as leap years, variations in months, and interactions between the day of the week and day of the month, etc.
  2. Composability: Allow for the reuse of a component by wiring it into different contexts for different purposes, for example, the same date picker can be utilized by both airline ticketing and hospital reservations.
  3. Configurability: Ideally, user can customize component’s behavior via configuration, such as setting the initial date of a date picker or defining its look and feel.

All contemporary graphic user interface (GUI) frameworks, including Reactjs, SwiftUI, and Vue, are built on the concept of components for good reason. Reusing components in different contexts allows for sharing of development costs, resulting in significant cost savings compared to building the same functionality from scratch, while enjoying the higher quality as well as reduced maintenance cost. Using prefabricated component can greatly reduce the time to market, as builder can get desired functionality by picking component instead of worrying about the implementation details.

UI Component as () -> T

Types are at core of programming, they are classifications of data that defines the possible values and operations that can be performed on given class of data. Type can be separated into two categories:
1. primitive type: also known as entity on many CUI platform, such as MovieTitle, a object of for this type can be “StarWars”, which can be triggered by user’s expression “Star Wars”.
2. composite type, which is a structure made of “slots”, each with a name and type.

A function type is a special composite type that utilizes slots for its formal parameters and has a return type in addition, an example of function type can be: sellMovieTicket(title: MovieTitle, showTime: LocalTime), where sellMovieTicket is type name, and name:type is format we used to define a slot. As it will become clear soon, users can only directly create objects for function types. Primitive and composite types are significant as they serve as the types for function parameters. Nowadays, the service APIs are typically expressed in OpenAPI syntax, so it is useful to support the same type system as OpenAPI, including user defined type, polymorphic type or interface, and container type. This will make integration with backend easier.

The main purpose of a user interface (UI) is to allow users to interact with and access various functionalities. To invoke a function, the UI must determine which function the user wants to call and gather the user’s preferences for all its parameters. It’s clear that the UI module as a whole is primarily designed to create objects of function types, and the most logical way to break down the UI module into components is to assign each UI component the responsibility of creating an object for a specific, fixed type. Let’s use movie ticketing as example, the goal of a UI component can then be to create a function object in form of sellMovieTicket(title=”StarWars”, showTime=8:00pm).

UI component can be further divided into two decoupled horizontal layers: perception layer and interaction logic layers to allow for flexibility in designing the UI. For example, the perception layer of a UI component can be adapted to different markets by swapping resource files or to different aesthetics by using different skins, while the interaction logic layer stay the same to reduce the development cost.

CUI Consideration: Composing

When creating a UI component for a composite type, how can we utilize the UI components for its individual constituent types? There are typically two approaches for connecting a UI component to a type: the use site, which is where the type is referenced, and the declaration site, which is where the type is defined.

GUI developer have full control of what user can do, so GUI components are hard wired at use site. It is thus possible to use different UI components for the same type in the same interaction session.

For CUI, user can say anything at any given turn, enumerating all possible execution paths is simply not cost-effective. So it is better to wire CUI component to type definition. On the surface, we lost the freedom to have different interactions on one type, but consistent interaction is actually more desirable.

CUI Consideration: Runtime

Wiring UI behavior to a type once and using is every time that type is referenced represents a good developer experience. But this approach places additional requirements on CUI runtime. For example:

  1. One requirement can be to stay on the same page with user while user switching between different topics, which in turn requires chatbot to compute pronoun antecedent from context accurately.
  2. Another requirements is to be insensitive to order of user input. Assuming user knows what they want, the function object created should stay the same regardless in what order user choose to provide their preferences.

It is not hard to notice that deterministic state machine is not enough for modeling interaction under these new requirement, and runtime need to be developed based on something more dynamic and composite.

CUI Consideration: Configuring

To support different languages, there should be simple annotations on these CUI components so that one can customize its dialog understanding and text generation behavior. Ideally, such configuration should requires no background in the natural language understanding or machine learning so that everyone can contribute to language aspects without going though steep learning curve. These annotations should support the context dependent understanding, and be effective for hot-fixing the understanding issues.

For task oriented conversation, the goal is always connecting user with desired services. So it should be possible for the CUI component to pair up with different service providers for maximal reuse.

Conclusion

The advent of high level component based frameworks greatly reduced the cost of building the GUI application, and resulted in ubiquitous availability for web and mobile apps. Lacking of well designed component based CUI framework has plagued the chatbot development for too long. With this detailed requirement analysis based on our experience in building opencui.io, we hope that we can start the discussion and collective move towards a modern chatbot development process.

--

--