From 141c16135fffb39e756d7fb09daebdbebf06fed6 Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Thu, 30 May 2024 13:55:05 -0500 Subject: [PATCH] Improve AI text generation error handling --- package.json | 4 +-- pnpm-lock.yaml | 20 +++++------ src/photo/actions.ts | 2 +- src/photo/ai/server.ts | 80 +++++++++++++++++++++++------------------- src/photo/index.ts | 8 ++--- 5 files changed, 61 insertions(+), 53 deletions(-) diff --git a/package.json b/package.json index 686369e1..628d3e8e 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "analyze": "ANALYZE=true next build" }, "dependencies": { - "@ai-sdk/openai": "^0.0.17", + "@ai-sdk/openai": "^0.0.18", "@aws-sdk/client-s3": "3.583.0", "@aws-sdk/s3-request-presigner": "3.583.0", "@next/bundle-analyzer": "14.2.3", @@ -30,7 +30,7 @@ "@vercel/blob": "^0.23.3", "@vercel/kv": "^2.0.0", "@vercel/speed-insights": "^1.0.11", - "ai": "^3.1.18", + "ai": "^3.1.21", "autoprefixer": "10.4.19", "camelcase-keys": "^9.1.3", "clsx": "^2.1.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9505f2e9..9fe7101a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@ai-sdk/openai': - specifier: ^0.0.17 - version: 0.0.17(zod@3.23.8) + specifier: ^0.0.18 + version: 0.0.18(zod@3.23.8) '@aws-sdk/client-s3': specifier: 3.583.0 version: 3.583.0 @@ -72,8 +72,8 @@ importers: specifier: ^1.0.11 version: 1.0.11(next@14.2.3(@babel/core@7.24.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)(svelte@4.2.17)(vue@3.4.27(typescript@5.4.5)) ai: - specifier: ^3.1.18 - version: 3.1.18(react@18.3.1)(solid-js@1.8.17)(svelte@4.2.17)(vue@3.4.27(typescript@5.4.5))(zod@3.23.8) + specifier: ^3.1.21 + version: 3.1.21(react@18.3.1)(solid-js@1.8.17)(svelte@4.2.17)(vue@3.4.27(typescript@5.4.5))(zod@3.23.8) autoprefixer: specifier: 10.4.19 version: 10.4.19(postcss@8.4.38) @@ -164,8 +164,8 @@ packages: '@adobe/css-tools@4.3.3': resolution: {integrity: sha512-rE0Pygv0sEZ4vBWHlAgJLGDU7Pm8xoO6p3wsEceb7GYAjScrOHpEo8KK/eVkAcnSM+slAEtXjA2JpdjLp4fJQQ==} - '@ai-sdk/openai@0.0.17': - resolution: {integrity: sha512-5Es+u9ICw23FZnRfRQLwn9AxkRcTDxGMFKcZjaLdj8suBeUd3B/CioUTNgXUTvfRCOPhkH/sbLrMyo746LkOAg==} + '@ai-sdk/openai@0.0.18': + resolution: {integrity: sha512-5iJ+/mbns0uLbNpACMYGUONUqQmqGJYrPbQvmGC+XVD4DZLvyZqBi0NDoQguOrZTz6u5O7rl51o9PDO+bEtmcA==} engines: {node: '>=18'} peerDependencies: zod: ^3.0.0 @@ -1704,8 +1704,8 @@ packages: resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} engines: {node: '>= 6.0.0'} - ai@3.1.18: - resolution: {integrity: sha512-/4fIiaD3uwxsnmoAPS7jWbRchImh9pDcuWs+yuTTQl+bp+FmVKgIQ1q+PIEndZI6hEq9M4/atlz2jZWcgW1bzg==} + ai@3.1.21: + resolution: {integrity: sha512-s/3L2pqbeC1EwFS0u5kyw1amtC3KOXPWzRCmEcXAK23xdv5RLlxxK8juuvdIDgGplb/AgfkJ7BjIlbmPQTYu9g==} engines: {node: '>=18'} peerDependencies: openai: ^4.42.0 @@ -4299,7 +4299,7 @@ snapshots: '@adobe/css-tools@4.3.3': {} - '@ai-sdk/openai@0.0.17(zod@3.23.8)': + '@ai-sdk/openai@0.0.18(zod@3.23.8)': dependencies: '@ai-sdk/provider': 0.0.8 '@ai-sdk/provider-utils': 0.0.11(zod@3.23.8) @@ -6440,7 +6440,7 @@ snapshots: transitivePeerDependencies: - supports-color - ai@3.1.18(react@18.3.1)(solid-js@1.8.17)(svelte@4.2.17)(vue@3.4.27(typescript@5.4.5))(zod@3.23.8): + ai@3.1.21(react@18.3.1)(solid-js@1.8.17)(svelte@4.2.17)(vue@3.4.27(typescript@5.4.5))(zod@3.23.8): dependencies: '@ai-sdk/provider': 0.0.8 '@ai-sdk/provider-utils': 0.0.11(zod@3.23.8) diff --git a/src/photo/actions.ts b/src/photo/actions.ts index b9ba4144..e3b0ac4b 100644 --- a/src/photo/actions.ts +++ b/src/photo/actions.ts @@ -325,7 +325,7 @@ export const syncPhotoAction = async (formData: FormData) => ...!photo.caption && { caption: aiCaption }, ...photo.tags.length === 0 && { tags: aiTags }, ...!photo.semanticDescription && - { semanticDescription: aiSemanticDescription }, + { semanticDescription: aiSemanticDescription }, }); await updatePhoto(photoFormDbInsert); diff --git a/src/photo/ai/server.ts b/src/photo/ai/server.ts index 367c89c0..8906f2c5 100644 --- a/src/photo/ai/server.ts +++ b/src/photo/ai/server.ts @@ -14,58 +14,65 @@ export const generateAiImageQueries = async ( caption?: string tags?: string semanticDescription?: string + error?: string }> => { let title: string | undefined; let caption: string | undefined; let tags: string | undefined; let semanticDescription: string | undefined; + let error: string | undefined; - if (imageBase64) { - if ( - textFieldsToGenerate.includes('title') && - textFieldsToGenerate.includes('caption') - ) { - const titleAndCaption = await generateOpenAiImageQuery( - imageBase64, - AI_IMAGE_QUERIES['title-and-caption'], - ); - if (titleAndCaption) { - const titleAndCaptionParsed = parseTitleAndCaption(titleAndCaption); - title = titleAndCaptionParsed.title; - caption = titleAndCaptionParsed.caption; + try { + if (imageBase64) { + if ( + textFieldsToGenerate.includes('title') && + textFieldsToGenerate.includes('caption') + ) { + const titleAndCaption = await generateOpenAiImageQuery( + imageBase64, + AI_IMAGE_QUERIES['title-and-caption'], + ); + if (titleAndCaption) { + const titleAndCaptionParsed = parseTitleAndCaption(titleAndCaption); + title = titleAndCaptionParsed.title; + caption = titleAndCaptionParsed.caption; + } + } else { + if (textFieldsToGenerate.includes('title')) { + title = cleanUpAiTextResponse( + await generateOpenAiImageQuery( + imageBase64, + AI_IMAGE_QUERIES['title'], + )); + } + if (textFieldsToGenerate.includes('caption')) { + caption = cleanUpAiTextResponse( + await generateOpenAiImageQuery( + imageBase64, + AI_IMAGE_QUERIES['caption'], + )); + } } - } else { - if (textFieldsToGenerate.includes('title')) { - title = cleanUpAiTextResponse( + + if (textFieldsToGenerate.includes('tags')) { + tags = cleanUpAiTextResponse( await generateOpenAiImageQuery( imageBase64, - AI_IMAGE_QUERIES['title'], + AI_IMAGE_QUERIES['tags'], )); } - if (textFieldsToGenerate.includes('caption')) { - caption = cleanUpAiTextResponse( + + if (textFieldsToGenerate.includes('semantic')) { + semanticDescription = cleanUpAiTextResponse( await generateOpenAiImageQuery( imageBase64, - AI_IMAGE_QUERIES['caption'], + AI_IMAGE_QUERIES['description-small'], )); } } - - if (textFieldsToGenerate.includes('tags')) { - tags = cleanUpAiTextResponse( - await generateOpenAiImageQuery( - imageBase64, - AI_IMAGE_QUERIES['tags'], - )); - } - - if (textFieldsToGenerate.includes('semantic')) { - semanticDescription = cleanUpAiTextResponse( - await generateOpenAiImageQuery( - imageBase64, - AI_IMAGE_QUERIES['description-small'], - )); - } + } catch (e: any) { + error = e.message; + console.log('Error generating AI image text', e.message); } return { @@ -73,5 +80,6 @@ export const generateAiImageQueries = async ( caption, tags, semanticDescription, + error, }; }; diff --git a/src/photo/index.ts b/src/photo/index.ts index 17b9342f..187de55c 100644 --- a/src/photo/index.ts +++ b/src/photo/index.ts @@ -22,11 +22,11 @@ export const INFINITE_SCROLL_LARGE_PHOTO_MULTIPLE = // INFINITE SCROLL: GRID PHOTOS export const INFINITE_SCROLL_GRID_PHOTO_INITIAL = HIGH_DENSITY_GRID - ? process.env.NODE_ENV === 'development' ? 8 : 24 - : process.env.NODE_ENV === 'development' ? 8 : 24; + ? process.env.NODE_ENV === 'development' ? 12 : 24 + : process.env.NODE_ENV === 'development' ? 12 : 24; export const INFINITE_SCROLL_GRID_PHOTO_MULTIPLE = HIGH_DENSITY_GRID - ? process.env.NODE_ENV === 'development' ? 8 : 48 - : process.env.NODE_ENV === 'development' ? 8 : 48; + ? process.env.NODE_ENV === 'development' ? 12 : 48 + : process.env.NODE_ENV === 'development' ? 12 : 48; // Thumbnails below /p/[photoId] export const RELATED_GRID_PHOTOS_TO_SHOW = 12;