"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getDefaultTrainingFilterQuery = exports.defaultSearchQuery = exports.SEARCH_SIZE = exports.REGRESSION_STATS = exports.REFRESH_ANALYTICS_LIST_STATE = exports.EMPTY_STAT = void 0; exports.getEvalQueryBody = getEvalQueryBody; exports.getValuesFromResponse = getValuesFromResponse; exports.useRefreshAnalyticsList = exports.refreshAnalyticsList$ = exports.loadEvalData = exports.loadDocsCount = exports.isResultsSearchBoolQuery = exports.isRegressionEvaluateResponse = exports.isQueryStringQuery = exports.isClassificationEvaluateResponse = void 0; var _react = require("react"); var _rxjs = require("rxjs"); var _operators = require("rxjs/operators"); var _lodash = require("lodash"); var _mlErrorUtils = require("@kbn/ml-error-utils"); var _mlDataFrameAnalyticsUtils = require("@kbn/ml-data-frame-analytics-utils"); var _ml_api_service = require("../../services/ml_api_service"); /* * 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. */ const SEARCH_SIZE = 1000; exports.SEARCH_SIZE = SEARCH_SIZE; const defaultSearchQuery = { match_all: {} }; exports.defaultSearchQuery = defaultSearchQuery; const getDefaultTrainingFilterQuery = (resultsField, isTraining) => ({ bool: { minimum_should_match: 1, should: [{ match: { [`${resultsField}.is_training`]: isTraining } }] } }); exports.getDefaultTrainingFilterQuery = getDefaultTrainingFilterQuery; const isResultsSearchBoolQuery = arg => { if (arg === undefined) return false; const keys = Object.keys(arg); return keys.length === 1 && keys[0] === 'bool'; }; exports.isResultsSearchBoolQuery = isResultsSearchBoolQuery; const isQueryStringQuery = arg => { if (arg === undefined) return false; const keys = Object.keys(arg); return keys.length === 1 && keys[0] === 'query_string'; }; exports.isQueryStringQuery = isQueryStringQuery; const isRegressionEvaluateResponse = arg => { var _arg$regression, _arg$regression2; const keys = Object.keys(arg); return keys.length === 1 && keys[0] === _mlDataFrameAnalyticsUtils.ANALYSIS_CONFIG_TYPE.REGRESSION && (arg === null || arg === void 0 ? void 0 : (_arg$regression = arg.regression) === null || _arg$regression === void 0 ? void 0 : _arg$regression.mse) !== undefined && (arg === null || arg === void 0 ? void 0 : (_arg$regression2 = arg.regression) === null || _arg$regression2 === void 0 ? void 0 : _arg$regression2.r_squared) !== undefined; }; exports.isRegressionEvaluateResponse = isRegressionEvaluateResponse; const isClassificationEvaluateResponse = arg => { var _arg$classification, _arg$classification2; const keys = Object.keys(arg); return keys.length === 1 && keys[0] === _mlDataFrameAnalyticsUtils.ANALYSIS_CONFIG_TYPE.CLASSIFICATION && ((arg === null || arg === void 0 ? void 0 : (_arg$classification = arg.classification) === null || _arg$classification === void 0 ? void 0 : _arg$classification.multiclass_confusion_matrix) !== undefined || (arg === null || arg === void 0 ? void 0 : (_arg$classification2 = arg.classification) === null || _arg$classification2 === void 0 ? void 0 : _arg$classification2.auc_roc) !== undefined); }; exports.isClassificationEvaluateResponse = isClassificationEvaluateResponse; let REFRESH_ANALYTICS_LIST_STATE; exports.REFRESH_ANALYTICS_LIST_STATE = REFRESH_ANALYTICS_LIST_STATE; (function (REFRESH_ANALYTICS_LIST_STATE) { REFRESH_ANALYTICS_LIST_STATE["ERROR"] = "error"; REFRESH_ANALYTICS_LIST_STATE["IDLE"] = "idle"; REFRESH_ANALYTICS_LIST_STATE["LOADING"] = "loading"; REFRESH_ANALYTICS_LIST_STATE["REFRESH"] = "refresh"; })(REFRESH_ANALYTICS_LIST_STATE || (exports.REFRESH_ANALYTICS_LIST_STATE = REFRESH_ANALYTICS_LIST_STATE = {})); const refreshAnalyticsList$ = new _rxjs.BehaviorSubject(REFRESH_ANALYTICS_LIST_STATE.IDLE); exports.refreshAnalyticsList$ = refreshAnalyticsList$; const useRefreshAnalyticsList = (callback = {}) => { (0, _react.useEffect)(() => { const distinct$ = refreshAnalyticsList$.pipe((0, _operators.distinctUntilChanged)()); const subscriptions = []; if (typeof callback.onRefresh === 'function') { subscriptions.push(distinct$.pipe((0, _operators.filter)(state => state === REFRESH_ANALYTICS_LIST_STATE.REFRESH)).subscribe(() => { if (typeof callback.onRefresh === 'function') { callback.onRefresh(); } })); } if (typeof callback.isLoading === 'function') { subscriptions.push(distinct$.subscribe(state => typeof callback.isLoading === 'function' && callback.isLoading(state === REFRESH_ANALYTICS_LIST_STATE.LOADING))); } return () => { subscriptions.map(sub => sub.unsubscribe()); }; // eslint-disable-next-line react-hooks/exhaustive-deps }, [callback.onRefresh]); return { refresh: () => { // A refresh is followed immediately by setting the state to loading // to trigger data fetching and loading indicators in one go. refreshAnalyticsList$.next(REFRESH_ANALYTICS_LIST_STATE.REFRESH); refreshAnalyticsList$.next(REFRESH_ANALYTICS_LIST_STATE.LOADING); } }; }; exports.useRefreshAnalyticsList = useRefreshAnalyticsList; const DEFAULT_SIG_FIGS = 3; const EMPTY_STAT = '--'; exports.EMPTY_STAT = EMPTY_STAT; function getValuesFromResponse(response) { const results = { mse: EMPTY_STAT, msle: EMPTY_STAT, huber: EMPTY_STAT, r_squared: EMPTY_STAT }; if (response !== null && response !== void 0 && response.regression) { for (const statType in response.regression) { if (response.regression.hasOwnProperty(statType)) { var _response$regression; let currentStatValue = (_response$regression = response.regression[statType]) === null || _response$regression === void 0 ? void 0 : _response$regression.value; if (currentStatValue && Number.isFinite(currentStatValue)) { currentStatValue = Number(currentStatValue.toPrecision(DEFAULT_SIG_FIGS)); } results[statType] = currentStatValue; } } } return results; } function getEvalQueryBody({ resultsField, isTraining, searchQuery, ignoreDefaultQuery }) { let query; const trainingQuery = { term: { [`${resultsField}.is_training`]: { value: isTraining } } }; const searchQueryClone = (0, _lodash.cloneDeep)(searchQuery); if (isResultsSearchBoolQuery(searchQueryClone)) { if (searchQueryClone.bool.must === undefined) { searchQueryClone.bool.must = []; } if (isTraining !== undefined) { searchQueryClone.bool.must.push(trainingQuery); } query = searchQueryClone; } else if (isQueryStringQuery(searchQueryClone)) { query = { bool: { must: [searchQueryClone] } }; if (isTraining !== undefined) { query.bool.must.push(trainingQuery); } } else { // Not a bool or string query so we need to create it so can add the trainingQuery query = { bool: { must: isTraining !== undefined ? [trainingQuery] : [] } }; } return query; } let REGRESSION_STATS; exports.REGRESSION_STATS = REGRESSION_STATS; (function (REGRESSION_STATS) { REGRESSION_STATS["MSE"] = "mse"; REGRESSION_STATS["MSLE"] = "msle"; REGRESSION_STATS["R_SQUARED"] = "rSquared"; REGRESSION_STATS["HUBER"] = "huber"; })(REGRESSION_STATS || (exports.REGRESSION_STATS = REGRESSION_STATS = {})); const loadEvalData = async ({ isTraining, index, dependentVariable, resultsField, predictionFieldName, searchQuery, ignoreDefaultQuery, jobType, requiresKeyword, rocCurveClassName, includeMulticlassConfusionMatrix = true }) => { const results = { success: false, eval: null, error: null }; const defaultPredictionField = `${dependentVariable}_prediction`; let predictedField = `${resultsField}.${predictionFieldName ? predictionFieldName : defaultPredictionField}`; if (jobType === _mlDataFrameAnalyticsUtils.ANALYSIS_CONFIG_TYPE.CLASSIFICATION && requiresKeyword === true) { predictedField = `${predictedField}.keyword`; } const query = getEvalQueryBody({ resultsField, isTraining, searchQuery, ignoreDefaultQuery }); const metrics = { classification: { accuracy: {}, recall: {}, ...(includeMulticlassConfusionMatrix ? { multiclass_confusion_matrix: {} } : {}), ...(rocCurveClassName !== undefined ? { auc_roc: { include_curve: true, class_name: rocCurveClassName } } : {}) }, regression: { r_squared: {}, mse: {}, msle: {}, huber: {} } }; const config = { index, query, evaluation: { [jobType]: { actual_field: dependentVariable, predicted_field: predictedField, ...(jobType === _mlDataFrameAnalyticsUtils.ANALYSIS_CONFIG_TYPE.CLASSIFICATION ? { top_classes_field: `${resultsField}.top_classes` } : {}), metrics: metrics[jobType] } } }; try { const evalResult = await _ml_api_service.ml.dataFrameAnalytics.evaluateDataFrameAnalytics(config); results.success = true; results.eval = evalResult; return results; } catch (e) { results.error = (0, _mlErrorUtils.extractErrorMessage)(e); return results; } }; exports.loadEvalData = loadEvalData; const loadDocsCount = async ({ ignoreDefaultQuery = true, isTraining, searchQuery, resultsField, destIndex }) => { const query = getEvalQueryBody({ resultsField, isTraining, ignoreDefaultQuery, searchQuery }); try { const body = { track_total_hits: true, query }; const resp = await _ml_api_service.ml.esSearch({ index: destIndex, size: 0, body }); const docsCount = resp.hits.total && resp.hits.total.value; return { docsCount, success: docsCount !== undefined }; } catch (e) { return { docsCount: null, success: false }; } }; exports.loadDocsCount = loadDocsCount;