Spaces:
Sleeping
Sleeping
Upload 5 files
Browse files- README.md +30 -2
- app.py +259 -0
- lyric_enhancer.py +353 -0
- requirements.txt +4 -0
- runtime.txt +1 -0
README.md
CHANGED
|
@@ -1,3 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
---
|
| 2 |
title: Harmonyaixlyricgenerator
|
| 3 |
emoji: 🌍
|
|
@@ -10,5 +40,3 @@ pinned: false
|
|
| 10 |
license: mit
|
| 11 |
short_description: Lyric generator
|
| 12 |
---
|
| 13 |
-
|
| 14 |
-
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
|
|
|
| 1 |
+
# Songsmith AI: Music Lyric Creator
|
| 2 |
+
|
| 3 |
+
This Hugging Face Space generates professional-quality song lyrics with proper musical structure. It creates catchy, singable lyrics with verse-chorus format and genre-specific style enhancements.
|
| 4 |
+
|
| 5 |
+
## Features
|
| 6 |
+
|
| 7 |
+
- **Genre-specific enhancements**: Each genre (pop, rock, rap, folk, r&b, country, indie, dance) has custom intensifiers, metaphors, and structural patterns
|
| 8 |
+
- **Professional song structure**: Proper verse-chorus format with optional bridge sections
|
| 9 |
+
- **Enhanced rhyming**: Intelligent rhyme patterns that match your selected scheme
|
| 10 |
+
- **Musical phrasing**: Short, catchy lines optimized for singing
|
| 11 |
+
- **Emotional hooks**: Repetition and emphasis in the right places
|
| 12 |
+
|
| 13 |
+
## How to Use
|
| 14 |
+
|
| 15 |
+
1. Enter a theme or topic for your song
|
| 16 |
+
2. Select a music genre (affects style, metaphors, and structure)
|
| 17 |
+
3. Choose a rhyme scheme (AABB or ABAB)
|
| 18 |
+
4. Adjust the maximum length as needed (longer = more sections)
|
| 19 |
+
5. Click "Generate Lyrics" and enjoy your AI-created song!
|
| 20 |
+
|
| 21 |
+
## Technical Details
|
| 22 |
+
|
| 23 |
+
- Built with Gradio 5.1.0
|
| 24 |
+
- Uses Hugging Face Transformers with DistilGPT-2
|
| 25 |
+
- Enhanced with custom lyric processing modules:
|
| 26 |
+
- IntensifierGenerator: Adds genre-specific intensifiers and metaphors
|
| 27 |
+
- RhymeEnhancer: Improves rhyming patterns
|
| 28 |
+
- SongStructureEnhancer: Creates proper verse-chorus-bridge structure
|
| 29 |
+
- Optimized for free-tier Spaces
|
| 30 |
+
|
| 31 |
---
|
| 32 |
title: Harmonyaixlyricgenerator
|
| 33 |
emoji: 🌍
|
|
|
|
| 40 |
license: mit
|
| 41 |
short_description: Lyric generator
|
| 42 |
---
|
|
|
|
|
|
app.py
ADDED
|
@@ -0,0 +1,259 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from transformers import pipeline
|
| 2 |
+
import gradio as gr
|
| 3 |
+
import random
|
| 4 |
+
from lyric_enhancer import IntensifierGenerator, RhymeEnhancer, SongStructureEnhancer
|
| 5 |
+
|
| 6 |
+
# Initialize models suitable for free tier
|
| 7 |
+
try:
|
| 8 |
+
# Try to load the primary model
|
| 9 |
+
generator = pipeline('text-generation', model='distilgpt2')
|
| 10 |
+
# Keep a backup model option ready
|
| 11 |
+
backup_model_name = 'gpt2'
|
| 12 |
+
except Exception as e:
|
| 13 |
+
print(f"Error loading primary model: {e}")
|
| 14 |
+
# Fallback to an even smaller model if needed
|
| 15 |
+
generator = pipeline('text-generation', model='gpt2')
|
| 16 |
+
backup_model_name = None
|
| 17 |
+
|
| 18 |
+
def generate_lyrics(theme, genre, rhyme_scheme="AABB", max_length=150):
|
| 19 |
+
"""Generate song lyrics based on input parameters"""
|
| 20 |
+
|
| 21 |
+
# Create enhancers
|
| 22 |
+
intensifier = IntensifierGenerator(genre=genre)
|
| 23 |
+
rhymer = RhymeEnhancer()
|
| 24 |
+
structure_enhancer = SongStructureEnhancer(genre=genre)
|
| 25 |
+
|
| 26 |
+
# Build a more musical prompt
|
| 27 |
+
prompt = f"""Write a catchy {genre} song about {theme} with {rhyme_scheme} rhyme pattern.
|
| 28 |
+
Keep lines short and musical. Include emotional hooks and repetition.
|
| 29 |
+
|
| 30 |
+
[Verse 1]
|
| 31 |
+
"""
|
| 32 |
+
|
| 33 |
+
try:
|
| 34 |
+
# Increase temperature for more creativity and reduce repetition
|
| 35 |
+
result = generator(prompt,
|
| 36 |
+
max_length=max_length,
|
| 37 |
+
num_return_sequences=1,
|
| 38 |
+
temperature=0.9, # Increased from 0.7
|
| 39 |
+
top_p=0.92, # Slightly increased
|
| 40 |
+
repetition_penalty=1.2) # Added to reduce repetition
|
| 41 |
+
|
| 42 |
+
# Extract the generated text
|
| 43 |
+
lyrics = result[0]['generated_text']
|
| 44 |
+
|
| 45 |
+
# Check if we got repetitive content
|
| 46 |
+
if lyrics.count("[Verse]") > 3 or lyrics.count("Write a") > 1:
|
| 47 |
+
raise ValueError("Repetitive output detected")
|
| 48 |
+
|
| 49 |
+
except Exception as e:
|
| 50 |
+
print(f"Error with primary generation: {e}")
|
| 51 |
+
|
| 52 |
+
# Try with a simpler prompt
|
| 53 |
+
simple_prompt = f"{genre} song lyrics about {theme}:\n\n[Verse 1]\n"
|
| 54 |
+
|
| 55 |
+
try:
|
| 56 |
+
# Try with different parameters
|
| 57 |
+
result = generator(simple_prompt,
|
| 58 |
+
max_length=max_length,
|
| 59 |
+
num_return_sequences=1,
|
| 60 |
+
temperature=1.0,
|
| 61 |
+
top_p=0.95,
|
| 62 |
+
repetition_penalty=1.5)
|
| 63 |
+
|
| 64 |
+
lyrics = result[0]['generated_text']
|
| 65 |
+
except Exception as e2:
|
| 66 |
+
print(f"Error with fallback generation: {e2}")
|
| 67 |
+
return f"Sorry, I couldn't generate lyrics at this time. Please try again with a different theme or genre."
|
| 68 |
+
|
| 69 |
+
# Better handling of output formatting
|
| 70 |
+
# Find the first occurrence of [Verse] or [Verse 1] and keep everything after it
|
| 71 |
+
verse_index = max(lyrics.find("[Verse]"), lyrics.find("[Verse 1]"))
|
| 72 |
+
|
| 73 |
+
if verse_index != -1:
|
| 74 |
+
# Keep everything from [Verse] onwards
|
| 75 |
+
formatted_lyrics = lyrics[verse_index:].strip()
|
| 76 |
+
else:
|
| 77 |
+
# If no verse markers found, try to find the actual content
|
| 78 |
+
lines = lyrics.split("\n")
|
| 79 |
+
# Skip empty lines and prompt-related lines
|
| 80 |
+
content_lines = []
|
| 81 |
+
skip_keywords = ["Write", "catchy", "rhyme pattern", "Keep lines", "Include"]
|
| 82 |
+
|
| 83 |
+
for line in lines:
|
| 84 |
+
# Skip empty lines and lines containing prompt keywords
|
| 85 |
+
if not line.strip() or any(keyword in line for keyword in skip_keywords):
|
| 86 |
+
continue
|
| 87 |
+
content_lines.append(line)
|
| 88 |
+
|
| 89 |
+
formatted_lyrics = "\n".join(content_lines).strip()
|
| 90 |
+
|
| 91 |
+
# If we couldn't extract anything meaningful, use a generic message
|
| 92 |
+
if not formatted_lyrics or len(formatted_lyrics.split()) < 5:
|
| 93 |
+
return "I couldn't generate good lyrics with this theme. Please try a different theme or genre."
|
| 94 |
+
|
| 95 |
+
# Check for repetitive content
|
| 96 |
+
lines = formatted_lyrics.split("\n")
|
| 97 |
+
unique_lines = set(line.strip() for line in lines if line.strip())
|
| 98 |
+
|
| 99 |
+
# If we have very few unique lines compared to total lines, it's repetitive
|
| 100 |
+
if len(lines) > 5 and len(unique_lines) < len(lines) / 2:
|
| 101 |
+
return "The model generated repetitive content. Please try again with a different theme or genre."
|
| 102 |
+
|
| 103 |
+
# Apply our enhancers to make the lyrics more musical
|
| 104 |
+
|
| 105 |
+
# 1. First, enhance the structure
|
| 106 |
+
enhanced_lyrics = structure_enhancer.enhance_structure(formatted_lyrics, add_bridge=(max_length > 150))
|
| 107 |
+
|
| 108 |
+
# 2. Apply line-by-line enhancements
|
| 109 |
+
enhanced_lines = []
|
| 110 |
+
current_section = None
|
| 111 |
+
section_lines = []
|
| 112 |
+
|
| 113 |
+
for line in enhanced_lyrics.split("\n"):
|
| 114 |
+
# Track sections for rhyming purposes
|
| 115 |
+
if line.startswith("["):
|
| 116 |
+
# Process previous section
|
| 117 |
+
if section_lines and current_section:
|
| 118 |
+
# Apply rhyme enhancement to the section
|
| 119 |
+
rhymed_lines = rhymer.enhance_section(section_lines, genre)
|
| 120 |
+
enhanced_lines.extend(rhymed_lines)
|
| 121 |
+
section_lines = []
|
| 122 |
+
|
| 123 |
+
# Start new section
|
| 124 |
+
enhanced_lines.append(line)
|
| 125 |
+
current_section = line
|
| 126 |
+
continue
|
| 127 |
+
|
| 128 |
+
# Apply intensifiers to individual lines
|
| 129 |
+
intensified_line = intensifier.generate(line)
|
| 130 |
+
section_lines.append(intensified_line)
|
| 131 |
+
|
| 132 |
+
# Process the last section
|
| 133 |
+
if section_lines and current_section:
|
| 134 |
+
rhymed_lines = rhymer.enhance_section(section_lines, genre)
|
| 135 |
+
enhanced_lines.extend(rhymed_lines)
|
| 136 |
+
|
| 137 |
+
# Final enhanced lyrics
|
| 138 |
+
formatted_lyrics = "\n".join(enhanced_lines)
|
| 139 |
+
|
| 140 |
+
return formatted_lyrics
|
| 141 |
+
|
| 142 |
+
# Custom CSS for better appearance
|
| 143 |
+
css = """
|
| 144 |
+
.container {
|
| 145 |
+
max-width: 900px;
|
| 146 |
+
margin: auto;
|
| 147 |
+
padding-top: 1.5rem;
|
| 148 |
+
}
|
| 149 |
+
.title {
|
| 150 |
+
text-align: center;
|
| 151 |
+
color: #7c3aed;
|
| 152 |
+
margin-bottom: 1rem;
|
| 153 |
+
}
|
| 154 |
+
.subtitle {
|
| 155 |
+
text-align: center;
|
| 156 |
+
color: #6b7280;
|
| 157 |
+
margin-bottom: 2rem;
|
| 158 |
+
}
|
| 159 |
+
.generate-btn {
|
| 160 |
+
background-color: #7c3aed !important;
|
| 161 |
+
}
|
| 162 |
+
.footer {
|
| 163 |
+
text-align: center;
|
| 164 |
+
margin-top: 2rem;
|
| 165 |
+
color: #6b7280;
|
| 166 |
+
font-size: 0.875rem;
|
| 167 |
+
}
|
| 168 |
+
"""
|
| 169 |
+
|
| 170 |
+
# Example themes for the interface
|
| 171 |
+
examples = [
|
| 172 |
+
["heartbreak and moving on", "pop", "AABB", 150],
|
| 173 |
+
["dancing all night", "dance", "ABAB", 150],
|
| 174 |
+
["fighting for your dreams", "rock", "AABB", 180],
|
| 175 |
+
["summer romance", "folk", "ABAB", 150],
|
| 176 |
+
["city lights and late nights", "rap", "ABAB", 200],
|
| 177 |
+
["lost love and redemption", "country", "AABB", 180],
|
| 178 |
+
["finding yourself", "indie", "ABAB", 170],
|
| 179 |
+
["midnight feelings", "r&b", "AABB", 160],
|
| 180 |
+
]
|
| 181 |
+
|
| 182 |
+
# Create Gradio interface with a custom theme
|
| 183 |
+
with gr.Blocks(css=css, theme="soft") as demo:
|
| 184 |
+
with gr.Column(elem_classes="container"):
|
| 185 |
+
gr.Markdown("# 🎵 Songsmith AI: Music Lyric Creator", elem_classes="title")
|
| 186 |
+
gr.Markdown("Create catchy, singable song lyrics with verse-chorus structure and genre-specific style", elem_classes="subtitle")
|
| 187 |
+
|
| 188 |
+
with gr.Row():
|
| 189 |
+
with gr.Column():
|
| 190 |
+
theme_input = gr.Textbox(
|
| 191 |
+
label="Theme or Topic",
|
| 192 |
+
placeholder="Enter a theme (e.g., lost in the forest)",
|
| 193 |
+
info="What should your song be about?"
|
| 194 |
+
)
|
| 195 |
+
genre_input = gr.Dropdown(
|
| 196 |
+
["pop", "rock", "folk", "rap", "r&b", "country", "indie", "dance"],
|
| 197 |
+
label="Music Genre",
|
| 198 |
+
value="pop",
|
| 199 |
+
info="Select the musical style for genre-specific enhancements"
|
| 200 |
+
)
|
| 201 |
+
rhyme_input = gr.Dropdown(
|
| 202 |
+
["AABB", "ABAB"],
|
| 203 |
+
label="Rhyme Scheme",
|
| 204 |
+
value="AABB",
|
| 205 |
+
info="AABB: consecutive lines rhyme, ABAB: alternating lines rhyme"
|
| 206 |
+
)
|
| 207 |
+
length_slider = gr.Slider(
|
| 208 |
+
50, 200, value=150,
|
| 209 |
+
label="Maximum Length",
|
| 210 |
+
info="Longer text = more content but may be less coherent"
|
| 211 |
+
)
|
| 212 |
+
generate_btn = gr.Button("✨ Generate Lyrics", elem_classes="generate-btn")
|
| 213 |
+
|
| 214 |
+
with gr.Column():
|
| 215 |
+
output = gr.Textbox(
|
| 216 |
+
label="Generated Lyrics",
|
| 217 |
+
lines=12,
|
| 218 |
+
show_copy_button=True
|
| 219 |
+
)
|
| 220 |
+
|
| 221 |
+
gr.Examples(
|
| 222 |
+
examples=examples,
|
| 223 |
+
inputs=[theme_input, genre_input, rhyme_input, length_slider],
|
| 224 |
+
outputs=output,
|
| 225 |
+
fn=generate_lyrics,
|
| 226 |
+
cache_examples=True,
|
| 227 |
+
)
|
| 228 |
+
|
| 229 |
+
gr.Markdown(
|
| 230 |
+
"""
|
| 231 |
+
### How to use
|
| 232 |
+
1. Enter a theme or topic for your song
|
| 233 |
+
2. Select a music genre (affects style, metaphors, and structure)
|
| 234 |
+
3. Choose a rhyme scheme
|
| 235 |
+
4. Adjust the length as needed (longer = more sections)
|
| 236 |
+
5. Click "Generate Lyrics" and enjoy your AI-created song!
|
| 237 |
+
|
| 238 |
+
### Features
|
| 239 |
+
- Genre-specific intensifiers and metaphors
|
| 240 |
+
- Enhanced rhyming patterns
|
| 241 |
+
- Proper song structure with verse-chorus format
|
| 242 |
+
- Bridge sections in longer songs
|
| 243 |
+
- Catchy, singable lines optimized for each genre
|
| 244 |
+
|
| 245 |
+
---
|
| 246 |
+
|
| 247 |
+
*Note: This app uses a lightweight AI model (DistilGPT-2) enhanced with specialized lyric processing.*
|
| 248 |
+
""",
|
| 249 |
+
elem_classes="footer"
|
| 250 |
+
)
|
| 251 |
+
|
| 252 |
+
generate_btn.click(
|
| 253 |
+
generate_lyrics,
|
| 254 |
+
inputs=[theme_input, genre_input, rhyme_input, length_slider],
|
| 255 |
+
outputs=output
|
| 256 |
+
)
|
| 257 |
+
|
| 258 |
+
# Launch the app
|
| 259 |
+
demo.launch()
|
lyric_enhancer.py
ADDED
|
@@ -0,0 +1,353 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import random
|
| 2 |
+
|
| 3 |
+
class IntensifierGenerator:
|
| 4 |
+
def __init__(self, genre="default", use_synonyms=True, use_metaphors=True):
|
| 5 |
+
self.genre = genre
|
| 6 |
+
self.use_synonyms = use_synonyms
|
| 7 |
+
self.use_metaphors = use_metaphors
|
| 8 |
+
self.intensifier_pool = self._load_intensifiers()
|
| 9 |
+
|
| 10 |
+
def _load_intensifiers(self):
|
| 11 |
+
base_pool = {
|
| 12 |
+
"default": {
|
| 13 |
+
"synonyms": ["wild", "burning", "endless", "raw"],
|
| 14 |
+
"metaphors": ["like a comet", "like thunder", "like wildfire"]
|
| 15 |
+
},
|
| 16 |
+
"pop": {
|
| 17 |
+
"synonyms": ["electric", "neon", "glossy", "magnetic"],
|
| 18 |
+
"metaphors": ["like a spotlight", "like glitter", "like a dream"]
|
| 19 |
+
},
|
| 20 |
+
"rap": {
|
| 21 |
+
"synonyms": ["cold", "lit", "savage", "dope"],
|
| 22 |
+
"metaphors": ["like a flex", "like a cipher", "like a drop"]
|
| 23 |
+
},
|
| 24 |
+
"rock": {
|
| 25 |
+
"synonyms": ["gritty", "loud", "reckless", "feral"],
|
| 26 |
+
"metaphors": ["like a riot", "like a storm", "like a scream"]
|
| 27 |
+
},
|
| 28 |
+
"folk": {
|
| 29 |
+
"synonyms": ["rustic", "earthy", "timeless", "weathered"],
|
| 30 |
+
"metaphors": ["like the mountains", "like the wind", "like an old tale"]
|
| 31 |
+
},
|
| 32 |
+
"r&b": {
|
| 33 |
+
"synonyms": ["smooth", "sultry", "silky", "deep"],
|
| 34 |
+
"metaphors": ["like midnight", "like honey", "like a slow dance"]
|
| 35 |
+
},
|
| 36 |
+
"country": {
|
| 37 |
+
"synonyms": ["dusty", "honest", "heartfelt", "rugged"],
|
| 38 |
+
"metaphors": ["like an open road", "like a sunset", "like a whiskey glass"]
|
| 39 |
+
},
|
| 40 |
+
"indie": {
|
| 41 |
+
"synonyms": ["quirky", "intimate", "ethereal", "raw"],
|
| 42 |
+
"metaphors": ["like a polaroid", "like a whisper", "like faded jeans"]
|
| 43 |
+
},
|
| 44 |
+
"dance": {
|
| 45 |
+
"synonyms": ["pulsing", "euphoric", "vibrant", "electric"],
|
| 46 |
+
"metaphors": ["like a neon sign", "like a heartbeat", "like the night"]
|
| 47 |
+
}
|
| 48 |
+
}
|
| 49 |
+
return base_pool.get(self.genre.lower(), base_pool["default"])
|
| 50 |
+
|
| 51 |
+
def generate(self, base_line):
|
| 52 |
+
"""Add genre-specific intensifiers to a line"""
|
| 53 |
+
# Don't modify section headers
|
| 54 |
+
if base_line.strip().startswith("[") and base_line.strip().endswith("]"):
|
| 55 |
+
return base_line
|
| 56 |
+
|
| 57 |
+
# Don't modify very short lines or empty lines
|
| 58 |
+
if not base_line.strip() or len(base_line.split()) < 3:
|
| 59 |
+
return base_line
|
| 60 |
+
|
| 61 |
+
# Only enhance some lines (not every line)
|
| 62 |
+
if random.random() > 0.4: # 40% chance to enhance
|
| 63 |
+
return base_line
|
| 64 |
+
|
| 65 |
+
intensifiers = []
|
| 66 |
+
if self.use_synonyms and random.random() > 0.5:
|
| 67 |
+
intensifiers.append(random.choice(self.intensifier_pool["synonyms"]))
|
| 68 |
+
if self.use_metaphors and random.random() > 0.7: # Less frequent metaphors
|
| 69 |
+
intensifiers.append(random.choice(self.intensifier_pool["metaphors"]))
|
| 70 |
+
|
| 71 |
+
if not intensifiers:
|
| 72 |
+
return base_line
|
| 73 |
+
|
| 74 |
+
# Add the intensifier in a natural position
|
| 75 |
+
words = base_line.split()
|
| 76 |
+
if len(words) > 4:
|
| 77 |
+
# Insert at a natural break point
|
| 78 |
+
insert_pos = len(words) // 2
|
| 79 |
+
words.insert(insert_pos, random.choice(intensifiers))
|
| 80 |
+
return " ".join(words)
|
| 81 |
+
else:
|
| 82 |
+
# Add at the end for short lines
|
| 83 |
+
return f"{base_line} {random.choice(intensifiers)}"
|
| 84 |
+
|
| 85 |
+
|
| 86 |
+
class RhymeEnhancer:
|
| 87 |
+
"""Enhance rhyming in lyrics"""
|
| 88 |
+
|
| 89 |
+
def __init__(self):
|
| 90 |
+
self.rhyme_endings = {
|
| 91 |
+
"pop": ["ight", "ay", "ove", "art", "ame"],
|
| 92 |
+
"rock": ["own", "ire", "ead", "ight", "one"],
|
| 93 |
+
"rap": ["ay", "ow", "ack", "op", "ame"],
|
| 94 |
+
"folk": ["ay", "ight", "ome", "and", "ow"],
|
| 95 |
+
"r&b": ["ove", "ight", "ay", "oul", "ime"],
|
| 96 |
+
"country": ["oad", "eart", "ome", "ight", "ay"],
|
| 97 |
+
"indie": ["ight", "own", "ay", "ime", "ow"],
|
| 98 |
+
"dance": ["ight", "ay", "ove", "own", "ire"]
|
| 99 |
+
}
|
| 100 |
+
|
| 101 |
+
def get_rhyme_ending(self, genre):
|
| 102 |
+
"""Get a rhyme ending for the given genre"""
|
| 103 |
+
genre = genre.lower()
|
| 104 |
+
if genre in self.rhyme_endings:
|
| 105 |
+
return random.choice(self.rhyme_endings[genre])
|
| 106 |
+
return random.choice(self.rhyme_endings["pop"]) # Default to pop
|
| 107 |
+
|
| 108 |
+
def enhance_line(self, line, rhyme_ending):
|
| 109 |
+
"""Try to make a line end with the given rhyme"""
|
| 110 |
+
if not line.strip() or line.strip().startswith("["):
|
| 111 |
+
return line
|
| 112 |
+
|
| 113 |
+
# Only enhance some lines
|
| 114 |
+
if random.random() > 0.3: # 30% chance to enhance
|
| 115 |
+
return line
|
| 116 |
+
|
| 117 |
+
words = line.split()
|
| 118 |
+
if len(words) < 3:
|
| 119 |
+
return line
|
| 120 |
+
|
| 121 |
+
# Try to find a word that could be replaced with a rhyming word
|
| 122 |
+
last_word = words[-1].lower().rstrip(",.!?;:")
|
| 123 |
+
|
| 124 |
+
# Simple rhyming word replacements
|
| 125 |
+
rhyme_words = {
|
| 126 |
+
"ight": ["night", "light", "bright", "sight", "right", "tight"],
|
| 127 |
+
"ay": ["day", "way", "stay", "play", "away", "today"],
|
| 128 |
+
"ove": ["love", "above", "dove", "shove", "glove"],
|
| 129 |
+
"art": ["heart", "start", "part", "chart", "smart"],
|
| 130 |
+
"ame": ["fame", "game", "name", "flame", "shame"],
|
| 131 |
+
"own": ["down", "town", "crown", "brown", "frown"],
|
| 132 |
+
"ire": ["fire", "desire", "wire", "higher", "inspire"],
|
| 133 |
+
"ead": ["head", "instead", "spread", "dread", "thread"],
|
| 134 |
+
"one": ["stone", "alone", "bone", "tone", "zone"],
|
| 135 |
+
"ack": ["back", "track", "black", "stack", "attack"],
|
| 136 |
+
"op": ["top", "stop", "drop", "shop", "pop"],
|
| 137 |
+
"ome": ["home", "roam", "dome", "chrome", "foam"],
|
| 138 |
+
"and": ["hand", "stand", "band", "land", "grand"],
|
| 139 |
+
"ow": ["now", "how", "bow", "allow", "somehow"],
|
| 140 |
+
"oul": ["soul", "control", "roll", "whole", "goal"],
|
| 141 |
+
"ime": ["time", "crime", "prime", "sublime", "climb"],
|
| 142 |
+
"oad": ["road", "load", "code", "mode", "showed"],
|
| 143 |
+
"eart": ["heart", "start", "part", "chart", "smart"],
|
| 144 |
+
}
|
| 145 |
+
|
| 146 |
+
if rhyme_ending in rhyme_words:
|
| 147 |
+
# Replace the last word with a rhyming word
|
| 148 |
+
words[-1] = random.choice(rhyme_words[rhyme_ending])
|
| 149 |
+
return " ".join(words)
|
| 150 |
+
|
| 151 |
+
return line
|
| 152 |
+
|
| 153 |
+
def enhance_section(self, lines, genre):
|
| 154 |
+
"""Enhance rhyming in a section of lyrics"""
|
| 155 |
+
if not lines:
|
| 156 |
+
return lines
|
| 157 |
+
|
| 158 |
+
# Choose a rhyme ending for this section
|
| 159 |
+
rhyme_ending = self.get_rhyme_ending(genre)
|
| 160 |
+
|
| 161 |
+
# Enhance every other line to create an ABAB or AABB pattern
|
| 162 |
+
enhanced_lines = []
|
| 163 |
+
for i, line in enumerate(lines):
|
| 164 |
+
if i % 2 == 1: # Every other line
|
| 165 |
+
enhanced_lines.append(self.enhance_line(line, rhyme_ending))
|
| 166 |
+
else:
|
| 167 |
+
enhanced_lines.append(line)
|
| 168 |
+
|
| 169 |
+
return enhanced_lines
|
| 170 |
+
|
| 171 |
+
|
| 172 |
+
class SongStructureEnhancer:
|
| 173 |
+
"""Enhance the structure of song lyrics"""
|
| 174 |
+
|
| 175 |
+
def __init__(self, genre="pop"):
|
| 176 |
+
self.genre = genre.lower()
|
| 177 |
+
self.chorus_templates = self._load_chorus_templates()
|
| 178 |
+
|
| 179 |
+
def _load_chorus_templates(self):
|
| 180 |
+
"""Load chorus templates by genre"""
|
| 181 |
+
templates = {
|
| 182 |
+
"pop": [
|
| 183 |
+
"Baby, {0}\nYeah, {0}",
|
| 184 |
+
"{0}\nI can't get enough\n{0}\nIt's never too much",
|
| 185 |
+
"Oh-oh-oh\n{0}\nYeah-yeah-yeah\n{0}",
|
| 186 |
+
"{0}\nAgain and again\n{0}\nUntil the end"
|
| 187 |
+
],
|
| 188 |
+
"rock": [
|
| 189 |
+
"{0}\nIt's burning inside\n{0}\nI won't be denied",
|
| 190 |
+
"Yeah! {0}\nWoah! {0}",
|
| 191 |
+
"{0}\nI'm breaking free\n{0}\nCan't you see",
|
| 192 |
+
"{0}\nIt's do or die\n{0}\nReach for the sky"
|
| 193 |
+
],
|
| 194 |
+
"rap": [
|
| 195 |
+
"{0}\nThat's right\n{0}\nAll night",
|
| 196 |
+
"{0}\nYou know what I'm saying\n{0}\nNo delaying",
|
| 197 |
+
"{0}\nFor real\n{0}\nThat's the deal",
|
| 198 |
+
"{0}\nYeah\n{0}\nUh"
|
| 199 |
+
],
|
| 200 |
+
"folk": [
|
| 201 |
+
"{0}\nThrough the years\n{0}\nDespite our fears",
|
| 202 |
+
"{0}\nLike the river flows\n{0}\nEverybody knows",
|
| 203 |
+
"{0}\nTime will tell\n{0}\nAll is well",
|
| 204 |
+
"{0}\nDay by day\n{0}\nCome what may"
|
| 205 |
+
],
|
| 206 |
+
"r&b": [
|
| 207 |
+
"Ooh baby, {0}\nYou know that {0}",
|
| 208 |
+
"{0}\nSo smooth\n{0}\nIn the groove",
|
| 209 |
+
"{0}\nAll night long\n{0}\nSo strong",
|
| 210 |
+
"{0}\nYou and me\n{0}\nDestiny"
|
| 211 |
+
],
|
| 212 |
+
"country": [
|
| 213 |
+
"{0}\nDown that old road\n{0}\nCarrying that load",
|
| 214 |
+
"{0}\nIn my heart\n{0}\nRight from the start",
|
| 215 |
+
"{0}\nDay by day\n{0}\nCome what may",
|
| 216 |
+
"{0}\nTrue and blue\n{0}\nThrough and through"
|
| 217 |
+
],
|
| 218 |
+
"indie": [
|
| 219 |
+
"{0}\nIn my mind\n{0}\nHard to find",
|
| 220 |
+
"{0}\nLike a dream\n{0}\nNothing's as it seems",
|
| 221 |
+
"{0}\nFading light\n{0}\nInto the night",
|
| 222 |
+
"{0}\nWe'll see\n{0}\nJust let it be"
|
| 223 |
+
],
|
| 224 |
+
"dance": [
|
| 225 |
+
"{0}\nFeel the beat\n{0}\nSweep you off your feet",
|
| 226 |
+
"{0}\nAll night long\n{0}\nCan't go wrong",
|
| 227 |
+
"{0}\nMove your body\n{0}\nEverybody",
|
| 228 |
+
"{0}\nDon't stop now\n{0}\nShow me how"
|
| 229 |
+
]
|
| 230 |
+
}
|
| 231 |
+
return templates.get(self.genre, templates["pop"])
|
| 232 |
+
|
| 233 |
+
def create_chorus(self, verse_line):
|
| 234 |
+
"""Create a chorus based on a line from the verse"""
|
| 235 |
+
if not verse_line or verse_line.startswith("["):
|
| 236 |
+
return ["[Chorus]", "We're living in the moment", "Feeling so alive"]
|
| 237 |
+
|
| 238 |
+
# Extract a short phrase from the verse line
|
| 239 |
+
words = verse_line.split()
|
| 240 |
+
if len(words) >= 4:
|
| 241 |
+
phrase = " ".join(words[-3:])
|
| 242 |
+
else:
|
| 243 |
+
phrase = verse_line
|
| 244 |
+
|
| 245 |
+
# Apply a chorus template
|
| 246 |
+
template = random.choice(self.chorus_templates)
|
| 247 |
+
chorus_text = template.format(phrase)
|
| 248 |
+
|
| 249 |
+
# Split into lines and add the chorus header
|
| 250 |
+
chorus_lines = ["[Chorus]"] + chorus_text.split("\n")
|
| 251 |
+
return chorus_lines
|
| 252 |
+
|
| 253 |
+
def create_bridge(self):
|
| 254 |
+
"""Create a bridge section"""
|
| 255 |
+
bridge_templates = [
|
| 256 |
+
["[Bridge]", "And now I see", "Everything has changed", "Nothing stays the same"],
|
| 257 |
+
["[Bridge]", "Take me higher", "Set my soul on fire", "This is my desire"],
|
| 258 |
+
["[Bridge]", "Breaking through", "Starting something new", "I'm coming back to you"],
|
| 259 |
+
["[Bridge]", "In between", "Not what it seems", "Living in a dream"]
|
| 260 |
+
]
|
| 261 |
+
return random.choice(bridge_templates)
|
| 262 |
+
|
| 263 |
+
def enhance_structure(self, lyrics, add_bridge=True):
|
| 264 |
+
"""Enhance the structure of the lyrics"""
|
| 265 |
+
if not lyrics:
|
| 266 |
+
return lyrics
|
| 267 |
+
|
| 268 |
+
lines = lyrics.split("\n")
|
| 269 |
+
|
| 270 |
+
# Find verse and chorus sections
|
| 271 |
+
verse_sections = []
|
| 272 |
+
chorus_section = None
|
| 273 |
+
current_section = []
|
| 274 |
+
current_type = None
|
| 275 |
+
|
| 276 |
+
for line in lines:
|
| 277 |
+
if "[Verse" in line:
|
| 278 |
+
# Save previous section
|
| 279 |
+
if current_type == "verse" and current_section:
|
| 280 |
+
verse_sections.append(current_section)
|
| 281 |
+
elif current_type == "chorus" and current_section:
|
| 282 |
+
chorus_section = current_section
|
| 283 |
+
|
| 284 |
+
# Start new verse section
|
| 285 |
+
current_section = [line]
|
| 286 |
+
current_type = "verse"
|
| 287 |
+
elif "[Chorus]" in line:
|
| 288 |
+
# Save previous section
|
| 289 |
+
if current_type == "verse" and current_section:
|
| 290 |
+
verse_sections.append(current_section)
|
| 291 |
+
|
| 292 |
+
# Start new chorus section
|
| 293 |
+
current_section = [line]
|
| 294 |
+
current_type = "chorus"
|
| 295 |
+
else:
|
| 296 |
+
current_section.append(line)
|
| 297 |
+
|
| 298 |
+
# Save the last section
|
| 299 |
+
if current_type == "verse" and current_section:
|
| 300 |
+
verse_sections.append(current_section)
|
| 301 |
+
elif current_type == "chorus" and current_section:
|
| 302 |
+
chorus_section = current_section
|
| 303 |
+
|
| 304 |
+
# If no chorus found, create one from the first verse
|
| 305 |
+
if not chorus_section and verse_sections:
|
| 306 |
+
verse_lines = verse_sections[0]
|
| 307 |
+
# Find a good line to base the chorus on
|
| 308 |
+
for line in verse_lines:
|
| 309 |
+
if line and not line.startswith("[") and len(line.split()) >= 3:
|
| 310 |
+
chorus_section = self.create_chorus(line)
|
| 311 |
+
break
|
| 312 |
+
|
| 313 |
+
if not chorus_section:
|
| 314 |
+
chorus_section = ["[Chorus]", "We're living in the moment", "Feeling so alive"]
|
| 315 |
+
|
| 316 |
+
# Rebuild the lyrics with proper structure
|
| 317 |
+
structured_lines = []
|
| 318 |
+
|
| 319 |
+
# Add first verse
|
| 320 |
+
if verse_sections:
|
| 321 |
+
structured_lines.extend(verse_sections[0])
|
| 322 |
+
structured_lines.append("") # Empty line for spacing
|
| 323 |
+
|
| 324 |
+
# Add chorus
|
| 325 |
+
if chorus_section:
|
| 326 |
+
structured_lines.extend(chorus_section)
|
| 327 |
+
structured_lines.append("") # Empty line for spacing
|
| 328 |
+
|
| 329 |
+
# Add second verse if available
|
| 330 |
+
if len(verse_sections) > 1:
|
| 331 |
+
structured_lines.extend(verse_sections[1])
|
| 332 |
+
structured_lines.append("") # Empty line for spacing
|
| 333 |
+
|
| 334 |
+
# Repeat chorus
|
| 335 |
+
if chorus_section:
|
| 336 |
+
structured_lines.extend(chorus_section)
|
| 337 |
+
structured_lines.append("") # Empty line for spacing
|
| 338 |
+
|
| 339 |
+
# Add bridge if requested and we have enough content
|
| 340 |
+
if add_bridge and len(structured_lines) > 10:
|
| 341 |
+
bridge = self.create_bridge()
|
| 342 |
+
structured_lines.extend(bridge)
|
| 343 |
+
structured_lines.append("") # Empty line for spacing
|
| 344 |
+
|
| 345 |
+
# Final chorus
|
| 346 |
+
if chorus_section:
|
| 347 |
+
structured_lines.extend(chorus_section)
|
| 348 |
+
|
| 349 |
+
# If we only have one verse and no second verse, add the chorus again
|
| 350 |
+
elif len(verse_sections) <= 1 and chorus_section:
|
| 351 |
+
structured_lines.extend(chorus_section)
|
| 352 |
+
|
| 353 |
+
return "\n".join(structured_lines)
|
requirements.txt
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
transformers>=4.30.0
|
| 2 |
+
gradio==5.1.0
|
| 3 |
+
torch>=2.0.0
|
| 4 |
+
accelerate>=0.20.0
|
runtime.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
python-3.10
|