diff --git a/x-pack/plugins/search_inference_endpoints/common/doc_links.ts b/x-pack/plugins/search_inference_endpoints/common/doc_links.ts index c3d8d31dffa6d..bb426180a36e8 100644 --- a/x-pack/plugins/search_inference_endpoints/common/doc_links.ts +++ b/x-pack/plugins/search_inference_endpoints/common/doc_links.ts @@ -8,14 +8,16 @@ import { DocLinks } from '@kbn/doc-links'; class InferenceEndpointsDocLinks { - public nlpImportModel: string = ''; - public supportedNlpModels: string = ''; + public createInferenceEndpoint: string = ''; + public semanticSearchElser: string = ''; + public semanticSearchE5: string = ''; constructor() {} setDocLinks(newDocLinks: DocLinks) { - this.nlpImportModel = newDocLinks.ml.nlpImportModel; - this.supportedNlpModels = newDocLinks.ml.supportedNlpModels; + this.createInferenceEndpoint = newDocLinks.enterpriseSearch.inferenceApiCreate; + this.semanticSearchElser = newDocLinks.enterpriseSearch.elser; + this.semanticSearchE5 = newDocLinks.enterpriseSearch.e5Model; } } diff --git a/x-pack/plugins/search_inference_endpoints/common/translations.ts b/x-pack/plugins/search_inference_endpoints/common/translations.ts index 8171b8bba0254..bb04ec80fafdc 100644 --- a/x-pack/plugins/search_inference_endpoints/common/translations.ts +++ b/x-pack/plugins/search_inference_endpoints/common/translations.ts @@ -21,14 +21,7 @@ export const CANCEL = i18n.translate('xpack.searchInferenceEndpoints.cancel', { export const MANAGE_INFERENCE_ENDPOINTS_LABEL = i18n.translate( 'xpack.searchInferenceEndpoints.allInferenceEndpoints.description', { - defaultMessage: 'Manage your inference endpoints.', - } -); - -export const ADD_ENDPOINT_LABEL = i18n.translate( - 'xpack.searchInferenceEndpoints.newInferenceEndpointButtonLabel', - { - defaultMessage: 'Add endpoint', + defaultMessage: 'View and manage your deployed inference endpoints.', } ); @@ -36,14 +29,14 @@ export const CREATE_FIRST_INFERENCE_ENDPOINT_DESCRIPTION = i18n.translate( 'xpack.searchInferenceEndpoints.addEmptyPrompt.createFirstInferenceEndpointDescription', { defaultMessage: - 'Connect to your third-party model provider to create an inference endpoint for semantic search.', + "Inference endpoints enable you to perform inference tasks using NLP models provided by third-party services or Elastic's built-in models like ELSER and E5. Set up tasks such as text embedding, completions, reranking, and more by using the Create Inference API.", } ); export const START_WITH_PREPARED_ENDPOINTS_LABEL = i18n.translate( 'xpack.searchInferenceEndpoints.addEmptyPrompt.startWithPreparedEndpointsLabel', { - defaultMessage: 'Get started quickly with our prepared endpoints:', + defaultMessage: 'Learn more about built-in NLP models:', } ); @@ -54,23 +47,50 @@ export const ELSER_TITLE = i18n.translate( } ); +export const LEARN_HOW_TO_CREATE_INFERENCE_ENDPOINTS_LINK = i18n.translate( + 'xpack.searchInferenceEndpoints.addEmptyPrompt.learnHowToCreateInferenceEndpoints', + { + defaultMessage: 'Learn how to create inference endpoints', + } +); + +export const SEMANTIC_SEARCH_WITH_ELSER_LINK = i18n.translate( + 'xpack.searchInferenceEndpoints.addEmptyPrompt.semanticSearchWithElser', + { + defaultMessage: 'Semantic search with ELSER', + } +); + +export const SEMANTIC_SEARCH_WITH_E5_LINK = i18n.translate( + 'xpack.searchInferenceEndpoints.addEmptyPrompt.semanticSearchWithE5', + { + defaultMessage: 'Semantic search with E5 Multilingual', + } +); + +export const VIEW_YOUR_MODELS_LINK = i18n.translate( + 'xpack.searchInferenceEndpoints.addEmptyPrompt.viewYourModels', + { + defaultMessage: 'View your models', + } +); + export const ELSER_DESCRIPTION = i18n.translate( 'xpack.searchInferenceEndpoints.addEmptyPrompt.elserDescription', { - defaultMessage: - 'ELSER is a sparse vector NLP model trained by Elastic for semantic search. Recommended for English language.', + defaultMessage: "ELSER is Elastic's sparse vector NLP model for semantic search in English.", } ); export const E5_TITLE = i18n.translate('xpack.searchInferenceEndpoints.addEmptyPrompt.e5Title', { - defaultMessage: 'Multilingual E5', + defaultMessage: 'E5 Multilingual', }); export const E5_DESCRIPTION = i18n.translate( 'xpack.searchInferenceEndpoints.addEmptyPrompt.e5Description', { defaultMessage: - 'E5 is a dense vector NLP model that enables you to perform multi-lingual semantic search.', + 'E5 is a third-party NLP model that enables you to perform multilingual semantic search by using dense vector representations.', } ); diff --git a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_endpoint/endpoint_info.test.tsx b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_endpoint/endpoint_info.test.tsx index c92c01240425c..69ebdc129be6b 100644 --- a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_endpoint/endpoint_info.test.tsx +++ b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_endpoint/endpoint_info.test.tsx @@ -9,6 +9,16 @@ import { render, screen } from '@testing-library/react'; import React from 'react'; import { EndpointInfo } from './endpoint_info'; +jest.mock('@kbn/ml-trained-models-utils', () => ({ + ...jest.requireActual('@kbn/ml-trained-models-utils'), + ELASTIC_MODEL_DEFINITIONS: { + 'model-with-mit-license': { + license: 'MIT', + licenseUrl: 'https://abc.com', + }, + }, +})); + describe('RenderEndpoint component tests', () => { describe('with cohere service', () => { const mockEndpoint = { @@ -254,4 +264,40 @@ describe('RenderEndpoint component tests', () => { expect(screen.queryByText('Rate limit:')).not.toBeInTheDocument(); }); }); + + describe('for MIT licensed models', () => { + const mockEndpointWithMitLicensedModel = { + model_id: 'model-123', + service: 'elasticsearch', + service_settings: { + num_allocations: 5, + num_threads: 10, + model_id: 'model-with-mit-license', + }, + } as any; + + it('renders the MIT license badge if the model is eligible', () => { + render(); + + const mitBadge = screen.getByTestId('mit-license-badge'); + expect(mitBadge).toBeInTheDocument(); + expect(mitBadge).toHaveAttribute('href', 'https://abc.com'); + }); + + it('does not render the MIT license badge if the model is not eligible', () => { + const mockEndpointWithNonMitLicensedModel = { + model_id: 'model-123', + service: 'elasticsearch', + service_settings: { + num_allocations: 5, + num_threads: 10, + model_id: 'model-without-mit-license', + }, + } as any; + + render(); + + expect(screen.queryByTestId('mit-license-badge')).not.toBeInTheDocument(); + }); + }); }); diff --git a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_endpoint/endpoint_info.tsx b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_endpoint/endpoint_info.tsx index ae482b609346f..ab0b7b3a67c2f 100644 --- a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_endpoint/endpoint_info.tsx +++ b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_endpoint/endpoint_info.tsx @@ -6,8 +6,11 @@ */ import React from 'react'; -import { InferenceAPIConfigResponse } from '@kbn/ml-trained-models-utils'; -import { EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui'; +import { + InferenceAPIConfigResponse, + ELASTIC_MODEL_DEFINITIONS, +} from '@kbn/ml-trained-models-utils'; +import { EuiFlexGroup, EuiFlexItem, EuiText, EuiBadge } from '@elastic/eui'; import { ServiceProviderKeys } from '../../types'; import { ModelBadge } from './model_badge'; import * as i18n from './translations'; @@ -38,13 +41,31 @@ export const EndpointModelInfo: React.FC = ({ endpoint }) => ? serviceSettings.model : undefined; + const isEligibleForMITBadge = modelId && ELASTIC_MODEL_DEFINITIONS[modelId]?.license === 'MIT'; + return ( - + {modelId && ( )} + + {isEligibleForMITBadge && ( + + + {i18n.MIT_LICENSE} + + + )} + {endpointModelAtrributes(endpoint)} diff --git a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_endpoint/translations.ts b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_endpoint/translations.ts index 52705999e8b44..d3e002505e64a 100644 --- a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_endpoint/translations.ts +++ b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/render_endpoint/translations.ts @@ -18,3 +18,10 @@ export const ALLOCATIONS = (numAllocations: number) => defaultMessage: 'Allocations: {numAllocations}', values: { numAllocations }, }); + +export const MIT_LICENSE = i18n.translate( + 'xpack.searchInferenceEndpoints.elasticsearch.mitLicense', + { + defaultMessage: 'License: MIT', + } +); diff --git a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/table_columns.tsx b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/table_columns.tsx index caca4449e02fa..659da35146a22 100644 --- a/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/table_columns.tsx +++ b/x-pack/plugins/search_inference_endpoints/public/components/all_inference_endpoints/render_table_columns/table_columns.tsx @@ -57,7 +57,7 @@ export const useTableColumns = () => { return null; }, sortable: false, - width: '265px', + width: '185px', }, { field: 'type', @@ -70,7 +70,7 @@ export const useTableColumns = () => { return null; }, sortable: false, - width: '265px', + width: '185px', }, actions, ]; diff --git a/x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/add_empty_prompt.test.tsx b/x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/add_empty_prompt.test.tsx index f9b7e11e48d94..755c1f0a1de54 100644 --- a/x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/add_empty_prompt.test.tsx +++ b/x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/add_empty_prompt.test.tsx @@ -6,28 +6,42 @@ */ import React from 'react'; -import { fireEvent, screen } from '@testing-library/react'; +import { screen } from '@testing-library/react'; import { AddEmptyPrompt } from './add_empty_prompt'; import { renderReactTestingLibraryWithI18n as render } from '@kbn/test-jest-helpers'; import '@testing-library/jest-dom'; -const setIsInferenceFlyoutVisibleMock = jest.fn(); describe('When empty prompt is loaded', () => { beforeEach(() => { - render(); + render(); }); it('should display the description for creation of the first inference endpoint', () => { expect( screen.getByText( - /Connect to your third-party model provider to create an inference endpoint for semantic search./ + /Inference endpoints enable you to perform inference tasks using NLP models provided by third-party services/ ) ).toBeInTheDocument(); }); - it('calls setIsInferenceFlyoutVisible when the addInferenceEndpoint button is clicked', async () => { - fireEvent.click(screen.getByTestId('addEndpointButtonForEmptyPrompt')); - expect(setIsInferenceFlyoutVisibleMock).toHaveBeenCalled(); + it('should have a learn-more link', () => { + const learnMoreLink = screen.getByTestId('learn-how-to-create-inference-endpoints'); + expect(learnMoreLink).toBeInTheDocument(); + }); + + it('should have a view-your-models link', () => { + const learnMoreLink = screen.getByTestId('view-your-models'); + expect(learnMoreLink).toBeInTheDocument(); + }); + + it('should have a semantic-search-with-elser link', () => { + const learnMoreLink = screen.getByTestId('semantic-search-with-elser'); + expect(learnMoreLink).toBeInTheDocument(); + }); + + it('should have a semantic-search-with-e5 link', () => { + const learnMoreLink = screen.getByTestId('semantic-search-with-e5'); + expect(learnMoreLink).toBeInTheDocument(); }); }); diff --git a/x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/add_empty_prompt.tsx b/x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/add_empty_prompt.tsx index ee858f7a8b640..782994975ada4 100644 --- a/x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/add_empty_prompt.tsx +++ b/x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/add_empty_prompt.tsx @@ -8,27 +8,27 @@ import React from 'react'; import { - EuiButton, EuiPageTemplate, EuiFlexGroup, EuiFlexItem, EuiImage, EuiSpacer, + EuiLink, } from '@elastic/eui'; +import { docLinks } from '../../../common/doc_links'; import * as i18n from '../../../common/translations'; import inferenceEndpoint from '../../assets/images/inference_endpoint.svg'; import { EndpointPrompt } from './endpoint_prompt'; +import { useTrainedModelPageUrl } from '../../hooks/use_trained_model_page_url'; import './add_empty_prompt.scss'; -interface AddEmptyPromptProps { - setIsInferenceFlyoutVisible: (value: boolean) => void; -} +export const AddEmptyPrompt: React.FC = () => { + const trainedModelPageUrl = useTrainedModelPageUrl(); -export const AddEmptyPrompt: React.FC = ({ setIsInferenceFlyoutVisible }) => { return ( = ({ setIsInferenceFl {i18n.CREATE_FIRST_INFERENCE_ENDPOINT_DESCRIPTION} - -
- setIsInferenceFlyoutVisible(true)} - > - {i18n.ADD_ENDPOINT_LABEL} - -
+ + + {i18n.LEARN_HOW_TO_CREATE_INFERENCE_ENDPOINTS_LINK} + + + + + {i18n.VIEW_YOUR_MODELS_LINK} +
} @@ -66,31 +67,31 @@ export const AddEmptyPrompt: React.FC = ({ setIsInferenceFl setIsInferenceFlyoutVisible(true)} + - {i18n.ADD_ENDPOINT_LABEL} - + {i18n.SEMANTIC_SEARCH_WITH_ELSER_LINK} + } /> setIsInferenceFlyoutVisible(true)} + - {i18n.ADD_ENDPOINT_LABEL} - + {i18n.SEMANTIC_SEARCH_WITH_E5_LINK} + } /> diff --git a/x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/endpoint_prompt.tsx b/x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/endpoint_prompt.tsx index b10812ef2e6a3..aa6ff9d582e10 100644 --- a/x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/endpoint_prompt.tsx +++ b/x-pack/plugins/search_inference_endpoints/public/components/empty_prompt/endpoint_prompt.tsx @@ -9,18 +9,12 @@ import React from 'react'; import { EuiCard } from '@elastic/eui'; interface EndpointPromptProps { - setIsInferenceFlyoutVisible: (value: boolean) => void; title: string; description: string; footer: React.ReactElement; } -export const EndpointPrompt: React.FC = ({ - setIsInferenceFlyoutVisible, - title, - description, - footer, -}) => ( +export const EndpointPrompt: React.FC = ({ title, description, footer }) => ( void; -} - -export const EmptyPromptPage: React.FC = ({ - setIsInferenceFlyoutVisible, -}) => ; diff --git a/x-pack/plugins/search_inference_endpoints/public/components/inference_endpoints.tsx b/x-pack/plugins/search_inference_endpoints/public/components/inference_endpoints.tsx index 0fa200991b8d1..011eb87fd9c09 100644 --- a/x-pack/plugins/search_inference_endpoints/public/components/inference_endpoints.tsx +++ b/x-pack/plugins/search_inference_endpoints/public/components/inference_endpoints.tsx @@ -5,39 +5,28 @@ * 2.0. */ -import React, { useState } from 'react'; +import React from 'react'; import { EuiPageTemplate } from '@elastic/eui'; import { useQueryInferenceEndpoints } from '../hooks/use_inference_endpoints'; import { TabularPage } from './all_inference_endpoints/tabular_page'; -import { EmptyPromptPage } from './empty_prompt_page'; +import { AddEmptyPrompt } from './empty_prompt/add_empty_prompt'; import { InferenceEndpointsHeader } from './inference_endpoints_header'; -import { InferenceFlyoutWrapperComponent } from './inference_flyout_wrapper_component'; export const InferenceEndpoints: React.FC = () => { const { inferenceEndpoints } = useQueryInferenceEndpoints(); - const [isInferenceFlyoutVisible, setIsInferenceFlyoutVisible] = useState(false); return ( <> - {inferenceEndpoints.length > 0 && ( - - )} + {inferenceEndpoints.length > 0 && } {inferenceEndpoints.length === 0 ? ( - + ) : ( )} - {isInferenceFlyoutVisible && ( - - )} ); }; diff --git a/x-pack/plugins/search_inference_endpoints/public/components/inference_endpoints_header.tsx b/x-pack/plugins/search_inference_endpoints/public/components/inference_endpoints_header.tsx index 6956e470a9b77..be8a922aa7c74 100644 --- a/x-pack/plugins/search_inference_endpoints/public/components/inference_endpoints_header.tsx +++ b/x-pack/plugins/search_inference_endpoints/public/components/inference_endpoints_header.tsx @@ -5,34 +5,40 @@ * 2.0. */ -import { EuiButton, EuiPageTemplate } from '@elastic/eui'; +import { EuiPageTemplate, EuiLink, EuiText, EuiSpacer } from '@elastic/eui'; import React from 'react'; import * as i18n from '../../common/translations'; +import { docLinks } from '../../common/doc_links'; +import { useTrainedModelPageUrl } from '../hooks/use_trained_model_page_url'; -interface InferenceEndpointsHeaderProps { - setIsInferenceFlyoutVisible: (isVisible: boolean) => void; -} +export const InferenceEndpointsHeader: React.FC = () => { + const trainedModelPageUrl = useTrainedModelPageUrl(); -export const InferenceEndpointsHeader: React.FC = ({ - setIsInferenceFlyoutVisible, -}) => ( - .euiFlexGroup': { flexWrap: 'wrap' } }} - data-test-subj="allInferenceEndpointsPage" - pageTitle={i18n.INFERENCE_ENDPOINT_LABEL} - description={i18n.MANAGE_INFERENCE_ENDPOINTS_LABEL} - bottomBorder={true} - rightSideItems={[ - setIsInferenceFlyoutVisible(true)} - > - {i18n.ADD_ENDPOINT_LABEL} - , - ]} - /> -); + return ( + +

+ {i18n.MANAGE_INFERENCE_ENDPOINTS_LABEL} + + + {i18n.LEARN_HOW_TO_CREATE_INFERENCE_ENDPOINTS_LINK} + +

+ + } + bottomBorder={true} + rightSideItems={[ + + {i18n.VIEW_YOUR_MODELS_LINK} + , + ]} + /> + ); +}; diff --git a/x-pack/plugins/search_inference_endpoints/public/components/inference_flyout_wrapper_component.tsx b/x-pack/plugins/search_inference_endpoints/public/components/inference_flyout_wrapper_component.tsx deleted file mode 100644 index 43dc7d7d1751c..0000000000000 --- a/x-pack/plugins/search_inference_endpoints/public/components/inference_flyout_wrapper_component.tsx +++ /dev/null @@ -1,187 +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 { EuiFlexItem, EuiCallOut, EuiText, EuiSpacer } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n-react'; -import { InferenceFlyoutWrapper } from '@kbn/inference_integration_flyout/components/inference_flyout_wrapper'; -import React, { useCallback, useEffect, useMemo, useState } from 'react'; - -import { InferenceTaskType } from '@elastic/elasticsearch/lib/api/types'; - -import { ModelConfig } from '@kbn/inference_integration_flyout/types'; -import { extractErrorProperties } from '@kbn/ml-error-utils'; -import { TrainedModelConfigResponse } from '@kbn/ml-plugin/common/types/trained_models'; -import { SUPPORTED_PYTORCH_TASKS, TRAINED_MODEL_TYPE } from '@kbn/ml-trained-models-utils'; -import { useMutation, useQueryClient } from '@tanstack/react-query'; -import { InferenceAPIConfigResponse } from '@kbn/ml-trained-models-utils'; -import * as i18n from '../../common/translations'; -import { INFERENCE_ENDPOINTS_QUERY_KEY } from '../../common/constants'; -import { useKibana } from '../hooks/use_kibana'; -import { docLinks } from '../../common/doc_links'; - -interface InferenceFlyoutWrapperComponentProps { - inferenceEndpoints: InferenceAPIConfigResponse[]; - isInferenceFlyoutVisible: boolean; - setIsInferenceFlyoutVisible: (isVisible: boolean) => void; -} - -export const InferenceFlyoutWrapperComponent: React.FC = ({ - inferenceEndpoints, - isInferenceFlyoutVisible, - setIsInferenceFlyoutVisible, -}) => { - const [inferenceAddError, setInferenceAddError] = useState(undefined); - const [isCreateInferenceApiLoading, setIsCreateInferenceApiLoading] = useState(false); - const [availableTrainedModels, setAvailableTrainedModels] = useState< - TrainedModelConfigResponse[] - >([]); - - const [inferenceEndpointError, setInferenceEndpointError] = useState( - undefined - ); - - const queryClient = useQueryClient(); - - const { - services: { ml, notifications }, - } = useKibana(); - - const toasts = notifications?.toasts; - - const createInferenceEndpointMutation = useMutation( - async ({ - inferenceId, - taskType, - modelConfig, - }: { - inferenceId: string; - taskType: InferenceTaskType; - modelConfig: ModelConfig; - }) => { - if (!ml) { - throw new Error(i18n.UNABLE_TO_CREATE_INFERENCE_ENDPOINT); - } - await ml?.mlApi?.inferenceModels?.createInferenceEndpoint(inferenceId, taskType, modelConfig); - toasts?.addSuccess({ - title: i18n.ENDPOINT_ADDED_SUCCESS, - text: i18n.ENDPOINT_ADDED_SUCCESS_DESCRIPTION(inferenceId), - }); - }, - { - onSuccess: () => { - queryClient.invalidateQueries([INFERENCE_ENDPOINTS_QUERY_KEY]); - }, - } - ); - - const onInferenceEndpointChange = useCallback( - async (inferenceId: string) => { - const modelsExist = inferenceEndpoints.some((i) => i.model_id === inferenceId); - if (modelsExist) { - setInferenceEndpointError(i18n.INFERENCE_ENDPOINT_ALREADY_EXISTS); - } else { - setInferenceEndpointError(undefined); - } - }, - [inferenceEndpoints] - ); - - const onSaveInferenceCallback = useCallback( - async (inferenceId: string, taskType: InferenceTaskType, modelConfig: ModelConfig) => { - setIsCreateInferenceApiLoading(true); - - createInferenceEndpointMutation - .mutateAsync({ inferenceId, taskType, modelConfig }) - .catch((error) => { - const errorObj = extractErrorProperties(error); - notifications?.toasts?.addError(errorObj.message ? new Error(error.message) : error, { - title: i18n.ENDPOINT_CREATION_FAILED, - }); - }) - .finally(() => { - setIsCreateInferenceApiLoading(false); - }); - setIsInferenceFlyoutVisible(!isInferenceFlyoutVisible); - }, - [ - createInferenceEndpointMutation, - isInferenceFlyoutVisible, - setIsInferenceFlyoutVisible, - notifications, - ] - ); - - const onFlyoutClose = useCallback(() => { - setInferenceAddError(undefined); - setIsInferenceFlyoutVisible(!isInferenceFlyoutVisible); - }, [isInferenceFlyoutVisible, setIsInferenceFlyoutVisible]); - - useEffect(() => { - const fetchAvailableTrainedModels = async () => { - let models; - try { - models = await ml?.mlApi?.trainedModels?.getTrainedModels(); - } catch (error) { - const errorObj = extractErrorProperties(error); - if (errorObj.statusCode === 403) { - setInferenceAddError(i18n.FORBIDDEN_TO_ACCESS_TRAINED_MODELS); - } else { - setInferenceAddError(errorObj.message); - } - } finally { - setAvailableTrainedModels(models || []); - } - }; - - fetchAvailableTrainedModels(); - }, [ml]); - - const trainedModels = useMemo(() => { - const availableTrainedModelsList = availableTrainedModels - .filter( - (model: TrainedModelConfigResponse) => - model.model_type === TRAINED_MODEL_TYPE.PYTORCH && - (model?.inference_config - ? Object.keys(model.inference_config).includes(SUPPORTED_PYTORCH_TASKS.TEXT_EMBEDDING) - : {}) - ) - .map((model: TrainedModelConfigResponse) => model.model_id); - - return availableTrainedModelsList; - }, [availableTrainedModels]); - - return ( - - - - - - - - - ) - } - onInferenceEndpointChange={onInferenceEndpointChange} - inferenceEndpointError={inferenceEndpointError} - trainedModels={trainedModels} - onSaveInferenceEndpoint={onSaveInferenceCallback} - onFlyoutClose={onFlyoutClose} - isInferenceFlyoutVisible={isInferenceFlyoutVisible} - supportedNlpModels={docLinks.supportedNlpModels} - nlpImportModel={docLinks.nlpImportModel} - isCreateInferenceApiLoading={isCreateInferenceApiLoading} - setInferenceEndpointError={setInferenceEndpointError} - /> - ); -}; diff --git a/x-pack/plugins/search_inference_endpoints/public/hooks/use_trained_model_page_url.tsx b/x-pack/plugins/search_inference_endpoints/public/hooks/use_trained_model_page_url.tsx new file mode 100644 index 0000000000000..63e64c5ffcbdd --- /dev/null +++ b/x-pack/plugins/search_inference_endpoints/public/hooks/use_trained_model_page_url.tsx @@ -0,0 +1,30 @@ +/* + * 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 { useEffect, useState } from 'react'; +import { useKibana } from './use_kibana'; + +export const useTrainedModelPageUrl = () => { + const { + services: { ml }, + } = useKibana(); + + const [trainedModelPageUrl, setTrainedModelPageUrl] = useState(undefined); + + useEffect(() => { + const fetchMlTrainedModelPageUrl = async () => { + const url = await ml?.locator?.getUrl({ + page: 'trained_models', + }); + setTrainedModelPageUrl(url); + }; + + fetchMlTrainedModelPageUrl(); + }, [ml]); + + return trainedModelPageUrl; +}; diff --git a/x-pack/plugins/search_inference_endpoints/tsconfig.json b/x-pack/plugins/search_inference_endpoints/tsconfig.json index a61af6c752250..c2693432fc885 100644 --- a/x-pack/plugins/search_inference_endpoints/tsconfig.json +++ b/x-pack/plugins/search_inference_endpoints/tsconfig.json @@ -16,7 +16,6 @@ "@kbn/i18n", "@kbn/i18n-react", "@kbn/kibana-react-plugin", - "@kbn/inference_integration_flyout", "@kbn/ml-plugin", "@kbn/ml-trained-models-utils", "@kbn/shared-ux-router",