diff --git a/public/pages/workflow_detail/workflow_inputs/processor_inputs/ml_processor_inputs.tsx b/public/pages/workflow_detail/workflow_inputs/processor_inputs/ml_processor_inputs.tsx
index 70e78cc0..a5ce285e 100644
--- a/public/pages/workflow_detail/workflow_inputs/processor_inputs/ml_processor_inputs.tsx
+++ b/public/pages/workflow_detail/workflow_inputs/processor_inputs/ml_processor_inputs.tsx
@@ -487,17 +487,7 @@ export function MLProcessorInputs(props: MLProcessorInputsProps) {
optionalField.id !== 'query_template'
- ) || []),
- ]
- : props.config.optionalFields || []
- }
+ configFields={props.config.optionalFields || []}
baseConfigPath={props.baseConfigPath}
/>
diff --git a/public/pages/workflow_detail/workflow_inputs/processor_inputs/modals/output_transform_modal.tsx b/public/pages/workflow_detail/workflow_inputs/processor_inputs/modals/output_transform_modal.tsx
index 558e3162..15ef0364 100644
--- a/public/pages/workflow_detail/workflow_inputs/processor_inputs/modals/output_transform_modal.tsx
+++ b/public/pages/workflow_detail/workflow_inputs/processor_inputs/modals/output_transform_modal.tsx
@@ -35,6 +35,7 @@ import {
IngestPipelineConfig,
JSONPATH_ROOT_SELECTOR,
MapArrayFormValue,
+ MapFormValue,
ModelInterface,
OutputTransformFormValues,
OutputTransformSchema,
@@ -157,7 +158,7 @@ export function OutputTransformModal(props: OutputTransformModalProps) {
sampleSourceOutput = JSON.parse(sourceOutput);
const output = generateTransform(
sampleSourceOutput,
- tempOutputMap[selectedTransformOption]
+ reverseKeysAndValues(tempOutputMap[selectedTransformOption])
);
setTransformedOutput(customStringify(output));
} catch {}
@@ -641,3 +642,14 @@ root object selector "${JSONPATH_ROOT_SELECTOR}"`}
);
}
+
+// since we persist the form keys/values reversed, we have a util fn to reverse back, so we can use
+// single util fns for manipulation of the form values (generating transforms, etc.)
+function reverseKeysAndValues(values: MapFormValue): MapFormValue {
+ return values.map((mapEntry) => {
+ return {
+ key: mapEntry.value,
+ value: mapEntry.key,
+ };
+ });
+}
diff --git a/public/pages/workflow_detail/workflow_inputs/processor_inputs/modals/override_query_modal.tsx b/public/pages/workflow_detail/workflow_inputs/processor_inputs/modals/override_query_modal.tsx
index b7d11e57..561ff8ee 100644
--- a/public/pages/workflow_detail/workflow_inputs/processor_inputs/modals/override_query_modal.tsx
+++ b/public/pages/workflow_detail/workflow_inputs/processor_inputs/modals/override_query_modal.tsx
@@ -68,13 +68,13 @@ export function OverrideQueryModal(props: OverrideQueryModalProps) {
);
// TODO: should handle edge case of multiple output maps configured. Currently
// defaulting to prediction 0 / assuming not multiple predictions to track.
- const outputMapKeys = getIn(outputMap, '0', []).map(
- (mapEntry: MapEntry) => mapEntry.key
+ const outputMapValues = getIn(outputMap, '0', []).map(
+ (mapEntry: MapEntry) => mapEntry.value
) as string[];
const finalModelOutputs =
- outputMapKeys.length > 0
- ? outputMapKeys.map((outputMapKey) => {
- return { label: outputMapKey };
+ outputMapValues.length > 0
+ ? outputMapValues.map((outputMapValue) => {
+ return { label: outputMapValue };
})
: modelOutputs.map((modelOutput) => {
return { label: modelOutput.label };
diff --git a/public/pages/workflows/new_workflow/quick_configure_modal.tsx b/public/pages/workflows/new_workflow/quick_configure_modal.tsx
index d2bac5fc..7ec123ca 100644
--- a/public/pages/workflows/new_workflow/quick_configure_modal.tsx
+++ b/public/pages/workflows/new_workflow/quick_configure_modal.tsx
@@ -293,10 +293,10 @@ function updateIngestProcessors(
if (outputMap.length > 0) {
outputMap[0] = {
...outputMap[0],
- key: defaultField,
+ value: defaultField,
};
} else {
- outputMap.push({ key: defaultField, value: '' });
+ outputMap.push({ key: '', value: defaultField });
}
}
field.value = [outputMap] as MapArrayFormValue;
@@ -344,16 +344,18 @@ function updateSearchRequestProcessors(
}
if (field.id === 'output_map') {
const outputMap = generateMapFromModelOutputs(modelInterface);
- const defaultKey = isVectorSearchUseCase ? VECTOR : defaultQueryValue;
+ const defaultValue = isVectorSearchUseCase
+ ? VECTOR
+ : defaultQueryValue;
if (outputMap.length > 0) {
outputMap[0] = {
...outputMap[0],
- key: defaultKey,
+ value: defaultValue,
};
} else {
outputMap.push({
- key: defaultKey,
- value: '',
+ key: '',
+ value: defaultValue,
});
}
field.value = [outputMap] as MapArrayFormValue;
@@ -412,10 +414,10 @@ function updateSearchResponseProcessors(
if (outputMap.length > 0) {
outputMap[0] = {
...outputMap[0],
- key: fields.llmResponseField,
+ value: fields.llmResponseField,
};
} else {
- outputMap.push({ key: fields.llmResponseField, value: '' });
+ outputMap.push({ key: '', value: fields.llmResponseField });
}
}
field.value = [outputMap] as MapArrayFormValue;
@@ -540,7 +542,7 @@ function generateMapFromModelInputs(
return inputMap;
}
-// generate a set of mappings s.t. each value is
+// generate a set of mappings s.t. each key is
// a unique model output
function generateMapFromModelOutputs(
modelInterface?: ModelInterface
@@ -550,8 +552,8 @@ function generateMapFromModelOutputs(
const modelOutputs = parseModelOutputs(modelInterface);
modelOutputs.forEach((modelOutput) => {
outputMap.push({
- key: '',
- value: modelOutput.label,
+ key: modelOutput.label,
+ value: '',
});
});
}
diff --git a/public/utils/utils.ts b/public/utils/utils.ts
index 34970ce6..dd29f916 100644
--- a/public/utils/utils.ts
+++ b/public/utils/utils.ts
@@ -229,13 +229,18 @@ function getTransformedResult(
// the entire value. This may happen if full_response_path=false
// and the input is the entire result with nothing else to parse out.
// get() does not cover this case, so we override manually.
- return path === '.'
- ? input
- : mapEntry.value.startsWith(JSONPATH_ROOT_SELECTOR)
- ? // JSONPath transform
- jsonpath.value(input, path)
- : // Standard dot notation
- get(input, path);
+ const result =
+ path === '.'
+ ? input
+ : mapEntry.value.startsWith(JSONPATH_ROOT_SELECTOR)
+ ? // JSONPath transform
+ jsonpath.query(input, path)
+ : // Standard dot notation
+ get(input, path);
+
+ // ML processors dynamically handle arrays vs. single values differently when indexing.
+ // We replicate that logic here to get consistent results
+ return Array.isArray(result) && result.length === 1 ? result[0] : result;
}
// Derive the collection of model inputs from the model interface JSONSchema into a form-ready list