diff --git a/src/app/api/ai-settings/library/[id]/route.ts b/src/app/api/ai-settings/library/[id]/route.ts index b6afdc4..a274842 100644 --- a/src/app/api/ai-settings/library/[id]/route.ts +++ b/src/app/api/ai-settings/library/[id]/route.ts @@ -38,6 +38,10 @@ export async function PUT( promptTagger: typeof body.promptTagger === 'string' ? body.promptTagger : undefined, promptExtract: typeof body.promptExtract === 'string' ? body.promptExtract : undefined, promptTranslate: typeof body.promptTranslate === 'string' ? body.promptTranslate : undefined, + maxTokensTag: typeof body.maxTokensTag === 'number' ? body.maxTokensTag : (body.maxTokensTag === null ? null : undefined), + maxTokensDescribe: typeof body.maxTokensDescribe === 'number' ? body.maxTokensDescribe : (body.maxTokensDescribe === null ? null : undefined), + maxTokensExtract: typeof body.maxTokensExtract === 'number' ? body.maxTokensExtract : (body.maxTokensExtract === null ? null : undefined), + maxTokensTranslate: typeof body.maxTokensTranslate === 'number' ? body.maxTokensTranslate : (body.maxTokensTranslate === null ? null : undefined), }) return NextResponse.json(getLibraryAiOverrides(id)) diff --git a/src/app/api/ai-settings/route.ts b/src/app/api/ai-settings/route.ts index 219e559..1de721b 100644 --- a/src/app/api/ai-settings/route.ts +++ b/src/app/api/ai-settings/route.ts @@ -30,6 +30,10 @@ export async function PUT(request: NextRequest) { promptExtract?: string promptTranslate?: string maxRetries?: number + maxTokensTag?: number + maxTokensDescribe?: number + maxTokensExtract?: number + maxTokensTranslate?: number } try { body = await request.json() @@ -42,6 +46,7 @@ export async function PUT(request: NextRequest) { modelTagging, modelDescribe, modelExtract, modelTranslate, promptDescribe, promptTagger, promptExtract, promptTranslate, maxRetries, + maxTokensTag, maxTokensDescribe, maxTokensExtract, maxTokensTranslate, } = body if (typeof endpoint !== 'string') { @@ -66,6 +71,10 @@ export async function PUT(request: NextRequest) { typeof promptTagger === 'string' ? promptTagger : undefined, typeof promptExtract === 'string' ? promptExtract : undefined, typeof promptTranslate === 'string' ? promptTranslate : undefined, + typeof maxTokensTag === 'number' ? maxTokensTag : undefined, + typeof maxTokensDescribe === 'number' ? maxTokensDescribe : undefined, + typeof maxTokensExtract === 'number' ? maxTokensExtract : undefined, + typeof maxTokensTranslate === 'number' ? maxTokensTranslate : undefined, ) if (typeof preferredLanguage === 'string' && preferredLanguage.trim()) { diff --git a/src/app/manage/ai-tagging/page.tsx b/src/app/manage/ai-tagging/page.tsx index e45b65c..c3db484 100644 --- a/src/app/manage/ai-tagging/page.tsx +++ b/src/app/manage/ai-tagging/page.tsx @@ -16,6 +16,10 @@ interface AiSettings { promptExtract: string promptTranslate: string maxRetries: number + maxTokensTag: number + maxTokensDescribe: number + maxTokensExtract: number + maxTokensTranslate: number } interface AiJob { @@ -47,6 +51,10 @@ interface LibraryOverride { promptTagger: string promptExtract: string promptTranslate: string + maxTokensTag: number | null + maxTokensDescribe: number | null + maxTokensExtract: number | null + maxTokensTranslate: number | null } function formatElapsed(startedAt: number): string { @@ -67,6 +75,7 @@ export default function AiTaggingPage() { enabled: false, preferredLanguage: 'English', promptDescribe: '', promptTagger: '', promptExtract: '', promptTranslate: '', maxRetries: 3, + maxTokensTag: 8192, maxTokensDescribe: 8192, maxTokensExtract: 8192, maxTokensTranslate: 8192, }) const [loading, setLoading] = useState(true) const [saving, setSaving] = useState(false) @@ -296,7 +305,7 @@ export default function AiTaggingPage() { } } - const updateLibraryOverride = (libraryId: string, field: keyof LibraryOverride, value: string) => { + const updateLibraryOverride = (libraryId: string, field: keyof LibraryOverride, value: string | number | null) => { setLibraryOverrides((prev) => ({ ...prev, [libraryId]: { ...(prev[libraryId] ?? emptyOverride()), [field]: value }, @@ -544,6 +553,25 @@ export default function AiTaggingPage() { /> + + + setSettings((s) => ({ ...s, maxTokensTag: Math.max(1, parseInt(e.target.value) || 8192) })) + } + className="w-32 rounded-lg px-3 py-2 text-sm outline-none focus:ring-2" + style={{ + backgroundColor: 'var(--background)', + border: '1px solid var(--border)', + color: 'var(--text-primary)', + }} + onFocus={(e) => ((e.currentTarget as HTMLElement).style.borderColor = 'var(--accent)')} + onBlur={(e) => ((e.currentTarget as HTMLElement).style.borderColor = 'var(--border)')} + /> + + + + + setSettings((s) => ({ ...s, maxTokensDescribe: Math.max(1, parseInt(e.target.value) || 8192) })) + } + className="w-32 rounded-lg px-3 py-2 text-sm outline-none focus:ring-2" + style={{ + backgroundColor: 'var(--background)', + border: '1px solid var(--border)', + color: 'var(--text-primary)', + }} + onFocus={(e) => ((e.currentTarget as HTMLElement).style.borderColor = 'var(--accent)')} + onBlur={(e) => ((e.currentTarget as HTMLElement).style.borderColor = 'var(--border)')} + /> + + + + + setSettings((s) => ({ ...s, maxTokensExtract: Math.max(1, parseInt(e.target.value) || 8192) })) + } + className="w-32 rounded-lg px-3 py-2 text-sm outline-none focus:ring-2" + style={{ + backgroundColor: 'var(--background)', + border: '1px solid var(--border)', + color: 'var(--text-primary)', + }} + onFocus={(e) => ((e.currentTarget as HTMLElement).style.borderColor = 'var(--accent)')} + onBlur={(e) => ((e.currentTarget as HTMLElement).style.borderColor = 'var(--border)')} + /> + + + + + setSettings((s) => ({ ...s, maxTokensTranslate: Math.max(1, parseInt(e.target.value) || 8192) })) + } + className="w-32 rounded-lg px-3 py-2 text-sm outline-none focus:ring-2" + style={{ + backgroundColor: 'var(--background)', + border: '1px solid var(--border)', + color: 'var(--text-primary)', + }} + onFocus={(e) => ((e.currentTarget as HTMLElement).style.borderColor = 'var(--accent)')} + onBlur={(e) => ((e.currentTarget as HTMLElement).style.borderColor = 'var(--border)')} + /> + +