mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
# Backport This will backport the following commits from `main` to `8.6`: - [[Enterprise Search][ML Inference] UX improvements (#145305)](https://github.com/elastic/kibana/pull/145305) <!--- Backport version: 8.9.7 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) <!--BACKPORT [{"author":{"name":"Rodney Norris","email":"rodney.norris@elastic.co"},"sourceCommit":{"committedDate":"2022-11-21T17:42:56Z","message":"[Enterprise Search][ML Inference] UX improvements (#145305)\n\n## Summary\r\n\r\n- [x] Drop subtext from \"Ingestion error logs\" card\r\n- [x] Update no items copy for Ingestion history table, align with\r\nerrors no items message\r\n- [x] Add to complete name help text \"This will create a pipeline named\r\n{complete name}\"\r\n- [x] Capitalize \"Space\" in \"This model isn't available in the space\"\r\nmessage\r\n- [x] Re-use \"This model isn't available in the space\" message for model\r\nselect display when re-using a pipeline with a redacted model.\r\n- [x] Add right padding to add inference modal back button, going back\r\nfrom review to test it is highlighted and ends at the `k` of `Back`\r\n- [x] Rename \"Destination field\" to \"Target field\" to align with\r\npipelines UI\r\n- [x] Update help text for Target field to call-out first class field\r\nwill be created\r\nSomething like: \"This names the field that holds the commonly searched\r\nvalue and names the subfield used to contain the complete processor\r\nresult. {{Line break}} Learn more (link to docs - to the guide when\r\navailable)\"\r\n- [x] Existing or New select value not retained when leaving configure\r\nstep and going back\r\n- [x] Removed inference history footer as we do not have a good doc to\r\nlink to currently.\r\n\r\n### Screenshots\r\nPipelines Screen\r\n\r\n\r\nAdd Inference Modal\r\n\r\n\r\nAdd inference pipeline modal Back button padding\r\n\r\n","sha":"acb4db605a61cd089c736946ce8fc0048775a1ad","branchLabelMapping":{"^v8.7.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Team:EnterpriseSearch","v8.6.0","v8.7.0"],"number":145305,"url":"https://github.com/elastic/kibana/pull/145305","mergeCommit":{"message":"[Enterprise Search][ML Inference] UX improvements (#145305)\n\n## Summary\r\n\r\n- [x] Drop subtext from \"Ingestion error logs\" card\r\n- [x] Update no items copy for Ingestion history table, align with\r\nerrors no items message\r\n- [x] Add to complete name help text \"This will create a pipeline named\r\n{complete name}\"\r\n- [x] Capitalize \"Space\" in \"This model isn't available in the space\"\r\nmessage\r\n- [x] Re-use \"This model isn't available in the space\" message for model\r\nselect display when re-using a pipeline with a redacted model.\r\n- [x] Add right padding to add inference modal back button, going back\r\nfrom review to test it is highlighted and ends at the `k` of `Back`\r\n- [x] Rename \"Destination field\" to \"Target field\" to align with\r\npipelines UI\r\n- [x] Update help text for Target field to call-out first class field\r\nwill be created\r\nSomething like: \"This names the field that holds the commonly searched\r\nvalue and names the subfield used to contain the complete processor\r\nresult. {{Line break}} Learn more (link to docs - to the guide when\r\navailable)\"\r\n- [x] Existing or New select value not retained when leaving configure\r\nstep and going back\r\n- [x] Removed inference history footer as we do not have a good doc to\r\nlink to currently.\r\n\r\n### Screenshots\r\nPipelines Screen\r\n\r\n\r\nAdd Inference Modal\r\n\r\n\r\nAdd inference pipeline modal Back button padding\r\n\r\n","sha":"acb4db605a61cd089c736946ce8fc0048775a1ad"}},"sourceBranch":"main","suggestedTargetBranches":["8.6"],"targetPullRequestStates":[{"branch":"8.6","label":"v8.6.0","labelRegex":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v8.7.0","labelRegex":"^v8.7.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/145305","number":145305,"mergeCommit":{"message":"[Enterprise Search][ML Inference] UX improvements (#145305)\n\n## Summary\r\n\r\n- [x] Drop subtext from \"Ingestion error logs\" card\r\n- [x] Update no items copy for Ingestion history table, align with\r\nerrors no items message\r\n- [x] Add to complete name help text \"This will create a pipeline named\r\n{complete name}\"\r\n- [x] Capitalize \"Space\" in \"This model isn't available in the space\"\r\nmessage\r\n- [x] Re-use \"This model isn't available in the space\" message for model\r\nselect display when re-using a pipeline with a redacted model.\r\n- [x] Add right padding to add inference modal back button, going back\r\nfrom review to test it is highlighted and ends at the `k` of `Back`\r\n- [x] Rename \"Destination field\" to \"Target field\" to align with\r\npipelines UI\r\n- [x] Update help text for Target field to call-out first class field\r\nwill be created\r\nSomething like: \"This names the field that holds the commonly searched\r\nvalue and names the subfield used to contain the complete processor\r\nresult. {{Line break}} Learn more (link to docs - to the guide when\r\navailable)\"\r\n- [x] Existing or New select value not retained when leaving configure\r\nstep and going back\r\n- [x] Removed inference history footer as we do not have a good doc to\r\nlink to currently.\r\n\r\n### Screenshots\r\nPipelines Screen\r\n\r\n\r\nAdd Inference Modal\r\n\r\n\r\nAdd inference pipeline modal Back button padding\r\n\r\n","sha":"acb4db605a61cd089c736946ce8fc0048775a1ad"}}]}] BACKPORT--> Co-authored-by: Rodney Norris <rodney.norris@elastic.co>
This commit is contained in:
parent
e1c4607e48
commit
22c00575cc
8 changed files with 142 additions and 58 deletions
|
@ -31,7 +31,7 @@ export const InferenceErrors: React.FC = () => {
|
|||
dataType: 'date',
|
||||
field: 'timestamp',
|
||||
name: i18n.translate(
|
||||
'xpack.enterpriseSearch.content.indices.pipelines.tabs.pipelineLogs.tableColumn.timestamp',
|
||||
'xpack.enterpriseSearch.content.indices.pipelines.tabs.pipelineInferenceLogs.tableColumn.timestamp',
|
||||
{ defaultMessage: 'Timestamp' }
|
||||
),
|
||||
},
|
||||
|
@ -39,8 +39,8 @@ export const InferenceErrors: React.FC = () => {
|
|||
dataType: 'string',
|
||||
field: 'message',
|
||||
name: i18n.translate(
|
||||
'xpack.enterpriseSearch.content.indices.pipelines.tabs.pipelineLogs.tableColumn.message',
|
||||
{ defaultMessage: 'Inference error' }
|
||||
'xpack.enterpriseSearch.content.indices.pipelines.tabs.pipelineInferenceLogs.tableColumn.message',
|
||||
{ defaultMessage: 'Error message' }
|
||||
),
|
||||
textOnly: true,
|
||||
},
|
||||
|
@ -48,7 +48,7 @@ export const InferenceErrors: React.FC = () => {
|
|||
dataType: 'number',
|
||||
field: 'doc_count',
|
||||
name: i18n.translate(
|
||||
'xpack.enterpriseSearch.content.indices.pipelines.tabs.pipelineLogs.tableColumn.docCount',
|
||||
'xpack.enterpriseSearch.content.indices.pipelines.tabs.pipelineInferenceLogs.tableColumn.docCount',
|
||||
{ defaultMessage: 'Approx. document count' }
|
||||
),
|
||||
},
|
||||
|
@ -63,15 +63,11 @@ export const InferenceErrors: React.FC = () => {
|
|||
title={
|
||||
<h2>
|
||||
{i18n.translate(
|
||||
'xpack.enterpriseSearch.content.indices.pipelines.tabs.pipelineLogs.title',
|
||||
{ defaultMessage: 'Ingestion logs' }
|
||||
'xpack.enterpriseSearch.content.indices.pipelines.tabs.pipelineInferenceLogs.title',
|
||||
{ defaultMessage: 'Inference errors' }
|
||||
)}
|
||||
</h2>
|
||||
}
|
||||
subtitle={i18n.translate(
|
||||
'xpack.enterpriseSearch.content.indices.pipelines.tabs.pipelineLogs.subtitle',
|
||||
{ defaultMessage: 'Errors and dropped data failures' }
|
||||
)}
|
||||
>
|
||||
{isLoading ? (
|
||||
<EuiLoadingSpinner />
|
||||
|
@ -82,7 +78,7 @@ export const InferenceErrors: React.FC = () => {
|
|||
items={inferenceErrors}
|
||||
rowHeader="message"
|
||||
noItemsMessage={i18n.translate(
|
||||
'xpack.enterpriseSearch.content.indices.pipelines.tabs.pipelineLogs.emptyMessage',
|
||||
'xpack.enterpriseSearch.content.indices.pipelines.tabs.pipelineInferenceLogs.emptyMessage',
|
||||
{ defaultMessage: 'This index has no inference errors' }
|
||||
)}
|
||||
/>
|
||||
|
|
|
@ -9,13 +9,7 @@ import React, { useEffect } from 'react';
|
|||
|
||||
import { useActions, useValues } from 'kea';
|
||||
|
||||
import {
|
||||
EuiBasicTable,
|
||||
EuiBasicTableColumn,
|
||||
EuiLink,
|
||||
EuiSpacer,
|
||||
EuiLoadingSpinner,
|
||||
} from '@elastic/eui';
|
||||
import { EuiBasicTable, EuiBasicTableColumn, EuiSpacer, EuiLoadingSpinner } from '@elastic/eui';
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
|
@ -71,17 +65,6 @@ export const InferenceHistory: React.FC = () => {
|
|||
'The following inference processors were found in the _ingest.processors field of documents on this index.',
|
||||
}
|
||||
)}
|
||||
footerDocLink={
|
||||
// TODO: insert real doc link
|
||||
<EuiLink href="#" target="_blank" color="subdued">
|
||||
{i18n.translate(
|
||||
'xpack.enterpriseSearch.content.indices.pipelines.tabs.inferenceHistory.docLink',
|
||||
{
|
||||
defaultMessage: 'Learn more about inference history',
|
||||
}
|
||||
)}
|
||||
</EuiLink>
|
||||
}
|
||||
>
|
||||
{isLoading ? (
|
||||
<EuiLoadingSpinner />
|
||||
|
@ -90,6 +73,10 @@ export const InferenceHistory: React.FC = () => {
|
|||
columns={historyColumns}
|
||||
items={inferenceHistory ?? []}
|
||||
rowHeader="pipeline"
|
||||
noItemsMessage={i18n.translate(
|
||||
'xpack.enterpriseSearch.content.indices.pipelines.tabs.inferenceHistory.emptyMessage',
|
||||
{ defaultMessage: 'This index has no inference history' }
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
</DataPanel>
|
||||
|
|
|
@ -15,4 +15,11 @@
|
|||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.enterpriseSearchInferencePipelineModalFooter {
|
||||
.euiButtonEmpty__content {
|
||||
padding-left: $euiSizeM;
|
||||
padding-right: $euiSizeM;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -215,7 +215,7 @@ export const ModalFooter: React.FC<
|
|||
break;
|
||||
}
|
||||
return (
|
||||
<EuiModalFooter>
|
||||
<EuiModalFooter className="enterpriseSearchInferencePipelineModalFooter">
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem grow={false}>
|
||||
{previousStep !== undefined ? (
|
||||
|
|
|
@ -33,6 +33,7 @@ import { IndexViewLogic } from '../../index_view_logic';
|
|||
import { EMPTY_PIPELINE_CONFIGURATION, MLInferenceLogic } from './ml_inference_logic';
|
||||
import { MlModelSelectOption } from './model_select_option';
|
||||
import { PipelineSelectOption } from './pipeline_select_option';
|
||||
import { TargetFieldHelpText } from './target_field_help_text';
|
||||
import { MODEL_REDACTED_VALUE, MODEL_SELECT_PLACEHOLDER } from './utils';
|
||||
|
||||
const MODEL_SELECT_PLACEHOLDER_VALUE = 'model_placeholder$$';
|
||||
|
@ -117,6 +118,7 @@ export const ConfigurePipeline: React.FC = () => {
|
|||
];
|
||||
|
||||
const inputsDisabled = configuration.existingPipeline !== false;
|
||||
const selectedModel = supportedMLModels.find((model) => model.model_id === modelID);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -173,6 +175,7 @@ export const ConfigurePipeline: React.FC = () => {
|
|||
existingPipeline: e.target.value === 'true',
|
||||
})
|
||||
}
|
||||
value={configuration.existingPipeline?.toString() ?? ''}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
|
@ -209,12 +212,21 @@ export const ConfigurePipeline: React.FC = () => {
|
|||
)}
|
||||
helpText={
|
||||
!nameError &&
|
||||
i18n.translate(
|
||||
'xpack.enterpriseSearch.content.indices.pipelines.addInferencePipelineModal.steps.configure.name.helpText',
|
||||
{
|
||||
defaultMessage:
|
||||
'Pipeline names are unique within a deployment and can only contain letters, numbers, underscores, and hyphens.',
|
||||
}
|
||||
configuration.existingPipeline === false && (
|
||||
<EuiText size="xs">
|
||||
{i18n.translate(
|
||||
'xpack.enterpriseSearch.content.indices.pipelines.addInferencePipelineModal.steps.configure.name.helpText',
|
||||
{
|
||||
defaultMessage:
|
||||
'Pipeline names are unique within a deployment and can only contain letters, numbers, underscores, and hyphens. This will create a pipeline named {pipelineName}.',
|
||||
values: {
|
||||
pipelineName: `ml-inference-${
|
||||
pipelineName.length > 0 ? pipelineName : '<name>'
|
||||
}`,
|
||||
},
|
||||
}
|
||||
)}
|
||||
</EuiText>
|
||||
)
|
||||
}
|
||||
error={nameError && formErrors.pipelineName}
|
||||
|
@ -312,29 +324,26 @@ export const ConfigurePipeline: React.FC = () => {
|
|||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
label={i18n.translate(
|
||||
'xpack.enterpriseSearch.content.indices.pipelines.addInferencePipelineModal.steps.configure.destinationField.label',
|
||||
'xpack.enterpriseSearch.content.indices.pipelines.addInferencePipelineModal.steps.configure.targetField.label',
|
||||
{
|
||||
defaultMessage: 'Destination field (optional)',
|
||||
defaultMessage: 'Target field (optional)',
|
||||
}
|
||||
)}
|
||||
helpText={
|
||||
formErrors.destinationField === undefined &&
|
||||
i18n.translate(
|
||||
'xpack.enterpriseSearch.content.indices.pipelines.addInferencePipelineModal.steps.configure.destinationField.helpText',
|
||||
{
|
||||
defaultMessage:
|
||||
'Your field name will be prefixed with "ml.inference.", if not set it will be defaulted to "ml.inference.{pipelineName}"',
|
||||
values: {
|
||||
pipelineName,
|
||||
},
|
||||
}
|
||||
configuration.existingPipeline !== true && (
|
||||
<TargetFieldHelpText
|
||||
pipelineName={pipelineName}
|
||||
targetField={destinationField}
|
||||
model={selectedModel}
|
||||
/>
|
||||
)
|
||||
}
|
||||
error={formErrors.destinationField}
|
||||
isInvalid={formErrors.destinationField !== undefined}
|
||||
>
|
||||
<EuiFieldText
|
||||
data-telemetry-id={`entSearchContent-${ingestionMethod}-pipelines-configureInferencePipeline-destionationField`}
|
||||
data-telemetry-id={`entSearchContent-${ingestionMethod}-pipelines-configureInferencePipeline-targetField`}
|
||||
disabled={inputsDisabled}
|
||||
placeholder="custom_field_name"
|
||||
value={destinationField}
|
||||
|
|
|
@ -11,21 +11,14 @@ import { EuiBadge, EuiFlexGroup, EuiFlexItem, EuiIcon, EuiTextColor, EuiTitle }
|
|||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { MLInferencePipelineOption } from './ml_inference_logic';
|
||||
import { EXISTING_PIPELINE_DISABLED_MISSING_SOURCE_FIELD } from './utils';
|
||||
import { EXISTING_PIPELINE_DISABLED_MISSING_SOURCE_FIELD, MODEL_REDACTED_VALUE } from './utils';
|
||||
|
||||
export interface PipelineSelectOptionProps {
|
||||
pipeline: MLInferencePipelineOption;
|
||||
}
|
||||
|
||||
const REDACTED_MODE_ID_DISPLAY = i18n.translate(
|
||||
'xpack.enterpriseSearch.content.indices.pipelines.addInferencePipelineModal.steps.configure.existingPipeline.redactedModel',
|
||||
{
|
||||
defaultMessage: 'Trained model not available in this space',
|
||||
}
|
||||
);
|
||||
|
||||
export const PipelineSelectOption: React.FC<PipelineSelectOptionProps> = ({ pipeline }) => {
|
||||
const modelIdDisplay = pipeline.modelId.length > 0 ? pipeline.modelId : REDACTED_MODE_ID_DISPLAY;
|
||||
const modelIdDisplay = pipeline.modelId.length > 0 ? pipeline.modelId : MODEL_REDACTED_VALUE;
|
||||
return (
|
||||
<EuiFlexGroup direction="column" gutterSize="xs">
|
||||
{pipeline.disabled && (
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* 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 React from 'react';
|
||||
|
||||
import { EuiText } from '@elastic/eui';
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage, FormattedNumber } from '@kbn/i18n-react';
|
||||
|
||||
import {
|
||||
getMlModelTypesForModelConfig,
|
||||
SUPPORTED_PYTORCH_TASKS,
|
||||
} from '../../../../../../../common/ml_inference_pipeline';
|
||||
import { TrainedModel } from '../../../../api/ml_models/ml_trained_models_logic';
|
||||
import { getMLType } from '../../../shared/ml_inference/utils';
|
||||
|
||||
export interface TargetFieldHelpTextProps {
|
||||
model?: TrainedModel;
|
||||
pipelineName: string;
|
||||
targetField: string;
|
||||
}
|
||||
|
||||
export const TargetFieldHelpText: React.FC<TargetFieldHelpTextProps> = ({
|
||||
pipelineName,
|
||||
targetField,
|
||||
model,
|
||||
}) => {
|
||||
const baseText = targetField
|
||||
? i18n.translate(
|
||||
'xpack.enterpriseSearch.content.indices.pipelines.addInferencePipelineModal.steps.configure.targetField.helpText.userProvided',
|
||||
{
|
||||
defaultMessage:
|
||||
'This names the field that holds the inference result. It will be prefixed with "ml.inference", ml.inference.{targetField}',
|
||||
values: {
|
||||
targetField,
|
||||
},
|
||||
}
|
||||
)
|
||||
: i18n.translate(
|
||||
'xpack.enterpriseSearch.content.indices.pipelines.addInferencePipelineModal.steps.configure.targetField.helpText.default',
|
||||
{
|
||||
defaultMessage:
|
||||
'This names the field that holds the inference result. It will be prefixed with "ml.inference", if not set it will be defaulted to "ml.inference.{pipelineName}"',
|
||||
values: {
|
||||
pipelineName: pipelineName || '<Pipeline Name>',
|
||||
},
|
||||
}
|
||||
);
|
||||
const fieldName = targetField || pipelineName || '<Pipeline Name>';
|
||||
const modelType = model ? getMLType(getMlModelTypesForModelConfig(model)) : '';
|
||||
if (modelType === SUPPORTED_PYTORCH_TASKS.TEXT_CLASSIFICATION) {
|
||||
return (
|
||||
<EuiText size="xs">
|
||||
<p>{baseText}</p>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="xpack.enterpriseSearch.content.indices.pipelines.addInferencePipelineModal.steps.configure.targetField.helpText.textClassificationModel"
|
||||
defaultMessage='Additionally the predicted_value will be copied to "{fieldName}", if the prediction_probability is greater than {probabilityThreshold}'
|
||||
values={{
|
||||
fieldName,
|
||||
probabilityThreshold: <FormattedNumber value={0.5} />,
|
||||
}}
|
||||
/>
|
||||
</p>
|
||||
</EuiText>
|
||||
);
|
||||
}
|
||||
if (modelType === SUPPORTED_PYTORCH_TASKS.TEXT_EMBEDDING) {
|
||||
return (
|
||||
<EuiText size="xs">
|
||||
<p>{baseText}</p>
|
||||
<p>
|
||||
{i18n.translate(
|
||||
'xpack.enterpriseSearch.content.indices.pipelines.addInferencePipelineModal.steps.configure.targetField.helpText.textEmbeddingModel',
|
||||
{
|
||||
defaultMessage: 'Additionally the predicted_value will be copied to "{fieldName}"',
|
||||
values: {
|
||||
fieldName,
|
||||
},
|
||||
}
|
||||
)}
|
||||
</p>
|
||||
</EuiText>
|
||||
);
|
||||
}
|
||||
return <EuiText size="xs">{baseText}</EuiText>;
|
||||
};
|
|
@ -74,5 +74,5 @@ export const MODEL_SELECT_PLACEHOLDER = i18n.translate(
|
|||
|
||||
export const MODEL_REDACTED_VALUE = i18n.translate(
|
||||
'xpack.enterpriseSearch.content.indices.pipelines.addInferencePipelineModal.steps.configure.model.redactedValue',
|
||||
{ defaultMessage: 'Model is unavailable' }
|
||||
{ defaultMessage: "This model isn't available in the Kibana space" }
|
||||
);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue