mirror of
https://github.com/leon-ai/leon.git
synced 2024-12-25 17:54:43 +03:00
refactor: switch from skill NLU config to skill config naming
This commit is contained in:
parent
141c89ecbf
commit
01f7515e6f
@ -37,7 +37,7 @@ def translate(key, dict = { }):
|
|||||||
output = ''
|
output = ''
|
||||||
variables = { }
|
variables = { }
|
||||||
|
|
||||||
file = open(path.join(dirname, '../../skills', intent_obj['domain'], intent_obj['skill'], 'nlu', intent_obj['lang'] + '.json'), 'r', encoding = 'utf8')
|
file = open(path.join(dirname, '../../skills', intent_obj['domain'], intent_obj['skill'], 'config', intent_obj['lang'] + '.json'), 'r', encoding = 'utf8')
|
||||||
obj = loads(file.read())
|
obj = loads(file.read())
|
||||||
file.close()
|
file.close()
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ dotenv.config()
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate skills endpoints script
|
* Generate skills endpoints script
|
||||||
* Parse and convert skills NLU config into a JSON file understandable by Fastify
|
* Parse and convert skills config into a JSON file understandable by Fastify
|
||||||
* to dynamically generate endpoints so skills can be accessible over HTTP
|
* to dynamically generate endpoints so skills can be accessible over HTTP
|
||||||
*/
|
*/
|
||||||
export default () => new Promise(async (resolve, reject) => {
|
export default () => new Promise(async (resolve, reject) => {
|
||||||
@ -40,7 +40,7 @@ export default () => new Promise(async (resolve, reject) => {
|
|||||||
for (let j = 0; j < skillKeys.length; j += 1) {
|
for (let j = 0; j < skillKeys.length; j += 1) {
|
||||||
const skillFriendlyName = skillKeys[j]
|
const skillFriendlyName = skillKeys[j]
|
||||||
const currentSkill = currentDomain.skills[skillFriendlyName]
|
const currentSkill = currentDomain.skills[skillFriendlyName]
|
||||||
const fileInfo = fs.statSync(path.join(currentSkill.path, 'nlu', `${lang}.json`))
|
const fileInfo = fs.statSync(path.join(currentSkill.path, 'config', `${lang}.json`))
|
||||||
const mtime = fileInfo.mtime.getTime()
|
const mtime = fileInfo.mtime.getTime()
|
||||||
|
|
||||||
if (mtime > mtimeEndpoints) {
|
if (mtime > mtimeEndpoints) {
|
||||||
@ -62,7 +62,7 @@ export default () => new Promise(async (resolve, reject) => {
|
|||||||
|
|
||||||
// Force if a language is given
|
// Force if a language is given
|
||||||
if (isFileNeedToBeGenerated) {
|
if (isFileNeedToBeGenerated) {
|
||||||
log.info('Parsing skills NLU configuration...')
|
log.info('Parsing skills configuration...')
|
||||||
|
|
||||||
for (let i = 0; i < domainKeys.length; i += 1) {
|
for (let i = 0; i < domainKeys.length; i += 1) {
|
||||||
const currentDomain = domains[domainKeys[i]]
|
const currentDomain = domains[domainKeys[i]]
|
||||||
@ -73,8 +73,8 @@ export default () => new Promise(async (resolve, reject) => {
|
|||||||
const skillFriendlyName = skillKeys[j]
|
const skillFriendlyName = skillKeys[j]
|
||||||
const currentSkill = currentDomain.skills[skillFriendlyName]
|
const currentSkill = currentDomain.skills[skillFriendlyName]
|
||||||
|
|
||||||
const nluFilePath = path.join(currentSkill.path, 'nlu', `${lang}.json`)
|
const configFilePath = path.join(currentSkill.path, 'config', `${lang}.json`)
|
||||||
const { actions } = JSON.parse(fs.readFileSync(nluFilePath, 'utf8'))
|
const { actions } = JSON.parse(fs.readFileSync(configFilePath, 'utf8'))
|
||||||
const actionsKeys = Object.keys(actions)
|
const actionsKeys = Object.keys(actions)
|
||||||
|
|
||||||
for (let k = 0; k < actionsKeys.length; k += 1) {
|
for (let k = 0; k < actionsKeys.length; k += 1) {
|
||||||
|
@ -26,15 +26,15 @@ export default (lang, nlp) => new Promise(async (resolve) => {
|
|||||||
const { name: skillName } = currentDomain.skills[skillKeys[j]]
|
const { name: skillName } = currentDomain.skills[skillKeys[j]]
|
||||||
const currentSkill = currentDomain.skills[skillKeys[j]]
|
const currentSkill = currentDomain.skills[skillKeys[j]]
|
||||||
|
|
||||||
log.info(`[${lang}] Using "${skillKeys[j]}" skill NLU data`)
|
log.info(`[${lang}] Using "${skillKeys[j]}" skill config data`)
|
||||||
|
|
||||||
const nluFilePath = path.join(currentSkill.path, 'nlu', `${lang}.json`)
|
const configFilePath = path.join(currentSkill.path, 'config', `${lang}.json`)
|
||||||
|
|
||||||
if (fs.existsSync(nluFilePath)) {
|
if (fs.existsSync(configFilePath)) {
|
||||||
const {
|
const {
|
||||||
actions,
|
actions,
|
||||||
variables
|
variables
|
||||||
} = await json.loadNluData(nluFilePath, lang) // eslint-disable-line no-await-in-loop
|
} = await json.loadConfigData(configFilePath, lang) // eslint-disable-line no-await-in-loop
|
||||||
const actionsKeys = Object.keys(actions)
|
const actionsKeys = Object.keys(actions)
|
||||||
|
|
||||||
for (let k = 0; k < actionsKeys.length; k += 1) {
|
for (let k = 0; k < actionsKeys.length; k += 1) {
|
||||||
|
@ -20,10 +20,10 @@ export default (lang, nlp) => new Promise(async (resolve) => {
|
|||||||
|
|
||||||
skillKeys.forEach(async (skillName) => {
|
skillKeys.forEach(async (skillName) => {
|
||||||
const currentSkill = currentDomain.skills[skillName]
|
const currentSkill = currentDomain.skills[skillName]
|
||||||
const nluFilePath = path.join(currentSkill.path, 'nlu', `${lang}.json`)
|
const configFilePath = path.join(currentSkill.path, 'config', `${lang}.json`)
|
||||||
|
|
||||||
if (fs.existsSync(nluFilePath)) {
|
if (fs.existsSync(configFilePath)) {
|
||||||
const { resolvers } = await json.loadNluData(nluFilePath, lang)
|
const { resolvers } = await json.loadConfigData(configFilePath, lang)
|
||||||
|
|
||||||
if (resolvers) {
|
if (resolvers) {
|
||||||
const resolversKeys = Object.keys(resolvers)
|
const resolversKeys = Object.keys(resolvers)
|
||||||
|
@ -158,8 +158,8 @@ class Brain {
|
|||||||
executionTime
|
executionTime
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
const { nluDataFilePath, classification: { action: actionName } } = obj
|
const { configDataFilePath, classification: { action: actionName } } = obj
|
||||||
const { actions } = JSON.parse(fs.readFileSync(nluDataFilePath, 'utf8'))
|
const { actions } = JSON.parse(fs.readFileSync(configDataFilePath, 'utf8'))
|
||||||
const action = actions[actionName]
|
const action = actions[actionName]
|
||||||
const { type: actionType } = action
|
const { type: actionType } = action
|
||||||
const nextAction = action.next_action ? actions[action.next_action] : null
|
const nextAction = action.next_action ? actions[action.next_action] : null
|
||||||
@ -360,10 +360,10 @@ class Brain {
|
|||||||
* "Dialog" action skill execution
|
* "Dialog" action skill execution
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const nluFilePath = path.join(
|
const configFilePath = path.join(
|
||||||
process.cwd(), 'skills', obj.classification.domain, obj.classification.skill, 'nlu', `${this._lang}.json`
|
process.cwd(), 'skills', obj.classification.domain, obj.classification.skill, 'config', `${this._lang}.json`
|
||||||
)
|
)
|
||||||
const { actions, entities } = await json.loadNluData(nluFilePath, this._lang)
|
const { actions, entities } = await json.loadConfigData(configFilePath, this._lang)
|
||||||
const utteranceHasEntities = obj.entities.length > 0
|
const utteranceHasEntities = obj.entities.length > 0
|
||||||
const { answers: rawAnswers } = obj
|
const { answers: rawAnswers } = obj
|
||||||
let answers = rawAnswers
|
let answers = rawAnswers
|
||||||
|
@ -53,7 +53,7 @@ class Conversation {
|
|||||||
const {
|
const {
|
||||||
slots,
|
slots,
|
||||||
isInActionLoop,
|
isInActionLoop,
|
||||||
nluDataFilePath,
|
configDataFilePath,
|
||||||
actionName,
|
actionName,
|
||||||
lang,
|
lang,
|
||||||
domain,
|
domain,
|
||||||
@ -63,7 +63,7 @@ class Conversation {
|
|||||||
const slotKeys = Object.keys(slots)
|
const slotKeys = Object.keys(slots)
|
||||||
const [skillName] = intent.split('.')
|
const [skillName] = intent.split('.')
|
||||||
const newContextName = `${domain}.${skillName}`
|
const newContextName = `${domain}.${skillName}`
|
||||||
const { actions } = JSON.parse(fs.readFileSync(nluDataFilePath, 'utf8'))
|
const { actions } = JSON.parse(fs.readFileSync(configDataFilePath, 'utf8'))
|
||||||
// Grab next action from the NLU data file
|
// Grab next action from the NLU data file
|
||||||
const { next_action: nextAction } = actions[actionName]
|
const { next_action: nextAction } = actions[actionName]
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ const defaultNluResultObj = {
|
|||||||
currentResolvers: [],
|
currentResolvers: [],
|
||||||
resolvers: [],
|
resolvers: [],
|
||||||
slots: null,
|
slots: null,
|
||||||
nluDataFilePath: null,
|
configDataFilePath: null,
|
||||||
answers: [], // For dialog action type
|
answers: [], // For dialog action type
|
||||||
classification: {
|
classification: {
|
||||||
domain: null,
|
domain: null,
|
||||||
@ -241,12 +241,12 @@ class Nlu {
|
|||||||
async handleActionLoop (utterance, opts) {
|
async handleActionLoop (utterance, opts) {
|
||||||
const { domain, intent } = this.conv.activeContext
|
const { domain, intent } = this.conv.activeContext
|
||||||
const [skillName, actionName] = intent.split('.')
|
const [skillName, actionName] = intent.split('.')
|
||||||
const nluDataFilePath = join(process.cwd(), 'skills', domain, skillName, `nlu/${this.brain.lang}.json`)
|
const configDataFilePath = join(process.cwd(), 'skills', domain, skillName, `config/${this.brain.lang}.json`)
|
||||||
this.nluResultObj = {
|
this.nluResultObj = {
|
||||||
...defaultNluResultObj, // Reset entities, slots, etc.
|
...defaultNluResultObj, // Reset entities, slots, etc.
|
||||||
slots: this.conv.activeContext.slots,
|
slots: this.conv.activeContext.slots,
|
||||||
utterance,
|
utterance,
|
||||||
nluDataFilePath,
|
configDataFilePath,
|
||||||
classification: {
|
classification: {
|
||||||
domain,
|
domain,
|
||||||
skill: skillName,
|
skill: skillName,
|
||||||
@ -256,11 +256,11 @@ class Nlu {
|
|||||||
}
|
}
|
||||||
this.nluResultObj.entities = await this.ner.extractEntities(
|
this.nluResultObj.entities = await this.ner.extractEntities(
|
||||||
this.brain.lang,
|
this.brain.lang,
|
||||||
nluDataFilePath,
|
configDataFilePath,
|
||||||
this.nluResultObj
|
this.nluResultObj
|
||||||
)
|
)
|
||||||
|
|
||||||
const { actions, resolvers } = JSON.parse(fs.readFileSync(nluDataFilePath, 'utf8'))
|
const { actions, resolvers } = JSON.parse(fs.readFileSync(configDataFilePath, 'utf8'))
|
||||||
const action = actions[this.nluResultObj.classification.action]
|
const action = actions[this.nluResultObj.classification.action]
|
||||||
const {
|
const {
|
||||||
name: expectedItemName, type: expectedItemType
|
name: expectedItemName, type: expectedItemType
|
||||||
@ -369,7 +369,7 @@ class Nlu {
|
|||||||
slots: processedData.slots,
|
slots: processedData.slots,
|
||||||
isInActionLoop: !!processedData.nextAction.loop,
|
isInActionLoop: !!processedData.nextAction.loop,
|
||||||
originalUtterance: processedData.utterance,
|
originalUtterance: processedData.utterance,
|
||||||
nluDataFilePath: processedData.nluDataFilePath,
|
configDataFilePath: processedData.configDataFilePath,
|
||||||
actionName: processedData.action.next_action,
|
actionName: processedData.action.next_action,
|
||||||
domain: processedData.classification.domain,
|
domain: processedData.classification.domain,
|
||||||
intent: `${processedData.classification.skill}.${processedData.action.next_action}`,
|
intent: `${processedData.classification.skill}.${processedData.action.next_action}`,
|
||||||
@ -510,13 +510,13 @@ class Nlu {
|
|||||||
log.title('NLU')
|
log.title('NLU')
|
||||||
log.success(`Intent found: ${this.nluResultObj.classification.skill}.${this.nluResultObj.classification.action} (domain: ${this.nluResultObj.classification.domain})`)
|
log.success(`Intent found: ${this.nluResultObj.classification.skill}.${this.nluResultObj.classification.action} (domain: ${this.nluResultObj.classification.domain})`)
|
||||||
|
|
||||||
const nluDataFilePath = join(process.cwd(), 'skills', this.nluResultObj.classification.domain, this.nluResultObj.classification.skill, `nlu/${this.brain.lang}.json`)
|
const configDataFilePath = join(process.cwd(), 'skills', this.nluResultObj.classification.domain, this.nluResultObj.classification.skill, `config/${this.brain.lang}.json`)
|
||||||
this.nluResultObj.nluDataFilePath = nluDataFilePath
|
this.nluResultObj.configDataFilePath = configDataFilePath
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.nluResultObj.entities = await this.ner.extractEntities(
|
this.nluResultObj.entities = await this.ner.extractEntities(
|
||||||
this.brain.lang,
|
this.brain.lang,
|
||||||
nluDataFilePath,
|
configDataFilePath,
|
||||||
this.nluResultObj
|
this.nluResultObj
|
||||||
)
|
)
|
||||||
} catch (e) /* istanbul ignore next */ {
|
} catch (e) /* istanbul ignore next */ {
|
||||||
@ -552,7 +552,7 @@ class Nlu {
|
|||||||
slots: { },
|
slots: { },
|
||||||
isInActionLoop: false,
|
isInActionLoop: false,
|
||||||
originalUtterance: this.nluResultObj.utterance,
|
originalUtterance: this.nluResultObj.utterance,
|
||||||
nluDataFilePath: this.nluResultObj.nluDataFilePath,
|
configDataFilePath: this.nluResultObj.configDataFilePath,
|
||||||
actionName: this.nluResultObj.classification.action,
|
actionName: this.nluResultObj.classification.action,
|
||||||
domain: this.nluResultObj.classification.domain,
|
domain: this.nluResultObj.classification.domain,
|
||||||
intent,
|
intent,
|
||||||
@ -574,7 +574,7 @@ class Nlu {
|
|||||||
slots: { },
|
slots: { },
|
||||||
isInActionLoop: !!processedData.nextAction.loop,
|
isInActionLoop: !!processedData.nextAction.loop,
|
||||||
originalUtterance: processedData.utterance,
|
originalUtterance: processedData.utterance,
|
||||||
nluDataFilePath: processedData.nluDataFilePath,
|
configDataFilePath: processedData.configDataFilePath,
|
||||||
actionName: processedData.action.next_action,
|
actionName: processedData.action.next_action,
|
||||||
domain: processedData.classification.domain,
|
domain: processedData.classification.domain,
|
||||||
intent: `${processedData.classification.skill}.${processedData.action.next_action}`,
|
intent: `${processedData.classification.skill}.${processedData.action.next_action}`,
|
||||||
@ -614,7 +614,7 @@ class Nlu {
|
|||||||
|
|
||||||
const { domain, intent } = this.conv.activeContext
|
const { domain, intent } = this.conv.activeContext
|
||||||
const [skillName, actionName] = intent.split('.')
|
const [skillName, actionName] = intent.split('.')
|
||||||
const nluDataFilePath = join(process.cwd(), 'skills', domain, skillName, `nlu/${this.brain.lang}.json`)
|
const configDataFilePath = join(process.cwd(), 'skills', domain, skillName, `config/${this.brain.lang}.json`)
|
||||||
|
|
||||||
this.nluResultObj = {
|
this.nluResultObj = {
|
||||||
...defaultNluResultObj, // Reset entities, slots, etc.
|
...defaultNluResultObj, // Reset entities, slots, etc.
|
||||||
@ -627,7 +627,7 @@ class Nlu {
|
|||||||
}
|
}
|
||||||
const entities = await this.ner.extractEntities(
|
const entities = await this.ner.extractEntities(
|
||||||
this.brain.lang,
|
this.brain.lang,
|
||||||
nluDataFilePath,
|
configDataFilePath,
|
||||||
this.nluResultObj
|
this.nluResultObj
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -657,7 +657,7 @@ class Nlu {
|
|||||||
// Assign slots only if there is a next action
|
// Assign slots only if there is a next action
|
||||||
slots: this.conv.activeContext.nextAction ? this.conv.activeContext.slots : { },
|
slots: this.conv.activeContext.nextAction ? this.conv.activeContext.slots : { },
|
||||||
utterance: this.conv.activeContext.originalUtterance,
|
utterance: this.conv.activeContext.originalUtterance,
|
||||||
nluDataFilePath,
|
configDataFilePath,
|
||||||
classification: {
|
classification: {
|
||||||
domain,
|
domain,
|
||||||
skill: skillName,
|
skill: skillName,
|
||||||
@ -691,7 +691,7 @@ class Nlu {
|
|||||||
slots,
|
slots,
|
||||||
isInActionLoop: false,
|
isInActionLoop: false,
|
||||||
originalUtterance: this.nluResultObj.utterance,
|
originalUtterance: this.nluResultObj.utterance,
|
||||||
nluDataFilePath: this.nluResultObj.nluDataFilePath,
|
configDataFilePath: this.nluResultObj.configDataFilePath,
|
||||||
actionName: this.nluResultObj.classification.action,
|
actionName: this.nluResultObj.classification.action,
|
||||||
domain: this.nluResultObj.classification.domain,
|
domain: this.nluResultObj.classification.domain,
|
||||||
intent,
|
intent,
|
||||||
@ -701,7 +701,7 @@ class Nlu {
|
|||||||
const notFilledSlot = this.conv.getNotFilledSlot()
|
const notFilledSlot = this.conv.getNotFilledSlot()
|
||||||
// Loop for questions if a slot hasn't been filled
|
// Loop for questions if a slot hasn't been filled
|
||||||
if (notFilledSlot) {
|
if (notFilledSlot) {
|
||||||
const { actions } = JSON.parse(fs.readFileSync(this.nluResultObj.nluDataFilePath, 'utf8'))
|
const { actions } = JSON.parse(fs.readFileSync(this.nluResultObj.configDataFilePath, 'utf8'))
|
||||||
const [currentSlot] = actions[this.nluResultObj.classification.action].slots
|
const [currentSlot] = actions[this.nluResultObj.classification.action].slots
|
||||||
.filter(({ name }) => name === notFilledSlot.name)
|
.filter(({ name }) => name === notFilledSlot.name)
|
||||||
|
|
||||||
|
@ -3,10 +3,10 @@ import path from 'path'
|
|||||||
|
|
||||||
const json = { }
|
const json = { }
|
||||||
|
|
||||||
json.loadNluData = async (nluFilePath, lang) => {
|
json.loadConfigData = async (configFilePath, lang) => {
|
||||||
const sharedDataPath = path.join(process.cwd(), 'core/data', lang)
|
const sharedDataPath = path.join(process.cwd(), 'core/data', lang)
|
||||||
const nluData = JSON.parse(fs.readFileSync(nluFilePath, 'utf8'))
|
const configData = JSON.parse(fs.readFileSync(configFilePath, 'utf8'))
|
||||||
const { entities } = nluData
|
const { entities } = configData
|
||||||
|
|
||||||
// Load shared data entities if entity = 'xxx.json'
|
// Load shared data entities if entity = 'xxx.json'
|
||||||
if (entities) {
|
if (entities) {
|
||||||
@ -18,10 +18,10 @@ json.loadNluData = async (nluFilePath, lang) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
nluData.entities = entities
|
configData.entities = entities
|
||||||
}
|
}
|
||||||
|
|
||||||
return nluData
|
return configData
|
||||||
}
|
}
|
||||||
|
|
||||||
export default json
|
export default json
|
||||||
|
Loading…
Reference in New Issue
Block a user