NLP
_ | | ____ | | ____ | _ \| || _ \ | | | | || |_| | |_| |_|\_) __/ |_|
NLP
The natural language processing (NLP) module enables Roboy to process and understand the human language.
That way he can interpret the meaning of the detected sentences.
We use a free, open-source NLP library for advanced NLP in Python: spaCy
You can find some hands-on examples here.
Extracted Features
Feature | Ravestate Properties/Signals | Description | Example Sentence: 'Revolutions need six fancy chickens!' |
---|---|---|---|
Tokenization | nlp.prop_tokens |
Segmenting text into words, punctuation marks etc. | 'Revolutions', 'need', 'six', 'fancy', 'chickens', '!' |
Part-of-Speech (POS) Tagging | nlp.prop_postags |
Assigning word types to tokens | 'NOUN', 'VERB', 'NUM', 'ADJ', 'NOUN', 'PUNCT' |
Detailed POS Tag | nlp.prop_tags |
Fine-grained part-of-speech | 'Revolutions' has the tag: 'NNS', which stand for: noun, plural 'need' has the tag: 'VBP', which stands for: verb, non-3rd person singular present List of POS tags |
Lemmatization | nlp.prop_lemmas |
Assigning the base forms of words | 'Revolutions' has the lemma: 'revolution' 'was' would have the lemma: 'be' |
Named Entity Recognition (NER) | nlp.prop_ner |
Labelling "real-world" objects ("NE"=Named Entity) | 'six' has the NE: 'CARDINAL', which are numerals that do not fall under another type List of NEs |
Triple Extraction | nlp.prop_triples |
A triple consists of subject, predicate, object of sentence | Triple: subject: 'Revolutions', predicate: 'need', object: 'chickens' |
About Roboy | nlp.prop_roboy |
Detecting whether sentence is about Roboy | 'you', 'roboy', 'robot', 'roboboy', ... |
Yes-No | nlp.prop_yesno |
Detecting answers to yes-no questions | Checking for 'yes', 'no', 'i don't know', 'probably', 'probably not' and synonyms of these |
Sentence Type: Question | nlp.sig_is_question |
Emitted if the input sentence is a question | |
Play Game | nlp.sig_intent_play |
Emitted when the interlocutor wants to play a game | input: "I want to play", "I like games" or something similar |
Additional features can be added and published to the system. All existing features can be found here.
Using the Features
React to Property Change
Each feature is stored in a ravestate property. A state which wants to access a property needs read permissions for that property.
Example: State that reads the "yesno" property
import ravestate as rs import ravestate_nlp as nlp import ravestate_rawio as rawio @rs.state( cond=nlp.prop_yesno.changed(), # state reacts to a change in the 'yesno' property read=nlp.prop_yesno, # state is allowed to read the 'yesno' property write=rawio.prop_out) # state is allowed to write to the output property def postive_chicken(ctx: ContextWrapper): if ctx[nlp.prop_yesno].yes(): ctx[rawio.prop_out] = "You seem to be a positive chicken!"
React to Signals
For 'Sentence Type: Question' a signal is emitted.
Example: State that reacts to the "is-question" signal
import ravestate as rs import ravestate_nlp as nlp import ravestate_rawio as rawio @rs.state( cond=nlp.sig_is_question, # state reacts to the is-question signal write=rawio.prop_out) # state is allowed to write to the output property def curious_chicken(ctx: ContextWrapper): ctx[nlp.prop_out] = "You seem to ask a lot of questions, chicken!"
Using the Triples for Sentence Analysis
The triple extraction is done in extract_triples.py by using the dependency tree of the sentence. A dependency tree shows the relation between the words of a sentence. The finite verb (predicate) is the structural center of the sentence and therefor of the tree. So starting with the predicate the algorithm searches through the dependency tree to find subject and object.
Analyzing a Sentence
Example: 'Chickens like revolutions' reaction state Triple: subject: 'Chickens', predicate: 'like', object: 'revolutions'
import ravestate as rs import ravestate_nlp as nlp import ravestate_rawio as rawio @rs.state( cond=nlp.prop_triples.changed(), # state reacts to a change in the 'triples' property read=nlp.prop_triples, # state is allowed to read the 'triples' property write=rawio.prop_out) # state is allowed to write to the output chanel def postive_chicken(ctx: ContextWrapper): triple = ctx[nlp.prop_triples][0] # gives you the first Triple object # check predicate and object correspondingly # match_either_lemma() is a method in the Triple class if triple.match_either_lemma(subj={"chicken", "dinosaur"}): # returns true when subj, pred or obj have the desired value ctx[rawio.prop_out] = "You said something about a chicken, i like chickens!"
Using User-defined Signals and Implementing Q/A-States
A user can define signals as needed and implement states reacting on them.
If both a signal is emitted and something is written to rawio
in one state, the state needs to be defined with emit_detached=True
.
React to User-defined States and Implement Q/A
Example: In one state a question is asks and then a user-defined signal is emitted that shows that the question has been stated. The other states reacts on the answer to this question.
import ravestate as rs import ravestate_nlp as nlp import ravestate_rawio as rawio chicken_signal = rs.Signal("chicken signal") @rs.state( cond=nlp.prop_tokens.changed(), write=rawio.prop_out, signal=chicken_signal, emit_detached=True ) def ask_chicken_question(ctx: rs.ContextWrapper): ctx[rawio.prop_out] = "Wanna know something awesome about chickens?" return rs.Emit() @rs.state( cond=chicken_signal & nlp.prop_yesno.changed(), read=nlp.prop_yesno, write=rawio.prop_out ) def answer_chicken_question(ctx: rs.ContextWrapper): if ctx[nlp.prop_yesno] == "yes": ctx[rawio.prop_out] = "Well, chicken's actually aren't that awesome." elif ctx[nlp.prop_yesno] == "no": ctx[rawio.prop_out] = "You're missing out on awesome chicken stories!"