fix: move punctuation logic to LLM - backend returns complete joined text

The frontend no longer does separator/punctuation logic. Both Maestro
modes (generate and complete) now simply setPrompt(result). The LLM
is instructed to return the user's exact words + continuation, properly
joined. This is the right layer for text joining decisions.
This commit is contained in:
rin.kagamine committed 2026-05-31 10:51:50 -04:00
1 parent b86b4e5011
commit 78c13ccf01
2 files changed
+7 -40

No files matched your search

+4 -7
View File
@@ -127,18 +127,15 @@ Output ONLY the prompt text. No numbers, no labels, no commentary."""
MAESTRO_COMPLETE_PROMPT = """You are Maestro, an expert music prompt writer for AI music generation models (specifically Google Lyria). MAESTRO_COMPLETE_PROMPT = """You are Maestro, an expert music prompt writer for AI music generation models (specifically Google Lyria).
The user has written the beginning of a prompt and wants you to continue it. Here is what they have: The user has started writing a prompt and wants you to continue it. Here is what they have:
"{user_input}" "{user_input}"
Continue and expand their idea. Add 2-3 sentences of specific musical detail — genre, instrumentation, mood, tempo, structure, production style. Your continuation will be appended directly after their text, so: Continue their idea by adding 2-3 sentences of specific musical detail — genre, instrumentation, mood, tempo, structure, production style.
- Do NOT repeat or rephrase what they wrote Return the COMPLETE prompt: the user's EXACT words, followed by your continuation, properly joined. Do not rephrase, rewrite, or change any of the user's words. Just continue from where they left off.
- Do NOT add a period if their text ends mid-sentence
- Start naturally as if picking up from where they left off
- Be vivid and specific — a producer should be able to generate from this
Output ONLY your continuation text. No labels, no commentary, no quotes.""" Output ONLY the complete prompt text. No labels, no commentary, no quotes."""
MAESTRO_STRUCTURED_PROMPT = """You are Maestro, an expert music prompt writer for AI music generation models (specifically Google Lyria). MAESTRO_STRUCTURED_PROMPT = """You are Maestro, an expert music prompt writer for AI music generation models (specifically Google Lyria).
+3 -33
View File
@@ -187,23 +187,8 @@ export default function Generator({ onGenerate }: Props) {
<label className="text-xs text-kithara-muted">Prompt</label> <label className="text-xs text-kithara-muted">Prompt</label>
<MaestroButton <MaestroButton
prompt={prompt} prompt={prompt}
onResult={(result, mode) => { onResult={(_result, _mode) => {
if (mode === 'complete') { setPrompt(_result)
// Append continuation to existing prompt
setPrompt(prev => {
const trimmed = prev.trimEnd()
const endsWithPunct = /[.!?,;:]$/.test(trimmed)
const startsLower = /^[a-z]/.test(result)
// Already punctuated? Just space.
// Flows naturally (lowercase)? Just space.
// Otherwise: period + space for a new sentence.
const separator = (endsWithPunct || startsLower) ? ' ' : '. '
return trimmed + separator + result
})
} else {
// Generate mode: replace empty prompt
setPrompt(result)
}
setError('') setError('')
}} }}
onError={(msg) => setError(msg)} onError={(msg) => setError(msg)}
@@ -226,22 +211,7 @@ export default function Generator({ onGenerate }: Props) {
<MaestroButton <MaestroButton
prompt={Object.values(structuredPrompt).filter(Boolean).join(' ')} prompt={Object.values(structuredPrompt).filter(Boolean).join(' ')}
structured={isPro} structured={isPro}
onResult={(result, mode) => { onResult={(_result, _mode) => { /* handled by onStructuredResult */ }}
if (mode === 'complete') {
// Fallback: append to additional field
setStructuredPrompt(prev => {
const existing = prev.additional?.trim() || ''
const endsWithPunct = /[.!?,;:]$/.test(existing)
const startsLower = /^[a-z]/.test(result)
const separator = (endsWithPunct || startsLower) ? ' ' : '. '
return { ...prev, additional: existing + separator + result }
})
} else {
// Generate: put in additional
setStructuredPrompt(prev => ({ ...prev, additional: result }))
}
setError('')
}}
onStructuredResult={(fields, mode) => { onStructuredResult={(fields, mode) => {
// Structured mode: merge fields into structuredPrompt, preserving user edits // Structured mode: merge fields into structuredPrompt, preserving user edits
setStructuredPrompt(prev => ({ setStructuredPrompt(prev => ({