Skip to content

Commit b1f240c

Browse files
authored
Cache form across ML transform types (#678)
Signed-off-by: Tyler Ohlsen <ohltyler@amazon.com>
1 parent 47d59fe commit b1f240c

File tree

4 files changed

+108
-16
lines changed

4 files changed

+108
-16
lines changed

common/interfaces.ts

+4
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,10 @@ export type OutputMapEntry = InputMapEntry;
126126
export type InputMapFormValue = InputMapEntry[];
127127
export type OutputMapFormValue = OutputMapEntry[];
128128

129+
export type MapCache = {
130+
[idx: number]: Transform[];
131+
};
132+
129133
export type InputMapArrayFormValue = InputMapFormValue[];
130134
export type OutputMapArrayFormValue = OutputMapFormValue[];
131135

public/pages/workflow_detail/workflow_inputs/processor_inputs/ml_processor_inputs/model_inputs.tsx

+33-12
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,13 @@ import {
3131
IndexMappings,
3232
InputMapEntry,
3333
InputMapFormValue,
34+
Transform,
3435
TRANSFORM_TYPE,
3536
EMPTY_INPUT_MAP_ENTRY,
3637
WorkflowConfig,
3738
getCharacterLimitedString,
3839
INPUT_TRANSFORM_OPTIONS,
40+
MapCache,
3941
} from '../../../../../../common';
4042
import {
4143
TextField,
@@ -49,6 +51,7 @@ import {
4951
sanitizeJSONPath,
5052
} from '../../../../../utils';
5153
import { ConfigureExpressionModal, ConfigureTemplateModal } from './modals/';
54+
import { updateCache } from './utils';
5255

5356
interface ModelInputsProps {
5457
config: IProcessorConfig;
@@ -98,14 +101,6 @@ export function ModelInputs(props: ModelInputsProps) {
98101
ModelInterface | undefined
99102
>(undefined);
100103

101-
// various modal states
102-
const [templateModalIdx, setTemplateModalIdx] = useState<number | undefined>(
103-
undefined
104-
);
105-
const [expressionModalIdx, setExpressionModalIdx] = useState<
106-
number | undefined
107-
>(undefined);
108-
109104
// get the model interface based on the selected ID and list of known models
110105
useEffect(() => {
111106
if (!isEmpty(models)) {
@@ -116,6 +111,19 @@ export function ModelInputs(props: ModelInputsProps) {
116111
}
117112
}, [models, getIn(values, modelFieldPath)?.id]);
118113

114+
// various modal states
115+
const [templateModalIdx, setTemplateModalIdx] = useState<number | undefined>(
116+
undefined
117+
);
118+
const [expressionModalIdx, setExpressionModalIdx] = useState<
119+
number | undefined
120+
>(undefined);
121+
122+
// Temporarily cache any configured transformations for different transform types.
123+
// For example, if a user configures a prompt, swaps the transform
124+
// type to "Data field", and swaps back to "Prompt", the prompt will be persisted.
125+
const [inputMapCache, setInputMapCache] = useState<MapCache>({});
126+
119127
// persisting doc/query/index mapping fields to collect a list
120128
// of options to display in the dropdowns when configuring input / output maps
121129
const [docFields, setDocFields] = useState<{ label: string }[]>([]);
@@ -346,6 +354,7 @@ export function ModelInputs(props: ModelInputsProps) {
346354
<EuiFlexItem grow={TYPE_FLEX_RATIO}>
347355
<EuiFlexItem>
348356
<EuiCompressedSuperSelect
357+
fullWidth={true}
349358
disabled={false}
350359
options={INPUT_TRANSFORM_OPTIONS.map(
351360
(option) =>
@@ -381,20 +390,32 @@ export function ModelInputs(props: ModelInputsProps) {
381390
) || ''
382391
}
383392
onChange={(option) => {
393+
// before updating, cache any form values
394+
const updatedCache = updateCache(
395+
inputMapCache,
396+
mapEntry,
397+
idx
398+
);
384399
setFieldValue(
385400
`${inputMapFieldPath}.${idx}.value.transformType`,
386401
option
387402
);
388-
// If the transform type changes, clear any set value and/or nested vars,
389-
// as it will likely not make sense under other types/contexts.
403+
// Pre-populate with any cached values, if found
404+
const curCacheForOption = updatedCache[
405+
idx
406+
]?.find(
407+
(transform: Transform) =>
408+
transform.transformType === option
409+
);
390410
setFieldValue(
391411
`${inputMapFieldPath}.${idx}.value.value`,
392-
''
412+
curCacheForOption?.value || ''
393413
);
394414
setFieldValue(
395415
`${inputMapFieldPath}.${idx}.value.nestedVars`,
396-
[]
416+
curCacheForOption?.nestedVars || []
397417
);
418+
setInputMapCache(updatedCache);
398419
}}
399420
/>
400421
</EuiFlexItem>

public/pages/workflow_detail/workflow_inputs/processor_inputs/ml_processor_inputs/model_outputs.tsx

+25-4
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,13 @@ import {
3434
EMPTY_OUTPUT_MAP_ENTRY,
3535
ExpressionVar,
3636
OUTPUT_TRANSFORM_OPTIONS,
37+
Transform,
38+
MapCache,
3739
} from '../../../../../../common';
3840
import { TextField } from '../../input_fields';
3941
import { AppState } from '../../../../../store';
4042
import { ConfigureMultiExpressionModal } from './modals';
43+
import { updateCache } from './utils';
4144

4245
interface ModelOutputsProps {
4346
config: IProcessorConfig;
@@ -93,6 +96,11 @@ export function ModelOutputs(props: ModelOutputsProps) {
9396
}
9497
}, [models, getIn(values, modelFieldPath)?.id]);
9598

99+
// Temporarily cache any configured transformations for different transform types.
100+
// For example, if a user configures a prompt, swaps the transform
101+
// type to "Data field", and swaps back to "Prompt", the prompt will be persisted.
102+
const [outputMapCache, setOutputMapCache] = useState<MapCache>({});
103+
96104
// Adding a map entry to the end of the existing arr
97105
function addMapEntry(curEntries: OutputMapFormValue): void {
98106
const updatedEntries = [...curEntries, EMPTY_OUTPUT_MAP_ENTRY];
@@ -211,6 +219,7 @@ export function ModelOutputs(props: ModelOutputsProps) {
211219
<EuiFlexItem grow={TYPE_FLEX_RATIO}>
212220
<EuiFlexItem>
213221
<EuiCompressedSuperSelect
222+
fullWidth={true}
214223
disabled={false}
215224
options={OUTPUT_TRANSFORM_OPTIONS.map(
216225
(option) =>
@@ -246,20 +255,32 @@ export function ModelOutputs(props: ModelOutputsProps) {
246255
) || ''
247256
}
248257
onChange={(option) => {
258+
// before updating, cache any form values
259+
const updatedCache = updateCache(
260+
outputMapCache,
261+
mapEntry,
262+
idx
263+
);
249264
setFieldValue(
250265
`${outputMapFieldPath}.${idx}.value.transformType`,
251266
option
252267
);
253-
// If the transform type changes, clear any set value and/or nested vars,
254-
// as it will likely not make sense under other types/contexts.
268+
// Pre-populate with any cached values, if found
269+
const curCacheForOption = updatedCache[
270+
idx
271+
]?.find(
272+
(transform: Transform) =>
273+
transform.transformType === option
274+
);
255275
setFieldValue(
256276
`${outputMapFieldPath}.${idx}.value.value`,
257-
''
277+
curCacheForOption?.value || ''
258278
);
259279
setFieldValue(
260280
`${outputMapFieldPath}.${idx}.value.nestedVars`,
261-
[]
281+
curCacheForOption?.nestedVars || []
262282
);
283+
setOutputMapCache(updatedCache);
263284
}}
264285
/>
265286
</EuiFlexItem>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright OpenSearch Contributors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
import { isEmpty } from 'lodash';
7+
import {
8+
MapCache,
9+
InputMapEntry,
10+
OutputMapEntry,
11+
Transform,
12+
} from '../../../../../../common';
13+
14+
// Update a cache of data transform values based on a given form value
15+
export function updateCache(
16+
cache: MapCache,
17+
mapEntry: InputMapEntry | OutputMapEntry,
18+
idx: number // the mapEntry index
19+
): MapCache {
20+
const updatedCache = cache;
21+
const curCache = updatedCache[idx];
22+
if (curCache === undefined || isEmpty(curCache)) {
23+
// case 1: there is no persisted state for this entry index. create a fresh arr
24+
updatedCache[idx] = [mapEntry.value];
25+
} else if (
26+
!curCache.some(
27+
(transform: Transform) =>
28+
transform.transformType === mapEntry.value.transformType
29+
)
30+
) {
31+
// case 2: there is persisted state for this entry index, but not for the particular
32+
// transform type. append to the arr
33+
updatedCache[idx] = [...updatedCache[idx], mapEntry.value];
34+
} else {
35+
// case 3: there is persisted state for this entry index, and for the particular transform type.
36+
// Update the cache with the current form value(s)
37+
updatedCache[idx] = updatedCache[idx].map((cachedEntry) => {
38+
if (cachedEntry.transformType === mapEntry.value.transformType) {
39+
return mapEntry.value;
40+
} else {
41+
return cachedEntry;
42+
}
43+
});
44+
}
45+
return updatedCache;
46+
}

0 commit comments

Comments
 (0)