diff --git a/CHANGELOG.md b/CHANGELOG.md index 967923ebff..b9f6a4a64d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,18 @@ All notable changes to Botonic will be documented in this file. +## [0.27.0] - tbd + +### Added + +### Changed + +- [@botonic/plugin-flow-builder](https://www.npmjs.com/package/@botonic/plugin-flow-builder) + + - [Modified Smart Intents api request to call smart intents inference v2](https://github.com/hubtype/botonic/pull/2825) + +### Fixed + ## [0.26.0] - 2024-04-30 ### Added diff --git a/packages/botonic-plugin-flow-builder/src/index.ts b/packages/botonic-plugin-flow-builder/src/index.ts index 66286b7903..c46f9f7b57 100644 --- a/packages/botonic-plugin-flow-builder/src/index.ts +++ b/packages/botonic-plugin-flow-builder/src/index.ts @@ -36,8 +36,8 @@ import { PayloadParamsBase, } from './types' import { getNodeByUserInput } from './user-input' +import { SmartIntentsInferenceConfig } from './user-input/smart-intent' import { resolveGetAccessToken } from './utils' - export default class BotonicPluginFlowBuilder implements Plugin { public cmsApi: FlowBuilderApi private flowUrl: string @@ -54,6 +54,7 @@ export default class BotonicPluginFlowBuilder implements Plugin { public getKnowledgeBaseResponse?: ( request: ActionRequest ) => Promise + public smartIntentsConfig: SmartIntentsInferenceConfig constructor(readonly options: BotonicPluginFlowBuilderOptions) { const apiUrl = options.apiUrl || FLOW_BUILDER_API_URL_PROD @@ -64,6 +65,10 @@ export default class BotonicPluginFlowBuilder implements Plugin { this.getAccessToken = resolveGetAccessToken(options) this.trackEvent = options.trackEvent this.getKnowledgeBaseResponse = options.getKnowledgeBaseResponse + this.smartIntentsConfig = { + ...options?.smartIntentsConfig, + useLatest: jsonVersion === FlowBuilderJSONVersion.LATEST, + } const customFunctions = options.customFunctions || {} this.functions = { ...DEFAULT_FUNCTIONS, ...customFunctions } } @@ -88,7 +93,8 @@ export default class BotonicPluginFlowBuilder implements Plugin { const nodeByUserInput = await getNodeByUserInput( this.cmsApi, resolvedLocale, - request as unknown as ActionRequest + request as unknown as ActionRequest, + this.smartIntentsConfig ) request.input.payload = this.cmsApi.getPayload(nodeByUserInput?.target) } diff --git a/packages/botonic-plugin-flow-builder/src/types.ts b/packages/botonic-plugin-flow-builder/src/types.ts index 9c552a504b..65d7160234 100644 --- a/packages/botonic-plugin-flow-builder/src/types.ts +++ b/packages/botonic-plugin-flow-builder/src/types.ts @@ -18,6 +18,7 @@ export interface BotonicPluginFlowBuilderOptions { getKnowledgeBaseResponse?: ( request: ActionRequest ) => Promise + smartIntentsConfig?: { numSmartIntentsToUse: number } } export interface FlowBuilderApiOptions { diff --git a/packages/botonic-plugin-flow-builder/src/user-input/index.ts b/packages/botonic-plugin-flow-builder/src/user-input/index.ts index 98576dbc2a..1068602e4b 100644 --- a/packages/botonic-plugin-flow-builder/src/user-input/index.ts +++ b/packages/botonic-plugin-flow-builder/src/user-input/index.ts @@ -8,12 +8,13 @@ import { } from '../content-fields/hubtype-fields' import { getIntentNodeByInput } from './intent' import { getKeywordNodeByInput } from './keyword' -import { SmartIntentsApi } from './smart-intent' +import { SmartIntentsApi, SmartIntentsInferenceConfig } from './smart-intent' export async function getNodeByUserInput( cmsApi: FlowBuilderApi, locale: string, - request: ActionRequest + request: ActionRequest, + smartIntentsConfig: SmartIntentsInferenceConfig ): Promise { if (request.input.data) { const keywordNode = await getKeywordNodeByInput( @@ -24,7 +25,11 @@ export async function getNodeByUserInput( ) if (keywordNode) return keywordNode - const smartIntentsApi = new SmartIntentsApi(cmsApi, request) + const smartIntentsApi = new SmartIntentsApi( + cmsApi, + request, + smartIntentsConfig + ) const smartIntentNode = smartIntentsApi.getNodeByInput() if (smartIntentNode) return smartIntentNode diff --git a/packages/botonic-plugin-flow-builder/src/user-input/smart-intent.ts b/packages/botonic-plugin-flow-builder/src/user-input/smart-intent.ts index 1987735aa9..a235f85291 100644 --- a/packages/botonic-plugin-flow-builder/src/user-input/smart-intent.ts +++ b/packages/botonic-plugin-flow-builder/src/user-input/smart-intent.ts @@ -4,32 +4,42 @@ import axios from 'axios' import { FlowBuilderApi } from '../api' import { HtSmartIntentNode } from '../content-fields/hubtype-fields/smart-intent' -interface InferenceParam { - name: string - definition: string +export interface SmartIntentsInferenceParams { + bot_id: string + text: string + num_smart_intents_to_use?: number + use_latest: boolean } -export class SmartIntentsApi { - public cmsApi: FlowBuilderApi - public currentRequest: ActionRequest - constructor(cmsApi: FlowBuilderApi, request: ActionRequest) { - this.currentRequest = request - this.cmsApi = cmsApi - } +export interface SmartIntentsInferenceConfig { + useLatest: boolean + numSmartIntentsToUse?: number +} + +export class SmartIntentsApi { + constructor( + public cmsApi: FlowBuilderApi, + public currentRequest: ActionRequest, + public smartIntentsConfig: SmartIntentsInferenceConfig + ) {} async getNodeByInput(): Promise { + if (!this.currentRequest.input.data) return undefined const smartIntentNodes = this.cmsApi.getSmartIntentNodes() + if (!smartIntentNodes.length) return undefined - if (smartIntentNodes.length === 0) { - return undefined + const params = { + bot_id: this.currentRequest.session.bot.id, + text: this.currentRequest.input.data, + num_smart_intents_to_use: this.smartIntentsConfig.numSmartIntentsToUse, + use_latest: this.smartIntentsConfig.useLatest, } - const params = this.getInferenceParams(smartIntentNodes) try { const response = await this.getInference(params) return smartIntentNodes.find( smartIntentNode => - smartIntentNode.content.title === response.data.intent_name + smartIntentNode.content.title === response.data.smart_intent_title ) } catch (e) { console.error(e) @@ -37,33 +47,17 @@ export class SmartIntentsApi { } } - private getInferenceParams( - smartIntentNodes: HtSmartIntentNode[] - ): InferenceParam[] { - const intentsInferenceParams = smartIntentNodes.map(smartIntentNode => { - return { - name: smartIntentNode.content.title, - definition: smartIntentNode.content.description, - } - }) - intentsInferenceParams.push({ - name: 'Other', - definition: 'The text does not belong to any other intent.', - }) - return intentsInferenceParams - } - private async getInference( - inferenceParams: InferenceParam[] - ): Promise<{ data: { intent_name: string } }> { + inferenceParams: SmartIntentsInferenceParams + ): Promise<{ data: { smart_intent_title: string } }> { return await axios({ method: 'POST', - url: `${process.env.HUBTYPE_API_URL}/external/v1/ai/smart_intents/inference/`, + url: `${process.env.HUBTYPE_API_URL}/external/v2/ai/smart_intents/inference/`, headers: { Authorization: `Bearer ${this.currentRequest.session._access_token}`, 'Content-Type': 'application/json', }, - data: { text: this.currentRequest.input.data, intents: inferenceParams }, + data: inferenceParams, timeout: 10000, }) } diff --git a/packages/botonic-plugin-flow-builder/tests/__mocks__/smart-intent.ts b/packages/botonic-plugin-flow-builder/tests/__mocks__/smart-intent.ts index 8498997f0a..57865359dc 100644 --- a/packages/botonic-plugin-flow-builder/tests/__mocks__/smart-intent.ts +++ b/packages/botonic-plugin-flow-builder/tests/__mocks__/smart-intent.ts @@ -11,6 +11,6 @@ export function mockSmartIntent(intentName?: string) { // Change the implementation of getInference getInferenceSpy.mockImplementation(async () => { - return intentName ? { data: { intent_name: intentName } } : undefined + return intentName ? { data: { smart_intent_title: intentName } } : undefined }) } diff --git a/packages/botonic-plugin-flow-builder/tests/smart-intent.test.ts b/packages/botonic-plugin-flow-builder/tests/smart-intent.test.ts index ecd89e36ec..06ec57f1c2 100644 --- a/packages/botonic-plugin-flow-builder/tests/smart-intent.test.ts +++ b/packages/botonic-plugin-flow-builder/tests/smart-intent.test.ts @@ -34,7 +34,6 @@ describe('Check the contents returned by the plugin when match a smart intent', request, flowBuilderPlugin ) - expect((contents[0] as FlowText).text).toBe( 'Message explaining how to add a bag' )