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] Listing all categorization wizard checks #60502

Merged
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
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
80 changes: 80 additions & 0 deletions x-pack/plugins/ml/common/constants/categorization_job.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { i18n } from '@kbn/i18n';
import { VALIDATION_RESULT } from '../types/categories';

export const NUMBER_OF_CATEGORY_EXAMPLES = 5;
export const CATEGORY_EXAMPLES_SAMPLE_SIZE = 1000;
export const CATEGORY_EXAMPLES_WARNING_LIMIT = 0.75;
export const CATEGORY_EXAMPLES_ERROR_LIMIT = 0.02;

export const VALID_TOKEN_COUNT = 3;
export const MEDIAN_LINE_LENGTH_LIMIT = 400;
export const NULL_COUNT_PERCENT_LIMIT = 0.75;

export enum CATEGORY_EXAMPLES_VALIDATION_STATUS {
VALID = 'valid',
PARTIALLY_VALID = 'partially_valid',
INVALID = 'invalid',
}

export const VALIDATION_CHECK_DESCRIPTION = {
[VALIDATION_RESULT.NO_EXAMPLES]: i18n.translate(
'xpack.ml.models.jobService.categorization.messages.validNoDataFound',
{
defaultMessage: 'Examples were successfully loaded.',
}
),
[VALIDATION_RESULT.FAILED_TO_TOKENIZE]: i18n.translate(
'xpack.ml.models.jobService.categorization.messages.validFailureToGetTokens',
{
defaultMessage: 'The examples loaded were tokenized successfully.',
}
),
[VALIDATION_RESULT.TOKEN_COUNT]: i18n.translate(
'xpack.ml.models.jobService.categorization.messages.validTokenLength',
{
defaultMessage:
'More than {tokenCount} tokens per example were found in over {percentage}% of the examples loaded.',
values: {
percentage: Math.floor(CATEGORY_EXAMPLES_WARNING_LIMIT * 100),
tokenCount: VALID_TOKEN_COUNT,
},
}
),
[VALIDATION_RESULT.MEDIAN_LINE_LENGTH]: i18n.translate(
'xpack.ml.models.jobService.categorization.messages.validMedianLineLength',
{
defaultMessage:
'The median line length of the examples loaded was less than {medianCharCount} characters.',
values: {
medianCharCount: MEDIAN_LINE_LENGTH_LIMIT,
},
}
),
[VALIDATION_RESULT.NULL_VALUES]: i18n.translate(
'xpack.ml.models.jobService.categorization.messages.validNullValues',
{
defaultMessage: 'Less than {percentage}% of the examples loaded were null.',
values: {
percentage: Math.floor(100 - NULL_COUNT_PERCENT_LIMIT * 100),
},
}
),
[VALIDATION_RESULT.TOO_MANY_TOKENS]: i18n.translate(
'xpack.ml.models.jobService.categorization.messages.validTooManyTokens',
{
defaultMessage: 'Less than 10000 tokens were found in total in the examples loaded.',
}
),
[VALIDATION_RESULT.INSUFFICIENT_PRIVILEGES]: i18n.translate(
'xpack.ml.models.jobService.categorization.messages.validUserPrivileges',
{
defaultMessage: 'The user has sufficient privileges to perform the checks.',
}
),
};
12 changes: 0 additions & 12 deletions x-pack/plugins/ml/common/constants/new_job.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,3 @@ export const DEFAULT_RARE_BUCKET_SPAN = '1h';
export const DEFAULT_QUERY_DELAY = '60s';

export const SHARED_RESULTS_INDEX_NAME = 'shared';

// Categorization
export const NUMBER_OF_CATEGORY_EXAMPLES = 5;
export const CATEGORY_EXAMPLES_SAMPLE_SIZE = 1000;
export const CATEGORY_EXAMPLES_WARNING_LIMIT = 0.75;
export const CATEGORY_EXAMPLES_ERROR_LIMIT = 0.02;

export enum CATEGORY_EXAMPLES_VALIDATION_STATUS {
VALID = 'valid',
PARTIALLY_VALID = 'partially_valid',
INVALID = 'invalid',
}
8 changes: 4 additions & 4 deletions x-pack/plugins/ml/common/types/categories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { CATEGORY_EXAMPLES_VALIDATION_STATUS } from '../constants/new_job';
import { CATEGORY_EXAMPLES_VALIDATION_STATUS } from '../constants/categorization_job';

export type CategoryId = number;

Expand Down Expand Up @@ -39,12 +39,12 @@ export interface CategoryFieldExample {
}

export enum VALIDATION_RESULT {
NO_EXAMPLES,
FAILED_TO_TOKENIZE,
TOO_MANY_TOKENS,
TOKEN_COUNT,
MEDIAN_LINE_LENGTH,
NULL_VALUES,
NO_EXAMPLES,
TOO_MANY_TOKENS,
FAILED_TO_TOKENIZE,
INSUFFICIENT_PRIVILEGES,
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ import {
CREATED_BY_LABEL,
DEFAULT_BUCKET_SPAN,
DEFAULT_RARE_BUCKET_SPAN,
CATEGORY_EXAMPLES_VALIDATION_STATUS,
} from '../../../../../../common/constants/new_job';
import { CATEGORY_EXAMPLES_VALIDATION_STATUS } from '../../../../../../common/constants/categorization_job';
import { ML_JOB_AGGREGATION } from '../../../../../../common/constants/aggregation_types';
import {
CategorizationAnalyzer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { JobCreator, JobCreatorType, isCategorizationJobCreator } from '../job_c
import { populateValidationMessages, checkForExistingJobAndGroupIds } from './util';
import { ExistingJobsAndGroups } from '../../../../services/job_service';
import { cardinalityValidator, CardinalityValidatorResult } from './validators';
import { CATEGORY_EXAMPLES_VALIDATION_STATUS } from '../../../../../../common/constants/new_job';
import { CATEGORY_EXAMPLES_VALIDATION_STATUS } from '../../../../../../common/constants/categorization_job';

// delay start of validation to allow the user to make changes
// e.g. if they are typing in a new value, try not to validate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { ml } from '../../../../services/ml_api_service';
import {
NUMBER_OF_CATEGORY_EXAMPLES,
CATEGORY_EXAMPLES_VALIDATION_STATUS,
} from '../../../../../../common/constants/new_job';
} from '../../../../../../common/constants/categorization_job';

export class CategorizationExamplesLoader {
private _jobCreator: CategorizationJobCreator;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,17 @@
*/

import React, { FC, Fragment } from 'react';
import { i18n } from '@kbn/i18n';
import { EuiAccordion, EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui';
import { CalendarsSelection } from './components/calendars';
import { CustomUrlsSelection } from './components/custom_urls';

const ButtonContent = <Fragment>Additional settings</Fragment>;
const buttonContent = i18n.translate(
'xpack.ml.newJob.wizard.jobDetailsStep.additionalSectionButton',
{
defaultMessage: 'Additional settings',
}
);

interface Props {
additionalExpanded: boolean;
Expand All @@ -22,7 +28,7 @@ export const AdditionalSection: FC<Props> = ({ additionalExpanded, setAdditional
<EuiSpacer />
<EuiAccordion
id="advanced-section"
buttonContent={ButtonContent}
buttonContent={buttonContent}
onToggle={setAdditionalExpanded}
initialIsOpen={additionalExpanded}
data-test-subj="mlJobWizardToggleAdditionalSettingsSection"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { ModelMemoryLimitInput } from '../../../common/model_memory_limit';
import { JobCreatorContext } from '../../../job_creator_context';
import { JOB_TYPE } from '../../../../../../../../../common/constants/new_job';

const ButtonContent = i18n.translate(
const buttonContent = i18n.translate(
'xpack.ml.newJob.wizard.jobDetailsStep.advancedSectionButton',
{
defaultMessage: 'Advanced',
Expand Down Expand Up @@ -55,7 +55,7 @@ export const AdvancedSection: FC<Props> = ({ advancedExpanded, setAdvancedExpand
<EuiSpacer size="xl" />
<EuiAccordion
id="advanced-section"
buttonContent={ButtonContent}
buttonContent={buttonContent}
onToggle={setAdvancedExpanded}
initialIsOpen={advancedExpanded}
data-test-subj="mlJobWizardToggleAdvancedSection"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,14 @@
*/

import React, { FC } from 'react';
import { EuiCallOut, EuiSpacer, EuiCallOutProps } from '@elastic/eui';
import {
EuiCallOut,
EuiSpacer,
EuiCallOutProps,
EuiAccordion,
EuiListGroup,
EuiListGroupItemProps,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';

Expand All @@ -14,14 +21,25 @@ import {
FieldExampleCheck,
} from '../../../../../../../../../common/types/categories';
import { EditCategorizationAnalyzerFlyout } from '../../../common/edit_categorization_analyzer_flyout';
import { CATEGORY_EXAMPLES_VALIDATION_STATUS } from '../../../../../../../../../common/constants/new_job';
import {
CATEGORY_EXAMPLES_VALIDATION_STATUS,
VALIDATION_CHECK_DESCRIPTION,
} from '../../../../../../../../../common/constants/categorization_job';
import { VALIDATION_RESULT } from '../../../../../../../../../common/types/categories';

interface Props {
validationChecks: FieldExampleCheck[];
overallValidStatus: CATEGORY_EXAMPLES_VALIDATION_STATUS;
categorizationAnalyzer: CategorizationAnalyzer;
}

const allChecksButtonContent = i18n.translate(
'xpack.ml.newJob.wizard.jobDetailsStep.allChecksButton',
{
defaultMessage: 'View all checks performed',
}
);

export const ExamplesValidCallout: FC<Props> = ({
overallValidStatus,
validationChecks,
Expand Down Expand Up @@ -66,6 +84,10 @@ export const ExamplesValidCallout: FC<Props> = ({
))}
<EuiSpacer size="s" />
{analyzerUsed}
<EuiSpacer size="s" />
<EuiAccordion id="all-checks" buttonContent={allChecksButtonContent}>
<AllValidationChecks validationChecks={validationChecks} />
</EuiAccordion>
</EuiCallOut>
);
};
Expand Down Expand Up @@ -96,3 +118,28 @@ const AnalyzerUsed: FC<{ categorizationAnalyzer: CategorizationAnalyzer }> = ({
</>
);
};

const AllValidationChecks: FC<{ validationChecks: FieldExampleCheck[] }> = ({
validationChecks,
}) => {
const list: EuiListGroupItemProps[] = Object.keys(VALIDATION_CHECK_DESCRIPTION).map((k, i) => {
peteharverson marked this conversation as resolved.
Show resolved Hide resolved
const failedCheck = validationChecks.find(vc => vc.id === i);
if (
failedCheck !== undefined &&
failedCheck?.valid !== CATEGORY_EXAMPLES_VALIDATION_STATUS.VALID
) {
return {
iconType: 'cross',
label: failedCheck.message,
size: 's',
};
}
return {
iconType: 'check',
label: VALIDATION_CHECK_DESCRIPTION[i as VALIDATION_RESULT],
size: 's',
};
});

return <EuiListGroup listItems={list} maxWidth={false} />;
};
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
CategoryFieldExample,
FieldExampleCheck,
} from '../../../../../../../../../common/types/categories';
import { CATEGORY_EXAMPLES_VALIDATION_STATUS } from '../../../../../../../../../common/constants/new_job';
import { CATEGORY_EXAMPLES_VALIDATION_STATUS } from '../../../../../../../../../common/constants/categorization_job';
import { LoadingWrapper } from '../../../charts/loading_wrapper';

interface Props {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { JobCreatorContext } from '../../../job_creator_context';
import { CategorizationJobCreator } from '../../../../../common/job_creator';
import { Results } from '../../../../../common/results_loader';
import { ml } from '../../../../../../../services/ml_api_service';
import { NUMBER_OF_CATEGORY_EXAMPLES } from '../../../../../../../../../common/constants/new_job';
import { NUMBER_OF_CATEGORY_EXAMPLES } from '../../../../../../../../../common/constants/categorization_job';

export const TopCategories: FC = () => {
const { jobCreator: jc, resultsLoader } = useContext(JobCreatorContext);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
CategoryFieldExample,
FieldExampleCheck,
} from '../../../../common/types/categories';
import { CATEGORY_EXAMPLES_VALIDATION_STATUS } from '../../../../common/constants/new_job';
import { CATEGORY_EXAMPLES_VALIDATION_STATUS } from '../../../../common/constants/categorization_job';
import { Category } from '../../../../common/types/categories';

export const jobs = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import { chunk } from 'lodash';
import { SearchResponse } from 'elasticsearch';
import { CATEGORY_EXAMPLES_SAMPLE_SIZE } from '../../../../../common/constants/new_job';
import { CATEGORY_EXAMPLES_SAMPLE_SIZE } from '../../../../../common/constants/categorization_job';
import {
Token,
CategorizationAnalyzer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,20 @@

import { i18n } from '@kbn/i18n';
import {
VALID_TOKEN_COUNT,
MEDIAN_LINE_LENGTH_LIMIT,
NULL_COUNT_PERCENT_LIMIT,
CATEGORY_EXAMPLES_VALIDATION_STATUS,
CATEGORY_EXAMPLES_ERROR_LIMIT,
CATEGORY_EXAMPLES_WARNING_LIMIT,
} from '../../../../../common/constants/new_job';
} from '../../../../../common/constants/categorization_job';
import {
FieldExampleCheck,
CategoryFieldExample,
VALIDATION_RESULT,
} from '../../../../../common/types/categories';
import { getMedianStringLength } from '../../../../../common/util/string_utils';

const VALID_TOKEN_COUNT = 3;
const MEDIAN_LINE_LENGTH_LIMIT = 400;
const NULL_COUNT_PERCENT_LIMIT = 0.75;

export class ValidationResults {
private _results: FieldExampleCheck[] = [];

Expand Down Expand Up @@ -187,7 +186,6 @@ export class ValidationResults {
valid: CATEGORY_EXAMPLES_VALIDATION_STATUS.PARTIALLY_VALID,
message,
});
return;
}
}

Expand Down
Loading