RavenClaw Grammar Mappings and Binding Filters

From Olympus
Jump to: navigation, search



A grammar mapping describes what a Request or Expect Agent expects to hear in the user response, and how the values from the semantic parse will be mapped into a corresponding value for the concept. A grammar mapping is a list of one or more grammar mapping element, each with with a single grammar slot name, and optional scope and binding filters or normalizations.

The syntax for the grammar mapping definition is:

 grammar_mapping ::= gm_element[','grammar_mapping]
 gm_element ::= [gm_scope] '['grammar_slot_name']' [ '>' (value | ':'binding_filter_name) ]
 gm_scope ::= '!' | '@' | '*' | '@('agent_referents')'
 agent_referents ::= agent_referent[';'agent_referents]

Here are four example grammar mappings:

  1. [Identification.user_name] This example uses a single nested grammar slot.
  2. ![Yes]>projector, [Projector]>projector This example as two grammar mapping elements, the first uses a scope modifier(!), and both of them use a the normalization >projector.
  3. [DateTime.date_relative]>:datetime This example uses a binding filter >:datetime.
  4. @(/RoomLine/AnythingElse)[NeedRoom.date_time]>:datetime This example uses the normalization @(/RoomLine/AnythingElse) and the binding filter >:datetime.

Grammar Slot

A grammar mapping is generally defined as a comma separated list of grammar mapping elements. Each element specifies one semantic grammar slot (e.g. [Identification.user_name], [Yes], etc.) During the input processing phase, the dialog engine will look for that slot in the current input. If the slot is found, the value for the slot (the corresponding string is the input) is used to update the requested concept. For instance, if the recognition result is my name is john doe we obtain the parse:

 [Identification] (my name is [user_name] (john doe))

In this case, according to grammar mapping (1), [Identification.user_name], the string john doe will be used to update the requested concept. If the grammar mapping were [something_else], there would be no binding and no concept update. If the grammar mapping were [Identification]<code>, the binding would be my name is john doe.


The <code>>value postfix construct allows system developers to perform a very simple normalization of the input string. For instance, for the user response That's right, we obtain the parse:

 [Yes] (that's right)

In this case, according to grammar mapping (2), the value projector will be used to update the requested concept.

Binding Filters

More sophisticated processing of the input can be accomplished by using binding filters. A binding filter is a developer-defined function that is applied to the parse string to construct a concept value. For instance, for grammar mapping (4), if the user responds I need a room tomorrow, we obtain the parse:

 [NeedRoom](i need a room) [DateTime]([date_relative](tomorrow))

In this case, according to grammar mapping (3), the string "tomorrow" is passed to the datetime binding filter. This filter will process the string and return an actual date-time value, such as 2006-03-22, that will be used to update the requested concept.

To take an example filter simpler than datetime, assume you have a grammar mapping for a location. The location concept is actually a structure with two fields: name, which is a string containing the name of the place and type which is an integer containing 1 if the place is an airport and 2 if the place is a city (there are of course different ways of dealing with places of different kinds, like using a different concept for each kind, but let's ignore these other methods here). The custom type for such a concept is defined as follows:


Assume your grammar is such that the [Place] slot can contain either a [Airport] slot or a [City] slot. The grammar mapping for this concept would look like this:


which uses a binding filter called place. To indicate to RavenClaw which function to use for the binding filter, you would need to add the following to your CORE_CONFIGURATION section:

   BINDING_FILTER("place", PlaceBindingFilter)

And you would also need to create a function called PlaceBindingFilter like the following:

 string PlaceBindingFilter(string sSlotName, string sSlotValue) {
   int iType = 1;
   if (sSlotName.find("City") != -1) {
     iType = 2;
   string sResult = "{\n";
   sResult += "name\t" + sSlotValue + "\n";
   sResult += "type\t" + iType + "\n";
   sResult += "}\n";
   return sResult;

Note that the function takes two strings containing the grammar slot name and its value (i.e. the string captured by the grammar slot in the input), and returns a string which contains the value of the concept. Since the concept is a structure here, the return strings follows the standard syntax of encompassing the whole struct in curly braces and adding key/value pairs separated by newlines in between.

Given all this, if the user input is "JFK", parsing as "[Place] ( [Airport] ( JFK ) )", the output of the binding filter (and thus the value of the place concept) is:

 name    JFK
 type    1

While this example might appear somewhat artificial, you might find that binding filters are a good solution when you're acquiring concepts that are inherently structured (e.g. dates) and/or non-string (e.g. numbers) from the user.

Scope Modifiers

During the input processing phase, each defined expectation can be either active or closed. A request-agent can collect information from the input only through active expectations. The system developer can control at what times expectations are active by using a scope operator in front of the grammar slot:

  • the ! operator; when this operator is used while defining an expectation (e.g. ![Yes]>true), the expectation will be active only when the agent that defines the expectation is actually in focus.
  • the * operator; when this operator is used, the expectation is always open.
  • the @(agent_referents) operator; the expectation is open only when the focus of the conversation is under one of agents in the specified list. For instance, if we wanted to allow the hotel_name concept to bind only while the conversation is on the first leg of the trip, but not the second leg of the trip, the expectation could be defined as: @(/FlightInfo/Leg1;/FlightInfo/Hotels)[HotelName]

Additionally, the system author can control when expectations are active by specifying a Boolean condition with an EXPECT_WHEN directive.

NB: this text was originally mostly copy-pasted from Dan Bohus' PhD thesis

Personal tools