Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ML] Adds E5 model configs #172053

Merged
merged 29 commits into from Dec 1, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
4792447
add E5 model configs
darnautov Nov 28, 2023
ef33448
getCuratedModelConfig, update tests
darnautov Nov 28, 2023
c74fc3a
rename GetElserOptions type
darnautov Nov 28, 2023
40edcf8
add flyout section
darnautov Nov 28, 2023
8144ee2
update description
darnautov Nov 28, 2023
3018b74
update header in the flyout
darnautov Nov 28, 2023
fd2860b
adjust spacing
darnautov Nov 28, 2023
4364b57
fix translation string id
darnautov Nov 28, 2023
ade6222
Update x-pack/plugins/ml/public/application/model_management/add_mode…
darnautov Nov 28, 2023
2bbdc6f
udpate text
darnautov Nov 29, 2023
f2e1522
update description
darnautov Nov 29, 2023
cdb32f4
rename name property with model_id
darnautov Nov 29, 2023
43c04fb
update TrainedModelsProvider interface
darnautov Nov 29, 2023
7f45e4c
remove logo from the tab
darnautov Nov 29, 2023
16eac1d
increase spacer
darnautov Nov 30, 2023
4944b3c
update jest tests
darnautov Nov 30, 2023
bf5ccd1
add type and license info
darnautov Nov 30, 2023
9602a86
mit license badge
darnautov Nov 30, 2023
3b6f7d2
update text
darnautov Nov 30, 2023
51f01d4
refactor
darnautov Nov 30, 2023
82c28a0
nlp5 doc link, target blank
darnautov Nov 30, 2023
5de0d40
Update x-pack/plugins/ml/public/application/model_management/add_mode…
darnautov Nov 30, 2023
232d691
Merge branch 'main' into ml-add-e5-config
kibanamachine Nov 30, 2023
6407bc0
fix mock
darnautov Nov 30, 2023
5b393cc
rename prop in elastic_assistant
darnautov Nov 30, 2023
a0b45f2
rename model_id prop for enterprise_search
darnautov Nov 30, 2023
56fc7cb
update mock
darnautov Nov 30, 2023
de7154e
fix typo
darnautov Nov 30, 2023
9216fa2
Merge branch 'main' into ml-add-e5-config
kibanamachine Dec 1, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion x-pack/packages/ml/trained_models_utils/index.ts
Expand Up @@ -19,7 +19,7 @@ export {
type ModelDefinition,
type ModelDefinitionResponse,
type ElserVersion,
type GetElserOptions,
type GetModelDownloadConfigOptions,
ELSER_ID_V1,
ELASTIC_MODEL_TAG,
ELASTIC_MODEL_TYPE,
Expand Down
Expand Up @@ -89,13 +89,42 @@ export const ELASTIC_MODEL_DEFINITIONS: Record<string, ModelDefinition> = Object
defaultMessage: 'Elastic Learned Sparse EncodeR v2, optimized for linux-x86_64',
}),
},
'.multilingual-e5-small': {
modelName: 'e5',
version: 1,
default: true,
config: {
input: {
field_names: ['text_field'],
},
},
description: i18n.translate('xpack.ml.trainedModels.modelsList.e5v1Description', {
defaultMessage: 'E5 multilingual embedding model',
}),
},
'.multilingual-e5-small_linux-x86_64': {
modelName: 'e5',
version: 1,
os: 'Linux',
arch: 'amd64',
config: {
input: {
field_names: ['text_field'],
},
},
description: i18n.translate('xpack.ml.trainedModels.modelsList.e5v1Description', {
saikatsarkar056 marked this conversation as resolved.
Show resolved Hide resolved
defaultMessage: 'E5 multilingual embedding model, optimized for linux-x86_64',
}),
},
} as const);

export type ElasticCurateModelName = 'elser' | 'e5';
darnautov marked this conversation as resolved.
Show resolved Hide resolved

export interface ModelDefinition {
/**
* Model name, e.g. elser
*/
modelName: string;
modelName: ElasticCurateModelName;
version: number;
/**
* Default PUT model configuration
Expand Down Expand Up @@ -129,6 +158,6 @@ export type ModelState = typeof MODEL_STATE[keyof typeof MODEL_STATE] | null;

export type ElserVersion = 1 | 2;

export interface GetElserOptions {
export interface GetModelDownloadConfigOptions {
version?: ElserVersion;
}
Expand Up @@ -187,6 +187,38 @@ const ElserTabContent: FC<ElserTabContentProps> = ({ modelDownloads, onModelDown
</div>
) : null}

{modelName === 'e5' ? (
<div>
<EuiTitle size={'s'}>
<h3>
<FormattedMessage
id="xpack.ml.trainedModels.modelsList.e5Title"
defaultMessage="E5 multilingual embedding model"
/>
</h3>
</EuiTitle>
<EuiSpacer size="s" />
<p>
<EuiText color={'subdued'} size={'s'}>
<FormattedMessage
id="xpack.ml.trainedModels.addModelFlyout.e5Description"
defaultMessage="E5 produces dense vectors embeddings that can be searched in multiple languages."
darnautov marked this conversation as resolved.
Show resolved Hide resolved
/>
</EuiText>
</p>
<EuiSpacer size="s" />
<p>
<EuiLink href={docLinks.links.ml.nlpElser} external>
darnautov marked this conversation as resolved.
Show resolved Hide resolved
<FormattedMessage
id="xpack.ml.trainedModels.modelsList.elserViewDocumentationLinkLabel"
defaultMessage="View documentation"
/>
</EuiLink>
</p>
<EuiSpacer size={'m'} />
</div>
) : null}

<EuiFormFieldset
legend={{
children: (
Expand Down
Expand Up @@ -5,7 +5,10 @@
* 2.0.
*/

import type { ModelDefinitionResponse, GetElserOptions } from '@kbn/ml-trained-models-utils';
import type {
ModelDefinitionResponse,
GetModelDownloadConfigOptions,
} from '@kbn/ml-trained-models-utils';
import { type TrainedModelsApiService } from './ml_api_service/trained_models';

export class ElasticModels {
Expand All @@ -17,7 +20,7 @@ export class ElasticModels {
* If any of the ML nodes run a different OS rather than Linux, or the CPU architecture isn't x86_64,
* a portable version of the model is returned.
*/
public async getELSER(options?: GetElserOptions): Promise<ModelDefinitionResponse> {
public async getELSER(options?: GetModelDownloadConfigOptions): Promise<ModelDefinitionResponse> {
return await this.trainedModels.getElserConfig(options);
}
}
Expand Up @@ -11,7 +11,10 @@ import type { IngestPipeline } from '@elastic/elasticsearch/lib/api/types';
import { useMemo } from 'react';
import type { HttpFetchQuery } from '@kbn/core/public';
import type { ErrorType } from '@kbn/ml-error-utils';
import type { GetElserOptions, ModelDefinitionResponse } from '@kbn/ml-trained-models-utils';
import type {
GetModelDownloadConfigOptions,
ModelDefinitionResponse,
} from '@kbn/ml-trained-models-utils';
import { ML_INTERNAL_BASE_PATH } from '../../../../common/constants/app';
import type { MlSavedObjectType } from '../../../../common/types/saved_objects';
import { HttpService } from '../http_service';
Expand Down Expand Up @@ -73,7 +76,7 @@ export function trainedModelsApiProvider(httpService: HttpService) {
/**
* Gets ELSER config for download based on the cluster OS and CPU architecture.
*/
getElserConfig(options?: GetElserOptions) {
getElserConfig(options?: GetModelDownloadConfigOptions) {
return httpService.http<ModelDefinitionResponse>({
path: `${ML_INTERNAL_BASE_PATH}/trained_models/elser_config`,
method: 'GET',
Expand Down
Expand Up @@ -76,6 +76,24 @@ describe('modelsProvider', () => {
version: 2,
modelName: 'elser',
},
{
config: { input: { field_names: ['text_field'] } },
description: 'E5 multilingual embedding model',
name: '.multilingual-e5-small',
default: true,
version: 1,
modelName: 'e5',
},
{
arch: 'amd64',
config: { input: { field_names: ['text_field'] } },
description: 'E5 multilingual embedding model, optimized for linux-x86_64',
name: '.multilingual-e5-small_linux-x86_64',
os: 'Linux',
recommended: true,
version: 1,
modelName: 'e5',
},
]);
});

Expand Down Expand Up @@ -129,6 +147,23 @@ describe('modelsProvider', () => {
version: 2,
modelName: 'elser',
},
{
config: { input: { field_names: ['text_field'] } },
description: 'E5 multilingual embedding model',
name: '.multilingual-e5-small',
recommended: true,
version: 1,
modelName: 'e5',
},
{
arch: 'amd64',
config: { input: { field_names: ['text_field'] } },
description: 'E5 multilingual embedding model, optimized for linux-x86_64',
name: '.multilingual-e5-small_linux-x86_64',
os: 'Linux',
version: 1,
modelName: 'e5',
},
]);
});
});
Expand Down Expand Up @@ -175,4 +210,37 @@ describe('modelsProvider', () => {
expect(result.name).toEqual('.elser_model_2_linux-x86_64');
});
});

describe('getCuratedModelConfig', () => {
test('provides a recommended definition by default', async () => {
const result = await modelService.getCuratedModelConfig('e5');
expect(result.name).toEqual('.multilingual-e5-small_linux-x86_64');
});

test('provides a default version if there is no recommended', async () => {
mockCloud.cloudId = undefined;
(mockClient.asInternalUser.transport.request as jest.Mock).mockResolvedValueOnce({
_nodes: {
total: 1,
successful: 1,
failed: 0,
},
cluster_name: 'default',
nodes: {
yYmqBqjpQG2rXsmMSPb9pQ: {
name: 'node-0',
roles: ['ml'],
attributes: {},
os: {
name: 'Mac OS X',
arch: 'aarch64',
},
},
},
});

const result = await modelService.getCuratedModelConfig('e5');
expect(result.name).toEqual('.multilingual-e5-small');
});
});
});
Expand Up @@ -19,10 +19,11 @@ import type {
} from '@elastic/elasticsearch/lib/api/types';
import {
ELASTIC_MODEL_DEFINITIONS,
type GetElserOptions,
type GetModelDownloadConfigOptions,
type ModelDefinitionResponse,
} from '@kbn/ml-trained-models-utils';
import type { CloudSetup } from '@kbn/cloud-plugin/server';
import type { ElasticCurateModelName } from '@kbn/ml-trained-models-utils/src/constants/trained_models';
import type { PipelineDefinition } from '../../../common/types/trained_models';
import type { MlClient } from '../../lib/ml_client';
import type { MLSavedObjectService } from '../../saved_objects';
Expand Down Expand Up @@ -52,6 +53,8 @@ interface ModelMapResult {
error: null | any;
}

export type GetCuratedModelConfigParams = Parameters<ModelsProvider['getCuratedModelConfig']>;

export class ModelsProvider {
private _transforms?: TransformGetTransformTransformSummary[];

Expand Down Expand Up @@ -410,8 +413,6 @@ export class ModelsProvider {
}
throw error;
}

return result;
}

/**
Expand Down Expand Up @@ -494,14 +495,19 @@ export class ModelsProvider {
}

/**
* Provides an ELSER model name and configuration for download based on the current cluster architecture.
* The current default version is 2. If running on Cloud it returns the Linux x86_64 optimized version.
* If any of the ML nodes run a different OS rather than Linux, or the CPU architecture isn't x86_64,
* a portable version of the model is returned.
* Provides an appropriate model ID and configuration for download based on the current cluster architecture.
*
* @param modelName
* @param options
* @returns
*/
async getELSER(options?: GetElserOptions): Promise<ModelDefinitionResponse> | never {
const modelDownloadConfig = await this.getModelDownloads();

async getCuratedModelConfig(
modelName: ElasticCurateModelName,
options?: GetModelDownloadConfigOptions
): Promise<ModelDefinitionResponse> | never {
const modelDownloadConfig = (await this.getModelDownloads()).filter(
(model) => model.modelName === modelName
darnautov marked this conversation as resolved.
Show resolved Hide resolved
);
let requestedModel: ModelDefinitionResponse | undefined;
let recommendedModel: ModelDefinitionResponse | undefined;
let defaultModel: ModelDefinitionResponse | undefined;
Expand All @@ -527,6 +533,18 @@ export class ModelsProvider {
return requestedModel || recommendedModel || defaultModel!;
}

/**
* Provides an ELSER model name and configuration for download based on the current cluster architecture.
* The current default version is 2. If running on Cloud it returns the Linux x86_64 optimized version.
* If any of the ML nodes run a different OS rather than Linux, or the CPU architecture isn't x86_64,
* a portable version of the model is returned.
*/
async getELSER(
options?: GetModelDownloadConfigOptions
): Promise<ModelDefinitionResponse> | never {
return await this.getCuratedModelConfig('elser', options);
}

/**
* Puts the requested ELSER model into elasticsearch, triggering elasticsearch to download the model.
* Assigns the model to the * space.
Expand Down
Expand Up @@ -8,14 +8,18 @@
import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import type { CloudSetup } from '@kbn/cloud-plugin/server';
import type { KibanaRequest, SavedObjectsClientContract } from '@kbn/core/server';
import type { GetElserOptions, ModelDefinitionResponse } from '@kbn/ml-trained-models-utils';
import type {
GetModelDownloadConfigOptions,
ModelDefinitionResponse,
} from '@kbn/ml-trained-models-utils';
import type {
MlInferTrainedModelRequest,
MlStopTrainedModelDeploymentRequest,
UpdateTrainedModelDeploymentRequest,
UpdateTrainedModelDeploymentResponse,
} from '../../lib/ml_client/types';
import { modelsProvider } from '../../models/model_management';
import type { GetCuratedModelConfigParams } from '../../models/model_management/models_provider';
import type { GetGuards } from '../shared_services';

export interface TrainedModelsProvider {
Expand Down Expand Up @@ -47,7 +51,7 @@ export interface TrainedModelsProvider {
putTrainedModel(
params: estypes.MlPutTrainedModelRequest
): Promise<estypes.MlPutTrainedModelResponse>;
getELSER(params?: GetElserOptions): Promise<ModelDefinitionResponse>;
getELSER(params?: GetModelDownloadConfigOptions): Promise<ModelDefinitionResponse>;
darnautov marked this conversation as resolved.
Show resolved Hide resolved
};
}

Expand Down Expand Up @@ -123,14 +127,22 @@ export function getTrainedModelsProvider(
return mlClient.putTrainedModel(params);
});
},
async getELSER(params?: GetElserOptions) {
async getELSER(params?: GetModelDownloadConfigOptions) {
return await guards
.isFullLicense()
.hasMlCapabilities(['canGetTrainedModels'])
.ok(async ({ scopedClient, mlClient }) => {
return modelsProvider(scopedClient, mlClient, cloud).getELSER(params);
});
},
async getCuratedModelConfig(...params: GetCuratedModelConfigParams) {
return await guards
.isFullLicense()
.hasMlCapabilities(['canGetTrainedModels'])
.ok(async ({ scopedClient, mlClient }) => {
return modelsProvider(scopedClient, mlClient, cloud).getCuratedModelConfig(...params);
});
},
};
},
};
Expand Down