Factory Rules - Numbers recognition



I would like to know if there is any possibility to have a factory rule that is able to recognize number. For example, Jibo hears “two hundred and thirty-four” and will return “234”.

I’m currently developing a work around to achieve this. But wouldn’t make much more sense if it’s implemented as a factory rule? :slight_smile:


Hi Gioeretti,

This is a great question and I hope the answer will save you some time!

Our speech recognition system on Jibo will automatically parse utterances of “five hundred” as the number 500. This is a bit hard to illustrate in the simulator where you can manually type in either a string “five” or an actual number 5 but I wanted to show a quick example and make sure you know how an actual Jibo robot would interpret it:

A. I created a rule that just returns whatever the speaker says:

TopRule = $* (
    $number_message{message= number_message._message}

number_message @= (+$w){_message= _parsed};

B. I then had Jibo ask the user via TTS to say a number or not and followed that TTS behavior with a listen behavior that has the following onResult argument seen in this image:

C. That is followed by a switch parent behavior with two children behaviors. One of those children has a Case decorator with the following conditional argument:

() => {
return  !isNaN(notepad.NLresult);

When this short skill is run on a Jibo robot ( or if you respond to the listen behavior by typing a number when running in the simulator) that first switch child will execute successfully and Jibo would say “you said a number.”

In short, our system will interpret utterances of numbers as numbers and not as their word/string equivalents (5, not “five”) so a factory rule would not be needed in just about all cases. :slight_smile:


Hi John!
Thank you for your reply, that’s perfect! :smiley:
What about words like “a”, “a couple”, “a dozen”, … I guess I have to do a rule for them.


Now I’ve another question about this thema.
There is a way to easily recognize the number in the text?
I need Jibo to understand the quantity of something, for example, if I say:

  • “I need 200 grams of cheese”
  • “I want 1 pencil”
  • “I want to buy 5 tomatoes”


With a little JavaScript to process what’s passed on from your rule file, you can easily pull out numeric quantities for just about anything. For instance, let’s say you’re listening for “I want to buy 5 tomatoes”…this rule will parse that:

TopRule = $* (
    ($buy{action='buyNow'} $buyItem{buyItem=buyItem._item})
) $*;

buyItem @= (+$w){_item=_parsed};
buy = (buy | purchase) ?(a | an);

…and turn it into:

        "Input": "I want to buy 5 tomatoes",
        "NLParse": {
            "action": "buyNow",
            "buyItem": "5 tomatoes"

Then, you can process what’s returned by NLParse with this JavaScript to separate the “5” from the “tomatoes”:

(listener) => {
    listener.on('cloud', function(asrResults, speakerIds) {
    		let results = asrResults.NLParse;
    			let nBuyItem = results.buyItem;
    			// Check if item contains an amount
    			let nBuyItemAmount = nBuyItem.replace(/[^0-9]/g,'');
    			  nBuyItemAmount = parseInt(nBuyItemAmount);
    			  nBuyItem= nBuyItem.replace(/[^A-Za-z ]/g,'');
    			  nBuyItem= nBuyItem.trim();
    			} else { nBuyItemAmount = 0; } // no amount specified

With the above code, you’ll have “5” in the variable nBuyItemAmount and “tomatoes” in the nBuyItem variable.

Personally I would do this post-processing outside of the listener, but this is just to give you an idea of how to do it.

Hope that helps!


Thanks, Michael! It will surely help :slight_smile:

I was hoping for a really simple trick that would do it in the Rule. I don’t like that much the idea of splitting the process of parsing in two different places.

I’m still stuck with the idea of a simple keyword like $number, implemented like this:
quantity @= (+$number){_item=_parsed};
would really be helpful :smiley:


I think the difficulty here is that the user could respond to your request in so many different ways that you need to have a little more control of what comes down the pipeline, numeric or not.

Let’s say that, using variations of the examples you provided, that the user says “I need a pencil” instead of “I need 1 pencil”, or “I want some tomatoes” instead of “I want 5 tomatoes”, your rule file will return unexpected results if it’s expecting a number in these situations. In the code I provided, these would be still be parsed correctly (with a nBuyItemAmount of 0) and you can modify the code further to swap an “a” or “an” with the number 1 and “a couple of” with 2, etc… This gives your user much more flexibility of what they can say to your skill rather than locking them down to a specific number.

Nonetheless, if it’s important that you do all your parsing in the rule file itself, you could always do this:

TopRule = $* (
    ($buy{action='buyNow'} $buyAmount{buyAmount=buyAmount._item} $buyItem{buyItem=buyItem._item})
) $*;

buyItem @= (+$w){_item=_parsed};
buyAmount @= ($w){_item=_parsed};
buy = (buy | purchase) ?(a | an);

…with an expected return of this:

"Input": "buy 25 bags of chips",
"NLParse": {
    "action": "buyNow",
    "buyAmount": "25",
    "buyItem": "bags of chips"

The drawback being that the buyAmount could be filled with words like “a”, “an”, “several”, or “some” if the user doesn’t say a number. Further, if the user says “a couple of”, you’d get a return like this:

"Input": "buy a couple of cameras",
"NLParse": {
    "action": "buyNow",
    "buyAmount": "couple",
    "buyItem": "of cameras"

In that case, you’d still need to do additional post-processing to cleanup the buyItem and convert the buyAmount to something usable.

Obviously this would be easier with a $factory:number ability, but until that time, you’ll have to play within these limits.


After leaving the rule behind for a while I finally figured out how to do exactly what I wanted in a kind of simple and clean way…

quantity =  (a couple) { _value = '2' }
            (a) { _value = '1' }
            (the) { _value = '1' }
            $number {_value = number._value}

number @=  [+$digit] {_value = _parsed} |
digit [(1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0)];


@gioretti Thanks for posting your solution to numbers recognition. I took what you had and improved upon it a little. It is very general for pulling numbers out of ASR parsed text. Of course the rule won’t handling everything. Consider a sentence like “I’ll take 2 apples and none of those tomatoes.


# Sample input strings which parse successfully:
# bring me a couple of pizzas
# i'll take 15 pies
# none for me please
# no sugar tonight in my coffee
# the correct answer is 101
# 1 more for the road
# there are not any chickens in there
# it will take several days to do the job
# he took some candy
# he is a man of few words
# don't get me any candy
# don't give me any flack
# he doesn't want a dime from you
# It don't mean a thing if it ain't got that swing
# I don't want anything from you but to love me
# give me alot of apples
# a lot of good that does me
# Example 1:
# [
#     {
#         "Input": "the marines need a few good men",
#         "NLParse": {
#             "status": "ambiguous",
#             "number": "null"
#         },
#         "heuristic_score": 4,
#         "index": 0
#     }
# ]
# Example 2:
# [
#     {
#         "Input": "bring me a couple of pizzas",
#         "NLParse": {
#             "status": "parsed",
#             "number": "2"
#         },
#         "heuristic_score": 12,
#         "index": 0
#     }
# ]
TopRule =
    $* (
    ( several | some | few | alot | lots | (a lot)) {number='null'} {status='ambiguous'} |
    (no | none | zero | zilch | (not any) |
        ((don\'t | doesn\'t) +$w (a | any | anything))) {number = '0'} {status='parsed'} |
    (a | the) { number = '1' } {status='parsed'} |
    (a couple ?of) { number = '2' } {status='parsed'} |
    $number {number = number._value} {status='parsed'}
    ) $*;

number @=  [+$digit] {_value = _parsed};
digit [(1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0)];