Skip to content

Commit

Permalink
Add initial component interfaces (#32)
Browse files Browse the repository at this point in the history
Signed-off-by: Tyler Ohlsen <[email protected]>
  • Loading branch information
ohltyler authored Sep 21, 2023
1 parent c73ffb0 commit d3bb6bb
Show file tree
Hide file tree
Showing 17 changed files with 594 additions and 4 deletions.
86 changes: 86 additions & 0 deletions public/component_types/base_interfaces.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* 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;
// will be used for grouping together in the drag-and-drop component library
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 * from './input_fields';
export { NewOrExistingTabs } from './new_or_existing_tabs';
export { InputFieldList } from './input_field_list';
62 changes: 62 additions & 0 deletions public/pages/workflow_builder/components/input_field_list.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React from 'react';
import { EuiFlexItem, EuiSpacer } from '@elastic/eui';
import { IComponentField } from '../../../component_types';
import { TextField, JsonField, SelectField } from './input_fields';

/**
* A helper component to format all of the input fields for a component. Dynamically
* render based on the input type.
*/

interface InputFieldListProps {
inputFields?: IComponentField[];
}

export function InputFieldList(props: InputFieldListProps) {
return (
<EuiFlexItem>
{props.inputFields?.map((field, idx) => {
let el;
switch (field.type) {
case 'string': {
el = (
<EuiFlexItem key={idx}>
<TextField
label={field.label}
placeholder={field.placeholder || ''}
/>
<EuiSpacer size="s" />
</EuiFlexItem>
);
break;
}
case 'json': {
el = (
<EuiFlexItem key={idx}>
<JsonField
label={field.label}
placeholder={field.placeholder || ''}
/>
</EuiFlexItem>
);
break;
}
case 'select': {
el = (
<EuiFlexItem key={idx}>
<SelectField />
</EuiFlexItem>
);
break;
}
}
return el;
})}
</EuiFlexItem>
);
}
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';
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 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} />
</>
);
}
Loading

0 comments on commit d3bb6bb

Please sign in to comment.