feat: AI Rearrange Scenario Detection from spec 45_SCENARIAO_AI

- 9 rearrange scenarios with keyword matching (arpeggio, harmonies,
  syncopation, walking bass, jazz, synthwave, cinematic, simplify, chromatic)
- detectRearrangeScenario() maps user prompt to specific technique rules
- buildRearrangeMessage auto-injects scenario-specific technique guidance
- 9 rearrange presets added to PromptTemplateManager (Rearrange / Variation)
This commit is contained in:
2026-07-28 11:03:26 +07:00
parent 2eb327056d
commit 3f7abe0c95
3 changed files with 219 additions and 11 deletions
+95 -11
View File
@@ -120,29 +120,111 @@ const AIGateway = (function() {
}
};
const REARRANGE_SCENARIOS = [
{
id: 'arpeggio',
keywords: ['arpeggio', 'arp', 'broken chord', 'broken chords', 'shimmering sequence'],
description: 'Arpeggio variation',
technique: 'Subdivide sustained chord notes (longer than 0.5 beats) into sequential 0.25-beat arpeggiated interval steps using octave/triad jumps. Create a driving, shimmering sequence.'
},
{
id: 'harmonies',
keywords: ['harmony', 'harmonize', 'harmonies', '3rd', '3rds', 'duet', 'chord voicing', 'voicing'],
description: 'Add parallel harmonies',
technique: 'For each source pitch P, insert parallel harmonizing notes at pitch P+3 or P+4 (Major/Minor 3rds) matching the same start_beat. Create richer, fuller texture resembling two instruments playing in duet.'
},
{
id: 'syncopation',
keywords: ['syncopation', 'syncopate', 'syncopated', 'off-beat', 'off beat', 'funk', 'latin', 'rnb', 'r&b'],
description: 'Syncopation / off-beat feel',
technique: 'Shift start_beat alignment off strong beats (0.0, 1.0, 2.0, 3.0) onto off-beats (0.5, 1.5, 2.5, 3.5). Create a rhythmic, syncopated feel.'
},
{
id: 'walking_bass',
keywords: ['walking bass', 'bassline', 'bass line', 'walking'],
description: 'Walking bass line',
technique: 'Lower pitches to bass register (36-48 range). Build continuous quarter-note steps (1.0 beat duration) following the chord outline. Create an improvisational walking bassline.'
},
{
id: 'jazz_swing',
keywords: ['jazz', 'swing', 'bebop', 'bop', 'jazz swing'],
description: 'Jazz Swing style',
technique: 'Apply Jazz Swing characteristics: off-beat syncopation, 7th/9th chord extensions, rhythmic variations, and swung eighth notes (triplet feel). Preserve the core melodic outline while adding jazz harmony.'
},
{
id: 'synthwave',
keywords: ['synthwave', '80s', 'retro', 'synth wave', 'outrun', 'retrowave'],
description: 'Synthwave / 80s style',
technique: 'Transform into 80s Synthwave style: driving 8th-note bass arpeggios, gated reverb snare, analog synth lead with portamento, and pulsating chord pads. Use octave jumps in the bass.'
},
{
id: 'cinematic',
keywords: ['cinematic', 'orchestral', 'epic', 'film score', 'movie', 'hollywood', 'symphonic'],
description: 'Cinematic Orchestral style',
technique: 'Transform into dramatic Cinematic Orchestral style: swelling dynamics, brass stabs on downbeats, string ostinato patterns, taiko percussion hits on strong beats. Layer multiple octaves for epic width.'
},
{
id: 'simplify',
keywords: ['simplify', 'minimal', 'strip', 'downbeat', 'reduce', 'sparse'],
description: 'Simplify / strip down',
technique: 'Keep only the downbeat notes (start_beat at 0.0, 1.0, 2.0, 3.0, etc.). Strip out embellishments, passing tones, and grace notes. Reduce chord voicings to root and 5th only.'
},
{
id: 'passing_tones',
keywords: ['passing tone', 'chromatic', 'chromaticism', 'smooth', 'approach note'],
description: 'Add passing tones / chromaticism',
technique: 'Insert passing tones and chromatic approach notes between chord tones to smooth out the melodic progression. Use half-step and whole-step approach notes targeting chord tones on strong beats.'
}
];
function detectRearrangeScenario(prompt) {
if (!prompt) return null;
const lower = prompt.toLowerCase();
const matched = [];
for (const sc of REARRANGE_SCENARIOS) {
const hits = sc.keywords.filter(kw => lower.includes(kw.toLowerCase()));
if (hits.length > 0) {
matched.push({ scenario: sc, hitCount: hits.length });
}
}
matched.sort((a, b) => b.hitCount - a.hitCount);
return matched.length > 0 ? matched[0].scenario : null;
}
function buildRearrangeMessage(prompt, sourceContext) {
const notesJson = JSON.stringify(sourceContext.notes, null, 2);
const scenario = detectRearrangeScenario(prompt);
const techniqueSection = scenario
? `\nDETECTED SCENARIO: ${scenario.description}\nSPECIFIC TECHNIQUE REQUIRED: ${scenario.technique}\n`
: '';
const rules = [
'1. Use the rearrange_midi_melody tool to return the rearranged notes.',
'2. PRESERVE the core melodic outline and overall structure unless the user explicitly asks for a complete transformation.',
'3. Keep the total duration (' + sourceContext.total_beats + ' beats) the same unless user requests a different length.',
'4. The rearranged_notes array MUST contain notes with pitch (0-127), start_beat (0.0 to ' + sourceContext.total_beats + '.0), duration_beats, and velocity (0.0-1.0).',
'5. Start beats should remain within 0-' + sourceContext.total_beats + ' range.',
'6. You may add, remove, or modify notes to achieve the requested style.',
'7. ALWAYS return a rearrange_title describing what was created (e.g. "Jazz Swing Variation of Piano Lead").'
];
return [
{ role: 'system', content: `You are a professional music arranger. Your task is to rearrange/re-harmonize the provided MIDI notes based on the user's request.
{ role: 'system', content: `You are a professional Music Composer & Arranger.
SOURCE MIDI CONTEXT:
- Track: ${sourceContext.track_name}
- Item: ${sourceContext.item_name}
- Duration: ${sourceContext.duration_bars} bars (${sourceContext.total_beats} beats)
- BPM: ${sourceContext.bpm}
- Time Signature: 4/4
- Total notes: ${sourceContext.total_notes}
SOURCE NOTES (pitch, note_name, start_beat, duration_beats, velocity):
ORIGINAL MELODY NOTES (pitch, note_name, start_beat, duration_beats, velocity):
${notesJson}
RULES:
1. Use the rearrange_midi_melody tool to return the rearranged notes.
2. PRESERVE the core melodic outline and overall structure unless the user explicitly asks for a complete transformation.
3. Keep the total duration (${sourceContext.total_beats} beats) the same unless user requests a different length.
4. The rearranged_notes array MUST contain notes with pitch (0-127), start_beat (0.0 to ${sourceContext.total_beats}.0), duration_beats, and velocity (0.0-1.0).
5. Start beats should remain within 0-${sourceContext.total_beats} range.
6. You may add, remove, or modify notes to achieve the requested style.` },
{ role: 'user', content: `User request: ${prompt}\n\nRearrange the source MIDI notes above according to this request. Return the result via the rearrange_midi_melody tool.` }
${techniqueSection}
STRICT REARRANGE RULES:
${rules.join('\n')}` },
{ role: 'user', content: `${prompt}\n\nRearrange the source MIDI notes above according to this request. Return the result via the rearrange_midi_melody tool.` }
];
}
@@ -362,6 +444,8 @@ Ví dụ: "Hãy chọn và copy từ bar 4 đến bar 12 của track 1 sau đó
return {
DEFAULT_TOOLS,
REARRANGE_TOOL_SPEC,
REARRANGE_SCENARIOS,
detectRearrangeScenario,
buildRearrangeMessage,
callLLM,
extractFunctionCalls,
@@ -38,6 +38,124 @@ const PromptTemplateManager = (function() {
is_user_defined: false,
is_favorite: false,
created_at: "2026-07-23T16:00:00Z"
},
// ── Rearrange & Variation Scenarios ──
{
id: "preset_rearrange_arpeggio",
name: "Arpeggio Variation",
keywords: ["arpeggio", "arp", "broken chord", "arpeggiate"],
category: "Rearrange / Variation",
default_bars: 8,
default_bpm: 120,
default_scale: "C Major",
system_instruction_template: "You are a professional arranger. Rearrange the source MIDI notes into an arpeggiated variation. Subdivide sustained chord notes into sequential 0.25-beat arpeggiated steps with octave/triad jumps. Create a driving, shimmering sequence while preserving the underlying chord progression.",
is_user_defined: false,
is_favorite: false,
created_at: "2026-07-28T11:00:00Z"
},
{
id: "preset_rearrange_harmonies",
name: "Add 3rd/4th Harmonies",
keywords: ["harmony", "harmonize", "harmonies", "3rd", "duet", "chord voicing"],
category: "Rearrange / Variation",
default_bars: 8,
default_bpm: 120,
default_scale: "C Major",
system_instruction_template: "You are a professional arranger. Add parallel harmonizing notes to the source melody. For each source pitch P, insert notes at P+3 or P+4 (Major/Minor 3rds) at the same start_beat. Create a richer, fuller texture resembling two instruments playing in duet.",
is_user_defined: false,
is_favorite: false,
created_at: "2026-07-28T11:00:00Z"
},
{
id: "preset_rearrange_syncopation",
name: "Syncopation / Off-beat",
keywords: ["syncopation", "syncopate", "syncopated", "off-beat", "off beat", "funk", "latin"],
category: "Rearrange / Variation",
default_bars: 8,
default_bpm: 120,
default_scale: "C Major",
system_instruction_template: "You are a professional arranger. Apply syncopation to the source melody. Shift start_beat alignment off strong beats (0.0, 1.0, 2.0, 3.0) onto off-beats (0.5, 1.5, 2.5, 3.5). Preserve the core melodic outline while creating a rhythmic, syncopated feel.",
is_user_defined: false,
is_favorite: false,
created_at: "2026-07-28T11:00:00Z"
},
{
id: "preset_rearrange_walking_bass",
name: "Walking Bass Line",
keywords: ["walking bass", "bassline", "walking"],
category: "Rearrange / Variation",
default_bars: 8,
default_bpm: 120,
default_scale: "C Major",
system_instruction_template: "You are a professional arranger. Transform the source melody into a walking bass line. Lower pitches to bass register (36-48 range). Build continuous quarter-note steps following the chord outline. Create an improvisational walking bassline matching the original chord progression.",
is_user_defined: false,
is_favorite: false,
created_at: "2026-07-28T11:00:00Z"
},
{
id: "preset_rearrange_jazz",
name: "Jazz Swing Rearrangement",
keywords: ["jazz", "swing", "jazz swing", "bebop"],
category: "Rearrange / Variation",
default_bars: 8,
default_bpm: 120,
default_scale: "C Major",
system_instruction_template: "You are a professional Jazz arranger. Rearrange the source melody into a rhythmic Jazz Swing style. Apply: off-beat syncopation, 7th/9th chord extensions, swung eighth notes (triplet feel), and rhythmic variations while preserving the core melodic outline.",
is_user_defined: false,
is_favorite: false,
created_at: "2026-07-28T11:00:00Z"
},
{
id: "preset_rearrange_synthwave",
name: "Synthwave / 80s Style",
keywords: ["synthwave", "80s", "retro", "synth wave", "retrowave", "outrun"],
category: "Rearrange / Variation",
default_bars: 8,
default_bpm: 120,
default_scale: "A Minor",
system_instruction_template: "You are a Synthwave producer. Transform the source melody into an 80s Synthwave style. Apply: driving 8th-note bass arpeggios, analog synth lead with portamento, pulsating chord pads, and octave jumps in the bass.",
is_user_defined: false,
is_favorite: false,
created_at: "2026-07-28T11:00:00Z"
},
{
id: "preset_rearrange_cinematic",
name: "Cinematic Orchestral",
keywords: ["cinematic", "orchestral", "epic", "film score", "symphonic", "hollywood"],
category: "Rearrange / Variation",
default_bars: 8,
default_bpm: 130,
default_scale: "C Minor",
system_instruction_template: "You are a cinematic composer. Transform the source melody into a dramatic Cinematic Orchestral arrangement. Apply: swelling dynamics, brass stabs on downbeats, string ostinato patterns, taiko percussion hits. Layer multiple octaves for epic width.",
is_user_defined: false,
is_favorite: false,
created_at: "2026-07-28T11:00:00Z"
},
{
id: "preset_rearrange_simplify",
name: "Simplify / Strip Down",
keywords: ["simplify", "minimal", "strip down", "sparse", "reduce"],
category: "Rearrange / Variation",
default_bars: 8,
default_bpm: 120,
default_scale: "C Major",
system_instruction_template: "You are a professional arranger. Simplify the source melody: keep only downbeat notes (start_beat at 0.0, 1.0, 2.0, 3.0). Strip out embellishments, passing tones, and grace notes. Reduce chord voicings to root and 5th only.",
is_user_defined: false,
is_favorite: false,
created_at: "2026-07-28T11:00:00Z"
},
{
id: "preset_rearrange_chromatic",
name: "Passing Tones & Chromaticism",
keywords: ["passing tone", "chromatic", "chromaticism", "smooth", "approach note"],
category: "Rearrange / Variation",
default_bars: 8,
default_bpm: 120,
default_scale: "C Major",
system_instruction_template: "You are a professional arranger. Add passing tones and chromatic approach notes to the source melody. Insert half-step and whole-step approach notes targeting chord tones on strong beats. Smooth out the melodic progression while preserving the harmonic framework.",
is_user_defined: false,
is_favorite: false,
created_at: "2026-07-28T11:00:00Z"
}
];