BraveyJS / Bravey

A simple JavaScript NLP-like library to help you creating your own bot.
https://braveyjs.github.io/
MIT License
78 stars 6 forks source link

Free text capture with RegexEntityRecognizer example #12

Open jbjonesjr opened 7 years ago

jbjonesjr commented 7 years ago

One of the things I'd like to process from the text input is a free form section of text. I assume I can do this via the RegexEntityRecognizer, but without any examples, I assume it's pretty inflexible. Illustrate my goal with an example:

console.log(nlp.test("I'd like some pasta"));
// { intent: "order_food", entitiesIndex: { food_type: { value: "pasta" } } }
console.log(nlp.test("I'd like some pasta with meatballs and cheese"));
// { intent: "order_food", entitiesIndex: { food_type: { value: "pasta" }, toppings: { value: "meatballs and cheese"}  } }
console.log(nlp.test("I'd like some pasta with meatballs and cheese on top"));
// { intent: "order_food", entitiesIndex: { food_type: { value: "pasta" }, toppings: { value: "meatballs and cheese"}  } }

I orginally found bravey as an alternative to a very regex-enumeration heavy text parsing solution, but I'm not sure if there are any better options to get this data then to dive back into Regex land. Suggestions?

BraveyJS commented 6 years ago

You can give a try to FreeTextEntityRecognizer...

var nlp=new Bravey.Nlp.Sequential("getdescription",{stemmer:Bravey.Language.EN.Stemmer});
nlp.addEntity(new Bravey.Language.EN.FreeTextEntityRecognizer("topping"));
var food = new Bravey.StringEntityRecognizer("food");
food.addMatch("pasta", "pasta");
food.addMatch("pizza", "pizza");
food.addMatch("pizza", "pizzas");
nlp.addEntity(food);
nlp.addDocument("I want {food}", "food", { fromTaggedSentence: true, expandIntent: true });
nlp.addDocument("I want {food} with {topping}", "food", { fromTaggedSentence: true, expandIntent: true });
console.log(nlp.test("Want few pizzas, please"));
// Intent: food, Entities: [food="pizza"] ["topping"=""]
console.log(nlp.test("I'd like some pasta"));
// Intent: food, Entities: [food="pasta"] ["topping"=""]
console.log(nlp.test("I'd like some pasta with meatballs and cheese"));
// Intent: food, Entities: [food="pasta"] ["topping"="with meatballs and cheese"]
console.log(nlp.test("I'd like some pasta with meatballs and cheese on top")); 
// Intent: food, Entities: [food="pasta"] ["topping"="with meatballs and cheese on top"]
console.log(nlp.test("I'd like some pasta having meatballs and cheese on top please")); 
// Intent: food, Entities: [food="pasta"] ["topping"="having meatballs and cheese on top"]

...but, as other entity recognizers in Bravey, it's mostly based on regular expressions. English version of the entity recognizer (Bravey.Language.EN.FreeTextEntityRecognize) is a vanilla one pre-configured with few common text delimiters. (https://github.com/BraveyJS/Bravey/blob/master/src/languages/en.js#L801) More delimiters can be added with addPrefix and addConjunction.

francescoagati commented 6 years ago

hi, there is an example for using some FreeTextEntityRecognize without StringEntityRecognizer? when i try to use only FreeTextEntityRecognize i get alway false on test the sequential nlp

BraveyJS commented 6 years ago

Okay!

var nlp=new Bravey.Nlp.Sequential("getdescription",{stemmer:Bravey.Language.EN.Stemmer});
nlp.addEntity(new Bravey.Language.EN.FreeTextEntityRecognizer("topping"));
nlp.addDocument("I want {topping} thanks", "food", { fromTaggedSentence: true, expandIntent: true });
nlp.addDocument("Just {topping}", "food", { fromTaggedSentence: true, expandIntent: true });        
console.log(nlp.test("I need meatball and cheese, please"));
// Intent: food, Entities: ["topping"="i need meatball and cheese"] 
console.log(nlp.test("meatball and cheese thanks"));
// Intent: food, Entities: ["topping"="meatball and cheese"]

FreeTextEntityRecognize is quite beta and experimental. It works well when surrounded with other entities, since it works mostly like a spring that tries to match everything in the middle - and that's why it works only with Sequential NLP. You can create non-meaningful entities in order to help the recognizer.

var nlp=new Bravey.Nlp.Sequential("getdescription",{stemmer:Bravey.Language.EN.Stemmer});
nlp.addEntity(new Bravey.Language.EN.FreeTextEntityRecognizer("topping"));
var splitter = new Bravey.StringEntityRecognizer("splitter");
splitter.addMatch("none", "with");
splitter.addMatch("none", "having");
splitter.addMatch("none", "need");
splitter.addMatch("none", "just");
nlp.addEntity(splitter);
nlp.addDocument("I {splitter} {topping} thanks", "food", { fromTaggedSentence: true, expandIntent: true });
nlp.addDocument("{topping} thanks", "food", { fromTaggedSentence: true, expandIntent: true });
console.log(nlp.test("I need meatball and cheese, please"));
// Intent: food, Entities: ["topping"="meatball and cheese"]    
console.log(nlp.test("Something with meatball and cheese thanks"));
// Intent: food, Entities: ["topping"="meatball and cheese"]            
console.log(nlp.test("I need meatball and cheese, please"));
// Intent: food, Entities: ["topping"="meatball and cheese"]    
console.log(nlp.test("meatball and cheese thanks"));
// Intent: food, Entities: ["topping"="meatball and cheese"]
francescoagati commented 6 years ago

thanks i will try

francescoagati commented 6 years ago

have you see ecolect? https://github.com/aholstenson/ecolect-js

BraveyJS commented 6 years ago

Yes, we're following the project very closely and it's a really interesting one! It uses a more deterministic approach, that gives very good results on free text entity recognizers but probably needs more training for intent matching. Bravey instead uses a mix of Bayesian filters and regexps, which needs less training but gives more statistical results.

const ecolect = require('ecolect');
const en = require('ecolect/language/en');
const Bravey = require("bravey");

// --- Ecolect

const intents = ecolect.intents(en)
    .intent('lights:on')
        .add('turn lights on')
        .done().build();

intents.match('turn lights on').then(results => {
    if(results.best) console.log('(ECOLECT) Intent:', results.best.intent);
    else console.log("(ECOLECT) No match");
});
// = (ECOLECT) Intent: lights:on

intents.match('turn the lights on').then(results => {
    if(results.best) console.log('(ECOLECT) Intent:', results.best.intent);
    else console.log("(ECOLECT) No match");
});
// = (ECOLECT) No match

// --- Bravey

const nlp = new Bravey.Nlp.Fuzzy();
nlp.addDocument('turn lights on', 'lights:on', { fromFullSentence: true, expandIntent: true });

console.log("(BRAVEY) Intent:",nlp.test('turn lights on').intent);
// = Intent: (BRAVEY) lights:on

console.log("(BRAVEY) Intent:",nlp.test('turn the lights on').intent);
// = Intent: (BRAVEY) lights:on

There probably isn't a true silver bullet on NLU for chatbots and you've to choose the one that suits your needs, in terms of performances and purposes.

francescoagati commented 6 years ago

yes i have see that bravey can recognize better some phrases. why you don't present bravey at milano chatbot meetup?