debug logs + tweaks
This commit is contained in:
+10
@@ -7,8 +7,18 @@ Generate complete songs with vocals and instrumentals from lyrics!
|
||||
|
||||
import sys
|
||||
import os
|
||||
import warnings
|
||||
import importlib.util
|
||||
|
||||
# Suppress cosmetic warnings from transformers about GenerationMixin and checkpointing format
|
||||
# These need to be set early, before transformers is imported
|
||||
warnings.filterwarnings("ignore", message=".*GenerationMixin.*")
|
||||
warnings.filterwarnings("ignore", message=".*old version of the checkpointing format.*")
|
||||
warnings.filterwarnings("ignore", message=".*doesn't directly inherit from.*")
|
||||
warnings.filterwarnings("ignore", message=".*will NOT inherit from.*")
|
||||
warnings.filterwarnings("ignore", message=".*_set_gradient_checkpointing.*")
|
||||
warnings.filterwarnings("ignore", category=FutureWarning, module="transformers.*")
|
||||
|
||||
# Get current directory
|
||||
current_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
||||
@@ -139,6 +139,14 @@ class CodecLM:
|
||||
bgm_wavs = list(bgm_wavs)
|
||||
|
||||
texts, audio_qt_embs = self._prepare_tokens_and_attributes(lyrics=lyrics, melody_wavs=melody_wavs, vocal_wavs=vocal_wavs, bgm_wavs=bgm_wavs, melody_is_wav=melody_is_wav)
|
||||
|
||||
# Debug: Log what's being passed to _generate_tokens
|
||||
print(f"\n[CodecLM DEBUG] ========== _generate_tokens INPUT ==========")
|
||||
print(f"[CodecLM DEBUG] texts (lyrics): {texts}")
|
||||
print(f"[CodecLM DEBUG] descriptions: {descriptions}")
|
||||
print(f"[CodecLM DEBUG] audio_qt_embs shape: {audio_qt_embs.shape if audio_qt_embs is not None else 'None'}")
|
||||
print(f"[CodecLM DEBUG] ================================================\n")
|
||||
|
||||
tokens = self._generate_tokens(texts, descriptions, audio_qt_embs)
|
||||
|
||||
if (tokens == self.lm.eos_token_id).any():
|
||||
|
||||
@@ -233,7 +233,13 @@ class LmModel(StreamingModule):
|
||||
if descriptions is not None:
|
||||
attr["text"]["type_info"] = descriptions[i]
|
||||
conditions.append(attr)
|
||||
print("conditions", conditions)
|
||||
# Enhanced debug logging for lyrics/descriptions
|
||||
print(f"\n[LmLevo DEBUG] ========== CONDITION ATTRIBUTES ==========")
|
||||
print(f"[LmLevo DEBUG] Available conditioners: {list(self.condition_provider.conditioners.keys())}")
|
||||
print(f"[LmLevo DEBUG] attr['text']['description'] (LYRICS): {repr(attr.text.get('description', 'NOT SET'))[:200]}")
|
||||
print(f"[LmLevo DEBUG] attr['text']['type_info'] (DESCRIPTION): {repr(attr.text.get('type_info', 'NOT SET'))[:200]}")
|
||||
print(f"[LmLevo DEBUG] Has prompt_audio: {'prompt_audio' in attr.audio}")
|
||||
print(f"[LmLevo DEBUG] =============================================\n")
|
||||
if prepare_null_condition:
|
||||
cfg_inference = ClassifierFreeGuidanceDropoutInference()
|
||||
null_conditions = cfg_inference(conditions, condition_types=["audio", "text"],
|
||||
|
||||
@@ -133,9 +133,22 @@ class QwTokenizerConditioner(TextConditioner):
|
||||
print("all structure tokens: ", {self.text_tokenizer.convert_ids_to_tokens(i):i for i in self.struct_token_ids})
|
||||
|
||||
def tokenize(self, x: tp.List[tp.Optional[str]]) -> tp.Dict[str, torch.Tensor]:
|
||||
# Debug: Log input before tokenization
|
||||
print(f"\n[QwTokenizerConditioner DEBUG] ========== TOKENIZE INPUT ==========")
|
||||
print(f"[QwTokenizerConditioner DEBUG] Input text (first item, first 300 chars): {repr(x[0][:300]) if x and x[0] else 'None/Empty'}")
|
||||
print(f"[QwTokenizerConditioner DEBUG] Number of inputs: {len(x)}")
|
||||
|
||||
x = ['<|im_start|>' + xi if xi is not None else "<|im_start|>" for xi in x]
|
||||
# x = [xi if xi is not None else "" for xi in x]
|
||||
inputs = self.text_tokenizer(x, return_tensors="pt", padding=True)
|
||||
|
||||
# Debug: Log tokenization result
|
||||
print(f"[QwTokenizerConditioner DEBUG] Tokenized shape: {inputs['input_ids'].shape}")
|
||||
print(f"[QwTokenizerConditioner DEBUG] First 20 token IDs: {inputs['input_ids'][0][:20].tolist()}")
|
||||
decoded = self.text_tokenizer.decode(inputs['input_ids'][0][:50])
|
||||
print(f"[QwTokenizerConditioner DEBUG] Decoded first 50 tokens: {repr(decoded)}")
|
||||
print(f"[QwTokenizerConditioner DEBUG] ===========================================\n")
|
||||
|
||||
return inputs
|
||||
|
||||
def forward(self, inputs: tp.Dict[str, torch.Tensor]) -> ConditionType:
|
||||
|
||||
@@ -3,8 +3,21 @@ FL Song Gen Lyrics Formatter Node.
|
||||
Helps users build properly formatted lyrics with section tags.
|
||||
"""
|
||||
|
||||
import re
|
||||
from typing import Tuple
|
||||
|
||||
# Regex to filter lyrics - keeps letters, numbers, whitespace, brackets, hyphens, and CJK characters
|
||||
# Removes punctuation like commas, apostrophes, quotes, etc.
|
||||
LYRICS_FILTER_REGEX = re.compile(
|
||||
r"[^\w\s\[\]\-\u4e00-\u9fff\u3040-\u309f\u30a0-\u30ff\uac00-\ud7af\u00c0-\u017f]"
|
||||
)
|
||||
|
||||
|
||||
def clean_lyrics_line(line: str) -> str:
|
||||
"""Clean a single lyrics line by removing unsupported punctuation."""
|
||||
cleaned = LYRICS_FILTER_REGEX.sub("", line)
|
||||
return cleaned.strip()
|
||||
|
||||
|
||||
class FL_SongGen_LyricsFormatter:
|
||||
"""
|
||||
@@ -228,9 +241,14 @@ class FL_SongGen_LyricsFormatter:
|
||||
"""
|
||||
Convert multiline text to SongGen format.
|
||||
Newlines become periods to separate phrases.
|
||||
Punctuation is removed to match model training data format.
|
||||
"""
|
||||
# Split by newlines, strip each line, filter empty
|
||||
lines = [line.strip() for line in text.strip().split("\n") if line.strip()]
|
||||
# Split by newlines, clean each line, filter empty
|
||||
lines = []
|
||||
for line in text.strip().split("\n"):
|
||||
cleaned = clean_lyrics_line(line)
|
||||
if cleaned:
|
||||
lines.append(cleaned)
|
||||
|
||||
# Join with period-space (matches original SongGeneration training data format)
|
||||
return ". ".join(lines)
|
||||
# Join with period only (matches official SongGeneration format)
|
||||
return ".".join(lines)
|
||||
|
||||
@@ -19,6 +19,10 @@ from omegaconf import OmegaConf
|
||||
# Suppress cosmetic warnings from transformers about GenerationMixin and checkpointing format
|
||||
warnings.filterwarnings("ignore", message=".*GenerationMixin.*")
|
||||
warnings.filterwarnings("ignore", message=".*old version of the checkpointing format.*")
|
||||
warnings.filterwarnings("ignore", message=".*doesn't directly inherit from.*")
|
||||
warnings.filterwarnings("ignore", message=".*will NOT inherit from.*")
|
||||
warnings.filterwarnings("ignore", message=".*_set_gradient_checkpointing.*")
|
||||
warnings.filterwarnings("ignore", category=FutureWarning, module="transformers.*")
|
||||
|
||||
# Get the fl_utils directory (same directory as this file)
|
||||
_FL_UTILS_DIR = os.path.dirname(__file__)
|
||||
|
||||
@@ -5,6 +5,7 @@ Encapsulates the inference logic from SongGeneration's generate.py.
|
||||
|
||||
import gc
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import tempfile
|
||||
import importlib.util
|
||||
@@ -15,6 +16,12 @@ import torch
|
||||
import torchaudio
|
||||
import soundfile as sf
|
||||
|
||||
# Regex to filter lyrics - keeps letters, numbers, whitespace, brackets, hyphens, and CJK characters
|
||||
# Removes punctuation like commas, apostrophes, quotes, etc. that the model wasn't trained on
|
||||
LYRICS_FILTER_REGEX = re.compile(
|
||||
r"[^\w\s\[\]\-;\.\u4e00-\u9fff\u3040-\u309f\u30a0-\u30ff\uac00-\ud7af\u00c0-\u017f]"
|
||||
)
|
||||
|
||||
# Get the fl_utils directory (same directory as this file)
|
||||
_FL_UTILS_DIR = os.path.dirname(__file__)
|
||||
|
||||
@@ -112,8 +119,9 @@ class SongGenWrapper:
|
||||
print(f"[FL SongGen] Duration {duration}s exceeds max {self.max_duration}s, clamping.")
|
||||
duration = self.max_duration
|
||||
|
||||
# Clean lyrics
|
||||
lyrics = lyrics.replace(" ", " ")
|
||||
# Clean lyrics - remove unsupported punctuation and normalize spaces
|
||||
lyrics = LYRICS_FILTER_REGEX.sub("", lyrics)
|
||||
lyrics = re.sub(r"\s+", " ", lyrics) # Normalize multiple spaces to single space
|
||||
|
||||
if self.low_mem:
|
||||
return self._generate_lowmem(
|
||||
@@ -193,6 +201,16 @@ class SongGenWrapper:
|
||||
'melody_is_wav': melody_is_wav,
|
||||
}
|
||||
|
||||
# Debug: Log what we're passing to the model
|
||||
print(f"\n[FL SongGen DEBUG] ========== GENERATION INPUT ==========")
|
||||
print(f"[FL SongGen DEBUG] Lyrics (first 200 chars): {repr(lyrics[:200]) if lyrics else 'None'}")
|
||||
print(f"[FL SongGen DEBUG] Description: {repr(description) if description else 'None'}")
|
||||
print(f"[FL SongGen DEBUG] melody_wavs shape: {pmt_wav.shape if pmt_wav is not None else 'None'}")
|
||||
print(f"[FL SongGen DEBUG] vocal_wavs shape: {vocal_wav.shape if vocal_wav is not None else 'None'}")
|
||||
print(f"[FL SongGen DEBUG] bgm_wavs shape: {bgm_wav.shape if bgm_wav is not None else 'None'}")
|
||||
print(f"[FL SongGen DEBUG] melody_is_wav: {melody_is_wav}")
|
||||
print(f"[FL SongGen DEBUG] ======================================\n")
|
||||
|
||||
print(f"[FL SongGen] Generating tokens for {duration}s song...")
|
||||
|
||||
with torch.autocast(device_type="cuda", dtype=torch.float16, enabled=self.device == "cuda"):
|
||||
@@ -359,6 +377,16 @@ class SongGenWrapper:
|
||||
'melody_is_wav': melody_is_wav,
|
||||
}
|
||||
|
||||
# Debug: Log what we're passing to the model (low mem path)
|
||||
print(f"\n[FL SongGen LowMem DEBUG] ========== GENERATION INPUT ==========")
|
||||
print(f"[FL SongGen LowMem DEBUG] Lyrics (first 200 chars): {repr(lyrics[:200]) if lyrics else 'None'}")
|
||||
print(f"[FL SongGen LowMem DEBUG] Description: {repr(description) if description else 'None'}")
|
||||
print(f"[FL SongGen LowMem DEBUG] melody_wavs shape: {pmt_wav.shape if pmt_wav is not None else 'None'}")
|
||||
print(f"[FL SongGen LowMem DEBUG] vocal_wavs shape: {vocal_wav.shape if vocal_wav is not None else 'None'}")
|
||||
print(f"[FL SongGen LowMem DEBUG] bgm_wavs shape: {bgm_wav.shape if bgm_wav is not None else 'None'}")
|
||||
print(f"[FL SongGen LowMem DEBUG] melody_is_wav: {melody_is_wav}")
|
||||
print(f"[FL SongGen LowMem DEBUG] ======================================\n")
|
||||
|
||||
print(f"[FL SongGen LowMem] Generating tokens...")
|
||||
with torch.autocast(device_type="cuda", dtype=torch.float16):
|
||||
with torch.no_grad():
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
[project]
|
||||
name = "comfyui_fl-songgen"
|
||||
description = "FL Song Gen - AI-powered song generation nodes for ComfyUI. Generate complete songs with vocals and instrumentals from lyrics using Tencent's SongGeneration (LeVo) model. Features style transfer, auto style presets, dual-track output, and up to 4m30s song generation."
|
||||
version = "1.0.8"
|
||||
version = "1.0.9"
|
||||
license = "Apache-2.0"
|
||||
dependencies = [
|
||||
"torch>=2.0.0",
|
||||
|
||||
Reference in New Issue
Block a user