mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
# Backport This will backport the following commits from `main` to `8.x`: - [Remove hardcoded preconfigured ELSER endpoint (#201300)](https://github.com/elastic/kibana/pull/201300) <!--- Backport version: 8.9.8 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) <!--BACKPORT [{"author":{"name":"Samiul Monir","email":"150824886+Samiul-TheSoccerFan@users.noreply.github.com"},"sourceCommit":{"committedDate":"2024-11-26T14:42:20Z","message":"Remove hardcoded preconfigured ELSER endpoint (#201300)\n\n## Summary\r\n\r\nThe Index mapping will have access to default elser inference endpoint\r\nso we do not need to hardcode endpoint names in the Kibana.\r\n\r\nThis needs to go after\r\n#https://github.com/elastic/elasticsearch/pull/117294 merges in `8.17`\r\nand further.\r\n\r\n\r\nhttps://github.com/user-attachments/assets/4a786fde-e250-440d-a9d7-2256dacc8edd\r\n\r\n---------\r\n\r\nCo-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>","sha":"b3d638b7cf3022fbe1e0fb019462ad9df6d52f25","branchLabelMapping":{"^v9.0.0$":"main","^v8.18.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","v9.0.0","Team:Search","backport:version","v8.17.0","v8.18.0"],"number":201300,"url":"https://github.com/elastic/kibana/pull/201300","mergeCommit":{"message":"Remove hardcoded preconfigured ELSER endpoint (#201300)\n\n## Summary\r\n\r\nThe Index mapping will have access to default elser inference endpoint\r\nso we do not need to hardcode endpoint names in the Kibana.\r\n\r\nThis needs to go after\r\n#https://github.com/elastic/elasticsearch/pull/117294 merges in `8.17`\r\nand further.\r\n\r\n\r\nhttps://github.com/user-attachments/assets/4a786fde-e250-440d-a9d7-2256dacc8edd\r\n\r\n---------\r\n\r\nCo-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>","sha":"b3d638b7cf3022fbe1e0fb019462ad9df6d52f25"}},"sourceBranch":"main","suggestedTargetBranches":["8.17","8.x"],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","labelRegex":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/201300","number":201300,"mergeCommit":{"message":"Remove hardcoded preconfigured ELSER endpoint (#201300)\n\n## Summary\r\n\r\nThe Index mapping will have access to default elser inference endpoint\r\nso we do not need to hardcode endpoint names in the Kibana.\r\n\r\nThis needs to go after\r\n#https://github.com/elastic/elasticsearch/pull/117294 merges in `8.17`\r\nand further.\r\n\r\n\r\nhttps://github.com/user-attachments/assets/4a786fde-e250-440d-a9d7-2256dacc8edd\r\n\r\n---------\r\n\r\nCo-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>","sha":"b3d638b7cf3022fbe1e0fb019462ad9df6d52f25"}},{"branch":"8.17","label":"v8.17.0","labelRegex":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"8.x","label":"v8.18.0","labelRegex":"^v8.18.0$","isSourceBranch":false,"state":"NOT_CREATED"}]}] BACKPORT-->
This commit is contained in:
parent
e006f0dbbf
commit
aeb5d06647
11 changed files with 59 additions and 96 deletions
|
@ -31,15 +31,10 @@ export interface IndexErrorProps {
|
|||
}
|
||||
|
||||
interface SemanticTextProperty extends MappingPropertyBase {
|
||||
inference_id?: string;
|
||||
inference_id: string;
|
||||
type: 'semantic_text';
|
||||
}
|
||||
|
||||
/*
|
||||
This will be repalce once we add default elser inference_id
|
||||
with the index mapping response.
|
||||
*/
|
||||
const ELSER_PRECONFIGURED_ENDPOINTS = '.elser-2-elasticsearch';
|
||||
const isInferencePreconfigured = (inferenceId: string) => inferenceId.startsWith('.');
|
||||
|
||||
const parseMapping = (mappings: MappingTypeMapping) => {
|
||||
|
@ -56,11 +51,6 @@ const getSemanticTextFields = (
|
|||
): Array<{ path: string; source: SemanticTextProperty }> => {
|
||||
return Object.entries(fields).flatMap(([key, value]) => {
|
||||
const currentPath: string = path ? `${path}.${key}` : key;
|
||||
if (value.type === 'semantic_text') {
|
||||
value = value.inference_id
|
||||
? value
|
||||
: { ...value, inference_id: ELSER_PRECONFIGURED_ENDPOINTS };
|
||||
}
|
||||
const currentField: Array<{ path: string; source: SemanticTextProperty }> =
|
||||
value.type === 'semantic_text' ? [{ path: currentPath, source: value }] : [];
|
||||
if (hasProperties(value)) {
|
||||
|
|
|
@ -9,7 +9,7 @@ import {
|
|||
Form,
|
||||
useForm,
|
||||
} from '../../../public/application/components/mappings_editor/shared_imports';
|
||||
import { registerTestBed } from '@kbn/test-jest-helpers';
|
||||
import { findTestSubject, registerTestBed } from '@kbn/test-jest-helpers';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import {
|
||||
SelectInferenceId,
|
||||
|
@ -152,4 +152,34 @@ describe('SelectInferenceId', () => {
|
|||
expect(find('data-inference-endpoint-list').contains('endpoint-2')).toBe(true);
|
||||
expect(find('data-inference-endpoint-list').contains('endpoint-3')).toBe(false);
|
||||
});
|
||||
|
||||
it('select the first endpoint by default', () => {
|
||||
find('inferenceIdButton').simulate('click');
|
||||
const defaultElser = findTestSubject(
|
||||
find('data-inference-endpoint-list'),
|
||||
'custom-inference_.preconfigured-elser'
|
||||
);
|
||||
expect(defaultElser.prop('aria-checked')).toEqual(true);
|
||||
});
|
||||
|
||||
it('does not select the other endpoints by default', () => {
|
||||
find('inferenceIdButton').simulate('click');
|
||||
const defaultE5 = findTestSubject(
|
||||
find('data-inference-endpoint-list'),
|
||||
'custom-inference_.preconfigured-e5'
|
||||
);
|
||||
expect(defaultE5.prop('aria-checked')).toEqual(false);
|
||||
|
||||
const endpoint1 = findTestSubject(
|
||||
find('data-inference-endpoint-list'),
|
||||
'custom-inference_endpoint-1'
|
||||
);
|
||||
expect(endpoint1.prop('aria-checked')).toEqual(false);
|
||||
|
||||
const endpoint2 = findTestSubject(
|
||||
find('data-inference-endpoint-list'),
|
||||
'custom-inference_endpoint-2'
|
||||
);
|
||||
expect(endpoint2.prop('aria-checked')).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -132,6 +132,14 @@ const SelectInferenceIdContent: React.FC<SelectInferenceIdContentProps> = ({
|
|||
'data-test-subj': `custom-inference_${endpoint.inference_id}`,
|
||||
checked: value === endpoint.inference_id ? 'on' : undefined,
|
||||
}));
|
||||
/**
|
||||
* Adding this check to ensure we have the preconfigured elser endpoint selected by default.
|
||||
*/
|
||||
const hasInferenceSelected = newOptions.some((option) => option.checked === 'on');
|
||||
if (!hasInferenceSelected && newOptions.length > 0) {
|
||||
newOptions[0].checked = 'on';
|
||||
}
|
||||
|
||||
if (value && !newOptions.find((option) => option.label === value)) {
|
||||
// Sometimes we create a new endpoint but the backend is slow in updating so we need to optimistically update
|
||||
const newOption: EuiSelectableOption = {
|
||||
|
@ -273,6 +281,7 @@ const SelectInferenceIdContent: React.FC<SelectInferenceIdContentProps> = ({
|
|||
searchable
|
||||
isLoading={isLoading}
|
||||
singleSelection="always"
|
||||
defaultChecked
|
||||
searchProps={{
|
||||
compressed: true,
|
||||
placeholder: i18n.translate(
|
||||
|
|
|
@ -13,16 +13,16 @@ import { act } from 'react-dom/test-utils';
|
|||
jest.mock('../../../../../../../../hooks/use_details_page_mappings_model_management', () => ({
|
||||
useDetailsPageMappingsModelManagement: () => ({
|
||||
fetchInferenceToModelIdMap: () => ({
|
||||
e5: {
|
||||
isDeployed: false,
|
||||
isDeployable: true,
|
||||
trainedModelId: '.multilingual-e5-small',
|
||||
},
|
||||
elser_model_2: {
|
||||
'.preconfigured_elser': {
|
||||
isDeployed: false,
|
||||
isDeployable: true,
|
||||
trainedModelId: '.elser_model_2',
|
||||
},
|
||||
'.preconfigured_e5': {
|
||||
isDeployed: false,
|
||||
isDeployable: true,
|
||||
trainedModelId: '.multilingual-e5-small',
|
||||
},
|
||||
openai: {
|
||||
isDeployed: false,
|
||||
isDeployable: false,
|
||||
|
@ -49,13 +49,13 @@ const mockField: Record<string, SemanticTextField> = {
|
|||
elser_model_2: {
|
||||
name: 'name',
|
||||
type: 'semantic_text',
|
||||
inference_id: 'elser_model_2',
|
||||
inference_id: '.preconfigured_elser',
|
||||
reference_field: 'title',
|
||||
},
|
||||
e5: {
|
||||
name: 'name',
|
||||
type: 'semantic_text',
|
||||
inference_id: 'e5',
|
||||
inference_id: '.preconfigured_e5',
|
||||
reference_field: 'title',
|
||||
},
|
||||
openai: {
|
||||
|
@ -100,16 +100,16 @@ const mockDispatch = jest.fn();
|
|||
jest.mock('../../../../../mappings_state_context', () => ({
|
||||
useMappingsState: jest.fn().mockReturnValue({
|
||||
inferenceToModelIdMap: {
|
||||
e5: {
|
||||
isDeployed: false,
|
||||
isDeployable: true,
|
||||
trainedModelId: '.multilingual-e5-small',
|
||||
},
|
||||
elser_model_2: {
|
||||
'.preconfigured_elser': {
|
||||
isDeployed: false,
|
||||
isDeployable: true,
|
||||
trainedModelId: '.elser_model_2',
|
||||
},
|
||||
'.preconfigured_e5': {
|
||||
isDeployed: false,
|
||||
isDeployable: true,
|
||||
trainedModelId: '.multilingual-e5-small',
|
||||
},
|
||||
openai: {
|
||||
isDeployed: false,
|
||||
isDeployable: false,
|
||||
|
@ -142,7 +142,7 @@ jest.mock('../../../../../../../services/api', () => ({
|
|||
getInferenceEndpoints: jest.fn().mockResolvedValue({
|
||||
data: [
|
||||
{
|
||||
inference_id: 'e5',
|
||||
inference_id: '.preconfigured_e5',
|
||||
task_type: 'text_embedding',
|
||||
service: 'elasticsearch',
|
||||
service_settings: {
|
||||
|
@ -212,28 +212,6 @@ describe('useSemanticText', () => {
|
|||
mockConfig.openai.modelConfig
|
||||
);
|
||||
});
|
||||
it('should handle semantic text with inference endpoint created from flyout correctly', async () => {
|
||||
const { result } = renderHook(() =>
|
||||
useSemanticText({
|
||||
form: mockForm.elasticModelEndpointCreatedfromFlyout,
|
||||
setErrorsInTrainedModelDeployment: jest.fn(),
|
||||
ml: mlMock,
|
||||
})
|
||||
);
|
||||
await act(async () => {
|
||||
result.current.handleSemanticText(mockField.my_elser_endpoint, mockConfig.elser);
|
||||
});
|
||||
|
||||
expect(mockDispatch).toHaveBeenCalledWith({
|
||||
type: 'field.add',
|
||||
value: mockField.my_elser_endpoint,
|
||||
});
|
||||
expect(mlMock.mlApi.inferenceModels.createInferenceEndpoint).toHaveBeenCalledWith(
|
||||
'my_elser_endpoint',
|
||||
'sparse_embedding',
|
||||
mockConfig.elser.modelConfig
|
||||
);
|
||||
});
|
||||
|
||||
it('should handle semantic text correctly', async () => {
|
||||
const { result } = renderHook(() =>
|
||||
|
@ -252,20 +230,6 @@ describe('useSemanticText', () => {
|
|||
type: 'field.add',
|
||||
value: mockField.elser_model_2,
|
||||
});
|
||||
expect(mlMock.mlApi.inferenceModels.createInferenceEndpoint).toHaveBeenCalledWith(
|
||||
'elser_model_2',
|
||||
'sparse_embedding',
|
||||
{
|
||||
service: 'elser',
|
||||
service_settings: {
|
||||
adaptive_allocations: {
|
||||
enabled: true,
|
||||
},
|
||||
num_threads: 1,
|
||||
model_id: '.elser_model_2',
|
||||
},
|
||||
}
|
||||
);
|
||||
});
|
||||
it('does not call create inference endpoint api, if default endpoint already exists', async () => {
|
||||
const { result } = renderHook(() =>
|
||||
|
|
|
@ -19,7 +19,6 @@ import { useMLModelNotificationToasts } from '../../../../../../../../hooks/use_
|
|||
|
||||
import { getInferenceEndpoints } from '../../../../../../../services/api';
|
||||
import { getFieldByPathName } from '../../../../../lib/utils';
|
||||
import { ELSER_PRECONFIGURED_ENDPOINTS } from '../../../../../constants';
|
||||
|
||||
interface UseSemanticTextProps {
|
||||
form: FormHook<Field, Field>;
|
||||
|
@ -63,9 +62,6 @@ export function useSemanticText(props: UseSemanticTextProps) {
|
|||
if (!form.getFormData().reference_field) {
|
||||
form.setFieldValue('reference_field', referenceField);
|
||||
}
|
||||
if (!form.getFormData().inference_id) {
|
||||
form.setFieldValue('inference_id', ELSER_PRECONFIGURED_ENDPOINTS);
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [fieldTypeValue]);
|
||||
|
|
|
@ -19,11 +19,7 @@ import { i18n } from '@kbn/i18n';
|
|||
|
||||
import { NormalizedField, NormalizedFields, State } from '../../../types';
|
||||
import { getTypeLabelFromField } from '../../../lib';
|
||||
import {
|
||||
CHILD_FIELD_INDENT_SIZE,
|
||||
ELSER_PRECONFIGURED_ENDPOINTS,
|
||||
LEFT_PADDING_SIZE_FIELD_ITEM_WRAPPER,
|
||||
} from '../../../constants';
|
||||
import { CHILD_FIELD_INDENT_SIZE, LEFT_PADDING_SIZE_FIELD_ITEM_WRAPPER } from '../../../constants';
|
||||
|
||||
import { FieldsList } from './fields_list';
|
||||
import { CreateField } from './create_field';
|
||||
|
@ -109,7 +105,6 @@ function FieldListItemComponent(
|
|||
const indent = treeDepth * CHILD_FIELD_INDENT_SIZE - substractIndentAmount;
|
||||
|
||||
const isSemanticText = source.type === 'semantic_text';
|
||||
const inferenceId: string = (source.inference_id as string) ?? ELSER_PRECONFIGURED_ENDPOINTS;
|
||||
|
||||
const indentCreateField =
|
||||
(treeDepth + 1) * CHILD_FIELD_INDENT_SIZE +
|
||||
|
@ -298,7 +293,7 @@ function FieldListItemComponent(
|
|||
|
||||
{isSemanticText && (
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiBadge color="hollow">{inferenceId}</EuiBadge>
|
||||
<EuiBadge color="hollow">{source.inference_id as string}</EuiBadge>
|
||||
</EuiFlexItem>
|
||||
)}
|
||||
|
||||
|
|
|
@ -13,9 +13,3 @@
|
|||
export const INDEX_DEFAULT = 'index_default';
|
||||
|
||||
export const STANDARD = 'standard';
|
||||
|
||||
/*
|
||||
This will be repalce once we add default elser inference_id
|
||||
with the index mapping response.
|
||||
*/
|
||||
export const ELSER_PRECONFIGURED_ENDPOINTS = '.elser-2-elasticsearch';
|
||||
|
|
|
@ -1126,22 +1126,10 @@ export const PARAMETERS_DEFINITION: { [key in ParameterName]: ParameterDefinitio
|
|||
},
|
||||
inference_id: {
|
||||
fieldConfig: {
|
||||
defaultValue: 'elser_model_2',
|
||||
defaultValue: '',
|
||||
label: i18n.translate('xpack.idxMgmt.mappingsEditor.parameters.inferenceIdLabel', {
|
||||
defaultMessage: 'Select an inference endpoint:',
|
||||
}),
|
||||
validations: [
|
||||
{
|
||||
validator: emptyField(
|
||||
i18n.translate(
|
||||
'xpack.idxMgmt.mappingsEditor.parameters.validations.inferenceIdIsRequiredErrorMessage',
|
||||
{
|
||||
defaultMessage: 'Inference ID is required.',
|
||||
}
|
||||
)
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
schema: t.string,
|
||||
},
|
||||
|
|
|
@ -23331,7 +23331,6 @@
|
|||
"xpack.idxMgmt.mappingsEditor.parameters.validations.fieldDataFrequency.numberGreaterThanOneErrorMessage": "La valeur doit être supérieure à un.",
|
||||
"xpack.idxMgmt.mappingsEditor.parameters.validations.greaterThanZeroErrorMessage": "Le facteur de montée en charge doit être supérieur à 0.",
|
||||
"xpack.idxMgmt.mappingsEditor.parameters.validations.ignoreAboveIsRequiredErrorMessage": "Limite de longueur de caractère obligatoire.",
|
||||
"xpack.idxMgmt.mappingsEditor.parameters.validations.inferenceIdIsRequiredErrorMessage": "L’ID d’inférence est requis.",
|
||||
"xpack.idxMgmt.mappingsEditor.parameters.validations.localeFieldRequiredErrorMessage": "Spécifiez un paramètre régional.",
|
||||
"xpack.idxMgmt.mappingsEditor.parameters.validations.maxInputLengthFieldRequiredErrorMessage": "Spécifiez une longueur d'entrée maximale.",
|
||||
"xpack.idxMgmt.mappingsEditor.parameters.validations.nameIsRequiredErrorMessage": "Donnez un nom au champ.",
|
||||
|
|
|
@ -23303,7 +23303,6 @@
|
|||
"xpack.idxMgmt.mappingsEditor.parameters.validations.fieldDataFrequency.numberGreaterThanOneErrorMessage": "値は1よりも大きい値でなければなりません。",
|
||||
"xpack.idxMgmt.mappingsEditor.parameters.validations.greaterThanZeroErrorMessage": "スケーリングファクターは0よりも大きくなくてはなりません。",
|
||||
"xpack.idxMgmt.mappingsEditor.parameters.validations.ignoreAboveIsRequiredErrorMessage": "文字数制限が必要です。",
|
||||
"xpack.idxMgmt.mappingsEditor.parameters.validations.inferenceIdIsRequiredErrorMessage": "推論IDは必須です。",
|
||||
"xpack.idxMgmt.mappingsEditor.parameters.validations.localeFieldRequiredErrorMessage": "ロケールを指定します。",
|
||||
"xpack.idxMgmt.mappingsEditor.parameters.validations.maxInputLengthFieldRequiredErrorMessage": "最大入力長さを指定します。",
|
||||
"xpack.idxMgmt.mappingsEditor.parameters.validations.nameIsRequiredErrorMessage": "フィールドに名前を付けます。",
|
||||
|
|
|
@ -23355,7 +23355,6 @@
|
|||
"xpack.idxMgmt.mappingsEditor.parameters.validations.fieldDataFrequency.numberGreaterThanOneErrorMessage": "值必须大于 1。",
|
||||
"xpack.idxMgmt.mappingsEditor.parameters.validations.greaterThanZeroErrorMessage": "缩放因数必须大于 0。",
|
||||
"xpack.idxMgmt.mappingsEditor.parameters.validations.ignoreAboveIsRequiredErrorMessage": "字符长度限制必填。",
|
||||
"xpack.idxMgmt.mappingsEditor.parameters.validations.inferenceIdIsRequiredErrorMessage": "“推理 ID”必填。",
|
||||
"xpack.idxMgmt.mappingsEditor.parameters.validations.localeFieldRequiredErrorMessage": "指定区域设置。",
|
||||
"xpack.idxMgmt.mappingsEditor.parameters.validations.maxInputLengthFieldRequiredErrorMessage": "指定最大输入长度。",
|
||||
"xpack.idxMgmt.mappingsEditor.parameters.validations.nameIsRequiredErrorMessage": "为字段提供名称。",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue