diff --git a/api/src/extensions/helpers/llm-nlu/index.helper.ts b/api/src/extensions/helpers/llm-nlu/index.helper.ts index ab33d7a2..cd207a79 100644 --- a/api/src/extensions/helpers/llm-nlu/index.helper.ts +++ b/api/src/extensions/helpers/llm-nlu/index.helper.ts @@ -1,5 +1,5 @@ /* - * Copyright © 2024 Hexastack. All rights reserved. + * Copyright © 2025 Hexastack. All rights reserved. * * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. @@ -20,6 +20,7 @@ import { NlpEntityService } from '@/nlp/services/nlp-entity.service'; import { SettingService } from '@/setting/services/setting.service'; import { LLM_NLU_HELPER_NAME } from './settings'; +import { LlmNluHelperSettings } from './types'; @Injectable() export default class LlmNluHelper @@ -47,10 +48,42 @@ export default class LlmNluHelper return __dirname; } + async loadSettings( + maxRetries: number = 5, + delay: number = 1000, + ): Promise { + let retryCount: number = 0; + + while (retryCount < maxRetries) { + try { + const settings: LlmNluHelperSettings | undefined = + await this.getSettings(); + + if (settings) { + return settings; + } + + this.logger.warn( + `Settings not available yet, retrying... (${retryCount + 1}/${maxRetries})`, + ); + } catch (error) { + this.logger.error('Error while loading settings:', error); + return undefined; + } + + retryCount++; + await new Promise((resolve) => setTimeout(resolve, delay)); + } + + this.logger.error('Failed to load settings after multiple attempts.'); + return undefined; + } + @OnEvent('hook:language:*') @OnEvent('hook:llm_nlu_helper:language_classifier_prompt_template') async buildLanguageClassifierPrompt() { - const settings = await this.getSettings(); + const settings: LlmNluHelperSettings | undefined = + await this.loadSettings(); if (settings) { const languages = await this.languageService.findAll(); const delegate = Handlebars.compile( @@ -64,7 +97,8 @@ export default class LlmNluHelper @OnEvent('hook:nlpValue:*') @OnEvent('hook:llm_nlu_helper:trait_classifier_prompt_template') async buildClassifiersPrompt() { - const settings = await this.getSettings(); + const settings: LlmNluHelperSettings | undefined = + await this.loadSettings(); if (settings) { const entities = await this.nlpEntityService.findAndPopulate({ lookups: 'trait', @@ -83,7 +117,6 @@ export default class LlmNluHelper async onModuleInit() { super.onModuleInit(); - await this.buildLanguageClassifierPrompt(); await this.buildClassifiersPrompt(); } diff --git a/api/src/extensions/helpers/llm-nlu/types.ts b/api/src/extensions/helpers/llm-nlu/types.ts new file mode 100644 index 00000000..f5bd7b31 --- /dev/null +++ b/api/src/extensions/helpers/llm-nlu/types.ts @@ -0,0 +1,13 @@ +/* + * Copyright © 2025 Hexastack. All rights reserved. + * + * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: + * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. + * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). + */ + +export type LlmNluHelperSettings = { + model: string; + language_classifier_prompt_template: string; + trait_classifier_prompt_template: string; +};