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] Trained models list: disables 'View training data' action if data frame analytics job no longer exists #171061

Merged
merged 8 commits into from Nov 21, 2023
1 change: 1 addition & 0 deletions x-pack/plugins/ml/common/types/trained_models.ts
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;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this needs to be optional route param. We should always perform this check when retrieving the models as it's useful information.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated in 7c06abd


metadata?: {
analytics_config: DataFrameAnalyticsConfig;
Expand Down
Expand Up @@ -142,6 +142,7 @@ export function useModelActions({
icon: 'visTable',
type: 'icon',
available: (item) => !!item.metadata?.analytics_config?.id,
enabled: (item) => item.origin_job_exists === true,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a tooltip to show why the action is disabled.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added in 6d8a4e5
Happy to get suggestions on the copy to use.
image

onClick: async (item) => {
if (item.metadata?.analytics_config === undefined) return;

Expand Down
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 Expand Up @@ -214,6 +215,7 @@ export const ModelsList: FC<Props> = ({
const response = await trainedModelsApiService.getTrainedModels(undefined, {
with_pipelines: true,
with_indices: true,
with_origin_job_check: true,
});

const newItems: ModelItem[] = [];
Expand Down
Expand Up @@ -33,6 +33,7 @@ export interface InferenceQueryParams {
// Custom kibana endpoint query params
with_pipelines?: boolean;
with_indices?: boolean;
with_origin_job_check?: boolean;
include?: 'total_feature_importance' | 'feature_importance_baseline' | string;
}

Expand Down
Expand Up @@ -49,6 +49,7 @@ export const getInferenceQuerySchema = schema.object({
size: schema.maybe(schema.string()),
with_pipelines: schema.maybe(schema.string()),
with_indices: schema.maybe(schema.oneOf([schema.string(), schema.boolean()])),
with_origin_job_check: schema.maybe(schema.oneOf([schema.string(), schema.boolean()])),
include: schema.maybe(schema.string()),
});

Expand Down
21 changes: 19 additions & 2 deletions x-pack/plugins/ml/server/routes/trained_models.ts
Expand Up @@ -90,6 +90,7 @@ export function trainedModelsRoutes(
const {
with_pipelines: withPipelines,
with_indices: withIndicesRaw,
with_origin_job_check: withOriginJobCheck,
...getTrainedModelsRequestParams
} = request.query;

Expand Down Expand Up @@ -191,10 +192,26 @@ export function trainedModelsRoutes(
mlLog.debug(e);
}

const body = filterForEnabledFeatureModels(result, getEnabledFeatures());
try {
if (withOriginJobCheck) {
for (const model of result) {
jgowdyelastic marked this conversation as resolved.
Show resolved Hide resolved
if (typeof model.metadata?.analytics_config?.id === 'string') {
jgowdyelastic marked this conversation as resolved.
Show resolved Hide resolved
const jobExistsResult = await mlClient.getDataFrameAnalytics({
id: model.metadata?.analytics_config?.id,
size: 1,
});
model.origin_job_exists = jobExistsResult.count === 1;
}
}
}
} catch (e) {
// Swallow error to prevent blocking trained models result
jgowdyelastic marked this conversation as resolved.
Show resolved Hide resolved
peteharverson marked this conversation as resolved.
Show resolved Hide resolved
}

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

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