diff --git a/server/src/core/conversation.js b/server/src/core/conversation.js index 695fc52c..a2ddcdd2 100644 --- a/server/src/core/conversation.js +++ b/server/src/core/conversation.js @@ -9,6 +9,7 @@ const defaultActiveContext = { currentEntities: [], entities: [], slots: { }, + isInActionLoop: false, nextAction: null, originalUtterance: null, activatedAt: 0 @@ -50,6 +51,7 @@ class Conversation { set activeContext (contextObj) { const { slots, + isInActionLoop, nluDataFilePath, actionName, lang, @@ -81,6 +83,7 @@ class Conversation { currentEntities: [], entities: [], slots: { }, + isInActionLoop, nextAction, originalUtterance: contextObj.originalUtterance, activatedAt: Date.now() @@ -112,6 +115,7 @@ class Conversation { currentEntities: entities, entities, slots: { }, + isInActionLoop, nextAction: null, originalUtterance: contextObj.originalUtterance, activatedAt: Date.now() diff --git a/server/src/core/nlu.js b/server/src/core/nlu.js index 5ee3a5ef..760da901 100644 --- a/server/src/core/nlu.js +++ b/server/src/core/nlu.js @@ -92,7 +92,7 @@ class Nlu { * TODO: split this method into several methods */ process (utterance, opts) { - console.log('this.conv.activeContext', this.conv.activeContext) + console.log('process() start this.conv.activeContext', this.conv.activeContext) const processingTimeStart = Date.now() return new Promise(async (resolve, reject) => { @@ -133,34 +133,66 @@ class Nlu { }) } - // TODO: make difference between context that needs slots and the ones who does not - // TODO: this case is only for slots context - // TODO: an action requiring slots must always have a next_action - console.log('THIS.CONV', this.conv.activeContext) + // Pre NLU processing according to the active context if there is one if (this.conv.hasActiveContext()) { - const processedData = await this.slotFill(utterance, opts) - console.log('processedData (slot filled over)', processedData) - - if (processedData && Object.keys(processedData).length > 0) { - processedData.nextAction = 'guess' - // Set new context with the next action if there is one - if (processedData.nextAction) { - this.conv.activeContext = { - lang: this.brain.lang, - slots: { }, - originalUtterance: processedData.utterance, - nluDataFilePath: processedData.nluDataFilePath, - actionName: processedData.nextAction, - domain: processedData.classification.domain, - intent: `${processedData.classification.skill}.${processedData.nextAction}`, - entities: [] + // When the active context is in an action loop, then directly trigger the action + if (this.conv.activeContext.isInActionLoop) { + const { domain, intent } = this.conv.activeContext + const [skillName, actionName] = intent.split('.') + const nluDataFilePath = join(process.cwd(), 'skills', domain, skillName, `nlu/${this.brain.lang}.json`) + this.nluResultObj = { + ...this.nluResultObj, + slots: this.conv.activeContext.slots, + utterance, + nluDataFilePath, + classification: { + domain, + skill: skillName, + action: actionName, + confidence: 1 } - - console.log('NEW ACTIVE CONTEXT', this.conv.activeContext) } + this.nluResultObj.entities = await this.ner.extractEntities( + this.brain.lang, + nluDataFilePath, + this.nluResultObj + ) + + const processedData = await this.brain.execute(this.nluResultObj, { mute: opts.mute }) + return resolve(processedData) } - return resolve(processedData) + // TODO: make difference between context that needs slots and the ones who does not + // TODO: this case is only for slots context + // TODO: an action requiring slots must always have a next_action + console.log('THIS.CONV', this.conv.activeContext) + // When the active context has slots filled + if (Object.keys(this.conv.activeContext.slots).length > 0) { + const processedData = await this.slotFill(utterance, opts) + console.log('processedData (slot filled over)', processedData) + + if (processedData && Object.keys(processedData).length > 0) { + processedData.nextAction = 'guess' + // Set new context with the next action if there is one + if (processedData.nextAction) { + this.conv.activeContext = { + lang: this.brain.lang, + slots: { }, + isInActionLoop: true, // TODO: dynamic value according to the skill output + originalUtterance: processedData.utterance, + nluDataFilePath: processedData.nluDataFilePath, + actionName: processedData.nextAction, + domain: processedData.classification.domain, + intent: `${processedData.classification.skill}.${processedData.nextAction}`, + entities: [] + } + + console.log('NEW ACTIVE CONTEXT', this.conv.activeContext) + } + } + + return resolve(processedData) + } } const result = await this.nlp.process(utterance) @@ -302,8 +334,8 @@ class Nlu { } } - const shouldLoop = await this.routeSlotFilling(intent) - if (shouldLoop) { + const shouldSlotLoop = await this.routeSlotFilling(intent) + if (shouldSlotLoop) { return resolve({ }) } diff --git a/server/src/intent-object.sample.json b/server/src/intent-object.sample.json index 3a03499a..2fcdd922 100644 --- a/server/src/intent-object.sample.json +++ b/server/src/intent-object.sample.json @@ -4,7 +4,9 @@ "skill": "is_it_down", "action": "run", "utterance": "Check if github.com, mozilla.org and twitter.com are up", - "entities": [ + "slots": {}, + "entities": [], + "current_entities": [ { "sourceText": "github.com", "utteranceText": "github.com", diff --git a/skills/games/guess_the_number/src/actions/guess.py b/skills/games/guess_the_number/src/actions/guess.py index fd94829a..d32d0a9a 100644 --- a/skills/games/guess_the_number/src/actions/guess.py +++ b/skills/games/guess_the_number/src/actions/guess.py @@ -11,6 +11,7 @@ def guess(params): nb_to_guess = 42 # TODO: pick up from DB # Find entities + # TODO: if no number entity found, then break the action loop for item in params['entities']: if item['entity'] == 'number': given_nb = item['resolution']['value'] @@ -18,8 +19,6 @@ def guess(params): if given_nb == nb_to_guess: return utils.output('end', 'guessed', '....CONGRATS....') if nb_to_guess < given_nb: - # TODO: enable loop - return utils.output('end', 'smaller', utils.translate('smaller') + return utils.output('end', 'smaller', utils.translate('smaller')) if nb_to_guess > given_nb: - # TODO: enable loop - return utils.output('end', 'bigger', utils.translate('bigger') + return utils.output('end', 'bigger', utils.translate('bigger'))