Skip to content

Commit

Permalink
Add initial component interfaces
Browse files Browse the repository at this point in the history
Signed-off-by: Tyler Ohlsen <[email protected]>
  • Loading branch information
ohltyler committed Sep 20, 2023
1 parent ac60ae0 commit 14024e9
Show file tree
Hide file tree
Showing 14 changed files with 533 additions and 4 deletions.
85 changes: 85 additions & 0 deletions public/component_types/base_interfaces.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { COMPONENT_CATEGORY } from '../utils';

/**
* ************ Types **************************
*/

// TODO: may change some/all of these to enums later
export type BaseClass = string;
export type UIFlow = string;
export type FieldType = 'string' | 'json' | 'select';

/**
* ************ Base interfaces ****************
*/

/**
* Represents a single base class as an input handle for a component.
* It may be optional. It may also accept multiples of that class.
*/
export interface IComponentInput {
id: string;
label: string;
baseClass: string;
optional: boolean;
acceptMultiple: boolean;
}

/**
* An input field for a component. Specifies enough configuration for the
* UI node to render it properly within the component (show it as optional,
* put it in advanced settings, placeholder values, etc.)
*/
export interface IComponentField {
label: string;
type: FieldType;
placeholder?: string;
optional?: boolean;
advanced?: boolean;
}

/**
* Represents the list of base classes as a single output handle for
* a component.
*/
export interface IComponentOutput {
id: string;
label: string;
baseClasses: BaseClass[];
}

/**
* The base interface the components will implement.
*/
export interface IComponent {
id: string;
type: BaseClass;
label: string;
description: string;
category: COMPONENT_CATEGORY;
// determines if this component allows for new creation. this means to
// allow a "create" option on the UI component, as well as potentially
// include in the use case template construction ('provisioning' flow)
allowsCreation: boolean;
// determines if this is something that will be included in the use
// case template construction (query or ingest flows). provisioning flow
// is handled by the allowsCreation flag above.
isApplicationStep: boolean;
// the set of allowed flows this component can be drug into the workspace
allowedFlows: UIFlow[];
// the list of base classes that will be used in the component output
baseClasses?: BaseClass[];
inputs?: IComponentInput[];
fields?: IComponentField[];
// if the component supports creation, we will have a different set of input fields
// the user needs to fill out
createFields?: IComponentField[];
outputs?: IComponentOutput[];
// we will need some init function when the component is drug into the workspace
init?(): Promise<any>;
}
8 changes: 8 additions & 0 deletions public/component_types/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

export * from './base_interfaces';
export * from './processors';
export * from './indices';
6 changes: 6 additions & 0 deletions public/component_types/indices/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

export * from './knn_index';
87 changes: 87 additions & 0 deletions public/component_types/indices/knn_index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { COMPONENT_CATEGORY } from '../../utils';
import {
IComponent,
IComponentField,
IComponentInput,
IComponentOutput,
UIFlow,
BaseClass,
} from '../base_interfaces';

/**
* A k-NN index UI component
*/
export class KnnIndex implements IComponent {
id: string;
type: BaseClass;
label: string;
description: string;
category: COMPONENT_CATEGORY;
allowsCreation: boolean;
isApplicationStep: boolean;
allowedFlows: UIFlow[];
baseClasses: BaseClass[];
inputs: IComponentInput[];
fields: IComponentField[];
createFields: IComponentField[];
outputs: IComponentOutput[];

constructor() {
this.id = 'knn_index';
this.type = 'knn_index';
this.label = 'k-NN Index';
this.description = 'A k-NN Index to be used as a vector store';
this.category = COMPONENT_CATEGORY.INDICES;
this.allowsCreation = true;
this.isApplicationStep = false;
// TODO: 'other' may not be how this is stored. the idea is 'other' allows
// for placement outside of the ingest or query flows- typically something
// that will be referenced/used as input across multiple flows
this.allowedFlows = ['Ingest', 'Query', 'Other'];
this.baseClasses = [this.type];
this.inputs = [];
this.fields = [
{
label: 'Index Name',
type: 'select',
optional: false,
advanced: false,
},
];
this.createFields = [
{
label: 'Index Name',
type: 'string',
optional: false,
advanced: false,
},
// we don't need to expose "settings" here since it will be index.knn by default
// just let users customize the mappings
// TODO: figure out how to handle defaults for all of these values. maybe toggle between
// simple form inputs vs. complex JSON editor
{
label: 'Mappings',
type: 'json',
placeholder: 'Enter an index mappings JSON blob...',
optional: false,
advanced: false,
},
];
this.outputs = [
{
id: this.id,
label: this.label,
baseClasses: this.baseClasses,
},
];
}

async init(): Promise<any> {
return new KnnIndex();
}
}
6 changes: 6 additions & 0 deletions public/component_types/processors/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

export * from './text_embedding_processor';
77 changes: 77 additions & 0 deletions public/component_types/processors/text_embedding_processor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { COMPONENT_CATEGORY } from '../../utils';
import {
IComponent,
IComponentField,
IComponentInput,
IComponentOutput,
UIFlow,
BaseClass,
} from '../base_interfaces';

/**
* A text embedding processor UI component
*/
export class TextEmbeddingProcessor implements IComponent {
id: string;
type: BaseClass;
label: string;
description: string;
category: COMPONENT_CATEGORY;
allowsCreation: boolean;
isApplicationStep: boolean;
allowedFlows: UIFlow[];
baseClasses: BaseClass[];
inputs: IComponentInput[];
fields: IComponentField[];
outputs: IComponentOutput[];

constructor() {
this.id = 'text_embedding_processor';
this.type = 'text_embedding_processor';
this.label = 'Text Embedding Processor';
this.description =
'A text embedding ingest processor to be used in an ingest pipeline';
this.category = COMPONENT_CATEGORY.INGEST_PROCESSORS;
this.allowsCreation = false;
this.isApplicationStep = false;
this.allowedFlows = ['Ingest'];
this.baseClasses = [this.type];
this.inputs = [];
this.fields = [
{
label: 'Model ID',
type: 'string',
optional: false,
advanced: false,
},
{
label: 'Input Field',
type: 'string',
optional: false,
advanced: false,
},
{
label: 'Output Field',
type: 'string',
optional: false,
advanced: false,
},
];
this.outputs = [
{
id: this.id,
label: this.label,
baseClasses: this.baseClasses,
},
];
}

async init(): Promise<any> {
return new TextEmbeddingProcessor();
}
}
8 changes: 8 additions & 0 deletions public/pages/workflow_builder/components/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

export { TextField } from './text_field';
export { JsonField } from './json_field';
export { SelectField } from './select_field';
27 changes: 27 additions & 0 deletions public/pages/workflow_builder/components/json_field.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React from 'react';
import { EuiText, EuiTextArea } from '@elastic/eui';

interface JsonFieldProps {
label: string;
placeholder: string;
}

/**
* An input field for a component where users select manually enter
* in some custom JSON
*/
export function JsonField(props: JsonFieldProps) {
return (
<>
<EuiText size="s" className="eui-textLeft">
{props.label}
</EuiText>
<EuiTextArea placeholder={props.placeholder} />
</>
);
}
46 changes: 46 additions & 0 deletions public/pages/workflow_builder/components/select_field.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React, { useState } from 'react';
import { EuiSuperSelect, EuiSuperSelectOption, EuiText } from '@elastic/eui';

// TODO: Should be fetched from global state.
// Need to have a way to determine where to fetch this dynamic data.
const existingIndices = [
{
value: 'index-1',
inputDisplay: <EuiText>my-index-1</EuiText>,
disabled: false,
},
{
value: 'index-2',
inputDisplay: <EuiText>my-index-2</EuiText>,
disabled: false,
},
] as Array<EuiSuperSelectOption<string>>;

/**
* An input field for a component where users select from a list of available
* options.
*/
export function SelectField() {
const options = existingIndices;

const [selectedOption, setSelectedOption] = useState<string>(
options[0].value
);

const onChange = (option: string) => {
setSelectedOption(option);
};

return (
<EuiSuperSelect
options={options}
valueOfSelected={selectedOption}
onChange={(option) => onChange(option)}
/>
);
}
25 changes: 25 additions & 0 deletions public/pages/workflow_builder/components/text_field.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React from 'react';
import { EuiFieldText } from '@elastic/eui';

interface TextFieldProps {
label: string;
placeholder: string;
}

/**
* An input field for a component where users input plaintext
*/
export function TextField(props: TextFieldProps) {
return (
<EuiFieldText
prepend={props.label}
compressed={false}
placeholder={props.placeholder || ''}
/>
);
}
1 change: 1 addition & 0 deletions public/pages/workflow_builder/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
*/

export { WorkflowBuilder } from './workflow_builder';
export { WorkflowComponent } from './workflow_component';
Loading

0 comments on commit 14024e9

Please sign in to comment.