From 3c2459483aaf9dcc4fc95b0e896e955e76a81b45 Mon Sep 17 00:00:00 2001 From: Shawn Yama Date: Wed, 24 Apr 2024 13:02:50 -0400 Subject: [PATCH] feat: model configurations can be accepted into stratify and model edit (#3426) --- .../ops/model-edit/model-edit-operation.ts | 4 ++- .../ops/model-edit/tera-model-edit-node.vue | 2 +- .../ops/model-edit/tera-model-edit.vue | 12 ++++++- .../stratify-mira/stratify-mira-operation.ts | 4 ++- .../ops/stratify-mira/tera-stratify-mira.vue | 11 +++++- .../src/services/model-configurations.ts | 5 +++ .../hmi-client/src/services/workflow.ts | 34 ++++++++++++------- .../client/hmi-client/src/types/workflow.ts | 1 + 8 files changed, 56 insertions(+), 17 deletions(-) diff --git a/packages/client/hmi-client/src/components/workflow/ops/model-edit/model-edit-operation.ts b/packages/client/hmi-client/src/components/workflow/ops/model-edit/model-edit-operation.ts index 02ccd41aaa..2be5ad0d44 100644 --- a/packages/client/hmi-client/src/components/workflow/ops/model-edit/model-edit-operation.ts +++ b/packages/client/hmi-client/src/components/workflow/ops/model-edit/model-edit-operation.ts @@ -15,7 +15,9 @@ export const ModelEditOperation: Operation = { displayName: 'Edit model', description: 'Edit a model', isRunnable: false, - inputs: [{ type: 'modelId', label: 'Model', acceptMultiple: false }], + inputs: [ + { type: 'modelId|modelConfigId', label: 'Model or Model configuration', acceptMultiple: false } + ], outputs: [{ type: 'modelId' }], action: async () => ({}), initState: () => { diff --git a/packages/client/hmi-client/src/components/workflow/ops/model-edit/tera-model-edit-node.vue b/packages/client/hmi-client/src/components/workflow/ops/model-edit/tera-model-edit-node.vue index 4243a844e8..018dea44a8 100644 --- a/packages/client/hmi-client/src/components/workflow/ops/model-edit/tera-model-edit-node.vue +++ b/packages/client/hmi-client/src/components/workflow/ops/model-edit/tera-model-edit-node.vue @@ -27,7 +27,7 @@ const props = defineProps<{ node: WorkflowNode; }>(); -const model = ref(null as Model | null); +const model = ref(null); const updateModel = async () => { const modelId = operator.getActiveOutput(props.node)?.value?.[0]; if (modelId && modelId !== model?.value?.id) { diff --git a/packages/client/hmi-client/src/components/workflow/ops/model-edit/tera-model-edit.vue b/packages/client/hmi-client/src/components/workflow/ops/model-edit/tera-model-edit.vue index 91ef25cda7..5a82d49b25 100644 --- a/packages/client/hmi-client/src/components/workflow/ops/model-edit/tera-model-edit.vue +++ b/packages/client/hmi-client/src/components/workflow/ops/model-edit/tera-model-edit.vue @@ -116,6 +116,7 @@ import TeraModelTemplateEditor from '@/components/model-template/tera-model-temp import TeraNotebookJupyterInput from '@/components/llm/tera-notebook-jupyter-input.vue'; import { KernelSessionManager } from '@/services/jupyter'; +import { getModelIdFromModelConfigurationId } from '@/services/model-configurations'; import { ModelEditOperationState } from './model-edit-operation'; const props = defineProps<{ @@ -150,7 +151,7 @@ const activeOutput = ref | null>(null); const kernelManager = new KernelSessionManager(); const isKernelReady = ref(false); const amr = ref(null); -const modelId = props.node.inputs[0].value?.[0]; + const newModelName = ref(''); let editor: VAceEditorInstance['_editor'] | null; const sampleAgentQuestions = [ @@ -281,6 +282,15 @@ const buildJupyterContext = () => { }; const inputChangeHandler = async () => { + const input = props.node.inputs[0]; + if (!input) return; + + let modelId: string | null = null; + if (input.type === 'modelId') { + modelId = input.value?.[0]; + } else if (input.type === 'modelConfigId') { + modelId = await getModelIdFromModelConfigurationId(input.value?.[0]); + } if (!modelId) return; amr.value = await getModel(modelId); diff --git a/packages/client/hmi-client/src/components/workflow/ops/stratify-mira/stratify-mira-operation.ts b/packages/client/hmi-client/src/components/workflow/ops/stratify-mira/stratify-mira-operation.ts index a910c3bf97..6e14024ff2 100644 --- a/packages/client/hmi-client/src/components/workflow/ops/stratify-mira/stratify-mira-operation.ts +++ b/packages/client/hmi-client/src/components/workflow/ops/stratify-mira/stratify-mira-operation.ts @@ -53,7 +53,9 @@ export const StratifyMiraOperation: Operation = { name: WorkflowOperationTypes.STRATIFY_MIRA, displayName: 'Stratify model', description: 'Stratify a model', - inputs: [{ type: 'modelId', label: 'Model', acceptMultiple: false }], + inputs: [ + { type: 'modelId|modelConfigId', label: 'Model or Model configuration', acceptMultiple: false } + ], outputs: [{ type: 'model' }], isRunnable: false, action: () => {}, diff --git a/packages/client/hmi-client/src/components/workflow/ops/stratify-mira/tera-stratify-mira.vue b/packages/client/hmi-client/src/components/workflow/ops/stratify-mira/tera-stratify-mira.vue index 4ae9a0ac25..f363d5dbd6 100644 --- a/packages/client/hmi-client/src/components/workflow/ops/stratify-mira/tera-stratify-mira.vue +++ b/packages/client/hmi-client/src/components/workflow/ops/stratify-mira/tera-stratify-mira.vue @@ -156,6 +156,7 @@ import '@/ace-config'; import TeraNotebookError from '@/components/drilldown/tera-notebook-error.vue'; import type { Model } from '@/types/Types'; import { AMRSchemaNames } from '@/types/common'; +import { getModelIdFromModelConfigurationId } from '@/services/model-configurations'; /* Jupyter imports */ import { KernelSessionManager } from '@/services/jupyter'; @@ -358,7 +359,15 @@ const getStatesAndParameters = (amrModel: Model) => { }; const inputChangeHandler = async () => { - const modelId = props.node.inputs[0].value?.[0]; + const input = props.node.inputs[0]; + if (!input) return; + + let modelId: string | null = null; + if (input.type === 'modelId') { + modelId = input.value?.[0]; + } else if (input.type === 'modelConfigId') { + modelId = await getModelIdFromModelConfigurationId(input.value?.[0]); + } if (!modelId) return; amr.value = await getModel(modelId); diff --git a/packages/client/hmi-client/src/services/model-configurations.ts b/packages/client/hmi-client/src/services/model-configurations.ts index dc4782ea84..7ef2185251 100644 --- a/packages/client/hmi-client/src/services/model-configurations.ts +++ b/packages/client/hmi-client/src/services/model-configurations.ts @@ -12,6 +12,11 @@ export const getModelConfigurationById = async (id: string) => { return (response?.data as ModelConfiguration) ?? null; }; +export const getModelIdFromModelConfigurationId = async (id: string) => { + const modelConfiguration = await getModelConfigurationById(id); + return modelConfiguration?.model_id ?? null; +}; + export const createModelConfiguration = async ( model_id: string | undefined, name: string, diff --git a/packages/client/hmi-client/src/services/workflow.ts b/packages/client/hmi-client/src/services/workflow.ts index 72586daeb6..9dd6ec9979 100644 --- a/packages/client/hmi-client/src/services/workflow.ts +++ b/packages/client/hmi-client/src/services/workflow.ts @@ -114,14 +114,11 @@ export const addEdge = ( ) => { const sourceNode = wf.nodes.find((d) => d.id === sourceId); const targetNode = wf.nodes.find((d) => d.id === targetId); - if (!sourceNode) return; - if (!targetNode) return; + if (!sourceNode || !targetNode) return; const sourceOutputPort = sourceNode.outputs.find((d) => d.id === sourcePortId); const targetInputPort = targetNode.inputs.find((d) => d.id === targetPortId); - - if (!sourceOutputPort) return; - if (!targetInputPort) return; + if (!sourceOutputPort || !targetInputPort) return; // Check if edge already exist const existingEdge = wf.edges.find( @@ -131,16 +128,15 @@ export const addEdge = ( d.target === targetId && d.targetPortId === targetPortId ); - if (existingEdge) return; - // Check if type is compatible if (sourceOutputPort.value === null) return; const allowedTypes = targetInputPort.type.split('|'); - if (!allowedTypes.includes(sourceOutputPort.type)) return; - - if (!targetInputPort.acceptMultiple && targetInputPort.status === WorkflowPortStatus.CONNECTED) { + if ( + !allowedTypes.includes(sourceOutputPort.type) || + (!targetInputPort.acceptMultiple && targetInputPort.status === WorkflowPortStatus.CONNECTED) + ) { return; } @@ -153,9 +149,10 @@ export const addEdge = ( targetInputPort.value = sourceOutputPort.value; } - // Transfer concrete type information where it can accept multiple types - // Note this will lock in the typing, even after unlink + // Transfer concrete type to the input type to match the output type + // Saves the original type in case we want to revert when we unlink the edge if (allowedTypes.length > 1) { + targetInputPort.originalType = targetInputPort.type; targetInputPort.type = sourceOutputPort.type; } @@ -181,12 +178,19 @@ export const removeEdge = (wf: Workflow, id: string) => { // Remove the data reference at the targetPort const targetNode = wf.nodes.find((d) => d.id === edgeToRemove.target); if (!targetNode) return; + const targetPort = targetNode.inputs.find((d) => d.id === edgeToRemove.targetPortId); if (!targetPort) return; + targetPort.value = null; targetPort.status = WorkflowPortStatus.NOT_CONNECTED; delete targetPort.label; + // Resets the type to the original type (used when multiple types for a port are allowed) + if (targetPort?.originalType) { + targetPort.type = targetPort.originalType; + } + // Edge re-assignment wf.edges = wf.edges.filter((edge) => edge.id !== id); @@ -229,6 +233,7 @@ const defaultPortLabels = { modelId: 'Model', modelConfigId: 'Model configuration', datasetId: 'Dataset', + simulationId: 'Simulation', codeAssetId: 'Code asset' }; @@ -241,6 +246,11 @@ export function getPortLabel({ label, type, isOptional }: WorkflowPort) { else if (defaultPortLabels[type]) { portLabel = defaultPortLabels[type]; } + // Create name if there are multiple types + else if (type.includes('|')) { + const types = type.split('|'); + portLabel = types.map((t) => defaultPortLabels[t] ?? t).join(' or '); + } if (isOptional) portLabel = portLabel.concat(' (optional)'); diff --git a/packages/client/hmi-client/src/types/workflow.ts b/packages/client/hmi-client/src/types/workflow.ts index a22fbb11e5..ac76758ed8 100644 --- a/packages/client/hmi-client/src/types/workflow.ts +++ b/packages/client/hmi-client/src/types/workflow.ts @@ -77,6 +77,7 @@ export interface Operation { export interface WorkflowPort { id: string; type: string; + originalType?: string; status: WorkflowPortStatus; label?: string; value?: any[] | null;