1
1
mirror of https://github.com/leon-ai/leon.git synced 2024-09-19 13:58:22 +03:00

feat(server): bootstrap Node.js bridge entry point

This commit is contained in:
louistiti 2023-04-27 20:16:08 +08:00
parent 12e4b7bccf
commit 8b2f06e305
7 changed files with 60 additions and 21 deletions

1
.gitignore vendored
View File

@ -26,6 +26,7 @@ bridges/python/src/Pipfile.lock
tcp_server/src/Pipfile.lock
!tcp_server/**/.gitkeep
!bridges/python/**/.gitkeep
!bridges/nodejs/dist/*
!**/*.sample*
packages/**/config/config.json
skills/**/src/config.json

View File

View File

@ -0,0 +1 @@
// TODO

View File

@ -19,9 +19,11 @@ export const GITHUB_URL = 'https://github.com/leon-ai/leon'
*/
export const BINARIES_FOLDER_NAME = SystemHelper.getBinariesFolderName()
export const PYTHON_BRIDGE_DIST_PATH = path.join('bridges', 'python', 'dist')
export const NODEJS_BRIDGE_DIST_PATH = path.join('bridges', 'nodejs', 'dist')
export const TCP_SERVER_DIST_PATH = path.join('tcp_server', 'dist')
export const PYTHON_BRIDGE_SRC_PATH = path.join('bridges', 'python', 'src')
export const NODEJS_BRIDGE_SRC_PATH = path.join('bridges', 'nodejs', 'src')
export const TCP_SERVER_SRC_PATH = path.join('tcp_server', 'src')
const PYTHON_BRIDGE_VERSION_FILE_PATH = path.join(
@ -40,6 +42,7 @@ export const [, TCP_SERVER_VERSION] = fs
.split("'")
export const PYTHON_BRIDGE_BIN_NAME = 'leon-python-bridge'
export const NODEJS_BRIDGE_BIN_NAME = 'leon-nodejs-bridge.js'
export const TCP_SERVER_BIN_NAME = 'leon-tcp-server'
export const TCP_SERVER_BIN_PATH = path.join(
@ -52,6 +55,10 @@ export const PYTHON_BRIDGE_BIN_PATH = path.join(
BINARIES_FOLDER_NAME,
PYTHON_BRIDGE_BIN_NAME
)
export const NODEJS_BRIDGE_BIN_PATH = `${process.execPath} ${path.join(
NODEJS_BRIDGE_DIST_PATH,
NODEJS_BRIDGE_BIN_NAME
)}`
export const LEON_VERSION = process.env['npm_package_version']

View File

@ -9,15 +9,24 @@ import type {
NERCustomEntity,
NLUResult
} from '@/core/nlp/types'
import type { SkillConfigSchema } from '@/schemas/skill-schemas'
import type { SkillConfigSchema, SkillSchema } from '@/schemas/skill-schemas'
import type {
BrainProcessResult,
IntentObject,
SkillResult
} from '@/core/brain/types'
import { SkillActionType, SkillOutputType } from '@/core/brain/types'
import {
SkillActionTypes,
SkillBridges,
SkillOutputTypes
} from '@/core/brain/types'
import { langs } from '@@/core/langs.json'
import { HAS_TTS, PYTHON_BRIDGE_BIN_PATH, TMP_PATH } from '@/constants'
import {
HAS_TTS,
PYTHON_BRIDGE_BIN_PATH,
NODEJS_BRIDGE_BIN_PATH,
TMP_PATH
} from '@/constants'
import { SOCKET_SERVER, TTS } from '@/core'
import { LangHelper } from '@/helpers/lang-helper'
import { LogHelper } from '@/helpers/log-helper'
@ -190,7 +199,7 @@ export default class Brain {
const obj = JSON.parse(data.toString())
if (typeof obj === 'object') {
if (obj.output.type === SkillOutputType.Intermediate) {
if (obj.output.type === SkillOutputTypes.Intermediate) {
LogHelper.title(`${this.skillFriendlyName} skill`)
LogHelper.info(data.toString())
@ -258,6 +267,7 @@ export default class Brain {
*/
private async executeLogicActionSkill(
nluResult: NLUResult,
skillBridge: SkillSchema['bridge'],
utteranceId: string,
intentObjectPath: string
): Promise<void> {
@ -282,10 +292,20 @@ export default class Brain {
intentObjectPath,
JSON.stringify(intentObject)
)
this.skillProcess = spawn(
`${PYTHON_BRIDGE_BIN_PATH} "${intentObjectPath}"`,
{ shell: true }
)
if (skillBridge === SkillBridges.Python) {
this.skillProcess = spawn(
`${PYTHON_BRIDGE_BIN_PATH} "${intentObjectPath}"`,
{ shell: true }
)
} else if (skillBridge === SkillBridges.NodeJS) {
this.skillProcess = spawn(
`${NODEJS_BRIDGE_BIN_PATH} "${intentObjectPath}"`,
{ shell: true }
)
} else {
LogHelper.error(`The skill bridge is not supported: ${skillBridge}`)
}
} catch (e) {
LogHelper.error(`Failed to save intent object: ${e}`)
}
@ -334,24 +354,25 @@ export default class Brain {
? actions[action.next_action]
: null
if (actionType === SkillActionType.Logic) {
if (actionType === SkillActionTypes.Logic) {
/**
* "Logic" action skill execution
*/
await this.executeLogicActionSkill(
nluResult,
utteranceId,
intentObjectPath
)
const domainName = nluResult.classification.domain
const skillName = nluResult.classification.skill
const { name: domainFriendlyName } =
await SkillDomainHelper.getSkillDomainInfo(domainName)
const { name: skillFriendlyName } =
const { name: skillFriendlyName, bridge: skillBridge } =
await SkillDomainHelper.getSkillInfo(domainName, skillName)
await this.executeLogicActionSkill(
nluResult,
skillBridge,
utteranceId,
intentObjectPath
)
this.domainFriendlyName = domainFriendlyName
this.skillFriendlyName = skillFriendlyName
@ -387,7 +408,7 @@ export default class Brain {
// Synchronize the downloaded content if enabled
if (
skillResult.output.type === SkillOutputType.End &&
skillResult.output.type === SkillOutputTypes.End &&
skillResult.output.options['synchronization'] &&
skillResult.output.options['synchronization'].enabled &&
skillResult.output.options['synchronization'].enabled ===

View File

@ -28,7 +28,7 @@ export interface SkillResult {
entities: NEREntity[]
slots: NLUSlots
output: {
type: SkillOutputType
type: SkillOutputTypes
codes: string[]
speech: string
core: SkillCoreData | undefined
@ -37,11 +37,15 @@ export interface SkillResult {
}
}
export enum SkillOutputType {
export enum SkillBridges {
Python = 'python',
NodeJS = 'nodejs'
}
export enum SkillOutputTypes {
Intermediate = 'inter',
End = 'end'
}
export enum SkillActionType {
export enum SkillActionTypes {
Logic = 'logic',
Dialog = 'dialog'
}

View File

@ -2,8 +2,13 @@ import type { Static } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { globalResolverSchemaObject } from '@/schemas/global-data-schemas'
import { SkillBridges } from '@/core/brain/types'
const skillBridges = [Type.Literal('python'), Type.Null()]
const skillBridges = [
Type.Literal(SkillBridges.Python),
Type.Literal(SkillBridges.NodeJS),
Type.Null()
]
const skillActionTypes = [
Type.Literal('logic', {
description: 'It runs the business logic implemented in actions via code.'