Refactor AI server action code

This commit is contained in:
Sam Becker 2024-03-19 20:07:56 -05:00
parent 137b718fb7
commit fdd392bf25
4 changed files with 39 additions and 26 deletions

View File

@ -44,7 +44,7 @@ export const {
},
});
export const safelyRunServerAdminAction = async <T>(
export const safelyRunAdminServerAction = async <T>(
callback: () => T,
): Promise<T> => {
const session = await auth();

View File

@ -33,10 +33,11 @@ import {
import { extractExifDataFromBlobPath } from './server';
import { TAG_FAVS, isTagFavs } from '@/tag';
import { convertPhotoToPhotoDbInsert } from '.';
import { safelyRunServerAdminAction } from '@/auth';
import { safelyRunAdminServerAction } from '@/auth';
import { ImageQuery, streamImageQuery } from './ai';
export async function createPhotoAction(formData: FormData) {
return safelyRunServerAdminAction(async () => {
return safelyRunAdminServerAction(async () => {
const photo = convertFormDataToPhotoDbInsert(formData, true);
const updatedUrl = await convertUploadToPhoto(photo.url, photo.id);
@ -52,7 +53,7 @@ export async function createPhotoAction(formData: FormData) {
}
export async function updatePhotoAction(formData: FormData) {
return safelyRunServerAdminAction(async () => {
return safelyRunAdminServerAction(async () => {
const photo = convertFormDataToPhotoDbInsert(formData);
await sqlUpdatePhoto(photo);
@ -67,7 +68,7 @@ export async function toggleFavoritePhotoAction(
photoId: string,
shouldRedirect?: boolean,
) {
return safelyRunServerAdminAction(async () => {
return safelyRunAdminServerAction(async () => {
const photo = await getPhoto(photoId);
if (photo) {
const { tags } = photo;
@ -88,7 +89,7 @@ export async function deletePhotoAction(
photoUrl: string,
shouldRedirect?: boolean,
) {
return safelyRunServerAdminAction(async () => {
return safelyRunAdminServerAction(async () => {
await sqlDeletePhoto(photoId).then(() => deleteStorageUrl(photoUrl));
revalidateAllKeysAndPaths();
if (shouldRedirect) {
@ -98,7 +99,7 @@ export async function deletePhotoAction(
};
export async function deletePhotoFormAction(formData: FormData) {
return safelyRunServerAdminAction(async () =>
return safelyRunAdminServerAction(async () =>
deletePhotoAction(
formData.get('id') as string,
formData.get('url') as string,
@ -107,7 +108,7 @@ export async function deletePhotoFormAction(formData: FormData) {
};
export async function deletePhotoTagGloballyAction(formData: FormData) {
return safelyRunServerAdminAction(async () => {
return safelyRunAdminServerAction(async () => {
const tag = formData.get('tag') as string;
await sqlDeletePhotoTagGlobally(tag);
@ -118,7 +119,7 @@ export async function deletePhotoTagGloballyAction(formData: FormData) {
}
export async function renamePhotoTagGloballyAction(formData: FormData) {
return safelyRunServerAdminAction(async () => {
return safelyRunAdminServerAction(async () => {
const tag = formData.get('tag') as string;
const updatedTag = formData.get('updatedTag') as string;
@ -132,7 +133,7 @@ export async function renamePhotoTagGloballyAction(formData: FormData) {
}
export async function deleteBlobPhotoAction(formData: FormData) {
return safelyRunServerAdminAction(async () => {
return safelyRunAdminServerAction(async () => {
await deleteStorageUrl(formData.get('url') as string);
revalidateAdminPaths();
@ -146,7 +147,7 @@ export async function deleteBlobPhotoAction(formData: FormData) {
export async function getExifDataAction(
photoFormPrevious: Partial<PhotoFormData>,
): Promise<Partial<PhotoFormData>> {
return safelyRunServerAdminAction(async () => {
return safelyRunAdminServerAction(async () => {
const { url } = photoFormPrevious;
if (url) {
const { photoFormExif } = await extractExifDataFromBlobPath(url);
@ -159,7 +160,7 @@ export async function getExifDataAction(
}
export async function syncPhotoExifDataAction(formData: FormData) {
return safelyRunServerAdminAction(async () => {
return safelyRunAdminServerAction(async () => {
const photoId = formData.get('id') as string;
if (photoId) {
const photo = await getPhoto(photoId);
@ -179,5 +180,13 @@ export async function syncPhotoExifDataAction(formData: FormData) {
}
export async function syncCacheAction() {
return safelyRunServerAdminAction(revalidateAllKeysAndPaths);
return safelyRunAdminServerAction(revalidateAllKeysAndPaths);
}
export async function streamImageQueryAction(
imageBase64: string,
query: ImageQuery,
) {
return safelyRunAdminServerAction(async () =>
streamImageQuery(imageBase64, query));
}

13
src/photo/ai.ts Normal file
View File

@ -0,0 +1,13 @@
import { streamOpenAiImageQuery } from '@/services/openai';
export type ImageQuery = 'title' | 'caption' | 'tags' | 'description';
export const IMAGE_QUERIES: Record<ImageQuery, string> = {
title: 'What is the title of this image?',
caption: 'What is the caption of this image?',
tags: 'Describe this image three or less comma-separated keywords',
description: 'Describe this image in detail',
};
export const streamImageQuery = (imageBase64: string, query: ImageQuery) =>
streamOpenAiImageQuery(imageBase64, IMAGE_QUERIES[query]);

View File

@ -5,7 +5,10 @@ import { createStreamableValue, render } from 'ai/rsc';
const provider = new OpenAI({ apiKey: process.env.OPENAI_SECRET_KEY });
const streamImageQueryRaw = async (imageBase64: string, query: string) => {
export const streamOpenAiImageQuery = async (
imageBase64: string,
query: string,
) => {
const stream = createStreamableValue('');
render({
@ -36,15 +39,3 @@ const streamImageQueryRaw = async (imageBase64: string, query: string) => {
return stream.value;
};
export type ImageQuery = 'title' | 'caption' | 'tags' | 'description';
export const IMAGE_QUERIES: Record<ImageQuery, string> = {
title: 'What is the title of this image?',
caption: 'What is the caption of this image?',
tags: 'Describe this image three or less comma-separated keywords',
description: 'Describe this image in detail',
};
export const streamImageQuery = (imageBase64: string, query: ImageQuery) =>
streamImageQueryRaw(imageBase64, IMAGE_QUERIES[query]);