Skip to content

Commit

Permalink
JSONPath bug fix & improved wording in input/output transforms (#479) (
Browse files Browse the repository at this point in the history
…#480)

(cherry picked from commit 697241e)

Signed-off-by: Tyler Ohlsen <[email protected]>
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
  • Loading branch information
1 parent b39fc0d commit 02ad5ea
Show file tree
Hide file tree
Showing 7 changed files with 37 additions and 32 deletions.
2 changes: 1 addition & 1 deletion common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,7 @@ export const ERROR_GETTING_WORKFLOW_MSG = 'Failed to retrieve template';
export const NO_TEMPLATES_FOUND_MSG = 'There are no templates';
export const NO_MODIFICATIONS_FOUND_TEXT =
'Template does not contain any modifications';
export const JSONPATH_ROOT_SELECTOR = '$.';
export const JSONPATH_ROOT_SELECTOR = '$';
export enum SORT_ORDER {
ASC = 'asc',
DESC = 'desc',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,12 @@ import { MapField } from './map_field';

interface MapArrayFieldProps {
fieldPath: string; // the full path in string-form to the field (e.g., 'ingest.enrich.processors.text_embedding_processor.inputField')
helpText?: string;
keyTitle?: string;
keyPlaceholder?: string;
keyHelpText?: string;
valueTitle?: string;
valuePlaceholder?: string;
valueHelpText?: string;
onMapAdd?: (curArray: MapArrayFormValue) => void;
onMapDelete?: (idxToDelete: number) => void;
keyOptions?: { label: string }[];
Expand Down Expand Up @@ -123,11 +124,12 @@ export function MapArrayField(props: MapArrayFieldProps) {
<EuiPanel grow={true}>
<MapField
fieldPath={`${props.fieldPath}.${idx}`}
helpText={props.helpText}
keyTitle={props.keyTitle}
keyPlaceholder={props.keyPlaceholder}
keyHelpText={props.keyHelpText}
valueTitle={props.valueTitle}
valuePlaceholder={props.valuePlaceholder}
valueHelpText={props.valueHelpText}
keyOptions={props.keyOptions}
valueOptions={props.valueOptions}
addEntryButtonText={props.addMapEntryButtonText}
Expand All @@ -144,13 +146,14 @@ export function MapArrayField(props: MapArrayFieldProps) {
<EuiPanel grow={true}>
<MapField
fieldPath={`${props.fieldPath}.0`}
helpText={props.helpText}
keyTitle={props.keyTitle}
keyPlaceholder={props.keyPlaceholder}
keyHelpText={props.keyHelpText}
valueTitle={props.valueTitle}
valuePlaceholder={props.valuePlaceholder}
keyOptions={props.keyOptions}
valueOptions={props.valueOptions}
valueHelpText={props.valueHelpText}
addEntryButtonText={props.addMapEntryButtonText}
mappingDirection={props.mappingDirection}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,12 @@ interface MapFieldProps {
fieldPath: string; // the full path in string-form to the field (e.g., 'ingest.enrich.processors.text_embedding_processor.inputField')
label?: string;
helpLink?: string;
helpText?: string;
keyTitle?: string;
keyPlaceholder?: string;
keyHelpText?: string;
valueTitle?: string;
valuePlaceholder?: string;
valueHelpText?: string;
keyOptions?: { label: string }[];
valueOptions?: { label: string }[];
addEntryButtonText?: string;
Expand Down Expand Up @@ -111,9 +112,21 @@ export function MapField(props: MapFieldProps) {
<EuiFlexItem style={{ marginBottom: '0px' }}>
<EuiFlexGroup direction="row" gutterSize="xs">
<EuiFlexItem grow={KEY_FLEX_RATIO}>
<EuiText size="s" color="subdued">
{props.keyTitle || 'Key'}
</EuiText>
<EuiFlexGroup direction="row" gutterSize="xs">
<EuiFlexItem grow={false}>
<EuiText size="s" color="subdued">
{props.keyTitle || 'Key'}
</EuiText>
</EuiFlexItem>
{props.keyHelpText && (
<EuiFlexItem grow={false}>
<EuiIconTip
content={props.keyHelpText}
position="right"
/>
</EuiFlexItem>
)}
</EuiFlexGroup>
</EuiFlexItem>
<EuiFlexItem grow={VALUE_FLEX_RATIO}>
<EuiFlexGroup direction="row" gutterSize="xs">
Expand All @@ -122,10 +135,10 @@ export function MapField(props: MapFieldProps) {
{props.valueTitle || 'Value'}
</EuiText>
</EuiFlexItem>
{props.helpText && (
{props.valueHelpText && (
<EuiFlexItem grow={false}>
<EuiIconTip
content={props.helpText}
content={props.valueHelpText}
position="right"
/>
</EuiFlexItem>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -378,8 +378,6 @@ export function MLProcessorInputs(props: MLProcessorInputsProps) {
<EuiSpacer size="s" />
<MapArrayField
fieldPath={inputMapFieldPath}
helpText={`An array specifying how to map fields from the ingested document to the model’s input. Dot notation is used by default. To explicitly use JSONPath, please ensure to prepend with the
root object selector "${JSONPATH_ROOT_SELECTOR}"`}
keyTitle="Name"
keyPlaceholder="Name"
keyOptions={parseModelInputs(modelInterface)}
Expand All @@ -393,6 +391,7 @@ export function MLProcessorInputs(props: MLProcessorInputsProps) {
? 'Specify a query field'
: 'Define a document field'
}
valueHelpText={`Specify a document field or define JSONPath to transform the document to map to a model input field.`}
valueOptions={
props.context === PROCESSOR_CONTEXT.INGEST
? docFields
Expand Down Expand Up @@ -435,10 +434,9 @@ export function MLProcessorInputs(props: MLProcessorInputsProps) {
<EuiSpacer size="s" />
<MapArrayField
fieldPath={outputMapFieldPath}
helpText={`An array specifying how to map the model’s output to new document fields. Dot notation is used by default. To explicitly use JSONPath, please ensure to prepend with the
root object selector "${JSONPATH_ROOT_SELECTOR}"`}
keyTitle="Name"
keyPlaceholder="Name"
keyHelpText={`Specify a model output field or define JSONPath to transform the model output to map to a new document field.`}
keyOptions={
fullResponsePath
? undefined
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ import {
IngestPipelineConfig,
InputTransformFormValues,
InputTransformSchema,
JSONPATH_ROOT_SELECTOR,
MapArrayFormValue,
ModelInterface,
PROCESSOR_CONTEXT,
Expand Down Expand Up @@ -291,8 +290,6 @@ export function InputTransformModal(props: InputTransformModalProps) {
const InputMap = (
<MapArrayField
fieldPath={'input_map'}
helpText={`An array specifying how to map fields from the ingested document to the model’s input. Dot notation is used by default. To explicitly use JSONPath, please ensure to prepend with the
root object selector "${JSONPATH_ROOT_SELECTOR}"`}
keyTitle="Name"
keyPlaceholder="Name"
keyOptions={parseModelInputs(props.modelInterface)}
Expand All @@ -306,6 +303,7 @@ export function InputTransformModal(props: InputTransformModalProps) {
? 'Specify a query field'
: 'Define a document field'
}
valueHelpText={`Specify a document field or define JSONPath to transform the document to map to a model input field.`}
valueOptions={props.valueOptions}
// If the map we are adding is the first one, populate the selected option to index 0
onMapAdd={(curArray) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ import {
IConfigField,
IProcessorConfig,
IngestPipelineConfig,
JSONPATH_ROOT_SELECTOR,
MapArrayFormValue,
MapFormValue,
ModelInterface,
Expand Down Expand Up @@ -213,10 +212,9 @@ export function OutputTransformModal(props: OutputTransformModalProps) {
const OutputMap = (
<MapArrayField
fieldPath={'output_map'}
helpText={`An array specifying how to map the model’s output to new fields. Dot notation is used by default. To explicitly use JSONPath, please ensure to prepend with the
root object selector "${JSONPATH_ROOT_SELECTOR}"`}
keyTitle="Name"
keyPlaceholder="Name"
keyHelpText={`Specify a model output field or define JSONPath to transform the model output to map to a new document field.`}
keyOptions={
tempFullResponsePath
? undefined
Expand Down
19 changes: 7 additions & 12 deletions public/utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,18 +229,13 @@ 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.
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;
return path === '.'
? input
: mapEntry.value.startsWith(JSONPATH_ROOT_SELECTOR)
? // JSONPath transform
jsonpath.query(input, path)
: // Standard dot notation
get(input, path);
}

// Derive the collection of model inputs from the model interface JSONSchema into a form-ready list
Expand Down

0 comments on commit 02ad5ea

Please sign in to comment.