Skip to content

Commit

Permalink
[ML] Trained models list: disable 'View training data' action if data…
Browse files Browse the repository at this point in the history
… frame analytics job no longer exists (#171061)

## Summary

Fixes #167667, disabling the
'View training data' action for models in the Trained Models list if the
data frame analytics job which created the model no longer exists

Adds `origin_job_exists` property to trained models list model items.
This is set during the models fetch for models with associated data
frame analytics jobs.

### Checklist

Delete any items that are not applicable to this PR.

- [ ] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)
- [ ]
[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)
was added for features that require explanation or tutorials
- [ ] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
- [ ] Any UI touched in this PR is usable by keyboard only (learn more
about [keyboard accessibility](https://webaim.org/techniques/keyboard/))
- [ ] Any UI touched in this PR does not create any new axe failures
(run axe in browser:
[FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/),
[Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US))
- [ ] If a plugin configuration key changed, check if it needs to be
allowlisted in the cloud and added to the [docker
list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)
- [ ] This renders correctly on smaller devices using a responsive
layout. (You can test this [in your
browser](https://www.browserstack.com/guide/responsive-testing-on-local-server))
- [ ] This was checked for [cross-browser
compatibility](https://www.elastic.co/support/matrix#matrix_browsers)

---------

Co-authored-by: Kibana Machine <[email protected]>
  • Loading branch information
alvarezmelissa87 and kibanamachine authored Nov 21, 2023
1 parent 5256108 commit 39af788
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 11 deletions.
1 change: 1 addition & 0 deletions x-pack/plugins/ml/common/types/trained_models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ export type TrainedModelConfigResponse = estypes.MlTrainedModelConfig & {
* Associated pipelines. Extends response from the ES endpoint.
*/
pipelines?: Record<string, PipelineDefinition> | null;
origin_job_exists?: boolean;

metadata?: {
analytics_config: DataFrameAnalyticsConfig;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,18 +130,19 @@ export function useModelActions({
return useMemo(
() => [
{
name: i18n.translate('xpack.ml.trainedModels.modelsList.viewTrainingDataActionLabel', {
name: i18n.translate('xpack.ml.trainedModels.modelsList.viewTrainingDataNameActionLabel', {
defaultMessage: 'View training data',
}),
description: i18n.translate(
'xpack.ml.trainedModels.modelsList.viewTrainingDataActionLabel',
{
defaultMessage: 'View training data',
defaultMessage: 'Training data can be viewed when data frame analytics job exists.',
}
),
icon: 'visTable',
type: 'icon',
available: (item) => !!item.metadata?.analytics_config?.id,
enabled: (item) => item.origin_job_exists === true,
onClick: async (item) => {
if (item.metadata?.analytics_config === undefined) return;

Expand All @@ -164,7 +165,6 @@ export function useModelActions({

await navigateToUrl(url);
},
isPrimary: true,
},
{
name: i18n.translate('xpack.ml.inference.modelsList.analyticsMapActionLabel', {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ export type ModelItem = TrainedModelConfigResponse & {
type?: string[];
stats?: Stats & { deployment_stats: TrainedModelDeploymentStatsResponse[] };
pipelines?: ModelPipelines['pipelines'] | null;
origin_job_exists?: boolean;
deployment_ids: string[];
putModelConfig?: object;
state: ModelState;
Expand Down
43 changes: 35 additions & 8 deletions x-pack/plugins/ml/server/routes/trained_models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,19 @@ import {
createIngestPipelineSchema,
modelDownloadsQuery,
} from './schemas/inference_schema';
import type {
import {
PipelineDefinition,
TrainedModelConfigResponse,
type TrainedModelConfigResponse,
} from '../../common/types/trained_models';
import { mlLog } from '../lib/log';
import { forceQuerySchema } from './schemas/anomaly_detectors_schema';
import { modelsProvider } from '../models/model_management';

export const DEFAULT_TRAINED_MODELS_PAGE_SIZE = 10000;

export function filterForEnabledFeatureModels(
models: TrainedModelConfigResponse[] | estypes.MlTrainedModelConfig[],
enabledFeatures: MlFeatures
) {
export function filterForEnabledFeatureModels<
T extends TrainedModelConfigResponse | estypes.MlTrainedModelConfig
>(models: T[], enabledFeatures: MlFeatures) {
let filteredModels = models;
if (enabledFeatures.nlp === false) {
filteredModels = filteredModels.filter((m) => m.model_type === 'tree_ensemble');
Expand Down Expand Up @@ -191,10 +190,38 @@ export function trainedModelsRoutes(
mlLog.debug(e);
}

const body = filterForEnabledFeatureModels(result, getEnabledFeatures());
const filteredModels = filterForEnabledFeatureModels(result, getEnabledFeatures());

try {
const jobIds = filteredModels
.map((model) => {
const id = model.metadata?.analytics_config?.id;
if (id) {
return `${id}*`;
}
})
.filter((id) => id !== undefined);

if (jobIds.length) {
const { data_frame_analytics: jobs } = await mlClient.getDataFrameAnalytics({
id: jobIds.join(','),
allow_no_match: true,
});

filteredModels.forEach((model) => {
const dfaId = model?.metadata?.analytics_config?.id;
if (dfaId !== undefined) {
// if this is a dfa model, set origin_job_exists
model.origin_job_exists = jobs.find((job) => job.id === dfaId) !== undefined;
}
});
}
} catch (e) {
// Swallow error to prevent blocking trained models result
}

return response.ok({
body,
body: filteredModels,
});
} catch (e) {
return response.customError(wrapError(e));
Expand Down

0 comments on commit 39af788

Please sign in to comment.