@@ -237,31 +237,33 @@ export default class BulkAiFlowPlugin extends AdminForthPlugin {
237237
238238 //recieve image URLs to analyze
239239 const attachmentFiles = await this . options . attachFiles ( { record : record } ) ;
240- //create prompt for OpenAI
241- const compiledOutputFields = this . compileOutputFieldsTemplates ( record ) ;
242- const prompt = `Analyze the following image(s) and return a single JSON in format like: {'param1': 'value1', 'param2': 'value2'}.
243- Do NOT return array of objects. Do NOT include any Markdown, code blocks, explanations, or extra text. Only return valid JSON.
244- Each object must contain the following fields: ${ JSON . stringify ( compiledOutputFields ) } Use the exact field names. If it's number field - return only number.
245- Image URLs:` ;
246-
247- //send prompt to OpenAI and get response
248- const chatResponse = await this . options . visionAdapter . generate ( { prompt, inputFileUrls : attachmentFiles } ) ;
249-
250- const resp : any = ( chatResponse as any ) . response ;
251- const topLevelError = ( chatResponse as any ) . error ;
252- if ( topLevelError || resp ?. error ) {
253- throw new Error ( `ERROR: ${ JSON . stringify ( topLevelError || resp ?. error ) } ` ) ;
254- }
240+ if ( attachmentFiles . length !== 0 ) {
241+ //create prompt for OpenAI
242+ const compiledOutputFields = this . compileOutputFieldsTemplates ( record ) ;
243+ const prompt = `Analyze the following image(s) and return a single JSON in format like: {'param1': 'value1', 'param2': 'value2'}.
244+ Do NOT return array of objects. Do NOT include any Markdown, code blocks, explanations, or extra text. Only return valid JSON.
245+ Each object must contain the following fields: ${ JSON . stringify ( compiledOutputFields ) } Use the exact field names. If it's number field - return only number.
246+ Image URLs:` ;
247+
248+ //send prompt to OpenAI and get response
249+ const chatResponse = await this . options . visionAdapter . generate ( { prompt, inputFileUrls : attachmentFiles } ) ;
250+
251+ const resp : any = ( chatResponse as any ) . response ;
252+ const topLevelError = ( chatResponse as any ) . error ;
253+ if ( topLevelError || resp ?. error ) {
254+ throw new Error ( `ERROR: ${ JSON . stringify ( topLevelError || resp ?. error ) } ` ) ;
255+ }
255256
256- const textOutput = resp ?. output ?. [ 0 ] ?. content ?. [ 0 ] ?. text ?? resp ?. output_text ?? resp ?. choices ?. [ 0 ] ?. message ?. content ;
257- if ( ! textOutput || typeof textOutput !== 'string' ) {
258- throw new Error ( 'Unexpected AI response format' ) ;
259- }
257+ const textOutput = resp ?. output ?. [ 0 ] ?. content ?. [ 0 ] ?. text ?? resp ?. output_text ?? resp ?. choices ?. [ 0 ] ?. message ?. content ;
258+ if ( ! textOutput || typeof textOutput !== 'string' ) {
259+ throw new Error ( 'Unexpected AI response format' ) ;
260+ }
260261
261- //parse response and update record
262- const resData = JSON . parse ( textOutput ) ;
262+ //parse response and update record
263+ const resData = JSON . parse ( textOutput ) ;
263264
264- return resData ;
265+ return resData ;
266+ } ;
265267 } ) ;
266268
267269 const result = await Promise . all ( tasks ) ;
@@ -386,7 +388,7 @@ export default class BulkAiFlowPlugin extends AdminForthPlugin {
386388 console . error ( `Error setting tag to true for object ${ oldRecord [ value ] } . File will not be auto-cleaned up` , e ) ;
387389 }
388390 }
389- if ( fieldsToUpdate [ idx ] [ key ] !== null ) {
391+ if ( fieldsToUpdate [ idx ] [ key ] && fieldsToUpdate [ idx ] [ key ] !== null ) {
390392 // remove tag from new file
391393 // in this case we let it crash if it fails: this is a new file which just was uploaded.
392394 await columnPlugin . pluginOptions . storageAdapter . markKeyForNotDeletation ( fieldsToUpdate [ idx ] [ value ] ) ;
@@ -479,27 +481,31 @@ export default class BulkAiFlowPlugin extends AdminForthPlugin {
479481 const fieldTasks = Object . keys ( this . options ?. generateImages || { } ) . map ( async ( key ) => {
480482 const prompt = this . compileGenerationFieldTemplates ( record ) [ key ] ;
481483 let images ;
482- if ( STUB_MODE ) {
483- await new Promise ( ( resolve ) => setTimeout ( resolve , 2000 ) ) ;
484- images = `https://picsum.photos/200/300?random=${ Math . floor ( Math . random ( ) * 1000 ) } ` ;
484+ if ( this . options . attachFiles && attachmentFiles . length === 0 ) {
485+ return { key, images : [ ] } ;
485486 } else {
486- let generationAdapter ;
487- if ( this . options . generateImages [ key ] . adapter ) {
488- generationAdapter = this . options . generateImages [ key ] . adapter ;
487+ if ( STUB_MODE ) {
488+ await new Promise ( ( resolve ) => setTimeout ( resolve , 2000 ) ) ;
489+ images = `https://picsum.photos/200/300?random= ${ Math . floor ( Math . random ( ) * 1000 ) } ` ;
489490 } else {
490- generationAdapter = this . options . imageGenerationAdapter ; ``
491- }
492- const resp = await generationAdapter . generate (
493- {
494- prompt,
495- inputFiles : attachmentFiles ,
496- n : 1 ,
497- size : this . options . generateImages [ key ] . outputSize ,
491+ let generationAdapter ;
492+ if ( this . options . generateImages [ key ] . adapter ) {
493+ generationAdapter = this . options . generateImages [ key ] . adapter ;
494+ } else {
495+ generationAdapter = this . options . imageGenerationAdapter ; ``
498496 }
499- )
500- images = resp . imageURLs [ 0 ] ;
501- }
502- return { key, images } ;
497+ const resp = await generationAdapter . generate (
498+ {
499+ prompt,
500+ inputFiles : attachmentFiles ,
501+ n : 1 ,
502+ size : this . options . generateImages [ key ] . outputSize ,
503+ }
504+ )
505+ images = resp . imageURLs [ 0 ] ;
506+ }
507+ return { key, images } ;
508+ }
503509 } ) ;
504510
505511 const fieldResults = await Promise . all ( fieldTasks ) ;
0 commit comments