From ce6157b60accccbc30bc2e95811b3104e5c3b6cc Mon Sep 17 00:00:00 2001 From: pgayvallet Date: Wed, 18 Dec 2024 14:22:40 +0100 Subject: [PATCH] Use default elser deployment for product documentation --- .../shared/ai-infra/inference-common/index.ts | 1 + .../src/inference_endpoints.ts} | 10 +++- .../product_doc_base/common/consts.ts | 5 +- .../endpoint_manager.test.ts | 58 ------------------- .../inference_endpoint/endpoint_manager.ts | 41 ------------- .../services/inference_endpoint/index.ts | 8 --- .../inference_endpoint/service.mock.ts | 20 ------- .../utils/get_model_install_status.ts | 34 ----------- .../inference_endpoint/utils/install_elser.ts | 35 ----------- .../utils/wait_until_model_deployed.ts | 39 ------------- .../package_installer/package_installer.ts | 13 +++-- .../utils/ensure_default_elser_deployed.ts | 19 ++++++ .../services/package_installer/utils/index.ts | 1 + 13 files changed, 39 insertions(+), 245 deletions(-) rename x-pack/platform/{plugins/shared/ai_infra/product_doc_base/server/services/inference_endpoint/utils/index.ts => packages/shared/ai-infra/inference-common/src/inference_endpoints.ts} (53%) delete mode 100644 x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/inference_endpoint/endpoint_manager.test.ts delete mode 100644 x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/inference_endpoint/endpoint_manager.ts delete mode 100644 x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/inference_endpoint/index.ts delete mode 100644 x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/inference_endpoint/service.mock.ts delete mode 100644 x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/inference_endpoint/utils/get_model_install_status.ts delete mode 100644 x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/inference_endpoint/utils/install_elser.ts delete mode 100644 x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/inference_endpoint/utils/wait_until_model_deployed.ts create mode 100644 x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/package_installer/utils/ensure_default_elser_deployed.ts diff --git a/x-pack/platform/packages/shared/ai-infra/inference-common/index.ts b/x-pack/platform/packages/shared/ai-infra/inference-common/index.ts index 134b0f02811fe..ba5c6e78b9e1a 100644 --- a/x-pack/platform/packages/shared/ai-infra/inference-common/index.ts +++ b/x-pack/platform/packages/shared/ai-infra/inference-common/index.ts @@ -95,3 +95,4 @@ export { } from './src/errors'; export { truncateList } from './src/truncate_list'; +export { defaultInferenceEndpoints } from './src/inference_endpoints'; diff --git a/x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/inference_endpoint/utils/index.ts b/x-pack/platform/packages/shared/ai-infra/inference-common/src/inference_endpoints.ts similarity index 53% rename from x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/inference_endpoint/utils/index.ts rename to x-pack/platform/packages/shared/ai-infra/inference-common/src/inference_endpoints.ts index 089997557f301..f66858c747239 100644 --- a/x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/inference_endpoint/utils/index.ts +++ b/x-pack/platform/packages/shared/ai-infra/inference-common/src/inference_endpoints.ts @@ -5,6 +5,10 @@ * 2.0. */ -export { waitUntilModelDeployed } from './wait_until_model_deployed'; -export { getModelInstallStatus } from './get_model_install_status'; -export { installElser } from './install_elser'; +/** + * Constants for all default (preconfigured) inference endpoints. + */ +export const defaultInferenceEndpoints = { + ELSER: '.elser-2-elasticsearch', + MULTILINGUAL_E5_SMALL: '.multilingual-e5-small-elasticsearch', +}; diff --git a/x-pack/platform/plugins/shared/ai_infra/product_doc_base/common/consts.ts b/x-pack/platform/plugins/shared/ai_infra/product_doc_base/common/consts.ts index 1622df5ed865c..d4df44af9090c 100644 --- a/x-pack/platform/plugins/shared/ai_infra/product_doc_base/common/consts.ts +++ b/x-pack/platform/plugins/shared/ai_infra/product_doc_base/common/consts.ts @@ -5,10 +5,11 @@ * 2.0. */ +import { defaultInferenceEndpoints } from '@kbn/inference-common'; + export const productDocInstallStatusSavedObjectTypeName = 'product-doc-install-status'; /** * The id of the inference endpoint we're creating for our product doc indices. - * Could be replaced with the default elser 2 endpoint once the default endpoint feature is available. */ -export const internalElserInferenceId = 'kibana-internal-elser2'; +export const internalElserInferenceId = defaultInferenceEndpoints.ELSER; diff --git a/x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/inference_endpoint/endpoint_manager.test.ts b/x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/inference_endpoint/endpoint_manager.test.ts deleted file mode 100644 index e5dabaaa9b7f7..0000000000000 --- a/x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/inference_endpoint/endpoint_manager.test.ts +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { loggerMock, type MockedLogger } from '@kbn/logging-mocks'; -import { elasticsearchServiceMock } from '@kbn/core/server/mocks'; -import { InferenceEndpointManager } from './endpoint_manager'; - -jest.mock('./utils'); -import { installElser, getModelInstallStatus, waitUntilModelDeployed } from './utils'; -const installElserMock = installElser as jest.MockedFn; -const getModelInstallStatusMock = getModelInstallStatus as jest.MockedFn< - typeof getModelInstallStatus ->; -const waitUntilModelDeployedMock = waitUntilModelDeployed as jest.MockedFn< - typeof waitUntilModelDeployed ->; - -describe('InferenceEndpointManager', () => { - let logger: MockedLogger; - let esClient: ReturnType; - let endpointManager: InferenceEndpointManager; - - beforeEach(() => { - logger = loggerMock.create(); - esClient = elasticsearchServiceMock.createElasticsearchClient(); - - endpointManager = new InferenceEndpointManager({ esClient, logger }); - }); - - afterEach(() => { - installElserMock.mockReset(); - getModelInstallStatusMock.mockReset(); - waitUntilModelDeployedMock.mockReset(); - }); - - describe('#ensureInternalElserInstalled', () => { - it('installs ELSER if not already installed', async () => { - getModelInstallStatusMock.mockResolvedValue({ installed: true }); - - await endpointManager.ensureInternalElserInstalled(); - - expect(installElserMock).not.toHaveBeenCalled(); - expect(waitUntilModelDeployedMock).toHaveBeenCalledTimes(1); - }); - it('does not install ELSER if already present', async () => { - getModelInstallStatusMock.mockResolvedValue({ installed: false }); - - await endpointManager.ensureInternalElserInstalled(); - - expect(installElserMock).toHaveBeenCalledTimes(1); - expect(waitUntilModelDeployedMock).toHaveBeenCalledTimes(1); - }); - }); -}); diff --git a/x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/inference_endpoint/endpoint_manager.ts b/x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/inference_endpoint/endpoint_manager.ts deleted file mode 100644 index 4f7467501d61d..0000000000000 --- a/x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/inference_endpoint/endpoint_manager.ts +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { ElasticsearchClient, Logger } from '@kbn/core/server'; -import { internalElserInferenceId } from '../../../common/consts'; -import { installElser, getModelInstallStatus, waitUntilModelDeployed } from './utils'; - -export class InferenceEndpointManager { - private readonly log: Logger; - private readonly esClient: ElasticsearchClient; - - constructor({ logger, esClient }: { logger: Logger; esClient: ElasticsearchClient }) { - this.log = logger; - this.esClient = esClient; - } - - async ensureInternalElserInstalled() { - const { installed } = await getModelInstallStatus({ - inferenceId: internalElserInferenceId, - client: this.esClient, - log: this.log, - }); - if (!installed) { - await installElser({ - inferenceId: internalElserInferenceId, - client: this.esClient, - log: this.log, - }); - } - - await waitUntilModelDeployed({ - modelId: internalElserInferenceId, - client: this.esClient, - log: this.log, - }); - } -} diff --git a/x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/inference_endpoint/index.ts b/x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/inference_endpoint/index.ts deleted file mode 100644 index e4098ff58fe51..0000000000000 --- a/x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/inference_endpoint/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -export { InferenceEndpointManager } from './endpoint_manager'; diff --git a/x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/inference_endpoint/service.mock.ts b/x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/inference_endpoint/service.mock.ts deleted file mode 100644 index e9715c4ad2acd..0000000000000 --- a/x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/inference_endpoint/service.mock.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { InferenceEndpointManager } from './endpoint_manager'; - -export type InferenceEndpointManagerMock = jest.Mocked; - -const createMock = (): InferenceEndpointManagerMock => { - return { - ensureInternalElserInstalled: jest.fn(), - } as unknown as InferenceEndpointManagerMock; -}; - -export const inferenceManagerMock = { - create: createMock, -}; diff --git a/x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/inference_endpoint/utils/get_model_install_status.ts b/x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/inference_endpoint/utils/get_model_install_status.ts deleted file mode 100644 index be6caa34d0ad1..0000000000000 --- a/x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/inference_endpoint/utils/get_model_install_status.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { InferenceTaskType } from '@elastic/elasticsearch/lib/api/types'; -import type { ElasticsearchClient, Logger } from '@kbn/core/server'; - -export const getModelInstallStatus = async ({ - inferenceId, - taskType = 'sparse_embedding', - client, -}: { - inferenceId: string; - taskType?: InferenceTaskType; - client: ElasticsearchClient; - log: Logger; -}) => { - const getInferenceRes = await client.inference.get( - { - task_type: taskType, - inference_id: inferenceId, - }, - { ignore: [404] } - ); - - const installed = (getInferenceRes.endpoints ?? []).some( - (endpoint) => endpoint.inference_id === inferenceId - ); - - return { installed }; -}; diff --git a/x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/inference_endpoint/utils/install_elser.ts b/x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/inference_endpoint/utils/install_elser.ts deleted file mode 100644 index c4ad3c43ce071..0000000000000 --- a/x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/inference_endpoint/utils/install_elser.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { ElasticsearchClient, Logger } from '@kbn/core/server'; - -export const installElser = async ({ - inferenceId, - client, - log, -}: { - inferenceId: string; - client: ElasticsearchClient; - log: Logger; -}) => { - await client.inference.put( - { - task_type: 'sparse_embedding', - inference_id: inferenceId, - inference_config: { - service: 'elasticsearch', - service_settings: { - adaptive_allocations: { enabled: true }, - num_threads: 1, - model_id: '.elser_model_2', - }, - task_settings: {}, - }, - }, - { requestTimeout: 5 * 60 * 1000 } - ); -}; diff --git a/x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/inference_endpoint/utils/wait_until_model_deployed.ts b/x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/inference_endpoint/utils/wait_until_model_deployed.ts deleted file mode 100644 index 83775ed80f5a0..0000000000000 --- a/x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/inference_endpoint/utils/wait_until_model_deployed.ts +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { ElasticsearchClient, Logger } from '@kbn/core/server'; - -export const waitUntilModelDeployed = async ({ - modelId, - client, - log, - maxRetries = 20, - delay = 2000, -}: { - modelId: string; - client: ElasticsearchClient; - log: Logger; - maxRetries?: number; - delay?: number; -}) => { - for (let i = 0; i < maxRetries; i++) { - const statsRes = await client.ml.getTrainedModelsStats({ - model_id: modelId, - }); - const deploymentStats = statsRes.trained_model_stats[0]?.deployment_stats; - if (!deploymentStats || deploymentStats.nodes.length === 0) { - log.debug(`ML model [${modelId}] was not deployed - attempt ${i + 1} of ${maxRetries}`); - await sleep(delay); - continue; - } - return; - } - - throw new Error(`Timeout waiting for ML model ${modelId} to be deployed`); -}; - -const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); diff --git a/x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/package_installer/package_installer.ts b/x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/package_installer/package_installer.ts index 7739219c15dc6..e0513594d82bc 100644 --- a/x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/package_installer/package_installer.ts +++ b/x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/package_installer/package_installer.ts @@ -14,8 +14,13 @@ import { type ProductName, } from '@kbn/product-doc-common'; import type { ProductDocInstallClient } from '../doc_install_status'; -import type { InferenceEndpointManager } from '../inference_endpoint'; -import { downloadToDisk, openZipArchive, loadMappingFile, type ZipArchive } from './utils'; +import { + downloadToDisk, + openZipArchive, + loadMappingFile, + ensureDefaultElserDeployed, + type ZipArchive, +} from './utils'; import { majorMinor, latestVersion } from './utils/semver'; import { validateArtifactArchive, @@ -39,7 +44,6 @@ export class PackageInstaller { private readonly artifactsFolder: string; private readonly esClient: ElasticsearchClient; private readonly productDocClient: ProductDocInstallClient; - private readonly endpointManager: InferenceEndpointManager; private readonly artifactRepositoryUrl: string; private readonly currentVersion: string; @@ -55,7 +59,6 @@ export class PackageInstaller { this.esClient = esClient; this.productDocClient = productDocClient; this.artifactsFolder = artifactsFolder; - this.endpointManager = endpointManager; this.artifactRepositoryUrl = artifactRepositoryUrl; this.currentVersion = majorMinor(kibanaVersion); this.log = logger; @@ -144,7 +147,7 @@ export class PackageInstaller { productVersion, }); - await this.endpointManager.ensureInternalElserInstalled(); + await ensureDefaultElserDeployed({ client: this.esClient }); const artifactFileName = getArtifactName({ productName, productVersion }); const artifactUrl = `${this.artifactRepositoryUrl}/${artifactFileName}`; diff --git a/x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/package_installer/utils/ensure_default_elser_deployed.ts b/x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/package_installer/utils/ensure_default_elser_deployed.ts new file mode 100644 index 0000000000000..14219fb003f2c --- /dev/null +++ b/x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/package_installer/utils/ensure_default_elser_deployed.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { ElasticsearchClient } from '@kbn/core/server'; +import { defaultInferenceEndpoints } from '@kbn/inference-common'; + +export const ensureDefaultElserDeployed = async ({ client }: { client: ElasticsearchClient }) => { + await client.inference.inference( + { + inference_id: defaultInferenceEndpoints.ELSER, + input: 'I just want to call the API to force the model to download and allocate', + }, + { requestTimeout: 10 * 60 * 1000 } + ); +}; diff --git a/x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/package_installer/utils/index.ts b/x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/package_installer/utils/index.ts index a612a8c6e9f46..1a1a2247b9dc0 100644 --- a/x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/package_installer/utils/index.ts +++ b/x-pack/platform/plugins/shared/ai_infra/product_doc_base/server/services/package_installer/utils/index.ts @@ -8,3 +8,4 @@ export { downloadToDisk } from './download'; export { openZipArchive, type ZipArchive } from './zip_archive'; export { loadManifestFile, loadMappingFile } from './archive_accessors'; +export { ensureDefaultElserDeployed } from './ensure_default_elser_deployed';