From c8b6a0b3e6df7fbb0ec2c3780de6a5a4ed78236f Mon Sep 17 00:00:00 2001 From: Julien Veyssier Date: Wed, 24 Jul 2024 19:12:40 +0200 Subject: [PATCH] add support for Enum field type, fix many issues Signed-off-by: Julien Veyssier --- lib/Service/AssistantService.php | 10 ++ src/assistant.js | 8 +- src/components/AssistantFormInputs.vue | 36 +++++-- .../AssistantTextProcessingForm.vue | 8 +- src/components/TaskList.vue | 2 +- src/components/TaskListItem.vue | 5 - src/components/fields/EnumField.vue | 97 +++++++++++++++++++ src/components/fields/TaskTypeField.vue | 8 ++ src/components/fields/TaskTypeFields.vue | 36 ++++++- src/constants.js | 1 + src/views/AssistantPage.vue | 6 +- 11 files changed, 197 insertions(+), 20 deletions(-) create mode 100644 src/components/fields/EnumField.vue diff --git a/lib/Service/AssistantService.php b/lib/Service/AssistantService.php index 959ea490..a366a2df 100644 --- a/lib/Service/AssistantService.php +++ b/lib/Service/AssistantService.php @@ -140,6 +140,8 @@ public function getAvailableTaskTypes(): array { EShapeType::ListOfAudios, ), ], + 'inputShapeEnumValues' => [], + 'inputShapeDefaults' => [], 'outputShape' => [ 'fileList' => new ShapeDescriptor( 'Output file list', @@ -157,8 +159,12 @@ public function getAvailableTaskTypes(): array { EShapeType::Image, ), ], + 'outputShapeEnumValues' => [], 'optionalInputShape' => [], + 'optionalInputShapeEnumValues' => [], + 'optionalInputShapeDefaults' => [], 'optionalOutputShape' => [], + 'optionalOutputShapeEnumValues' => [], ]; } /** @var string $typeId */ @@ -179,8 +185,12 @@ public function getAvailableTaskTypes(): array { 'name' => $this->l10n->t('Chat with AI'), 'description' => $this->l10n->t('Chat with an AI model.'), 'inputShape' => [], + 'inputShapeEnumValues' => [], + 'inputShapeDefaults' => [], 'outputShape' => [], 'optionalInputShape' => [], + 'optionalInputShapeEnumValues' => [], + 'optionalInputShapeDefaults' => [], 'optionalOutputShape' => [], 'priority' => self::TASK_TYPE_PRIORITIES['chatty-llm'] ?? 1000, ]; diff --git a/src/assistant.js b/src/assistant.js index f739541b..964f31fa 100644 --- a/src/assistant.js +++ b/src/assistant.js @@ -106,6 +106,7 @@ export async function openAssistantForm({ } else if (finishedTask.status === TASK_STATUS_STRING.failed) { showError(t('assistant', 'Your task has failed')) console.error('[assistant] Task failed', finishedTask) + view.outputs = null } resolve(finishedTask) view.loading = false @@ -130,7 +131,7 @@ export async function openAssistantForm({ }) view.$on('load-task', (task) => { if (!view.loading) { - console.debug('aaaaa loading task', task) + console.debug('[assistant] loading task', task) view.selectedTaskTypeId = task.taskType view.inputs = task.input view.outputs = task.status === TASK_STATUS_STRING.successful ? task.output : null @@ -364,12 +365,17 @@ export async function openAssistantTask(task) { if (finishedTask.status === TASK_STATUS_STRING.successful) { view.outputs = finishedTask?.output view.selectedTaskId = finishedTask?.id + } else if (finishedTask.status === TASK_STATUS_STRING.failed) { + showError(t('assistant', 'Your task has failed')) + console.error('[assistant] Task failed', finishedTask) + view.outputs = null } // resolve(finishedTask) view.loading = false view.showSyncTaskRunning = false }).catch(error => { console.debug('[assistant] poll error', error) + view.outputs = null }) }) .catch(error => { diff --git a/src/components/AssistantFormInputs.vue b/src/components/AssistantFormInputs.vue index 7ee508d0..218ba578 100644 --- a/src/components/AssistantFormInputs.vue +++ b/src/components/AssistantFormInputs.vue @@ -10,6 +10,8 @@ :is-output="false" :shape="selectedTaskType.inputShape" :optional-shape="selectedTaskType.optionalInputShape ?? null" + :shape-options="selectedTaskType.inputShapeEnumValues ?? null" + :optional-shape-options="selectedTaskType.optionalInputShapeEnumValues ?? null" :values="inputs" :show-advanced="showAdvanced" @update:show-advanced="$emit('update:show-advanced', $event)" @@ -35,6 +37,10 @@ export default { type: Object, default: () => {}, }, + selectedTaskId: { + type: [Number, null], + default: null, + }, selectedTaskType: { type: [Object, null], default: null, @@ -60,17 +66,35 @@ export default { }, }, mounted() { + console.debug('[assistant] mounted AssistantFormInputs', this.selectedTaskId, this.selectedTaskType) + // don't set the default values if there is a loaded task (initial or from history) + if (this.selectedTaskType && this.selectedTaskId === null) { + this.setDefaultValues() + } }, methods: { resetInputs() { + this.setDefaultValues() + }, + setDefaultValues() { + console.debug('[assistant] set default values', this.selectedTaskType?.inputShapeDefaults, this.selectedTaskType?.optionalInputShapeDefaults) const inputs = {} - /* - Object.keys(this.selectedTaskType.inputShape).forEach(key => { - inputs[key] = null - }) - */ + // set default values + if (this.selectedTaskType.inputShapeDefaults) { + Object.keys(this.selectedTaskType.inputShapeDefaults).forEach(key => { + if (this.selectedTaskType.inputShapeDefaults[key]) { + inputs[key] = this.selectedTaskType.inputShapeDefaults[key] + } + }) + } + if (this.selectedTaskType.optionalInputShapeDefaults) { + Object.keys(this.selectedTaskType.optionalInputShapeDefaults).forEach(key => { + if (this.selectedTaskType.optionalInputShapeDefaults[key]) { + inputs[key] = this.selectedTaskType.optionalInputShapeDefaults[key] + } + }) + } this.$emit('update:inputs', inputs) - // TODO do it with optional input shape as well }, }, } diff --git a/src/components/AssistantTextProcessingForm.vue b/src/components/AssistantTextProcessingForm.vue index 47b811a0..9ef9dd65 100644 --- a/src/components/AssistantTextProcessingForm.vue +++ b/src/components/AssistantTextProcessingForm.vue @@ -48,6 +48,7 @@
{ const index = this.tasks.findIndex(t => { return t.id === task.id }) if (index !== -1) { diff --git a/src/components/TaskListItem.vue b/src/components/TaskListItem.vue index 91254977..0fab05e1 100644 --- a/src/components/TaskListItem.vue +++ b/src/components/TaskListItem.vue @@ -152,11 +152,6 @@ export default { return this.task.type === 'core:text2image' }, mainName() { - if (this.task.taskType === 'copywriter') { - return this.task.input.sourceMaterial - } else if (this.task.taskType === 'speech-to-text') { - return t('assistant', 'Audio input') - } return t('assistant', 'Input') + ': ' + this.textInputPreview }, subName() { diff --git a/src/components/fields/EnumField.vue b/src/components/fields/EnumField.vue new file mode 100644 index 00000000..e5e47d49 --- /dev/null +++ b/src/components/fields/EnumField.vue @@ -0,0 +1,97 @@ + + + + + diff --git a/src/components/fields/TaskTypeField.vue b/src/components/fields/TaskTypeField.vue index 8b2ccd92..d353b299 100644 --- a/src/components/fields/TaskTypeField.vue +++ b/src/components/fields/TaskTypeField.vue @@ -4,6 +4,7 @@ :field-key="fieldKey" :value="value" :field="field" + :options="options ?? undefined" :is-output="isOutput" @update:value="$emit('update:value', $event)" /> @@ -12,6 +13,7 @@ import TextField from './TextField.vue' import NumberField from './NumberField.vue' import MediaField from './MediaField.vue' +import EnumField from './EnumField.vue' import ListOfMediaField from './ListOfMediaField.vue' import ListOfTextsField from './ListOfTextsField.vue' @@ -36,6 +38,10 @@ export default { type: Object, required: true, }, + options: { + type: [Array, null], + default: null, + }, isOutput: { type: Boolean, required: true, @@ -79,6 +85,8 @@ export default { return ListOfMediaField } else if (this.field.type === SHAPE_TYPE_NAMES.ListOfTexts) { return ListOfTextsField + } else if (this.field.type === SHAPE_TYPE_NAMES.Enum) { + return EnumField } return TextField }, diff --git a/src/components/fields/TaskTypeFields.vue b/src/components/fields/TaskTypeFields.vue index de39f640..94c8465e 100644 --- a/src/components/fields/TaskTypeFields.vue +++ b/src/components/fields/TaskTypeFields.vue @@ -5,6 +5,7 @@ :field-key="key" :field="field" :value="values[key] ?? null" + :options="getInputFieldOptions(field, key)" :is-output="isOutput" @update:value="onValueChange(key, $event)" />