Load a large text model as a planner (main LLM) to create better lyrics
-
+
+ Advanced Settings
+
+
@@ -241,8 +260,6 @@ select{
-
-
@@ -256,8 +273,10 @@ select{
+
-
+
+ Connection settings
@@ -266,15 +285,19 @@ select{
-
+
-
-
+
+
+
+
+
+
@@ -283,8 +306,8 @@ select{
-
Click 'Plan' first to generate lyrics, BPM and duration. Edit as needed.
- When satisfied, click 'Generate' to make the music
+
Click 'Plan Lyrics' first to generate lyrics, BPM and duration. Edit as needed.
+ When satisfied, click 'Generate Music' to make the music
@@ -401,7 +424,14 @@ async function fetchVoices(){
}
var has_llm_loaded = false;
+let statsRequestId = 0;
+let plannerSelectionVersion = 0;
async function fetchStats(){
+ const requestId = ++statsRequestId;
+ const selectionVersion = plannerSelectionVersion;
+ has_llm_loaded = false;
+ document.getElementById("planner").value = "music_lm";
+ updatePlannerOptions();
try{
const base = document.getElementById("baseUrl").value.trim();
const url = (base ? base.replace(/\/$/,"") : "") + "/api/extra/version";
@@ -419,9 +449,11 @@ async function fetchStats(){
if(!res.ok) throw new Error();
const perf = await res.json();
- if(perf && perf.llm)
- {
- has_llm_loaded = true;
+ if(requestId !== statsRequestId) return;
+ has_llm_loaded = !!(perf && perf.llm);
+ if(selectionVersion === plannerSelectionVersion){
+ document.getElementById("planner").value = has_llm_loaded ? "main_llm" : "music_lm";
+ updatePlannerOptions();
}
}catch(e){
@@ -556,10 +588,6 @@ function randomizeSeed(){
seedInput.value = randomSeed;
}
-function toggleAdvanced(){
- document.getElementById("advanced").classList.toggle("hidden");
-}
-
function getFormData(){
const ids=["caption","lyrics","bpm","duration","keyscale","timesignature",
"vocal_language","seed","lm_temperature","lm_cfg_scale","lm_top_p","lm_top_k","lm_rep_pen","inference_steps",
@@ -570,7 +598,10 @@ function getFormData(){
const el=document.getElementById(id);
if(!el) return;
const v=el.value;
- if(v!=="") {data[id]=isNaN(v)?v:Number(v);}
+ if(v!=="") {
+ const isText = ["caption", "lyrics", "keyscale", "vocal_language", "audio_codes"].includes(id);
+ data[id] = isText || isNaN(v) ? v : Number(v);
+ }
});
data["stereo"] = (document.getElementById("stereo").checked ? true : false);
data["use_mp3"] = (document.getElementById("use_mp3").checked ? true : false);
@@ -584,7 +615,12 @@ function updateForm(data){
Object.keys(data).forEach(k=>{
if(document.getElementById(k))
{
- document.getElementById(k).value=data[k]??"";
+ const el = document.getElementById(k);
+ if(el.type === "checkbox"){
+ el.checked = data[k] === true;
+ }else{
+ el.value=data[k]??"";
+ }
}else{
if(k=="input") //for tts input
{
@@ -617,14 +653,19 @@ function deriveTitle(caption){
{
caption = "Untitled";
}
- let output = caption.trim().split("\n")[0].slice(0,30);
+ let output = String(caption).trim().split("\n")[0].slice(0,30);
output += ` ${rnd_id}`;
return output;
}
+function updatePlannerOptions(){
+ const useLLM = document.getElementById("planner").value === "main_llm";
+ document.getElementById("gen_codes_option").classList.toggle("hidden", useLLM);
+}
+
async function planSong()
{
- const useLLM = document.getElementById("plan_with_main_llm").checked;
+ const useLLM = document.getElementById("planner").value === "main_llm";
if(useLLM)
{
planSongWithLLM();
@@ -694,8 +735,14 @@ async function planSongWithLLM(){
}
let origPayload = getFormData();
- let origCaption = (origPayload["caption"] ? origPayload["caption"] : "an interesting song");
- let payload = {"temperature":1.0, "rep_pen":1.04, "top_p":0.97, "messages":[{"role":"system","content":"Please use the music generation tool to generate the caption and full song lyrics based on the request information provided by the user, with outputs wrapped in a JSON format. Ensure BPM, duration and keyscale values are appropriate to the song length and genre, generation may fail if parameters are unrealistic."},{"role":"user","content":origCaption}],"tool_choice":{"type":"function","function":{"name":"generate_music"}},"tools":[{"type":"function","function":{"name":"generate_music","description":"Generates a new song based on provided request. All output fields are mandatory.","parameters":{"type":"object","properties":{"caption":{"type":"string","description":"Acoustically relevant and detailed description of the song such as the genre and iconic elements."},"lyrics":{"type":"string","description":"The complete full song lyrics, suitably long for its genre. Each line should be on a newline, with double newlines between verses, and stanza headings in square brackets e.g. [Verse 1]"},"bpm":{"type":"integer","description":"The appropriate BPM (beats per minute) for the genre of the song."},"duration":{"type":"integer","description":"Total song duration in seconds, based on BPM and amount of lyrics."},"keyscale":{"type":"string","description":"Keyscale to use for the song. A/B/C/D/E/F/G Major/Minor/Dorian/Pentatonic etc."},"timesignature":{"type":"integer","description":"Time signature to use for the song, as a single integer. Valid values 2,3,4,6"},"vocal_language":{"type":"string","description":"Language code for this song lyrics, e.g. en"}},"required":["caption","lyrics","bpm","duration","keyscale","timesignature","vocal_language"]}}}]};
+ const songDetails = {caption: origPayload.caption || "an interesting song"};
+ ["lyrics", "bpm", "duration", "keyscale", "timesignature", "vocal_language"].forEach(key=>{
+ if(origPayload[key] !== undefined) songDetails[key] = origPayload[key];
+ });
+ let origCaption = "Plan a song using these details. Preserve supplied lyrics and song settings; fill in missing details. " +
+ (origPayload.rewrite_caption ? "You may rewrite the caption.\n" : "Preserve the caption unchanged.\n") +
+ JSON.stringify(songDetails);
+ let payload = {"temperature":1.0, "rep_pen":1.04, "top_p":0.97, "max_tokens":2048, "messages":[{"role":"system","content":"Please use the music generation tool to generate the caption and full song lyrics based on the request information provided by the user, with outputs wrapped in a JSON format. Ensure BPM, duration and keyscale values are appropriate to the song length and genre, generation may fail if parameters are unrealistic."},{"role":"user","content":origCaption}],"tool_choice":{"type":"function","function":{"name":"generate_music"}},"tools":[{"type":"function","function":{"name":"generate_music","description":"Generates a new song based on provided request. All output fields are mandatory.","parameters":{"type":"object","properties":{"caption":{"type":"string","description":"Acoustically relevant and detailed description of the song such as the genre and iconic elements."},"lyrics":{"type":"string","description":"The complete full song lyrics, suitably long for its genre. Each line should be on a newline, with double newlines between verses, and stanza headings in square brackets e.g. [Verse 1]"},"bpm":{"type":"integer","description":"The appropriate BPM (beats per minute) for the genre of the song."},"duration":{"type":"integer","description":"Total song duration in seconds, based on BPM and amount of lyrics."},"keyscale":{"type":"string","description":"Keyscale to use for the song. A/B/C/D/E/F/G Major/Minor/Dorian/Pentatonic etc."},"timesignature":{"type":"integer","description":"Time signature to use for the song, as a single integer. Valid values 2,3,4,6"},"vocal_language":{"type":"string","description":"Language code for this song lyrics, e.g. en"}},"required":["caption","lyrics","bpm","duration","keyscale","timesignature","vocal_language"]}}}]};
let headers = {"Content-Type":"application/json"};
if(document.getElementById("baseUrlKey").value!="")
@@ -717,6 +764,9 @@ async function planSongWithLLM(){
{
let toolres = data.choices[0].message.tool_calls[0].function.arguments;
toolres = JSON.parse(toolres);
+ if(!origPayload.rewrite_caption){
+ delete toolres.caption;
+ }
updateForm(toolres);
showMessage("Plan generated.");
}catch(e){
@@ -859,18 +909,22 @@ function loadLibrary(){
let savfmt = (ismp3?".mp3":".wav");
let currtrack = `${item.type==="tts" ? "🗣 " : "🎵 "}${item.title}`;
div.innerHTML=`
-