Allow AI model override

This commit is contained in:
Sam Becker 2026-01-30 20:42:47 -06:00
parent bcb37d93e6
commit 3edc64d5cf
4 changed files with 26 additions and 4 deletions

View File

@ -92,7 +92,8 @@ To auto-generate text descriptions of photo:
1. Setup OpenAI
- Create [OpenAI](https://openai.com) account and fund it ([see thread](https://github.com/sambecker/exif-photo-blog/issues/110) if you're having issues)
- Setup usage limits to avoid unexpected charges (_recommended_)
- Set `OPENAI_BASE_URL` in order to use alternate OpenAI-compatible providers (experimental)
- Set `OPENAI_MODEL` to choose a specific model (set to 'compatible' to use gpt-4o)
- Set `OPENAI_BASE_URL` to use alternate OpenAI-compatible providers (experimental)
2. Generate API key and store in environment variable `OPENAI_SECRET_KEY` (enable Responses API write access if customizing permissions)
3. Add [rate limiting](#rate-limiting) (_recommended_)
4. Configure auto-generated fields (optional)

View File

@ -81,6 +81,7 @@ export default function AdminAppConfigurationClient({
imageQuality,
isBlurEnabled,
// AI
hasOpenaiModel,
hasOpenaiBaseUrl,
isAiTextGenerationEnabled,
aiTextAutoGeneratedFields,
@ -555,6 +556,17 @@ export default function AdminAppConfigurationClient({
)}):
{renderEnvVars(['AI_TEXT_AUTO_GENERATED_FIELDS'])}
</ChecklistRow>
<ChecklistRow
title="Model override"
status={hasOpenaiModel}
optional
>
Store model in environment variable to use
alternate OpenAI model
{' '}
{'(set to \'compatible\' to use gpt-4o):'}
{renderEnvVars(['OPENAI_MODEL'])}
</ChecklistRow>
<ChecklistRow
title="Base URL override (experimental)"
status={hasOpenaiBaseUrl}

View File

@ -257,6 +257,7 @@ export const BLUR_ENABLED =
// AI
export const OPENAI_SECRET_KEY = process.env.OPENAI_SECRET_KEY;
export const OPENAI_MODEL = process.env.OPENAI_MODEL;
export const OPENAI_BASE_URL = process.env.OPENAI_BASE_URL;
export const AI_CONTENT_GENERATION_ENABLED = Boolean(OPENAI_SECRET_KEY);
export const AI_TEXT_AUTO_GENERATED_FIELDS = parseAiAutoGeneratedFieldsString(
@ -453,6 +454,7 @@ export const APP_CONFIGURATION = {
imageQuality: IMAGE_QUALITY,
isBlurEnabled: BLUR_ENABLED,
// AI
hasOpenaiModel: Boolean(OPENAI_MODEL),
hasOpenaiBaseUrl: Boolean(OPENAI_BASE_URL),
isAiTextGenerationEnabled: AI_CONTENT_GENERATION_ENABLED,
aiTextAutoGeneratedFields: process.env.AI_TEXT_AUTO_GENERATED_FIELDS

View File

@ -1,7 +1,7 @@
import { generateText, Output, streamText } from 'ai';
import { createStreamableValue } from '@ai-sdk/rsc';
import { createOpenAI } from '@ai-sdk/openai';
import { OPENAI_BASE_URL, OPENAI_SECRET_KEY } from '@/app/config';
import { OPENAI_BASE_URL, OPENAI_MODEL, OPENAI_SECRET_KEY } from '@/app/config';
import { removeBase64Prefix } from '@/utility/image';
import { cleanUpAiTextResponse } from '@/photo/ai';
import {
@ -9,14 +9,21 @@ import {
} from '@/platforms/rate-limit';
import { z } from 'zod';
type OpenAIModel = Parameters<NonNullable<typeof openai>>[0];
const MODEL_DEFAULT: OpenAIModel = 'gpt-5.2';
const MODEL_COMPATIBLE: OpenAIModel = 'gpt-4o';
const MODEL: OpenAIModel = OPENAI_MODEL === 'compatible'
? MODEL_COMPATIBLE
: (OPENAI_MODEL || MODEL_DEFAULT);
const checkRateLimitAndThrow = (isBatch?: boolean) =>
_checkRateLimitAndThrow({
identifier: 'openai-image-query',
...isBatch && { tokens: 1200, duration: '1d' },
});
const MODEL: Parameters<NonNullable<typeof openai>>[0] = 'gpt-5.2';
const openai = OPENAI_SECRET_KEY
? createOpenAI({
apiKey: OPENAI_SECRET_KEY,