Skip to content

Commit d2826b6

Browse files
authored
chore: add dropdown to select model type (#1043)
## TL;DR Adds dropdown to select the type of generalised model to use for AISAY action. Context: AISAY added a new model type called 'Vision' to their generalised model. AISAY's API doc: https://app.swaggerhub.com/apis-docs/DAMIENSKTWORK/bgp-aisay_document_extraction_api/1.0.11#/DocumentParserResponse ## Solution **Improvements**: - Add dropdown to select generalised model: `Standard` (default) or `Vision` (new) ## How to test? - [ ] Existing AISAY actions work as intended without making any changes - [ ] Show the model type as `Standard` by default - [ ] Existing AISAY action can be updated to use new `Vision` model - [ ] Create new AISAY action with `Vision` model and runs as intended - [ ] Create new AISAY action with `Standard` model and runs as intended ## What changed? * Additional dropdown field called `Model type` with the following options: `Standard` (default), `Vision` (new) * Add tests to validate the model type selection * Add model type to api call as `additional_features` ## Before & After Screenshots **BEFORE**: <img width="975" alt="Screenshot 2025-06-06 at 2 49 19 PM" src="https://github.com/user-attachments/assets/9063c9ef-7770-4e96-af14-7fa6e0f750a8" /> **AFTER**: <img width="968" alt="Screenshot 2025-06-06 at 2 52 50 PM" src="https://github.com/user-attachments/assets/24103909-31da-4b01-be8f-7f0c49cc4d2e" /> https://github.com/user-attachments/assets/b0b0093f-75d6-4457-9552-02ffe80fa348
1 parent 2d6626d commit d2826b6

File tree

4 files changed

+92
-17
lines changed

4 files changed

+92
-17
lines changed

packages/backend/src/apps/aisay/__tests__/common/schema.test.ts

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { assert, beforeEach, describe, it } from 'vitest'
1+
import { assert, beforeEach, describe, expect, it } from 'vitest'
22

33
import {
44
generalisedModelSchema,
@@ -52,6 +52,36 @@ describe('AISAY schema', () => {
5252
const result = generalisedModelSchema.safeParse(generalisedModelPayload)
5353
assert(result.success === false)
5454
})
55+
56+
describe('should validate the model type', () => {
57+
it('should return null if is default model type', () => {
58+
generalisedModelPayload.modelType = 'standard'
59+
const result = generalisedModelSchema.safeParse(generalisedModelPayload)
60+
assert(result.success === true)
61+
expect(result.data.modelType).toBeNull()
62+
})
63+
64+
it('should return the model type if is not default model type', () => {
65+
generalisedModelPayload.modelType = 'DOC_EXTRACTION_V2'
66+
const result = generalisedModelSchema.safeParse(generalisedModelPayload)
67+
assert(result.success === true)
68+
expect(result.data.modelType).toEqual({ DOC_EXTRACTION_V2: {} })
69+
})
70+
71+
it('should return null if model type is not a valid model type', () => {
72+
generalisedModelPayload.modelType = 'INVALID_MODEL_TYPE'
73+
const result = generalisedModelSchema.safeParse(generalisedModelPayload)
74+
assert(result.success === true)
75+
expect(result.data.modelType).toBeNull()
76+
})
77+
78+
it('should return null if no model type provided (for backward compatibility)', () => {
79+
delete generalisedModelPayload.modelType
80+
const result = generalisedModelSchema.safeParse(generalisedModelPayload)
81+
assert(result.success === true)
82+
expect(result.data.modelType).toBeNull()
83+
})
84+
})
5585
})
5686

5787
describe('specific model schema', () => {

packages/backend/src/apps/aisay/actions/use-generalised-model/index.ts

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ import logger from '@/helpers/logger'
55
import Step from '@/models/step'
66

77
import { getToken } from '../../auth/get-token'
8+
import {
9+
DEFAULT_GENERALISED_MODEL_TYPE,
10+
GENERALISED_MODEL_OPTIONS,
11+
} from '../../common/constants'
812
import { parseError } from '../../common/error-parser'
913
import { generalisedModelSchema } from '../../common/schema'
1014
import { getAttachmentFromS3, getValidationError } from '../../common/utils'
@@ -16,6 +20,16 @@ const action: IRawAction = {
1620
key: 'useGeneralisedModel',
1721
description: 'Optimised for standard and non-standard documents',
1822
arguments: [
23+
{
24+
label: 'Model type',
25+
key: 'modelType',
26+
type: 'dropdown',
27+
required: true,
28+
variables: false,
29+
showOptionValue: false,
30+
options: GENERALISED_MODEL_OPTIONS,
31+
value: DEFAULT_GENERALISED_MODEL_TYPE,
32+
},
1933
{
2034
label: 'File',
2135
key: 'file',
@@ -50,35 +64,32 @@ const action: IRawAction = {
5064
getDataOutMetadata,
5165

5266
async run($) {
53-
const { file, prompts } = $.step.parameters as {
54-
file: string
55-
prompts: Array<{ prompt: string }>
56-
}
67+
const result = generalisedModelSchema.safeParse($.step.parameters)
68+
if (!result.success) {
69+
const { stepErrorName, stepErrorSolution } = getValidationError(result)
5770

58-
if (!$.auth.data?.clientId || !$.auth.data?.clientSecret) {
5971
throw new StepError(
60-
'Missing client ID or client secret',
61-
'Please check the client ID and client secret',
72+
stepErrorName,
73+
stepErrorSolution,
6274
$.step.position,
6375
$.app.name,
6476
)
6577
}
6678

67-
const result = generalisedModelSchema.safeParse({ file, prompts })
68-
if (!result.success) {
69-
const { stepErrorName, stepErrorSolution } = getValidationError(result)
70-
79+
if (!$.auth.data?.clientId || !$.auth.data?.clientSecret) {
7180
throw new StepError(
72-
stepErrorName,
73-
stepErrorSolution,
81+
'Missing client ID or client secret',
82+
'Please check the client ID and client secret',
7483
$.step.position,
7584
$.app.name,
7685
)
7786
}
7887

7988
try {
89+
const { file, prompts, modelType } = result.data
90+
8091
// get attachment from S3 first
81-
const attachment = await getAttachmentFromS3(result.data.file, $.flow.id)
92+
const attachment = await getAttachmentFromS3(file, $.flow.id)
8293

8394
// Step 1: get AWS Cognito access token
8495
const token = await getToken($)
@@ -93,7 +104,8 @@ const action: IRawAction = {
93104
Authorization: `Bearer ${token}`,
94105
},
95106
data: {
96-
gpt_query: result.data.prompts,
107+
...(modelType && { additional_features: modelType }),
108+
gpt_query: prompts,
97109
image: attachment.data,
98110
},
99111
})

packages/backend/src/apps/aisay/common/constants.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,9 @@ export const DOCUMENT_TYPES = [
55
'PASSPORT',
66
'RECEIPT',
77
]
8+
9+
export const DEFAULT_GENERALISED_MODEL_TYPE = 'standard'
10+
export const GENERALISED_MODEL_OPTIONS = [
11+
{ label: 'Standard', value: DEFAULT_GENERALISED_MODEL_TYPE }, // LLM
12+
{ label: 'Vision', value: 'DOC_EXTRACTION_V2' }, // VLM
13+
]

packages/backend/src/apps/aisay/common/schema.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@ import { z } from 'zod'
22

33
import { parseS3Id } from '@/helpers/s3'
44

5-
import { DOCUMENT_TYPES } from './constants'
5+
import {
6+
DEFAULT_GENERALISED_MODEL_TYPE,
7+
DOCUMENT_TYPES,
8+
GENERALISED_MODEL_OPTIONS,
9+
} from './constants'
610

711
export const fileSchema = z.string().transform((value, context) => {
812
if (!value) {
@@ -36,6 +40,29 @@ export const generalisedModelSchema = z.object({
3640
})
3741
return result
3842
}),
43+
/**
44+
* NOTE: the custom model type is indicated by the 'additonal_features' field in the request body
45+
* 1. this function returns null when using the standard model as it is not required by default.
46+
* 2. it is only included when using the vision generalised model.
47+
* API doc: https://app.swaggerhub.com/apis-docs/DAMIENSKTWORK/bgp-aisay_document_extraction_api/1.0.11#/DocumentParserRequestS3GenericV2
48+
*/
49+
modelType: z
50+
.string()
51+
.optional()
52+
.transform((value) => {
53+
if (!value || value === DEFAULT_GENERALISED_MODEL_TYPE) {
54+
return null
55+
}
56+
57+
const allowedValues = GENERALISED_MODEL_OPTIONS.map(
58+
(option) => option.value,
59+
)
60+
61+
if (!allowedValues.includes(value)) {
62+
return null
63+
}
64+
return { [value]: {} }
65+
}),
3966
})
4067

4168
export const documentTypeEnum = z.enum(DOCUMENT_TYPES as [string, ...string[]])

0 commit comments

Comments
 (0)