Skip to content

Commit

Permalink
feat(server): persist entities into contexts
Browse files Browse the repository at this point in the history
  • Loading branch information
louistiti committed Apr 5, 2022
1 parent 860571b commit 8757577
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 48 deletions.
56 changes: 39 additions & 17 deletions server/src/core/conversation.js
Expand Up @@ -68,18 +68,18 @@ class Conversation {
const [nextAction] = actionsKeys.filter((key) => actions[key].input_context === outputContext)

/**
* If there is an active context and a new one is triggered
* If a new context is triggered
* then save the current active context to the contexts history
*/
if (this._activeContext.name && this._activeContext.name !== outputContext) {
if (this._activeContext.name !== outputContext) {
this.pushToPreviousContextsStack()
} else if (!this._activeContext.name) {
// Activate new context
this._activeContext = {
...defaultActiveContext,
name: outputContext,
domain,
intent,
entities: [],
slots: { },
nextAction,
originalUtterance: contextObj.originalUtterance,
activatedAt: Date.now()
Expand All @@ -90,20 +90,37 @@ class Conversation {
}

this.setSlots(lang, entities, slots)
} else if (entities.length > 0) {
console.log('entities', entities)
// Activate new context
this._activeContext = {
...defaultActiveContext,
name: 'test',
domain,
intent,
entities,
originalUtterance: contextObj.originalUtterance,
activatedAt: Date.now()
} else {
const [skillName] = intent.split('.')
const newContextName = `${domain}.${skillName}`

if (this._activeContext.name && this._activeContext.name !== newContextName) {
this.cleanActiveContext()
}

console.log('1this._activeContext', this._activeContext)
/**
* Activate new context and persist entities in a new context
* as long as the skill is being used
*/
if (this._activeContext.name !== newContextName) {
// Activate new context
this._activeContext = {
name: newContextName,
domain,
intent,
entities,
slots: { },
nextAction: null,
originalUtterance: contextObj.originalUtterance,
activatedAt: Date.now()
}

log.title('Conversation')
log.info(`New active context: ${newContextName}`)
} else {
// Add new entities at the end of the context entities array
this._activeContext.entities.push(...entities)
}
}
}

Expand Down Expand Up @@ -175,6 +192,9 @@ class Conversation {
* Clean up active context
*/
cleanActiveContext () {
log.title('Conversation')
log.info('Clean active context')

this.pushToPreviousContextsStack()
this._activeContext = defaultActiveContext
}
Expand All @@ -190,7 +210,9 @@ class Conversation {
delete this._previousContexts[previousContextsKeys[0]]
}

this._previousContexts[this._activeContext.name] = this._activeContext
if (this._activeContext.name) {
this._previousContexts[this._activeContext.name] = this._activeContext
}
}
}

Expand Down
74 changes: 43 additions & 31 deletions server/src/core/nlu.js
Expand Up @@ -267,20 +267,26 @@ class Nlu {
}
}

if (this.nluResultObj.entities.length > 0) {
this.conv.activeContext = {
name: `${this.nluResultObj.classification.domain}.${this.nluResultObj.classification.skill}`,
lang: this.brain.lang,
entities: this.nluResultObj.entities,
originalUtterance: this.nluResultObj.utterance,
actionName: this.nluResultObj.classification.action,
domain: this.nluResultObj.classification.domain,
intent
}
const newContextName = `${this.nluResultObj.classification.domain}.${skillName}`
if (this.conv.activeContext.name !== newContextName) {
this.conv.cleanActiveContext()
}
this.conv.activeContext = {
lang: this.brain.lang,
slots: { },
originalUtterance: this.nluResultObj.utterance,
nluDataFilePath: this.nluResultObj.nluDataFilePath,
actionName: this.nluResultObj.classification.action,
domain: this.nluResultObj.classification.domain,
intent,
entities: this.nluResultObj.entities
}
// Pass context entities to the NLU result object
this.nluResultObj.entities = this.conv.activeContext.entities

// console.log('this.conv.activeContext', this.conv.activeContext)

try {
// Inject action entities with the others if there is
const data = await this.brain.execute(this.nluResultObj, { mute: opts.mute })
const processingTimeEnd = Date.now()
const processingTime = processingTimeEnd - processingTimeStart
Expand Down Expand Up @@ -308,6 +314,10 @@ class Nlu {
* and ask for more entities if necessary
*/
async slotFill (utterance, opts) {
if (!this.conv.activeContext.nextAction) {
return null
}

const { domain, intent } = this.conv.activeContext
const [skillName, actionName] = intent.split('.')
const nluDataFilePath = join(process.cwd(), 'skills', domain, skillName, `nlu/${this.brain.lang}.json`)
Expand Down Expand Up @@ -348,9 +358,6 @@ class Nlu {
if (!this.conv.areSlotsAllFilled()) {
this.brain.talk(`${this.brain.wernicke('random_context_out_of_topic')}.`)
} else {
if (!this.conv.activeContext.nextAction) {
return null
}
/**
* TODO:
* 1. [OK] Extract entities from utterance
Expand All @@ -372,7 +379,8 @@ class Nlu {

this.nluResultObj = {
...this.nluResultObj,
slots: this.conv.activeContext.slots,
// Assign slots only if there is a next action
slots: this.conv.activeContext.nextAction ? this.conv.activeContext.slots : { },
utterance: this.conv.activeContext.originalUtterance,
nluDataFilePath,
classification: {
Expand Down Expand Up @@ -409,24 +417,28 @@ class Nlu {
*/
async routeSlotFilling (intent) {
const slots = await this.nlp.slotManager.getMandatorySlots(intent)
this.conv.activeContext = {
lang: this.brain.lang,
slots,
originalUtterance: this.nluResultObj.utterance,
nluDataFilePath: this.nluResultObj.nluDataFilePath,
actionName: this.nluResultObj.classification.action,
domain: this.nluResultObj.classification.domain,
intent,
entities: this.nluResultObj.entities
}
const hasMandatorySlots = Object.keys(slots)?.length > 0

if (hasMandatorySlots) {
this.conv.activeContext = {
lang: this.brain.lang,
slots,
originalUtterance: this.nluResultObj.utterance,
nluDataFilePath: this.nluResultObj.nluDataFilePath,
actionName: this.nluResultObj.classification.action,
domain: this.nluResultObj.classification.domain,
intent,
entities: this.nluResultObj.entities
}

const notFilledSlot = this.conv.getNotFilledSlot()
// Loop for questions if a slot hasn't been filled
if (notFilledSlot) {
this.brain.talk(notFilledSlot.pickedQuestion)
this.brain.socket.emit('is-typing', false)
const notFilledSlot = this.conv.getNotFilledSlot()
// Loop for questions if a slot hasn't been filled
if (notFilledSlot) {
this.brain.talk(notFilledSlot.pickedQuestion)
this.brain.socket.emit('is-typing', false)

return true
return true
}
}

return false
Expand Down

0 comments on commit 8757577

Please sign in to comment.