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

[AI Connector] Migrates AI inference Connector to use a shared components from '@kbn/inference-endpoint-ui-common' #204885

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
1719e63
Adding package by extracting UI components from AI connector
Samiul-TheSoccerFan Dec 16, 2024
1c50825
Integrating packaged library into inference management and add connec…
Samiul-TheSoccerFan Dec 16, 2024
eab4a68
Addig test subjects, comments and unit tests
Samiul-TheSoccerFan Dec 18, 2024
dc0465b
Adding FTR tests for adding inference management ui
Samiul-TheSoccerFan Dec 18, 2024
4d16097
[CI] Auto-commit changed files from 'node scripts/generate codeowners'
kibanamachine Dec 18, 2024
8ed537a
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine Dec 18, 2024
93d448b
[AI Connector] Migrates AI inference Connector to use a shared compon…
YulNaumenko Dec 19, 2024
227c6a4
Merge remote-tracking branch 'upstream/main' into ai-connector-uses-s…
YulNaumenko Dec 30, 2024
6499af2
cleanup
YulNaumenko Dec 30, 2024
be6ea81
[CI] Auto-commit changed files from 'node scripts/yarn_deduplicate'
kibanamachine Dec 30, 2024
c201d79
removed labels
YulNaumenko Dec 30, 2024
f5f5a0b
Merge branch 'ai-connector-uses-shared-ui-components' of github.com:Y…
YulNaumenko Dec 30, 2024
96fcf4b
Merge branch 'main' into ai-connector-uses-shared-ui-components
YulNaumenko Jan 2, 2025
05c1685
fixed task type on edit
YulNaumenko Jan 2, 2025
011c7e3
Merge branch 'main' into ai-connector-uses-shared-ui-components
YulNaumenko Jan 3, 2025
19de8d9
Merge branch 'main' into ai-connector-uses-shared-ui-components
YulNaumenko Jan 6, 2025
1be7407
removed get providers from connectors and uses the common hook from t…
YulNaumenko Jan 7, 2025
37c2517
Merge branch 'main' into ai-connector-uses-shared-ui-components
YulNaumenko Jan 7, 2025
60df2fa
[CI] Auto-commit changed files from 'node scripts/notice'
kibanamachine Jan 7, 2025
cadcb90
[CI] Auto-commit changed files from 'node scripts/yarn_deduplicate'
kibanamachine Jan 7, 2025
747e41d
[CI] Auto-commit changed files from 'node scripts/styled_components_m…
kibanamachine Jan 7, 2025
8955abd
fixed build fail
YulNaumenko Jan 7, 2025
fce116f
Merge branch 'ai-connector-uses-shared-ui-components' of github.com:Y…
YulNaumenko Jan 7, 2025
f7b66f5
[CI] Auto-commit changed files from 'node scripts/notice'
kibanamachine Jan 7, 2025
713e039
translations fix
YulNaumenko Jan 7, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@
*/

export { InferenceServiceFormFields } from './src/components/inference_service_form_fields';
export { useProviders } from './src/hooks/use_providers';

export * from './src/types/types';
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ interface AdditionalOptionsFieldsProps {
onTaskTypeOptionsSelect: (taskType: string, provider?: string) => void;
selectedTaskType?: string;
taskTypeOptions: TaskTypeOption[];
isEdit?: boolean;
}

export const AdditionalOptionsFields: React.FC<AdditionalOptionsFieldsProps> = ({
Expand All @@ -61,6 +62,7 @@ export const AdditionalOptionsFields: React.FC<AdditionalOptionsFieldsProps> = (
selectedTaskType,
onSetProviderConfigEntry,
onTaskTypeOptionsSelect,
isEdit,
}) => {
const xsFontSize = useEuiFontSize('xs').fontSize;
const { euiTheme } = useEuiTheme();
Expand Down Expand Up @@ -106,7 +108,18 @@ export const AdditionalOptionsFields: React.FC<AdditionalOptionsFieldsProps> = (

return (
<EuiFormRow id="taskType" fullWidth isInvalid={isInvalid} error={errorMessage}>
{taskTypeOptions.length === 1 ? (
{isEdit ? (
<EuiButton
css={{
background: euiTheme.colors.disabled,
color: euiTheme.colors.lightestShade,
}}
data-test-subj="taskTypeSelectDisabled"
isDisabled
>
{config.taskType}
</EuiButton>
) : taskTypeOptions.length === 1 ? (
<EuiButton
css={{
background: euiTheme.colors.darkShade,
Expand Down Expand Up @@ -140,7 +153,11 @@ export const AdditionalOptionsFields: React.FC<AdditionalOptionsFieldsProps> = (
selectedTaskType,
config.taskType,
xsFontSize,
euiTheme.colors,
euiTheme.colors.textSubdued,
euiTheme.colors.disabled,
euiTheme.colors.lightestShade,
euiTheme.colors.darkShade,
isEdit,
taskTypeOptions,
onTaskTypeOptionsSelect,
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { Form, useForm } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib';
import { I18nProvider } from '@kbn/i18n-react';
import { httpServiceMock } from '@kbn/core-http-browser-mocks';
import { notificationServiceMock } from '@kbn/core-notifications-browser-mocks';

const providers = [
const mockProviders = [
{
service: 'hugging_face',
name: 'Hugging Face',
Expand Down Expand Up @@ -110,6 +112,15 @@ const providers = [
},
] as InferenceProvider[];

jest.mock('../hooks/use_providers', () => ({
useProviders: jest.fn(() => ({
data: mockProviders,
})),
}));

const httpMock = httpServiceMock.createStartContract();
const notificationsMock = notificationServiceMock.createStartContract();

const MockFormProvider = ({ children }: { children: React.ReactElement }) => {
const { form } = useForm();

Expand All @@ -124,7 +135,7 @@ describe('Inference Services', () => {
it('renders', () => {
render(
<MockFormProvider>
<InferenceServiceFormFields providers={providers} />
<InferenceServiceFormFields http={httpMock} toasts={notificationsMock.toasts} />
</MockFormProvider>
);

Expand All @@ -134,7 +145,7 @@ describe('Inference Services', () => {
it('renders Selectable', async () => {
render(
<MockFormProvider>
<InferenceServiceFormFields providers={providers} />
<InferenceServiceFormFields http={httpMock} toasts={notificationsMock.toasts} />
</MockFormProvider>
);

Expand All @@ -145,7 +156,7 @@ describe('Inference Services', () => {
it('renders selected provider fields - hugging_face', async () => {
render(
<MockFormProvider>
<InferenceServiceFormFields providers={providers} />
<InferenceServiceFormFields http={httpMock} toasts={notificationsMock.toasts} />
</MockFormProvider>
);

Expand All @@ -165,7 +176,7 @@ describe('Inference Services', () => {
it('re-renders fields when selected to anthropic from hugging_face', async () => {
render(
<MockFormProvider>
<InferenceServiceFormFields providers={providers} />
<InferenceServiceFormFields http={httpMock} toasts={notificationsMock.toasts} />
</MockFormProvider>
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ import {
import { FormattedMessage } from '@kbn/i18n-react';
import { ConnectorFormSchema } from '@kbn/triggers-actions-ui-plugin/public';

import { HttpSetup, IToasts } from '@kbn/core/public';
import * as LABELS from '../translations';
import { Config, ConfigEntryView, FieldType, InferenceProvider, Secrets } from '../types/types';
import { Config, ConfigEntryView, FieldType, Secrets } from '../types/types';
import { SERVICE_PROVIDERS } from './providers/render_service_provider/service_provider';
import { DEFAULT_TASK_TYPE, ServiceProviderKeys } from '../constants';
import { SelectableProvider } from './providers/selectable';
Expand All @@ -36,12 +37,20 @@ import { ConfigurationFormItems } from './configuration/configuration_form_items
import { AdditionalOptionsFields } from './additional_options_fields';
import { ProviderSecretHiddenField } from './hidden_fields/provider_secret_hidden_field';
import { ProviderConfigHiddenField } from './hidden_fields/provider_config_hidden_field';
import { useProviders } from '../hooks/use_providers';

interface InferenceServicesProps {
providers: InferenceProvider[];
http: HttpSetup;
toasts: IToasts;
isEdit?: boolean;
}

export const InferenceServiceFormFields: React.FC<InferenceServicesProps> = ({ providers }) => {
export const InferenceServiceFormFields: React.FC<InferenceServicesProps> = ({
http,
toasts,
isEdit,
}) => {
const { data: providers, isLoading } = useProviders(http, toasts);
const [isProviderPopoverOpen, setProviderPopoverOpen] = useState(false);
const [providerSchema, setProviderSchema] = useState<ConfigEntryView[]>([]);
const [taskTypeOptions, setTaskTypeOptions] = useState<TaskTypeOption[]>([]);
Expand Down Expand Up @@ -213,8 +222,9 @@ export const InferenceServiceFormFields: React.FC<InferenceServicesProps> = ({ p
const providerSuperSelect = useCallback(
(isInvalid: boolean) => (
<EuiFormControlLayout
clear={{ onClick: onClearProvider }}
clear={isEdit ? undefined : { onClick: onClearProvider }}
isDropdown
isDisabled={isEdit}
isInvalid={isInvalid}
fullWidth
icon={!config?.provider ? { type: 'sparkles', side: 'left' } : providerIcon}
Expand All @@ -223,6 +233,7 @@ export const InferenceServiceFormFields: React.FC<InferenceServicesProps> = ({ p
onClick={toggleProviderPopover}
data-test-subj="provider-select"
isInvalid={isInvalid}
disabled={isEdit}
onKeyDown={handleProviderKeyboardOpen}
value={config?.provider ? providerName : ''}
fullWidth
Expand All @@ -239,16 +250,31 @@ export const InferenceServiceFormFields: React.FC<InferenceServicesProps> = ({ p
</EuiFormControlLayout>
),
[
config?.provider,
handleProviderKeyboardOpen,
toggleProviderPopover,
isProviderPopoverOpen,
isEdit,
onClearProvider,
config?.provider,
providerIcon,
toggleProviderPopover,
handleProviderKeyboardOpen,
providerName,
isProviderPopoverOpen,
]
);

useEffect(() => {
if (config?.provider && isEdit) {
const newProvider = providers?.find((p) => p.service === config.provider);
// Update connector providerSchema
const newProviderSchema = Object.keys(newProvider?.configurations ?? {}).map((k) => ({
key: k,
isValid: true,
...newProvider?.configurations[k],
})) as ConfigEntryView[];

setProviderSchema(newProviderSchema);
}
}, [config?.provider, config?.taskType, isEdit, providers]);

useEffect(() => {
if (isSubmitting) {
validateFields(['config.providerConfig']);
Expand Down Expand Up @@ -291,7 +317,7 @@ export const InferenceServiceFormFields: React.FC<InferenceServicesProps> = ({ p
setRequiredProviderFormFields(existingConfiguration.filter((p) => p.required || p.sensitive));
}, [config?.providerConfig, providerSchema, secrets]);

return (
return !isLoading ? (
<>
<UseField
path="config.provider"
Expand Down Expand Up @@ -329,7 +355,7 @@ export const InferenceServiceFormFields: React.FC<InferenceServicesProps> = ({ p
className="rightArrowIcon"
>
<SelectableProvider
providers={providers}
providers={providers ?? []}
onClosePopover={closeProviderPopover}
onProviderChange={onProviderChange}
/>
Expand All @@ -355,6 +381,7 @@ export const InferenceServiceFormFields: React.FC<InferenceServicesProps> = ({ p
onTaskTypeOptionsSelect={onTaskTypeOptionsSelect}
taskTypeOptions={taskTypeOptions}
selectedTaskType={selectedTaskType}
isEdit={isEdit}
/>
<EuiSpacer size="m" />
<EuiHorizontalRule margin="xs" />
Expand All @@ -371,5 +398,5 @@ export const InferenceServiceFormFields: React.FC<InferenceServicesProps> = ({ p
</>
) : null}
</>
);
) : null;
};
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@

import type { HttpSetup } from '@kbn/core-http-browser';
import { useQuery } from '@tanstack/react-query';
import { FieldType, InferenceProvider } from '@kbn/inference-endpoint-ui-common';
import { KibanaServerError } from '@kbn/kibana-utils-plugin/common';
import { useKibana } from './use_kibana';
import * as i18n from './translations';
import { IToasts } from '@kbn/core/public';
import { FieldType, InferenceProvider } from '../..';
import * as i18n from '../translations';

const getProviders = (http: HttpSetup): InferenceProvider[] => {
return [
Expand Down Expand Up @@ -624,9 +624,7 @@ const getProviders = (http: HttpSetup): InferenceProvider[] => {
];
};

export const useProviders = () => {
const { services } = useKibana();
const toasts = services.notifications?.toasts;
export const useProviders = (http: HttpSetup, toasts: IToasts) => {
const onErrorFn = (error: { body: KibanaServerError }) => {
toasts?.addError(new Error(error.body.message), {
title: i18n.GET_PROVIDERS_FAILED,
Expand All @@ -635,7 +633,7 @@ export const useProviders = () => {
};

const query = useQuery(['user-profile'], {
queryFn: () => getProviders(services.http),
queryFn: () => getProviders(http),
staleTime: Infinity,
refetchOnWindowFocus: false,
onError: onErrorFn,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,10 @@ export const RE_ENTER_SECRETS = (label: string) => {
values: { label },
});
};

export const GET_PROVIDERS_FAILED = i18n.translate(
'xpack.inferenceEndpointUICommon.hooks.unableToFindProvidersQueryMessage',
{
defaultMessage: 'Unable to find providers',
}
);
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@
"@kbn/i18n-react",
"@kbn/search-connectors",
"@kbn/es-ui-shared-plugin",
"@kbn/triggers-actions-ui-plugin"
"@kbn/triggers-actions-ui-plugin",
"@kbn/core-http-browser",
"@kbn/kibana-utils-plugin",
"@kbn/core",
"@kbn/core-http-browser-mocks",
"@kbn/core-notifications-browser-mocks"
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -44983,35 +44983,22 @@
"xpack.stackConnectors.components.index.preconfiguredIndexHelpText": "Les documents sont indexés dans l'index {alertHistoryIndex}.",
"xpack.stackConnectors.components.index.resetDefaultIndexLabel": "Réinitialiser l'index par défaut",
"xpack.stackConnectors.components.index.selectMessageText": "Indexez les données dans Elasticsearch.",
"xpack.stackConnectors.components.inference.additionalOptionsLabel": "Options supplémentaires",
"xpack.stackConnectors.components.inference.bodyCodeEditorAriaLabel": "Éditeur de code",
"xpack.stackConnectors.components.inference.bodyFieldLabel": "Corps",
"xpack.stackConnectors.components.inference.completionInputLabel": "Entrée",
"xpack.stackConnectors.components.inference.completionInputTypeLabel": "Type d'entrée",
"xpack.stackConnectors.components.inference.config.optionalValue": "Facultatif",
"xpack.stackConnectors.components.inference.connectorTypeTitle": "Connecteur IA",
"xpack.stackConnectors.components.inference.copied.tooltip": "Copié !",
"xpack.stackConnectors.components.inference.copy.tooltip": "Copier dans le presse-papiers",
"xpack.stackConnectors.components.inference.copyLabel": "Copier",
"xpack.stackConnectors.components.inference.documentation": "Documentation de l'API d'inférence",
"xpack.stackConnectors.components.inference.error.requiredProviderText": "Le fournisseur est requis.",
"xpack.stackConnectors.components.inference.inferenceEndpointHelpLabel": "Les points de terminaison d'inférence fournissent une méthode simplifiée pour utiliser cette configuration, en particulier à partir de l'API",
"xpack.stackConnectors.components.inference.inferenceEndpointLabel": "Point de terminaison d'inférence",
"xpack.stackConnectors.components.inference.inferenceIdHelpLabel": "Cet identifiant ne peut pas être modifié une fois créé.",
"xpack.stackConnectors.components.inference.invalidActionText": "Nom d'action non valide.",
"xpack.stackConnectors.components.inference.providerFieldLabel": "Fournisseur",
"xpack.stackConnectors.components.inference.providerLabel": "Service",
"xpack.stackConnectors.components.inference.providerOptionalSettingsHelpLabel": "Configurer le fournisseur d'inférence. Ces paramètres sont des paramètres de fournisseur facultatifs.",
"xpack.stackConnectors.components.inference.providerOptionalSettingsLabel": "Paramètres de service",
"xpack.stackConnectors.components.inference.requiredGenericTextField": "{field} est obligatoire.",
"xpack.stackConnectors.components.inference.rerankQueryLabel": "Recherche",
"xpack.stackConnectors.components.inference.selectable.providerSearch": "Recherche",
"xpack.stackConnectors.components.inference.selectMessageText": "Envoyez des demandes aux fournisseurs d'IA tels qu'Amazon Bedrock, OpenAI et bien d'autres.",
"xpack.stackConnectors.components.inference.selectProvider": "Sélectionner un service",
"xpack.stackConnectors.components.inference.taskTypeDetailsLabel": "Paramètres des tâches",
"xpack.stackConnectors.components.inference.taskTypeFieldLabel": "Type de tâche",
"xpack.stackConnectors.components.inference.taskTypeHelpLabel": "Configurer la tâche d'inférence. Ces paramètres sont spécifiques au service et au modèle sélectionnés.",
"xpack.stackConnectors.components.inference.unableToFindProvidersQueryMessage": "Impossible de trouver des fournisseurs",
"xpack.stackConnectors.components.jira.apiTokenTextFieldLabel": "Token d'API",
"xpack.stackConnectors.components.jira.apiUrlTextFieldLabel": "URL",
"xpack.stackConnectors.components.jira.commentsTextAreaFieldLabel": "Commentaires supplémentaires",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44833,35 +44833,22 @@
"xpack.stackConnectors.components.index.preconfiguredIndexHelpText": "ドキュメントは{alertHistoryIndex}インデックスにインデックスされます。",
"xpack.stackConnectors.components.index.resetDefaultIndexLabel": "デフォルトのインデックスをリセット",
"xpack.stackConnectors.components.index.selectMessageText": "データを Elasticsearch にインデックスしてください。",
"xpack.stackConnectors.components.inference.additionalOptionsLabel": "その他のオプション",
"xpack.stackConnectors.components.inference.bodyCodeEditorAriaLabel": "コードエディター",
"xpack.stackConnectors.components.inference.bodyFieldLabel": "本文",
"xpack.stackConnectors.components.inference.completionInputLabel": "インプット",
"xpack.stackConnectors.components.inference.completionInputTypeLabel": "入力タイプ",
"xpack.stackConnectors.components.inference.config.optionalValue": "オプション",
"xpack.stackConnectors.components.inference.connectorTypeTitle": "AIコネクター",
"xpack.stackConnectors.components.inference.copied.tooltip": "コピー完了",
"xpack.stackConnectors.components.inference.copy.tooltip": "クリップボードにコピー",
"xpack.stackConnectors.components.inference.copyLabel": "コピー",
"xpack.stackConnectors.components.inference.documentation": "推論APIドキュメント",
"xpack.stackConnectors.components.inference.error.requiredProviderText": "プロバイダーは必須です。",
"xpack.stackConnectors.components.inference.inferenceEndpointHelpLabel": "推論エンドポイントは、特にAPIから、この構成を簡単に利用できる方法を提供します。",
"xpack.stackConnectors.components.inference.inferenceEndpointLabel": "推論エンドポイント",
"xpack.stackConnectors.components.inference.inferenceIdHelpLabel": "このIDは、作成すると、変更できません。",
"xpack.stackConnectors.components.inference.invalidActionText": "無効なアクション名です。",
"xpack.stackConnectors.components.inference.providerFieldLabel": "プロバイダー",
"xpack.stackConnectors.components.inference.providerLabel": "サービス",
"xpack.stackConnectors.components.inference.providerOptionalSettingsHelpLabel": "推論プロバイダーを構成します。これらの設定はオプションのプロバイダー設定です。",
"xpack.stackConnectors.components.inference.providerOptionalSettingsLabel": "サービス設定",
"xpack.stackConnectors.components.inference.requiredGenericTextField": "{field}は必須です。",
"xpack.stackConnectors.components.inference.rerankQueryLabel": "クエリー",
"xpack.stackConnectors.components.inference.selectable.providerSearch": "検索",
"xpack.stackConnectors.components.inference.selectMessageText": "Amazon Bedrock、OpenAIなどのAIプロバイダーに要求を送信します。",
"xpack.stackConnectors.components.inference.selectProvider": "サービスを選択",
"xpack.stackConnectors.components.inference.taskTypeDetailsLabel": "タスク設定",
"xpack.stackConnectors.components.inference.taskTypeFieldLabel": "タスクタイプ",
"xpack.stackConnectors.components.inference.taskTypeHelpLabel": "推論タスクを構成します。これらの設定は、選択したサービスおよびモデルに固有です。",
"xpack.stackConnectors.components.inference.unableToFindProvidersQueryMessage": "プロバイダーが見つかりません",
"xpack.stackConnectors.components.jira.apiTokenTextFieldLabel": "APIトークン",
"xpack.stackConnectors.components.jira.apiUrlTextFieldLabel": "URL",
"xpack.stackConnectors.components.jira.commentsTextAreaFieldLabel": "追加のコメント",
Expand Down
Loading
Loading