@@ -13,6 +13,7 @@ import BulkAiFlowPlugin from '../../plugins/adminforth-bulk-ai-flow/index.js';
1313
1414
1515import CompletionAdapterOpenAIChatGPT from '../../adapters/adminforth-completion-adapter-open-ai-chat-gpt/index.js' ;
16+ import CompletionAdapterGoogleGemini from '../../adapters/adminforth-completion-adapter-google-gemini/index.js' ;
1617import ImageGenerationAdapterOpenAI from '../../adapters/adminforth-image-generation-adapter-openai/index.js' ;
1718import AdminForthStorageAdapterLocalFilesystem from "../../adapters/adminforth-storage-adapter-local/index.js" ;
1819import AdminForthAdapterS3Storage from '../../adapters/adminforth-storage-adapter-amazon-s3/index.js' ;
@@ -96,6 +97,10 @@ export default function carsResourseTemplate(resourceId: string, dataSource: str
9697 type : AdminForthDataTypes . TEXT ,
9798 sortable : false ,
9899 showIn : { list : false } ,
100+ components : {
101+ show : "@/renderers/RichText.vue" ,
102+ list : "@/renderers/RichText.vue" ,
103+ } ,
99104 } ,
100105 {
101106 name : 'listed' ,
@@ -158,49 +163,37 @@ export default function carsResourseTemplate(resourceId: string, dataSource: str
158163
159164 *********************************************************************************/
160165 new UploadPlugin ( {
161- storageAdapter : new AdminForthStorageAdapterLocalFilesystem ( {
162- fileSystemFolder : "./images" ,
163- adminServeBaseUrl : "static/source" ,
164- mode : "public" ,
165- signingSecret : "TOP_SECRET" ,
166+ storageAdapter : new AdminForthAdapterS3Storage ( {
167+ bucket : process . env . AWS_BUCKET_NAME as string ,
168+ region : process . env . AWS_REGION as string ,
169+ accessKeyId : process . env . AWS_ACCESS_KEY_ID as string ,
170+ secretAccessKey : process . env . AWS_SECRET_ACCESS_KEY as string ,
171+ s3ACL : 'public-read' ,
166172 } ) ,
167- // storageAdapter: new AdminForthAdapterS3Storage({
168- // bucket: process.env.AWS_BUCKET_NAME as string,
169- // region: process.env.AWS_REGION as string,
170- // accessKeyId: process.env.AWS_ACCESS_KEY_ID as string,
171- // secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY as string,
172- // }),
173173 pathColumnName : 'photos' ,
174174 allowedFileExtensions : [ 'jpg' , 'jpeg' , 'png' , 'gif' , 'webm' , 'webp' ] ,
175175 maxFileSize : 1024 * 1024 * 20 , // 20 MB
176176 filePath : ( { originalFilename, originalExtension, contentType} ) =>
177- `sqlite /car_images/cars/${ originalFilename } .${ originalExtension } ` ,
177+ `${ dataSource } /car_images/cars/${ originalFilename } _ ${ Date . now ( ) } .${ originalExtension } ` ,
178178 preview : {
179179 maxShowWidth : "300px" ,
180- previewUrl : ( { filePath} ) => `/static/source/${ filePath } ` ,
181180 } ,
182181 } ) ,
183182 new UploadPlugin ( {
184- storageAdapter : new AdminForthStorageAdapterLocalFilesystem ( {
185- fileSystemFolder : "./images" ,
186- adminServeBaseUrl : "static/source" ,
187- mode : "public" ,
188- signingSecret : "TOP_SECRET" ,
183+ storageAdapter : new AdminForthAdapterS3Storage ( {
184+ bucket : process . env . AWS_BUCKET_NAME as string ,
185+ region : process . env . AWS_REGION as string ,
186+ accessKeyId : process . env . AWS_ACCESS_KEY_ID as string ,
187+ secretAccessKey : process . env . AWS_SECRET_ACCESS_KEY as string ,
188+ s3ACL : 'public-read' ,
189189 } ) ,
190- // storageAdapter: new AdminForthAdapterS3Storage({
191- // bucket: process.env.AWS_BUCKET_NAME as string,
192- // region: process.env.AWS_REGION as string,
193- // accessKeyId: process.env.AWS_ACCESS_KEY_ID as string,
194- // secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY as string,
195- // }),
196190 pathColumnName : 'promo_picture' ,
197191 allowedFileExtensions : [ 'jpg' , 'jpeg' , 'png' , 'gif' , 'webm' , 'webp' ] ,
198192 maxFileSize : 1024 * 1024 * 20 , // 20 MB
199193 filePath : ( { originalFilename, originalExtension, contentType} ) =>
200- `sqlite /car_images/cars_promo_images/${ originalFilename } _${ Date . now ( ) } .${ originalExtension } ` ,
194+ `${ dataSource } /car_images/cars_promo_images/${ originalFilename } _${ Date . now ( ) } .${ originalExtension } ` ,
201195 preview : {
202196 maxShowWidth : "300px" ,
203- previewUrl : ( { filePath} ) => `/static/source/${ filePath } ` ,
204197 } ,
205198 } ) ,
206199 new RichEditorPlugin ( {
@@ -240,79 +233,95 @@ export default function carsResourseTemplate(resourceId: string, dataSource: str
240233 ...( process . env . OPENAI_API_KEY ?
241234 [
242235 new UploadPlugin ( {
243- storageAdapter : new AdminForthStorageAdapterLocalFilesystem ( {
244- fileSystemFolder : "./images" ,
245- adminServeBaseUrl : "static/source" ,
246- mode : "public" ,
247- signingSecret : "TOP_SECRET" ,
236+ storageAdapter : new AdminForthAdapterS3Storage ( {
237+ bucket : process . env . AWS_BUCKET_NAME as string ,
238+ region : process . env . AWS_REGION as string ,
239+ accessKeyId : process . env . AWS_ACCESS_KEY_ID as string ,
240+ secretAccessKey : process . env . AWS_SECRET_ACCESS_KEY as string ,
241+ s3ACL : 'public-read' ,
248242 } ) ,
249- // storageAdapter: new AdminForthAdapterS3Storage({
250- // bucket: process.env.AWS_BUCKET_NAME as string,
251- // region: process.env.AWS_REGION as string,
252- // accessKeyId: process.env.AWS_ACCESS_KEY_ID as string,
253- // secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY as string,
254- // }),
255243 pathColumnName : 'generated_promo_picture' ,
256244 allowedFileExtensions : [ 'jpg' , 'jpeg' , 'png' , 'gif' , 'webm' , 'webp' ] ,
257245 maxFileSize : 1024 * 1024 * 20 , // 20 MB
258246 filePath : ( { originalFilename, originalExtension, contentType} ) =>
259- `sqlite /car_images/cars_promo_images_generated/${ originalFilename } .${ originalExtension } ` ,
247+ `${ dataSource } /car_images/cars_promo_images_generated/${ originalFilename } _ ${ Date . now ( ) } .${ originalExtension } ` ,
260248 preview : {
261249 maxShowWidth : "300px" ,
262- previewUrl : ( { filePath} ) => `/static/source/${ filePath } ` ,
263250 } ,
264251 generation : {
265- countToGenerate : 2 , // how much images generate in one shot
252+ countToGenerate : 2 ,
266253 adapter : new ImageGenerationAdapterOpenAI ( {
267254 openAiApiKey : process . env . OPENAI_API_KEY as string ,
268255 model : 'gpt-image-1' ,
269256 } ) ,
270257 fieldsForContext : [ 'description' , 'model' , 'color' , 'body_type' , 'engine_type' ] ,
271- outputSize : '1536x1024' // size of generated image
258+ outputSize : '1536x1024'
272259 }
273260 } ) ,
274261 new TextCompletePlugin ( {
275262 fieldName : 'model' ,
276263 adapter : new CompletionAdapterOpenAIChatGPT ( {
277264 openAiApiKey : process . env . OPENAI_API_KEY as string ,
278- model : 'gpt-4o' , // default "gpt-4o-mini"
265+ model : 'gpt-4o' ,
279266 expert : {
280- temperature : 0.7 //Model temperature, default 0.7
267+ temperature : 0.7
281268 }
282269 } ) ,
283270 } ) ,
284271 new BulkAiFlowPlugin ( {
285- actionName : 'Analyze' ,
286- attachFiles : async ( { record } : { record : any } ) => {
287- if ( ! record . promo_picture ) {
288- return [ ] ;
289- }
290- afLogger . info ( `Attaching file for analysis: http://localhost:3000/static/source/cars_promo_images/${ record . promo_picture } ` ) ;
291- return [ `http://localhost:3000/static/source/${ record . promo_picture } ` ] ;
272+ actionName : 'Generate description and Price' ,
273+ askConfirmationBeforeGenerating : true ,
274+ textCompleteAdapter : new CompletionAdapterGoogleGemini ( {
275+ geminiApiKey : process . env . GEMINI_API_KEY as string ,
276+ expert : {
277+ temperature : 0.7
278+ }
279+ } ) ,
280+ fillPlainFields : {
281+ description : "Create a desription for the car with name {{model}} and engine type {{engine_type}}." ,
282+ price : "Based on the car model {{model}} and engine type {{engine_type}}, suggest a competitive market price in USD."
283+ }
284+ } ) ,
285+ new BulkAiFlowPlugin ( {
286+ actionName : 'Analyze image' ,
287+ askConfirmationBeforeGenerating : true ,
288+ visionAdapter : new AdminForthImageVisionAdapterOpenAi ( {
289+ openAiApiKey : process . env . OPENAI_API_KEY as string ,
290+ model : 'gpt-4.1-mini' ,
291+ } ) ,
292+ fillFieldsFromImages : {
293+ body_type : "What is the body type of the car shown in the image?" ,
294+ color : "What is the color of the car shown in the image?" ,
295+ mileage : "Estimate the mileage of the car shown in the image in kilometers." ,
292296 } ,
293- visionAdapter : new AdminForthImageVisionAdapterOpenAi (
294- {
295- openAiApiKey : process . env . OPENAI_API_KEY as string ,
296- model : 'gpt-4.1-mini' ,
297+ attachFiles : async ( { record } ) => {
298+ if ( ! record . promo_picture ) {
299+ return [ ] ;
297300 }
298- ) ,
301+ return [ `https://tmpbucket-adminforth.s3.eu-central-1.amazonaws.com/${ record . promo_picture } ` ] ;
302+ } ,
303+ } ) ,
304+ new BulkAiFlowPlugin ( {
305+ actionName : 'Generate promo image' ,
306+ askConfirmationBeforeGenerating : true ,
299307 imageGenerationAdapter : new ImageGenerationAdapterOpenAI ( {
300308 openAiApiKey : process . env . OPENAI_API_KEY as string ,
301309 model : 'gpt-image-1' ,
302310 } ) ,
303- fillFieldsFromImages : {
304- color : "Which color is the car in the image?" ,
305- body_type : "What is the body type of the car in the image?" ,
306- production_year : "What is the production year of the car in the image?" ,
311+ generateImages : {
312+ generated_promo_picture : {
313+ countToGenerate : 1 ,
314+ outputSize : '1536x1024' ,
315+ prompt : "Create a high-quality promotional image for a {{color}} car shown on attached image. Generated image should be in anime style" ,
316+ }
317+ } ,
318+
319+ attachFiles : async ( { record } ) => {
320+ if ( ! record . promo_picture ) {
321+ return [ ] ;
322+ }
323+ return [ `https://tmpbucket-adminforth.s3.eu-central-1.amazonaws.com/${ record . promo_picture } ` ] ;
307324 } ,
308- // generateImages: {
309- // generated_promo_picture: {
310- // prompt: 'Transform this photo into a cartoon-style car picture. Imagine that we are in 90s japan and this car was tuned for the drifting competitions.',
311- // outputSize: '1024x1024',
312- // countToGenerate: 2,
313- // rateLimit: '3/1h'
314- // },
315- // },
316325 } ) ,
317326 ] : [ ] ) ,
318327 ] ,
0 commit comments